Панорамирование и масштабирование (на колесе мыши) в зависимости от положения курсора - PullRequest
0 голосов
/ 26 февраля 2019

Цель моего кода - возможность панорамирования и масштабирования элемента div.Он прекрасно работает, за исключением того, что масштабирование выполняется из центра (что нормально).Мне нужно, чтобы div изменял масштаб на основе местоположения курсора (вроде как работает масштабирование на картах Google), поэтому я использовал transform-origin, чтобы сместить масштаб от центра к местоположению курсора.Он работает совершенно нормально, за исключением того, что всякий раз, когда я меняю положение мыши для увеличения масштаба, элемент div «перепрыгивает» на несколько пикселей, а после этого «прыжка» он работает (масштабирование и панорамирование) снова совершенно нормально.

Iдумаю, причина в том, что я не рассчитываю новые расстояния правильно (после масштабирования), поскольку источник div изменяется.

Кто-нибудь может помочь с этим, пожалуйста?

Примечание: если я уменьшу масштаб, то увеличу до точно такой же шкалы, «скачка» не будет.

Выможете посмотреть мой код здесь, если я не достаточно ясно:

window.onload = function () {
    initializeImage();
};


function initializeImage() {

    var recElements = document.getElementsByClassName("rec");
    var rec = recElements[0];
    rec.panning = {};
    rec.imageZoom = 100;

    rec.stoprecMove = function () {
        this.panning.xMouseDown = null;
        this.panning.yMouseDownn = null;
    };

    rec.recMove = function() {
        var dx = 0;
        var dy = 0;
        var scale = this.imageZoom * 0.01;
        var pos = this.getBoundingClientRect();
        dx = (this.panning.xMove - this.panning.xMouseDown) / scale;
        dy = (this.panning.yMove - this.panning.yMouseDown) / scale;        
        dx = startOffsetX + dx;
        dy = startOffsetY + dy;

        var xZoom = this.xZoom;
        var yZoom = this.yZoom;
        var xTransform = xZoom - dx;
        var yTransform = yZoom - dy;
        
        var dxInPixel = dx + "px";
        var dyInPixel = dy + "px";

        this.style.transform = "translate(" + dxInPixel + "," + dyInPixel + ")" + "scale(" + scale + ")";
        this.style.transformOrigin = xTransform + "px" + " " + yTransform + "px";

        this.lastX = dx;
        this.lastY = dy;

    };

    rec.onmousewheel = function (e) {
        this.panning.xMove = 0;
        this.panning.yMove = 0;
        this.panning.xMouseDown = 0;
        this.panning.yMouseDown = 0;
        this.xZoom = e.clientX;
        this.yZoom = e.clientY;
        if (typeof this.lastX === "undefined") {
           startOffsetX = 0;
           startOffsetY = 0;
        }
        else {
           startOffsetX = this.lastX;
           startOffsetY = this.lastY;
        }
        var zoom = rec.imageZoom;
        var delta = event.detail ? event.detail * -120 : event.wheelDelta;
        zoom += delta / 15;
        if (zoom > 300) zoom = 300; else if (zoom < 30) zoom = 30;
        rec.imageZoom = zoom;

        this.recMove();
    };

    rec.onmousedown = function (e) {
        var xMouseDown = e.clientX;
        var yMouseDown = e.clientY;
        console.log("x: " + xMouseDown + " y: " + yMouseDown);
        this.panning.xMouseDown = xMouseDown;
        this.panning.yMouseDown = yMouseDown;
        if (typeof this.lastX === "undefined") {
            startOffsetX = 0;
            startOffsetY = 0;
        }
        else {
            startOffsetX = this.lastX;
            startOffsetY = this.lastY;
        }
        e.preventDefault();
    };

    rec.onmousemove = function (e) {
        if (this.panning.xMouseDown && this.panning.yMouseDown) {
            this.panning.xMove = e.clientX;
            this.panning.yMove = e.clientY;
            this.recMove();

            e.preventDefault();
        }

    };

    rec.onmouseup = function () {
        this.stoprecMove();
    };

    rec.onmouseout = function () {
        this.stoprecMove();
    };


}
.rec {
    width: 200px;
    height: 100px;
    background-image: repeating-linear-gradient(to right, yellow, gray 10%, green 15%, yellow 30%, gray 40%, green 45%, yellow 60%, gray 70%, green 75%, yellow 90%, gray 100%);
    position: fixed;
    top: 0;
    left: 0;
<!DOCTYPE html>

<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
    <meta charset="utf-8" />
    <title></title>
    <script src="script.js" type="text/javascript"></script>
    <link rel="stylesheet" type="text/css" href="styles.css"/>
</head>
<body>
    <div class = "rec"></div>
</body>
</html>
...