先上图
代码
代码
<!DOCTYPE html>
<html>
<head>
<title>选中Canvas中的直线</title>
</head>
<body>
<canvas id="myCanvas">Your browser does not support HTML5 Canvas. </canvas>
</body>
</html>
<script type="text/javascript">
var myCanvas = document.getElementById("myCanvas");
myCanvas.style.cssText = "position:absolute;left:0;top:0; border: 1px solid #ccc;"; // 画布样式
myCanvas.width = 800; // 画布的宽度
myCanvas.height = 800; // 画布的高度
var ctx = myCanvas.getContext('2d');
var a = 300, b = 300; // 原点
var lines = [
{ p1: { x: a, y: b }, p2: { x: a + 200, y: b }, flag: 0, }, // 原点右移200px;
{ p1: { x: a, y: b }, p2: { x: a, y: b - 200 }, flag: 0 }, // 原点上移200px;
{ p1: { x: a, y: b }, p2: { x: a - 200, y: b }, flag: 0 }, // 原点左移200px;
{ p1: { x: a, y: b }, p2: { x: a, y: b + 200 }, flag: 0 }, // 原点下移200px;
{ p1: { x: a, y: b }, p2: { x: a + 100, y: b - 80 }, flag: 0 }, // 第1象限
{ p1: { x: a, y: b }, p2: { x: a - 100, y: b - 100 }, flag: 0 }, // 第2象限
{ p1: { x: a, y: b }, p2: { x: a - 100, y: b + 100 }, flag: 0 }, // 第3象限
{ p1: { x: a, y: b }, p2: { x: a + 100, y: b + 80 }, flag: 0 }, // 第4象限
{ p1: { x: 100, y: 580 }, p2: { x: 200, y: 550 }, flag: 0 },
{ p1: { x: 200, y: 580 }, p2: { x: 300, y: 600 }, flag: 0 },
{ p1: { x: 80, y: 520 }, p2: { x: 10, y: 450 }, flag: 0 },
{ p1: { x: 10, y: 490 }, p2: { x: 60, y: 480 }, flag: 0 },
];
// 画线
drawAllLines();
// Click 事件
myCanvas.onclick = function (e) {
// 鼠标点击的坐标
var px = e.clientX,
py = e.clientY;
// 逐条线确定是否有点中
var offset = 5; // 可接受(偏移)范围
for (var i = 0; i < lines.length; i++) {
var p1 = lines[i].p1; // 直线起点
var p2 = lines[i].p2; // 直线终点
var flag = 0; // 1 - 点中
var minX = Math.min(p1.x, p2.x); // 较小的X轴坐标值
var maxX = Math.max(p1.x, p2.x); // 较大的X轴坐标值
var minY = Math.min(p1.y, p2.y); // 较小的Y轴坐标值
var maxY = Math.max(p1.y, p2.y); // 较大的Y轴坐标值
if (p1.y === p2.y) {
// 水平线
if ((px >= minX && px <= maxX) && (py >= minY - offset && py <= maxY + offset)) {
flag = 1;
lines[i].crossPoint = { x: px, y: p1.y }; // 直线上交叉点
}
}
else if (p1.x === p2.x) {
// 垂直线
if ((py >= minY && py <= maxY) && (px >= minX - offset && px <= maxX + offset)) {
flag = 1;
lines[i].crossPoint = { x: p1.x, y: py }; // 直线上交叉点
}
}
else {
// 斜线 (先判断点是否进入可接受大范围(矩形),然后再根据直线上的交叉点进行小范围比较)
if ((px >= minX && px <= maxX) && (py >= minY - offset && py <= maxY + offset)) {
//求Y轴坐标
//方法1:根据tanθ= y/x = y1/x1, 即y = (y1/x1)*x (该方法有局限性,垂直线(p2.x - p1.x)=0,不能用)
//var y = ((p2.y - p1.y) / (p2.x - p1.x)) * (px - p1.x);
//方法2:先求弧度hudu,根据cosθ=x/r, r=x/cosθ,求得r,再根据sinθ=y/r, y=sinθ*r, 求得y
var hudu = Math.atan2(p2.y - p1.y, p2.x - p1.x); // 直线的弧度(倾斜度)
// 用三角函数计出直线上的交叉点
var r = (px - p1.x) / Math.cos(hudu); // 直角三角形的斜边(或理解成圆的半径)
var y = Math.sin(hudu) * r; // Y轴坐标
var p = { x: px, y: p1.y + y }; // 直线上的交叉点
if ((Math.abs(px - p.x) <= offset) && (Math.abs(py - p.y) <= offset)) {
flag = 1; // 1 - 点中
}
lines[i].crossPoint = p; // 直线上的交叉点
}
}
if (flag === 1) {
lines[i].flag = ((lines[i].flag + 1) % 2); // 0、1切换
break;
}
}
// 重画线
drawAllLines();
};
// 画所有线函数
function drawAllLines() {
// 清空画布
ctx.clearRect(0, 0, myCanvas.width, myCanvas.height);
// 画出逐条线
for (var i = 0; i < lines.length; i++) {
var color = lines[i].flag === 1 ? "orange" : "blue";
drawLine(ctx, lines[i].p1, lines[i].p2, color);
// 画交叉点
if (lines[i].crossPoint) {
drawPoint(lines[i].crossPoint.x, lines[i].crossPoint.y);
}
lines[i].crossPoint = null;
}
}
// 画单条线函数
function drawLine(ctx, p1, p2, color) {
color = color || 'blue';
ctx.strokeStyle = color;
ctx.beginPath();
ctx.moveTo(p1.x, p1.y);
ctx.lineTo(p2.x, p2.y);
ctx.stroke();
ctx.closePath();
// 计算弧度
var hudu = Math.atan2(p2.y - p1.y, p2.x - p1.x);
var msg = "x:" + p2.x + " y:" + p2.y + " 弧度:" + hudu + " (rad)";
// 线长
var l1 = Math.sqrt(Math.pow(p2.x - p1.x, 2) + Math.pow(p2.y - p1.y, 2));
msg = msg + " 线长: " + l1;
ctx.fillText(msg, p2.x, p2.y);
}
// 画圆点
function drawPoint(x, y, color) {
color = color || 'red';
ctx.strokeStyle = color;
ctx.beginPath();
ctx.arc(x, y, 2, 0, 2 * Math.PI);
ctx.stroke();
ctx.closePath();
}
</script>