[英]Making javascript animation smooth?
Basically what I want to achieve is to drag some div within another container div. 基本上我想要实现的是在另一个容器div中拖动一些div。 Inner div should stop when it reaches the boundaries of the container div.
内部div应该在到达容器div的边界时停止。 I managed to do the most parts.
我成功完成了大部分工作。 But the problem is that if I drag inner div slowly & carefully it stops where it is supposed to be on the edges, however if I drag it faster, it sometimes overflow the edges or stops way before the edges.
但问题是,如果我慢慢地小心地拖动内部div,它会停在它应该位于边缘的位置,但是如果我将它拖得更快,它有时会溢出边缘或在边缘之前停止。 What is the problem here?
这里有什么问题? What should I do to fix this?
我该怎么做才能解决这个问题?
function mouseMove(e) {
e.preventDefault();
console.log("mouse moving");
if(isMouseDown > 0 && currentElement) {
mouseX = e.clientX;
mouseY = e.clientY;
var diffX = mouseX - lastMouseX;
var diffY = mouseY - lastMouseY;
if(diffX + lastElementX + elementWidth < rightLimit && diffX + lastElementX > leftLimit) {
lastElementX += diffX;
lastMouseX = mouseX;
}
if(diffY + lastElementY + elementHeight < bottomLimit && diffY + lastElementY > topLimit) {
lastElementY += diffY;
lastMouseY = mouseY;
}
setCurrentElementPosition(lastElementX, lastElementY);
}
}
Above code runs on mouse move event changing inner div's position. 上面的代码运行在鼠标移动事件改变内部div的位置。
Here's my solution for you, I've programmed video games before, and you run into this problem a lot. 这是我的解决方案,我以前编写过视频游戏,你经常遇到这个问题。
You're checking if it'll go out, but not doing anything if it does! 你正在检查它是否会熄灭,但如果确实没有做任何事情! If it goes outside, you have to set it to the edge.
如果它外出,你必须将它设置到边缘。
https://jsfiddle.net/7btv7oqy/3/ https://jsfiddle.net/7btv7oqy/3/
var lastElementX = 0; //last X position of element
var lastElementY = 0; //last Y position of element
var lastMouseX = 0; //last X position of mouse
var lastMouseY = 0;//last Y position of mouse
var mouseX = 0; //current mouse position X
var mouseY = 0; //current mouse position Y
var currentElement = null; //currently selected div
var elementWidth = 0;
var elementHeight = 0;
var container = null; //container div
var isMouseDown = 0; //if greater than zero, mouse is down
//limits of container div
var bottomLimit = 0;
var topLimit = 0;
var leftLimit = 0;
var rightLimit = 0;
function init() {
container = document.getElementsByClassName("container")[0];
topLimit = container.getBoundingClientRect().top;
bottomLimit = container.getBoundingClientRect().bottom;
leftLimit = container.getBoundingClientRect().left;
rightLimit = container.getBoundingClientRect().right;
document.addEventListener("mousedown", function mouseDown(e) {
e.preventDefault();
++isMouseDown;
document.addEventListener("mousemove", mouseMove);
setCurrentElement(getElementUnderMouse(e)); //set current element
currentElement.style.position = "absolute";
lastElementX = currentElement.getBoundingClientRect().left;
lastElementY = currentElement.getBoundingClientRect().top;
lastMouseX = e.clientX;
lastMouseY = e.clientY;
});
document.addEventListener("mouseup", function mouseUp(e) {
e.preventDefault();
--isMouseDown;
setCurrentElement(null);
document.removeEventListener("mousemove", mouseMove);
});
}
function mouseMove(e) {
e.preventDefault();
console.log("mouse moving");
// report(e);
if(isMouseDown > 0 && currentElement) {
mouseX = e.clientX;
mouseY = e.clientY;
var diffX = mouseX - lastMouseX;
var diffY = mouseY - lastMouseY;
if(diffX + lastElementX + elementWidth < rightLimit && diffX + lastElementX > leftLimit) {
lastElementX += diffX;
} else {
//without this, the location wouldn't update at all:
//check if it would go off the right edge, set to right edge
if (diffX + lastElementX + elementWidth >= rightLimit) {
lastElementX = rightLimit - elementWidth;
}
//check if it would go off the left edge, set to left edge
if(diffX + lastElementX <= leftLimit) {
lastElementX = leftLimit;
}
}
//this will always happen:
lastMouseX = mouseX;
if(diffY + lastElementY + elementHeight < bottomLimit && diffY + lastElementY > topLimit) {
lastElementY += diffY;
} else {
//without this, the location wouldn't update at all:
//check if it would go off the bottom edge, set to bottom edge
if(diffY + lastElementY + elementHeight >= bottomLimit) {
lastElementY = bottomLimit - elementHeight;
}
//check if it would go off the top edge, set to top edge
if(diffY + lastElementY <= topLimit) {
lastElementY = topLimit;
}
}
//this will always happen:
lastMouseY = mouseY;
setCurrentElementPosition(lastElementX, lastElementY);
}
}
function setCurrentElementPosition(left = null, top = null) {
if(currentElement) {
currentElement.style.top = top + 'px'
currentElement.style.left = left + 'px';
}
}
function setCurrentElement(element) {
currentElement = element;
if(element) {
elementWidth = currentElement.offsetWidth;
elementHeight = currentElement.offsetHeight;
} else {
elementWidth = 0;
elementHeight = 0;
}
}
function hasClass(element, cls) {
return ("" + element.className + "").indexOf("" + cls + "") > -1;
}
function getElementUnderMouse(e) {
var x = e.clientX;
var y = e.clientY;
return document.elementFromPoint(x, y);
}
function report(e) {
console.log("isMouseDown: " + isMouseDown);
console.log("mouseX: " + e.clientX);
console.log("mouseY: " + e.clientY);
console.log("currentElement: " + currentElement);
console.log("currentElement top: " + currentElement.getBoundingClientRect().top);
console.log("currentElement bottom: " + currentElement.getBoundingClientRect().bottom);
console.log("container top: " + container.getBoundingClientRect().top);
console.log("container bottom: " + container.getBoundingClientRect().bottom);
}
init();
EDIT: Not sure why it's missing by one pixel at the right and bottom, you'll have to do some investigation on that front. 编辑:不知道为什么它在右边和底部的一个像素缺失,你将不得不在这方面做一些调查。 Seems like it's not taking into consideration the border, despite you using
offsetWidth
. 看起来它没有考虑边框,尽管你使用了
offsetWidth
。 Good luck! 祝好运!
Here's my take; 这是我的看法; I've decoupled the element's movement from diffX/diffY:
我已经将元素的运动与diffX / diffY分离了:
https://jsfiddle.net/ttyrtjez/ https://jsfiddle.net/ttyrtjez/
// in onmousedown
offsetX = e.clientX - lastElementX;
offsetY = e.clientY - lastElementY;
// in onmousemove
var newElementX = mouseX - offsetX;
var newElementY = mouseY - offsetY;
if (newElementX + elementWidth >= rightLimit - 1) newElementX = rightLimit - elementWidth - 2;
if (newElementX < leftLimit) newElementX = leftLimit;
if (newElementY + elementHeight >= bottomLimit - 1) newElementY = bottomLimit - elementHeight - 2;
if (newElementY < topLimit) newElementY = topLimit;
setCurrentElementPosition(newElementX, newElementY);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.