<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>計算矩形中心點連線與邊框交點</title>
</head>
<body>
<canvas id="cSketchPad" width="640" height="480" style="border: 2px solid gray" />
<script src="//code.jquery.com/jquery-1.11.0.min.js"></script>
<script>
var $canvas = $("#cSketchPad");
var ctx = $canvas[0].getContext("2d");
var box = { x: 100, y: 150, w: 140, h: 90 };
var st = { x: box.x + box.w / 2, y: box.y + box.h / 2 };
function init() {
//清空背景
ctx.fillStyle = "white";
ctx.fillRect(0, 0, $canvas.width(), $canvas.height());
//繪製矩形
ctx.beginPath();
ctx.rect(box.x, box.y, box.w, box.h);
ctx.strokeStyle = "red";
ctx.stroke();
//繪製中心點
ctx.fillStyle = "black";
ctx.fillRect(st.x - 1, st.y - 1, 3, 3);
ctx.save();
}
init();
var ed, pos = $canvas.position(), mx = pos.left, my = pos.top;
$canvas.mousedown(function(e) {
init();
ed = { x: e.pageX - mx, y: e.pageY - my };
//繪製目標點
ctx.fillStyle="black";
ctx.fillRect(ed.x - 1, ed.y - 1, 3, 3);
//計算與邊框相交點
var pnt = findEdgePoint(st, ed, box.w, box.h);
drawLine(st, pnt, "#ccc");
drawCross(pnt, "black");
drawLine(pnt, ed, "blue", true);
});
function drawCross(p, c) {
var d = 3;
drawLine({ x: p.x - d, y: p.y - d }, { x: p.x + d, y: p.y + d }, c);
drawLine({ x: p.x + d, y: p.y - d }, { x: p.x - d, y: p.y + d }, c);
}
function drawLine(s, e, c, arrow) {
ctx.beginPath();
ctx.moveTo(s.x, s.y);
ctx.lineTo(e.x, e.y);
ctx.strokeStyle = c;
ctx.stroke();
//畫箭頭
if (arrow) {
ctx.save();
ctx.fillStyle = c;
ctx.translate(e.x, e.y);
var ang = Math.atan2(e.y - s.y, e.x - s.x) + Math.PI / 2;
ctx.rotate(ang);
ctx.moveTo(0, 0);
ctx.lineTo(-5, 10);
ctx.lineTo(5, 10);
ctx.closePath();
ctx.fill();
ctx.restore();
}
}
Math.sign = function(n) { return n == 0 ? 0 : n / Math.abs(n); }
function findEdgePoint(src, dst, w, h)
{
var dy = dst.y - src.y;
var dx = dst.x - src.x;
//計算斜率
var ang = Math.atan2(dy, dx);
//對角線斜率
var a1 = Math.atan2(h, w), a2 = Math.PI - a1;
//計算交點到中心的長度
var l =
(ang >= -a1 && ang <= a1 || ang >= a2 || ang <= -a2 ) ?
Math.sign(dx) * w / Math.cos(ang): //交點在左右側時X軸長度要等於正負w
Math.sign(dy) * h / Math.sin(ang); //交點在上下側時Y軸長度要等於正負h
//顯示角度(Debug用)
ctx.fillText(ang * 180 / Math.PI, 12, 12);
//計算交點座標
var tx = src.x + l * Math.cos(ang) / 2;
var ty = src.y + l * Math.sin(ang) / 2;
return { x: tx, y: ty };
}
</script>
</body>
</html>