Make javascript animation smooth?

Basically, I want to drag some div to another div container. The inner div should stop when it reaches the borders of the div container. I managed to do the most. But the problem is that if I drag the inner div slowly and carefully, it stops where it should be at the edges, however, if I drag it faster, it sometimes overflows the edges or stops in front of the edges. What is the problem? What should I do to fix this?

Here is the complete code

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);                              
    }                                                         
}

The mouse move event that changes the internal position of the div runs through the code.

+4
source share
2 answers

; diffX/diffY:

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);
+2

, , .

, , , ! , .

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();

: , , . , , , offsetWidth. !

+3

Source: https://habr.com/ru/post/1664301/


All Articles