【问题标题】:Avoiding jerky animation when using mouseover and mouseout使用 mouseover 和 mouseout 时避免生涩的动画
【发布时间】:2017-07-18 04:16:58
【问题描述】:

我正在使用Web Animation API 创建一个简单的动画,这样当用户在target 上移动鼠标时,动画应该从左到右开始,当用户将鼠标从target 上移开时,动画应该反转,target 应该从右向左移动。

目前如果用户在动画过程中将鼠标移入/移出,动画是生涩的,我没有平滑的效果。

我想知道如何解决这个问题。

注意:目前我正在使用 Web Animation API。但是在使用 CSS Keyframe Animation 时也会出现同样的问题。

我也尝试使用以下解决方案解决此问题,这改善了情况,但仍然存在问题。这是一个活生生的例子https://jsfiddle.net/x784xwoa/5/

var elm = document.getElementById("target");
var player = document.getElementById("target");

elm.addEventListener('mouseover', function(event) {
  console.log('mouseover', player.playState, 'animate');
  player = elm.animate(
    [{
      left: "0px",
      boxShadow: 'rgba(0, 0, 0, 0.5) 0px 0px 0px 0px'
    }, {
      left: "100px",
      boxShadow: 'rgba(0, 0, 0, 0.9) 50px 150px 100px 0px'
    }], {
      duration: 3000,
      direction: "normal",
      fill: "forwards",
      iterations: 1
    }
  );
});

elm.addEventListener('mouseout', function(event) {
  console.log('mouseout', player.playState, 'reverse');
  player.reverse();
});
#target {
  position: relative;
  top: 0;
  left: 0;
  width: 100px;
  height: 150px;
  background-color: red;
}
<div id="target"></div>

【问题讨论】:

  • 您注意到更新后的 codepen 有什么急躁?目前 Chrome 和 Firefox 都在实现附加动画(Web Animations 的一部分),这将允许您制作一个动画,平滑过渡到另一个动画。

标签: javascript css animation web-animations


【解决方案1】:

我总是使用 mouseenter / mouseleave 而不是 mouseover / mouseout 成功。

尽管它们的操作方式相同,但mouseenter 事件仅在鼠标指针进入选定元素时触发。如果鼠标指针也进入任何子元素,则会触发mouseover 事件。

【讨论】:

  • 感谢您的评论,我已经尝试过您的建议,不幸的是我仍然遇到同样的问题jsfiddle.net/r39f461s/2
【解决方案2】:

我能够使用以下脚本解决这个问题,添加一些逻辑来检查playState。 如果您有更好的解决方案,请将其发布为答案,因为我真的很想收到您的反馈。

   document.addEventListener("DOMContentLoaded", function (event) {
            var elm = document.getElementById("target");
            var player = null;



            elm.addEventListener('mouseenter', function (event) {
                if (player === null) {
                    player = elm.animate(
                      [{
                          left: "0px",
                          boxShadow: 'rgba(0, 0, 0, 0.5) 0px 0px 0px 0px'
                      }, {
                          left: "100px",
                          boxShadow: 'rgba(0, 0, 0, 0.9) 50px 150px 100px 0px'
                      }], {
                          duration: 3000,
                          direction: "normal",
                          fill: "forwards",
                          iterations: 1
                      }
                    );
                }
                else if (player.playState === 'running') {
                    player.reverse();
                }
                else if (player.playState === 'finished') {
                    player.reverse();

                }
            });

            elm.addEventListener('mouseout', function (event) {
                if (player.playState === 'running' || player.playState === 'finished') {
                    player.reverse();
                }
            });

            setInterval(function () {
                if (player) {
                    console.log(player.playState);
                }
            }, 1000);


        });
        #target {
            position: relative;
            top: 0;
            left: 0;
            width: 100px;
            height: 150px;
            background-color: red;
        }
    <div id="target"></div>

【讨论】:

    【解决方案3】:

    每次触发鼠标悬停事件时,您都会为元素制作一个新动画。通过预先创建动画并在使用之前暂停它来避免这种情况。

    我还将player.reverse(); 替换为player.playBackRate = (-)1;。我不确定为什么这也会导致问题。

    var elm = document.getElementById("target");
    var player = elm.animate(
      [{
        left: "0px",
        boxShadow: 'rgba(0, 0, 0, 0.5) 0px 0px 0px 0px'
      }, {
        left: "100px",
        boxShadow: 'rgba(0, 0, 0, 0.9) 50px 150px 100px 0px'
      }], {
        duration: 3000,
        direction: "normal",
        fill: "forwards",
        iterations: 1
      }
    );
    player.pause();
    
    elm.addEventListener('mouseover', function(event) {
      player.playbackRate = 1;
      player.play();
    });
    
    elm.addEventListener('mouseout', function(event) {
      player.playbackRate = -1;
    });
    #target {
      position: relative;
      top: 0;
      left: 0;
      width: 100px;
      height: 150px;
      background-color: red;
    }
    <div id="target"></div>

    剩下的唯一问题是当元素从鼠标下方移动时 mouseout 事件不会触发。它仅在鼠标移动时触发。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-06-01
      • 2012-04-24
      • 1970-01-01
      • 2012-05-13
      • 1970-01-01
      相关资源
      最近更新 更多