在鼠标移动时为 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");
}
如果您希望它在使用 mousemove 触发移动时仍具有动画效果,则可以忽略 class 方法,只需在 css 上点击过渡 属性。但这将模拟恼人的鼠标延迟效果,类似于视频游戏由于垂直同步而导致的输入延迟。
如果您正在绘制一个圆并四处移动,我建议绘制到 <canvas>
元素,而不是通过设置其 top
和 [=13= 来移动 <div>
] 特性。即使使用 transform: translate(x, y)
可能会更好。
为了使用 JavaScript 将你的点从一个位置平滑地过渡到另一个位置,你需要:
- 点的当前位置为
x
和y
坐标,
- 圆点的目标位置为
x
和y
坐标,
- 点作为标量移动的速度。
更新当前位置是在每个动画帧完成的 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,但是如果你知道 x
和 y
, 那么你可以将它们设置为 top
和 bottom
).
回答我自己的问题,感谢 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
我有两个不同宽度的 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");
}
如果您希望它在使用 mousemove 触发移动时仍具有动画效果,则可以忽略 class 方法,只需在 css 上点击过渡 属性。但这将模拟恼人的鼠标延迟效果,类似于视频游戏由于垂直同步而导致的输入延迟。
如果您正在绘制一个圆并四处移动,我建议绘制到 <canvas>
元素,而不是通过设置其 top
和 [=13= 来移动 <div>
] 特性。即使使用 transform: translate(x, y)
可能会更好。
为了使用 JavaScript 将你的点从一个位置平滑地过渡到另一个位置,你需要:
- 点的当前位置为
x
和y
坐标, - 圆点的目标位置为
x
和y
坐标, - 点作为标量移动的速度。
更新当前位置是在每个动画帧完成的 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,但是如果你知道 x
和 y
, 那么你可以将它们设置为 top
和 bottom
).
回答我自己的问题,感谢 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