152 lines
6.2 KiB
HTML
152 lines
6.2 KiB
HTML
<!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 = 20; // 可接受(偏移)范围
|
||
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.shadowOffsetX = 10;
|
||
ctx.shadowOffsetY = 10;
|
||
ctx.shadowBlur = 5;
|
||
ctx.shadowColor = 'rgba(0,0,0,0.5)';
|
||
|
||
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> |