当您拖动蓝色div时,我希望它在释放鼠标按钮时"捕捉"到绿色高亮显示的正方形的中间.我似乎找不到从box[](Path2D())界面读取坐标的方法.那么,有没有一种简单的方法来实现这一点?我应该单独保存正方形的坐标吗?或者我还能以某种方式从Path2D界面中获取点吗?

const board = document.getElementById("board");
const ctxB = board.getContext("2d");
var Grid = false;
const boxsize = 64;
const amountOfrows = 8;
const amountOfHorBoxes = 7;
const totalAmountOfBoxes = amountOfrows * amountOfHorBoxes;
board.width = boxsize * 7.5;
board.height = boxsize * 8;
var addHorBox = 0;
var addVertBox = 0;
let boxes = [];

function drawGrid(){
    Grid=true;
    // for the amout of rows
    for (let rowcount = 0; rowcount < amountOfrows; rowcount++) {
        ctxB.lineWidth = 1;
        ctxB.strokeStyle = "black";
        ctxB.fillStyle = "white";
        // filling the rows
        if(rowcount%2==0){
            for (let boxcount = 0; boxcount < amountOfHorBoxes; boxcount++) {
                let box = new Path2D();
                box.rect(addHorBox, addVertBox, boxsize, boxsize);
                boxes.push(box);
                ctxB.fill(box);
                ctxB.stroke(box);
                addHorBox+=boxsize;
            }
        }
        addHorBox=0;
        addVertBox+=boxsize;
    }
}
MoveUnit(document.getElementById("unit"));
function MoveUnit(unit){
    const rect = board.getBoundingClientRect();
    const checkX = unit.clientWidth/2 - rect.left;
    const checkY = unit.clientHeight/2 - rect.top;
    var initialX;
    var initialY;
    var tile;
    unit.onmousedown = mouseDown;
    function mouseDown(e){
        e = e || window.event;
        e.preventDefault();
        initialX = e.clientX;
        initialY = e.clientY;
        document.onmouseup = mouseUp;
        document.onmousemove = moveMouse;
    }
    function moveMouse(e){
        e = e || window.event;
        e.preventDefault();
        unit.style.top = (unit.offsetTop + e.clientY - initialY) + "px";
        unit.style.left = (unit.offsetLeft + e.clientX - initialX) + "px";

        boxes.forEach(box => {
            if (ctxB.isPointInPath(box, unit.offsetLeft + checkX, unit.offsetTop + checkY)) {
                ctxB.lineWidth = 2;
                ctxB.fillStyle = 'green';
                ctxB.fill(box);
                ctxB.stroke(box);
                tile=box;
            }else{
                ctxB.lineWidth = 1;
                ctxB.strokeStyle = "black";
                ctxB.fillStyle = 'white';
                ctxB.fill(box);
                ctxB.stroke(box);
            }
        });
        // saving new mousepos after moving the unit
        initialX = e.clientX;
        initialY = e.clientY;
    }
    function mouseUp(){
        document.onmousemove = false;
        
    }
}
function loop(timestamp){    
    // draw once
    if(Grid==false) drawGrid();
    requestAnimationFrame(loop);
}
loop();
#board{
    background-color: #999;
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
}
#unit{
    background-color: rgb(134, 162, 224);
    position: absolute;
    cursor: pointer;
    z-index: 1;
    width: 30px;
    height: 30px;
}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="testing.css"/>
    <title>Gridding</title>
</head>
<body>
    <div id="unit"></div>
    <canvas id="board"></canvas></div>
    <script src="testing.js"></script>
</body>
</html>

推荐答案

在这些Path2D实例中,我们可以添加一些有用的数据,以满足您的需要:

let box = new Path2D();
box.rect(...
box.data = { row, column }

然后在function mouseUp上,我们用它"咬合"到中间

unit.style.top = ((box.data.column + 0.5) * boxsize) + "px";
unit.style.left = ((box.data.row + 0.5) * boxsize) + "px";

我在下面的示例中减少了很多代码,我只关注这个问题,你在提问时也应该这样做,这有助于其他人更快地切入要点,并为你提供更好的快速回答机会.

const board = document.getElementById("board");
const ctxB = board.getContext("2d");
const unit = document.getElementById("unit");

const boxsize = 32;
board.width = board.height = boxsize * 4;

let boxes = [];
for (let r = 0; r < 4; r++) {
  for (let c = 0; c < 4; c++) {
    let box = new Path2D();
    box.rect(r * boxsize, c * boxsize, boxsize -0.5, boxsize -0.5);
    box.data = { r, c }
    boxes.push(box);
  }
}

var position = { x: -1, y: -1 }
function mouseDown(e) {
  document.onmouseup = mouseUp;
  document.onmousemove = moveMouse;
  position = { x: e.clientX, y: e.clientY}
}

function mouseUp() {
  document.onmousemove = false;
  boxes.forEach(box => {
    if (ctxB.isPointInPath(box, position.x, position.y)) {
      unit.style.top = ((box.data.c + 0.5) * boxsize) + "px";
      unit.style.left = ((box.data.r + 0.5) * boxsize) + "px";
    }
  });
}

function moveMouse(e) {
  unit.style.top = (unit.offsetTop + e.clientY - position.y) + "px";
  unit.style.left = (unit.offsetLeft + e.clientX - position.x) + "px";
  position = { x: e.clientX, y: e.clientY}
}

function loop(timestamp) {
  ctxB.clearRect(0, 0, board.width, board.height)
  boxes.forEach(box => {
    ctxB.fillStyle = ctxB.isPointInPath(box, position.x, position.y)? 'green' : 'white'
    ctxB.fill(box);
    ctxB.stroke(box);
  });
  requestAnimationFrame(loop);
}
loop();
unit.onmousedown = mouseDown;
#unit {
  background-color: blue;
  position: absolute;
  width: 20px;
  height: 20px;
}
<canvas id="board"></canvas>
<br>
<div id="unit"></div>

在我的代码中,我将鼠标事件与绘图分离,

  • 我们只在回路上绘制.
  • 事件会更改状态变量.

还注意到,在某些情况下,两个框同时高亮显示,将rect的大小更改了一点点,固定为boxsize -0.5

Javascript相关问答推荐

如何用显示网格平滑地将元素从一个地方移动到另一个地方?

使搜索栏更改语言

如何从一个列表中创建一个2列的表?

Spring boot JSON解析错误:意外字符错误

无法检测卡片重叠状态的问题

JSDoc创建并从另一个文件导入类型

VUE 3捕获错误并呈现另一个组件

我在Django中的视图中遇到多值键错误

Use Location位置成员在HashRouter内为空

类构造函数忽略Reaction Native中的可选字段,但在浏览器中按预期工作

VSCode中出现随机行

警告框不显示包含HTML输入字段的总和

我想使用GAS和HTML将从Electron 表格中获得的信息插入到文本字段的初始值中

如何使本地html页面在重新加载时保持当前可隐藏部分的打开状态?

如何在每隔2分钟刷新OKTA令牌后停止页面刷新

在对象的嵌套数组中添加两个属性

由于http.get,*ngIf的延迟很大

浮动标签效果移除时,所需的也被移除

Playwright:ReferenceError:browserContext未定义

在特定区域的图像上 Select x和y,并在其上创建边框