我可以在 canvas 上突出显示的方块上捕捉这个(蓝色)div 吗?
Can I snap this (blue) div on the highlighted square on the canvas?
当您拖动蓝色 div 时,我希望它在释放鼠标按钮时 'snap' 进入突出显示的绿色方块的中间。我似乎找不到从 box[]
(Path2D()) 界面读取坐标的方法。那么有没有一种简单的方法可以实现这一目标?我应该将正方形的坐标保存在 dividually 中吗?或者我还能以某种方式从 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
我们用它 'snap' 到中间
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>
在我的代码中,我将鼠标事件与绘图分开,
- 我们只在循环上绘制。
- 事件改变状态变量。
还注意到,在某些情况下,两个框同时突出显示,将矩形的大小更改为 boxsize -0.5
当您拖动蓝色 div 时,我希望它在释放鼠标按钮时 'snap' 进入突出显示的绿色方块的中间。我似乎找不到从 box[]
(Path2D()) 界面读取坐标的方法。那么有没有一种简单的方法可以实现这一目标?我应该将正方形的坐标保存在 dividually 中吗?或者我还能以某种方式从 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
我们用它 'snap' 到中间
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>
在我的代码中,我将鼠标事件与绘图分开,
- 我们只在循环上绘制。
- 事件改变状态变量。
还注意到,在某些情况下,两个框同时突出显示,将矩形的大小更改为 boxsize -0.5