我在“mousemove”事件上使用 offsetX 和 offsetY 属性时遇到问题

I have trouble using the offsetX and offsetY properties on `mousemove` events

提问人:Courby 提问时间:11/6/2023 更新时间:11/6/2023 访问量:58

问:

我正在尝试通过制作国际象棋游戏来进一步学习 JS。

我制作了一个 800*800 的画布,其中放置了 16 个 SVG

然后,我为 mousedown、mousemove 和 mouseup 添加了事件侦听器,以使这些片段可拖动。

除了鼠标移动部分外,一切都很好。我已经在图像尺寸的一半处设置了偏移量,因此在移动图像时光标位于图像的中心,只要我全屏运行页面,它就可以正常工作。但是,如果我减小窗口大小并移动滚动条,则图像位置将关闭。

听说了 offsetX 和 offsetY 属性,我尝试使用它们。但我认为我做错了,因为我所能做的就是在移动鼠标时让图像到处传送。

这是我的代码的一个简短、快速测试的版本:

[HTML全文]

<html>
    <head>
        <meta charset="UTF-8">
        <link rel="stylesheet" href="style.css">
        <title>Chess</title>
    </head>
    <body>
        <div id ="container" style="position:relative;">
            <div id="gameBox" class="game">
                <canvas id="board" width="800px" height="800px" style = "position:absolute;z-index=-1"></canvas>
                <img id ="brook1" src="assets/piecebrook.svg" style="position:absolute;left:0px;top:0px;" draggable="false"/>
            </div>
        </div>
        <script type="text/javascript" src="js/utility.js"></script>
        <script type="text/javascript" src="js/main.js"></script>
    </body>
</html>

JS系列

class ChessGame {
    constructor () {
    this.b = document.getElementById("board");
    this.c = document.getElementById("gameBox");
    this.bContext = this.b.getContext("2d");
    this.bContext.fillStyle = "#825e2b";
    this.bContext.lineWidth = "5";
    this.pieces = [];
    this.selectedPiece = null;
}

    
    addListeners = function() {
        this.c.addEventListener('mousedown', function(event) {
            var x = event.clientX;
            var y = event.clientY;
            eventOnMouseDown(document.elementFromPoint(x,y));
    }, false);
        window.addEventListener('mouseup', eventOnMouseUp, false);
    }
    
    fillBoard = function() {
        this.bContext.clearRect(0, 0, 800, 800);
        var fill = true;
        for (let i = 0; i < 8; i++) {
            fill = (fill) ? false : true;
            for (let j = 0; j < 8; j++) {
                this.bContext.beginPath()
                {
                    this.bContext.fillStyle = (fill) ? "#76521f" : "#ffffff";
                    this.bContext.fillRect(j * 100, i * 100, 100, 100);
                }
                fill = (fill) ? false : true;
            }
        }
    }
        
    startGame = function() {
        this.fillBoard();
        this.generatePieces();
        this.addListeners();
        var obj = document.getElementById("brook1");
        this.pieces[id] = obj;
    }
}

    
eventOnMouseDown = function(elem) {
        if (elem.id != "board") {
            var piece = game.pieces[elem.id];
                game.selectedPiece = document.getElementById(elem.id);
                game.selectedPiece.style.zIndex = "50";
                window.addEventListener('mousemove', movePiece, true);
        }
    }
eventOnMouseUp = function(event) {
        window.removeEventListener('mousemove', movePiece, true);

    }
movePiece = function(event) {
        let offsetX = game.selectedPiece.width / 2;
        let offsetY = game.selectedPiece.height / 2;
        game.selectedPiece.style.top = (event.clientY - offsetY) + 'px';
        game.selectedPiece.style.left = (event.clientX - offsetX) + 'px';
    }

var game = new ChessGame();
game.startGame();

我正在使用的 SVG:https://svgshare.com/s/zMV

尝试过有和没有偏移量,尝试使用事件。OffsetX,事件。LayerX 和事件。离开了,但他们都结束了这场运动。我所期望的是,即使我调整窗口大小,图像也会保留在光标上

JavaScript 事件 画布 mouseevent 偏移

评论

0赞 Nina Scholz 11/6/2023
顺便说一句,为什么路径被包裹在一个块中?{ this.bContext.fillStyle ...

答:

0赞 waffentrager 11/6/2023 #1

我检查了您的代码,找到了最适合我的解决方案。 图片在移动过程中位于光标的中心

body, html {
  padding: 0;
  margin: 0;
  width: 100%;
  height: 100%;
  overflow: hidden;
}

您应该隐藏页面上的滚动条,这样您就不必考虑 scrollLeft 和 scrollTop,它也可以称为 offsetLeft 和 offsetTop。css 属性对此负责。如果您确实想保留滚动条,则需要考虑 canvas 元素本身的偏移量,它可能还具有其他可能影响光标位置的属性overflow: hidden;

movePiece = function(event) {
        let offsetX = game.selectedPiece.width / 2;
        let offsetY = game.selectedPiece.height / 2;
        let winY = window.scrollY || window.pageYOffset;
        let winX = window.scrollX || window.pageXOffset;
        game.selectedPiece.style.top = (event.clientY - game.selectedPiece.offsetParent.offsetTop + winY - offsetY) + 'px';
        game.selectedPiece.style.left = (event.clientX - game.selectedPiece.offsetParent.offsetLeft + winX - offsetX) + 'px';
}