请求Canvas鼠标拖动已绘制直线并获取新坐标的示例代码
Canvas直线拖动功能实现
下面是实现鼠标拖动Canvas直线并在拖动完成后输出新坐标的完整代码:
<canvas id="graph" width="200" height="200" style="border:1px solid #ccc;"></canvas> <script> const canvas = document.getElementById('graph'); const ctx = canvas.getContext('2d'); // 存储直线的起点和终点坐标 let line = { start: { x: 50, y: 100 }, end: { x: 150, y: 100 } }; let isDragging = false; let dragOffset = { x: 0, y: 0 }; // 绘制直线的函数 function drawLine() { ctx.clearRect(0, 0, canvas.width, canvas.height); ctx.beginPath(); ctx.moveTo(line.start.x, line.start.y); ctx.lineTo(line.end.x, line.end.y); ctx.stroke(); } // 判断点是否在直线附近(容错范围5px) function isPointNearLine(mouseX, mouseY) { const { start, end } = line; // 计算点到直线的距离 const numerator = Math.abs( (end.y - start.y) * mouseX - (end.x - start.x) * mouseY + end.x * start.y - end.y * start.x ); const denominator = Math.sqrt(Math.pow(end.y - start.y, 2) + Math.pow(end.x - start.x, 2)); const distance = numerator / denominator; // 同时判断点是否在直线的 bounding box 内 const minX = Math.min(start.x, end.x); const maxX = Math.max(start.x, end.x); const minY = Math.min(start.y, end.y); const maxY = Math.max(start.y, end.y); return distance <= 5 && mouseX >= minX - 5 && mouseX <= maxX + 5 && mouseY >= minY -5 && mouseY <= maxY +5; } // 获取鼠标在Canvas内的坐标 function getMousePos(e) { const rect = canvas.getBoundingClientRect(); return { x: e.clientX - rect.left, y: e.clientY - rect.top }; } canvas.addEventListener('mousedown', (e) => { const mousePos = getMousePos(e); if (isPointNearLine(mousePos.x, mousePos.y)) { isDragging = true; // 计算鼠标相对于直线中点的偏移 const midX = (line.start.x + line.end.x) / 2; const midY = (line.start.y + line.end.y) / 2; dragOffset.x = mousePos.x - midX; dragOffset.y = mousePos.y - midY; } }); canvas.addEventListener('mousemove', (e) => { if (!isDragging) return; const mousePos = getMousePos(e); // 根据偏移更新直线的起点和终点 const midX = mousePos.x - dragOffset.x; const midY = mousePos.y - dragOffset.y; const lineLength = Math.sqrt(Math.pow(line.end.x - line.start.x, 2) + Math.pow(line.end.y - line.start.y, 2)); const angle = Math.atan2(line.end.y - line.start.y, line.end.x - line.start.x); line.start.x = midX - (lineLength / 2) * Math.cos(angle); line.start.y = midY - (lineLength / 2) * Math.sin(angle); line.end.x = midX + (lineLength / 2) * Math.cos(angle); line.end.y = midY + (lineLength / 2) * Math.sin(angle); drawLine(); }); canvas.addEventListener('mouseup', () => { if (isDragging) { isDragging = false; // 输出新坐标到控制台 console.log('直线新坐标:'); console.log('起点:', line.start); console.log('终点:', line.end); } }); // 初始绘制直线 drawLine(); </script>
关键功能说明
- 直线坐标存储:用
line对象保存直线的起点和终点,方便后续更新。 - 拖动检测:
isPointNearLine函数通过计算点到直线的距离,设置5px的容错范围,让用户更容易选中直线。 - 鼠标事件处理:
mousedown:检测是否点击直线,记录拖动偏移量,开启拖动状态。mousemove:拖动状态下,根据鼠标位置更新直线坐标,保持直线长度不变,并重绘。mouseup:结束拖动,输出新坐标到控制台。
- 重绘机制:每次拖动时先清空Canvas,再绘制更新后的直线,避免残留旧图形。
内容的提问来源于stack exchange,提问作者mcigorli
相关产品推荐
相关产品推荐

