在鼠标移动时为 Javascript 中的元素设置动画

Animate an element in Javascript on mousemove

我有两个不同宽度的 DIV 彼此重叠。上面DIVdisplayDIV比下面DIVcaptureDIV.

displayDIV 中,我画了一个 X 位置与 captureDIV 内的鼠标位置成比例的点。

当您在 captureDIV 中移动鼠标时,点在 DisplayDIV 中按比例移动。

如果你看看这个就更有意义了 fiddle

我的代码如下...

let capture = document.getElementById('captureDIV');
let display = document.getElementById('displayDIV');
let circle = document.getElementById('circle');
capture.addEventListener('mousemove', handleMouseMove);

function handleMouseMove(event) {
  const captureRect = capture.getBoundingClientRect();
  const captureWidth = captureRect.right - captureRect.left;
  const relativeX = event.x - captureRect.left;
  let percent = (relativeX / captureWidth) * 100;
  let roundedPercent = parseFloat(Math.round(percent * 100) / 100).toFixed(2);

  moveDotTo(roundedPercent);
}


function moveDotTo(percentage) {
  const displayRect = display.getBoundingClientRect();
  const displayWidth = displayRect.right - displayRect.left;
  const circleX = displayRect.left + displayWidth * (percentage / 100);
  const circleY = displayRect.top + (displayRect.height / 2);
  const style = `top:${circleY}px;left:${circleX}px;`;
  circle.setAttribute('style', style);
}

我还有一些按钮可以在 DisplayDIV 中设置点的位置,例如...

let move20 = document.getElementById('move20');
move20.addEventListener('click', function(event) {
  moveDotTo(20);
});

使用 Vanilla JS 而不是 CSS 技巧,我如何创建一个函数来将点从其现有位置动画化(而不是移动)到新位置。

function animateDotTo(percentage) {
  // clever code here
}

我需要能够从按钮或 mousemove 事件处理程序调用 animateDotTo(percentage) 函数。

无论移动是如何触发的,点都应该始终动画到它的新位置。例如,如果鼠标移出 captureDIV 底部的左侧,然后移至 captureDIV 的右侧,则点应该在 DisplayDIV 上移动而不是跳跃现在。同样按下 move to x% 按钮之一应该使点从当前位置动画到新位置。

css 转换中的一个简单技巧将解决此问题。

当然可以。当您实际移动鼠标时,您不希望它设置动画。所以我所做的是将过渡 css 属性 与另一个 class 分开,然后在鼠标移动时删除 class,当我们单击移动按钮时重新附加它.

CSS

#circle {
  position: absolute;
  left: -100px;
  top: -100px;
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background-color: #000;

  transition: none;
}

#circle.animate{
    transition: 500ms ease;
}

JS

move20.addEventListener('click', function(event) {
  moveDotTo(20); animateDotTo();
});

move60.addEventListener('click', function(event) {
  moveDotTo(60);animateDotTo();
});

move80.addEventListener('click', function(event) {
  moveDotTo(80);animateDotTo();
});

function moveDotTo(percentage) {
    circle.classList.remove("animate");

  const displayRect = display.getBoundingClientRect();
  const displayWidth = displayRect.right - displayRect.left;
  const circleX = displayRect.left + displayWidth * (percentage / 100);
  const circleY = displayRect.top + (displayRect.height / 2);
  const style = `top:${circleY}px;left:${circleX}px;`;
  circle.setAttribute('style', style);
}

function animateDotTo(percentage) {
    circle.classList.add("animate");
}

http://jsfiddle.net/8pm2grjd/

如果您希望它在使用 mousemove 触发移动时仍具有动画效果,则可以忽略 class 方法,只需在 css 上点击过渡 属性。但这将模拟恼人的鼠标延迟效果,类似于视频游戏由于垂直同步而导致的输入延迟。

如果您正在绘制一个圆并四处移动,我建议绘制到 <canvas> 元素,而不是通过设置其 top 和 [=13= 来移动 <div> ] 特性。即使使用 transform: translate(x, y) 可能会更好。

为了使用 JavaScript 将你的点从一个位置平滑地过渡到另一个位置,你需要:

  • 点的当前位置为xy坐标,
  • 圆点的目标位置为xy坐标,
  • 点作为标量移动​​的速度。

更新当前位置是在每个动画帧完成的 window.requestAnimationFrame. With these in hand, and a way of applying the resulting calculated position to the dot, you can use a method like this one: How to move an object using X and Y coordinates in JavaScript 来移动你的点(这个例子移动了 canvas,但是如果你知道 xy, 那么你可以将它们设置为 topbottom).

回答我自己的问题,感谢 Billy Brown 为我指明了正确的方向。使用 window.requestAnimationFrame 是要走的路。

var currentPercentage;
var startPercentage;
var targetPercentage;


function animateDotTo(percentage) {
    targetPercentage = percentage;
    startPercentage = currentPercentage;
    window.requestAnimationFrame(step);
}

function step(timestamp) {
    var fps = 7;
    var maxStep = 30;
    var distStartToTarget = Math.abs(startPercentage - targetPercentage);
    var stepSize = Math.min(distStartToTarget / fps, maxStep);
    if (targetPercentage < startPercentage) {
        currentPercentage -= stepSize,0;
        if (currentPercentage > targetPercentage) {
            window.requestAnimationFrame(step);
        }
    } else if (targetPercentage > startPercentage) {
        currentPercentage += stepSize,100;
        if (currentPercentage < targetPercentage) {
            window.requestAnimationFrame(step);
        }
    } else {
        return;
    }
    if (currentPercentage > 100 ) { currentPercentage = 100; }
    if (currentPercentage < 0 ) { currentPercentage = 0; }
    moveDotTo(currentPercentage);
}

已更新 fiddle