我有两个彼此不同宽度的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%
按钮之一,应将点从其当前位置动画化为新的点。
答案 0 :(得分:1)
如果您要绘制一个圆并四处移动,我建议您将其绘制到<canvas>
元素上,而不要通过设置其<div>
和top
属性来移动left
。甚至使用transform: translate(x, y)
也会更好。
为了使用JavaScript将点从一个位置平稳过渡到另一个位置,您需要:
x
和y
坐标,x
和y
坐标,并且在每个动画帧上使用window.requestAnimationFrame
更新当前位置。有了这些,以及将所得的计算位置应用于点的方法,您可以使用如下方法:How to move an object using X and Y coordinates in JavaScript移动点(示例移动画布,但是如果您知道{{ 1}}和x
,则可以将它们分别设置为y
和top
)。
答案 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");
}
如果即使要使用mousemove触发移动,也要为其设置动画,则可以忽略类方法,而只需将css的过渡属性拍一下即可。但这将模拟令人讨厌的鼠标延迟效果,类似于由于V-Sync造成的视频游戏输入延迟。