如何在html5 canvas中用它的连接线拖动点?
How to drag points with it's connecting line in html5 canvas?
以下是我的代码。拖动点时遇到问题。问题是每当我拖动点时,所有的线都连接到一个点。我需要在 html5 Canvas 中有可拖动的点。但是我有一个补充约束:这 2 个点必须用一条线连接起来。当我拖动一个点时,线必须是动态绘制的,并且仍然链接到2个点。
let points= [];
let drag_point= -1;
let pointSize= 6;
let canvas = document.querySelector("#myCanvas");
let w = canvas.width;
let h = canvas.height;
var ctx = canvas.getContext("2d");
$("#myCanvas").mousedown(function (e) {
var pos = getPosition(e);
drag_point = getPointAt(pos.x, pos.y);
console.log("pos", drag_point);
if (drag_point == -1) {
// no point at that position, add new point
drawlines(pos.x, pos.y);
points.push(pos);
}
});
$("#myCanvas").mousemove(function (e) {
if (drag_point != -1) {
// if currently dragging a point...
var pos = getPosition(e);
//...update that.points position...
points[drag_point].x = pos.x;
points[drag_point].y = pos.y;
redraw(); // ... and redraw myCanvas
}
});
$("#myCanvas").mouseup(function (e) {
drag_point = -1;
});
function getPosition(event) {
var rect = canvas.getBoundingClientRect();
var x = event.clientX - rect.left;
var y = event.clientY - rect.top;
console.log(x, y);
return { x: x, y: y };
}
function getPointAt(x, y) {
for (var i = 0; i < points.length; i++) {
if (
Math.abs(points[i].x - x) < pointSize &&
Math.abs(points[i].y - y) < pointSize
)
// check if x,y is inside points bounding box. replace with pythagoras theorem if you like.
return i;
}
return -1; // no point at x,y
}
function redraw() {
ctx.clearRect(0, 0, canvas.width, canvas.height); // clear canvas
for (var i = 0; i < points.length; i++) {
// draw all points again
drawlines(points[i].x, points[i].y);
}
}
function drawlines(x, y) {
drawImages(x, y);
if (points.length > 0) {
var last = points[points.length - 1];
ctx.beginPath();
ctx.moveTo(last.x, last.y);
ctx.lineTo(x, y);
ctx.strokeStyle = "blue";
ctx.stroke();
}
}
function drawImages(x, y) {
var ctx = document.getElementById("myCanvas").getContext("2d");
ctx.beginPath();
ctx.arc(x, y, pointSize, 0, Math.PI * 2, true);
ctx.strokeStyle = "red";
ctx.stroke();
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<canvas
id="myCanvas"
width="1000"
height="1000"
style="border: 1px solid #d3d3d3"
></canvas>
.
查看下面的代码...
我重构了你的 drawlines
和 drawImages
以独立调用而不是在一个公共循环中,在我的代码中我们画了所有的线,然后我们画了所有的圆,这样我们就没有了一直来回改变颜色并防止圆圈上的线条重叠,鼠标按下还有另一个变化我称之为重绘而不是画线。
根据你的代码猜测问题出在你的:
var last = points[points.length - 1];
这看起来很不对劲,从技术上讲,这使得最后一个总是相同的
let points = [{x:10,y:10},{x:55,y:50},{x:100,y:10}];
let drag_point = -1;
let pointSize = 6;
let canvas = document.querySelector("#myCanvas");
var ctx = canvas.getContext("2d");
$("#myCanvas").mousedown(function(e) {
var pos = getPosition(e);
drag_point = getPointAt(pos.x, pos.y);
if (drag_point == -1) {
points.push(pos);
redraw();
}
});
$("#myCanvas").mousemove(function(e) {
if (drag_point != -1) {
var pos = getPosition(e);
points[drag_point].x = pos.x;
points[drag_point].y = pos.y;
redraw();
}
});
$("#myCanvas").mouseup(function(e) {
drag_point = -1;
});
function getPosition(event) {
var rect = canvas.getBoundingClientRect();
var x = event.clientX - rect.left;
var y = event.clientY - rect.top;
return {x, y};
}
function getPointAt(x, y) {
for (var i = 0; i < points.length; i++) {
if (
Math.abs(points[i].x - x) < pointSize &&
Math.abs(points[i].y - y) < pointSize
)
return i;
}
return -1;
}
function redraw() {
if (points.length > 0) {
ctx.clearRect(0, 0, canvas.width, canvas.height);
drawLines()
drawCircles()
}
}
function drawLines() {
ctx.beginPath();
ctx.moveTo(points[0].x, points[0].y);
ctx.strokeStyle = "blue";
ctx.lineWidth = 2;
points.forEach((p) => {
ctx.lineTo(p.x, p.y);
})
ctx.stroke();
}
function drawCircles() {
ctx.strokeStyle = "red";
ctx.lineWidth = 4;
points.forEach((p) => {
ctx.beginPath();
ctx.arc(p.x, p.y, pointSize, 0, Math.PI * 2, true);
ctx.stroke();
})
}
redraw()
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<canvas id="myCanvas" width="160" height="160" style="border: 1px solid #d3d3d3"></canvas>
以下是我的代码。拖动点时遇到问题。问题是每当我拖动点时,所有的线都连接到一个点。我需要在 html5 Canvas 中有可拖动的点。但是我有一个补充约束:这 2 个点必须用一条线连接起来。当我拖动一个点时,线必须是动态绘制的,并且仍然链接到2个点。
let points= [];
let drag_point= -1;
let pointSize= 6;
let canvas = document.querySelector("#myCanvas");
let w = canvas.width;
let h = canvas.height;
var ctx = canvas.getContext("2d");
$("#myCanvas").mousedown(function (e) {
var pos = getPosition(e);
drag_point = getPointAt(pos.x, pos.y);
console.log("pos", drag_point);
if (drag_point == -1) {
// no point at that position, add new point
drawlines(pos.x, pos.y);
points.push(pos);
}
});
$("#myCanvas").mousemove(function (e) {
if (drag_point != -1) {
// if currently dragging a point...
var pos = getPosition(e);
//...update that.points position...
points[drag_point].x = pos.x;
points[drag_point].y = pos.y;
redraw(); // ... and redraw myCanvas
}
});
$("#myCanvas").mouseup(function (e) {
drag_point = -1;
});
function getPosition(event) {
var rect = canvas.getBoundingClientRect();
var x = event.clientX - rect.left;
var y = event.clientY - rect.top;
console.log(x, y);
return { x: x, y: y };
}
function getPointAt(x, y) {
for (var i = 0; i < points.length; i++) {
if (
Math.abs(points[i].x - x) < pointSize &&
Math.abs(points[i].y - y) < pointSize
)
// check if x,y is inside points bounding box. replace with pythagoras theorem if you like.
return i;
}
return -1; // no point at x,y
}
function redraw() {
ctx.clearRect(0, 0, canvas.width, canvas.height); // clear canvas
for (var i = 0; i < points.length; i++) {
// draw all points again
drawlines(points[i].x, points[i].y);
}
}
function drawlines(x, y) {
drawImages(x, y);
if (points.length > 0) {
var last = points[points.length - 1];
ctx.beginPath();
ctx.moveTo(last.x, last.y);
ctx.lineTo(x, y);
ctx.strokeStyle = "blue";
ctx.stroke();
}
}
function drawImages(x, y) {
var ctx = document.getElementById("myCanvas").getContext("2d");
ctx.beginPath();
ctx.arc(x, y, pointSize, 0, Math.PI * 2, true);
ctx.strokeStyle = "red";
ctx.stroke();
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<canvas
id="myCanvas"
width="1000"
height="1000"
style="border: 1px solid #d3d3d3"
></canvas>
.
查看下面的代码...
我重构了你的 drawlines
和 drawImages
以独立调用而不是在一个公共循环中,在我的代码中我们画了所有的线,然后我们画了所有的圆,这样我们就没有了一直来回改变颜色并防止圆圈上的线条重叠,鼠标按下还有另一个变化我称之为重绘而不是画线。
根据你的代码猜测问题出在你的:
var last = points[points.length - 1];
这看起来很不对劲,从技术上讲,这使得最后一个总是相同的
let points = [{x:10,y:10},{x:55,y:50},{x:100,y:10}];
let drag_point = -1;
let pointSize = 6;
let canvas = document.querySelector("#myCanvas");
var ctx = canvas.getContext("2d");
$("#myCanvas").mousedown(function(e) {
var pos = getPosition(e);
drag_point = getPointAt(pos.x, pos.y);
if (drag_point == -1) {
points.push(pos);
redraw();
}
});
$("#myCanvas").mousemove(function(e) {
if (drag_point != -1) {
var pos = getPosition(e);
points[drag_point].x = pos.x;
points[drag_point].y = pos.y;
redraw();
}
});
$("#myCanvas").mouseup(function(e) {
drag_point = -1;
});
function getPosition(event) {
var rect = canvas.getBoundingClientRect();
var x = event.clientX - rect.left;
var y = event.clientY - rect.top;
return {x, y};
}
function getPointAt(x, y) {
for (var i = 0; i < points.length; i++) {
if (
Math.abs(points[i].x - x) < pointSize &&
Math.abs(points[i].y - y) < pointSize
)
return i;
}
return -1;
}
function redraw() {
if (points.length > 0) {
ctx.clearRect(0, 0, canvas.width, canvas.height);
drawLines()
drawCircles()
}
}
function drawLines() {
ctx.beginPath();
ctx.moveTo(points[0].x, points[0].y);
ctx.strokeStyle = "blue";
ctx.lineWidth = 2;
points.forEach((p) => {
ctx.lineTo(p.x, p.y);
})
ctx.stroke();
}
function drawCircles() {
ctx.strokeStyle = "red";
ctx.lineWidth = 4;
points.forEach((p) => {
ctx.beginPath();
ctx.arc(p.x, p.y, pointSize, 0, Math.PI * 2, true);
ctx.stroke();
})
}
redraw()
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<canvas id="myCanvas" width="160" height="160" style="border: 1px solid #d3d3d3"></canvas>