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>
|