在mousemove上对Javascript中的元素进行动画处理

时间:2018-11-29 01:05:17

标签: javascript mousemove

我有两个彼此不同宽度的DIV。顶部DIV displayDIV比底部DIV captureDIV宽。

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
}

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

无论如何触发移动,点都应始终设置为新位置的动画。例如,如果将鼠标从captureDIV的左侧移至底部的底部,然后移至captureDIV的右侧,则该点应在DisplayDIV上进行动画处理,因此不会跳动现在做。同样按下move to x%按钮之一,应将点从其当前位置动画化为新的点。

3 个答案:

答案 0 :(得分:1)

如果您要绘制一个圆并四处移动,我建议您将其绘制到<canvas>元素上,而不要通过设置其<div>top属性来移动left 。甚至使用transform: translate(x, y)也会更好。

为了使用JavaScript将点从一个位置平稳过渡到另一个位置,您需要:

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

在每个动画帧上使用window.requestAnimationFrame更新当前位置。有了这些,以及将所得的计算位置应用于点的方法,您可以使用如下方法:How to move an object using X and Y coordinates in JavaScript移动点(示例移动画布,但是如果您知道{{ 1}}和x,则可以将它们分别设置为ytop)。

答案 1 :(得分:1)

感谢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

答案 2 :(得分:0)

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

当然。您实际上不希望在移动鼠标时对其进行动画处理。所以我要做的是,我将另一个类的transition css属性分开,然后在鼠标移动时删除该类,并在单击移动按钮时重新附加它。

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触发移动,也要为其设置动画,则可以忽略类方法,而只需将css的过渡属性拍一下即可。但这将模拟令人讨厌的鼠标延迟效果,类似于由于V-Sync造成的视频游戏输入延迟。