文本输入中的打字机效果在 Firefox 中不起作用

Typewriter effect in text input not working in Firefox

当用户将鼠标悬停在输入上时,此代码会在输入中产生打字机动画效果,它会为占位符文本设置动画。当用户离开时,我希望动画停止并且输入返回其原始状态。

$(function() {

    var sppInput,
        sppInputName = $('#spp-input-name'),
        sppInputNamePlace = sppInputName.attr('placeholder');

    // Typewriter Effect
    function sppInputStart(elm, n, text) {
        if (n < (text.length)) {
            $(elm).attr('placeholder', text.substring(0, n + 1));
            n++;
            sppInput = setTimeout(function () {
                sppInputStart(elm, n, text);
            }, 80);
        }
    }
    function sppInputStop(elm, place) {
        clearTimeout(sppInput);
        $(elm).attr('placeholder', place);
    }

    // Typewriter Effect for Name
    sppInputName.mouseover(function () {
        sppInputStart(this, 0, sppInputName.data('typewriter'));
    });
    sppInputName.mouseout(function () {
        sppInputStop(this, sppInputNamePlace);
    });

});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input placeholder="Name" data-typewriter="Insert the Name" type="text" id="spp-input-name" name="name" required>

此代码适用于所有浏览器(包括 IE),但不适用于 firefox。

为什么?

在 Firefox 中 mouseovermouseout 触发多次。事实上,有很多事情会导致它们重新燃烧。这里更改占位符 属性 就可以了,可能是因为 FX 在更改视觉效果后正在重新计算布局。在其他浏览器中很可能存在您尚未发现的类似问题。

您不能依赖 mouseovermouseout(或实际上任何位置事件)只触发一次来启动您的效果并再次触发它。

改为将其作为输入状态并切换标志:

$(function() {

    var sppInput,
        sppInputName = $('#spp-input-name'),
        sppInputNamePlace = sppInputName.attr('placeholder'),
        inputAnimating = false;

    // Typewriter Effect
    function sppInputStart(elm, n, text) {
        if(!inputAnimating) {
            setTimeout(function () {
                sppInputStart(elm, n, text);
            }, 500);
            return;
        }
        
        if (n < (text.length)) {
            $(elm).attr('placeholder', text.substring(0, n + 1));
            n++;
            sppInput = setTimeout(function () {
                sppInputStart(elm, n, text);
            }, 80);
        }
    }
    function sppInputStop(elm, place) {
        clearTimeout(sppInput);
        $(elm).attr('placeholder', place);
    }

    // Typewriter Effect for Name
    sppInputName.mouseover(function () {
        inputAnimating = true;
    });
    sppInputName.mouseout(function () {
        inputAnimating = false;
    });
    
    sppInputStart(sppInputName, 0, sppInputName.data('typewriter'));

});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input placeholder="Name" data-typewriter="Insert the Name" type="text" id="spp-input-name" name="name" required>

这适用于 FX。

但是,请考虑使用 requestAnimationFrame 或使用 placeholder 属性 以外的其他东西,因为这可能会导致丢帧,尤其是在移动设备上。

您也可能会导致 A11Y 问题,因为屏幕阅读器将无法阅读您每 80 毫秒更改一次的属性。

看起来更改 placeholder 值会重新触发 mouseover 事件

一个"hack"有效:

$(document).ready(function() {

    var sppInput,
        sppInputName = $('#spp-input-name'),
        sppInputNamePlace = sppInputName.attr('placeholder');

    // Typewriter Effect
    function sppInputStart(elm, n, text) {
        if (n < (text.length)) {
            $(elm).attr('placeholder', text.substring(0, n + 1));
            n++;
            sppInput = setTimeout(function() {
                sppInputStart(elm, n, text);
            }, 80);
        }
    }

    function sppInputStop(elm, place) {
        clearTimeout(sppInput);
        $(elm).attr('placeholder', place);
    }

    // Typewriter Effect for Name
    sppInputName.mouseover(function() {
        // hack
        if ($(this).data('flag') != '1') {
            $(this).data('flag', '1');
            sppInputStart(this, 0, sppInputName.data('typewriter'));
        }
    });
    sppInputName.mouseout(function() {
        // hack
        $(this).data('flag', '0');
        sppInputStop(this, sppInputNamePlace);
    });

});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input placeholder="Name" data-typewriter="Insert the Name" type="text" id="spp-input-name" name="name" required>