1. 程式人生 > >矩形區域與圓心區域的碰撞檢測

矩形區域與圓心區域的碰撞檢測

var canvas = document.getElementById("canvas"); var context = canvas.getContext("2d"); var rx1 = 140, ry1 = 100, rx2 = 260, ry2 = 220, cx = 440, cy = 160, cr = 40; var mx = 0, my = 0, qx = 0, qy = 0; var min = Math.min; var max = Math.max; function clamp(v, x, y) { return v < x ? x : v > y ? y : v; } function
dist(x1, y1, x2, y2) {
var dx = x1 - x2, dy = y1 - y2; return Math.sqrt(dx * dx + dy * dy); } function p2c(px, py, cx, cy, cr) { return dist(px, py, cx, cy) < cr; } function r2c(rx1, ry1, rx2, ry2, cx, cy, cr) { return dist(clamp(cx, rx1, rx2), clamp(cy, ry1, ry2), cx, cy) < cr; } function
p2r(px, py, rx1, ry1, rx2, ry2) {
return px > rx1 && py > ry1 && px < rx2 && py < ry2; } context.strokeCircle = function(x, y, r) { this.beginPath(); this.arc(x, y, r, 0, Math.PI * 2, false); this.closePath(); this.stroke(); } var
hx, hy, hr = 7; // handle data var over = -1, dragging = false; function render() { var time = 0 | new Date(), x, y; updateTime = time + 25; // context.clearRect(0, 0, 640, 320); // if (over >= 0 && dragging) { x = mx - qx; y = my - qy; switch (over) { case 0: cx += x - hx; qx = mx - hx; cy += y - hy; qy = my - hy; break; case 1: cr = max(16, dist(cx, cy, x, y)); break; case 2: rx1 = min(x, rx2 - 16); ry1 = min(y, ry2 - 16); break; case 3: rx2 = max(x, rx1 + 16); ry1 = min(y, ry2 - 16); break; case 4: rx1 = min(x, rx2 - 16); ry2 = max(y, ry1 + 16); break; case 5: rx2 = max(x, rx1 + 16); ry2 = max(y, ry1 + 16); break; case 6: ry1 = min(y, ry2 - 16); break; case 7: ry2 = max(y, ry1 + 16); break; case 8: rx1 = min(x, rx2 - 16); break; case 9: rx2 = max(x, rx1 + 16); break; case 10: rx1 += x - hx; ry1 += y - hy; rx2 += x - hx; ry2 += y - hy; qx = mx - hx; qy = my - hy; break; } } // var co = r2c(rx1, ry1, rx2, ry2, cx, cy, cr); context.strokeStyle = co ? "red" : "blue"; context.strokeCircle(cx, cy, cr); context.strokeCircle(cx, cy, 1); context.strokeRect(rx1, ry1, rx2 - rx1, ry2 - ry1); if (!co) { x = clamp(cx, rx1, rx2); y = clamp(cy, ry1, ry2); context.strokeCircle(x, y, 4); var dx = x - cx; var dy = y - cy; var dd = Math.sqrt(dx * dx + dy * dy); var csx = cx + dx / dd * cr; var csy = cy + dy / dd * cr; context.strokeCircle(csx, csy, 4); // context.beginPath(); context.moveTo(x, y); context.lineTo(csx, csy); context.closePath(); context.stroke(); } // if (over >= 0 && !dragging) { context.strokeStyle = "red"; context.strokeCircle(hx, hy, hr); } } var interval = null; var redraw = false; function update() { if (redraw) { redraw = false; render(); } } function hp(i, x, y, c) { if (p2c(mx, my, x, y, hr)) { hx = x; hy = y; over = i; canvas.style.cursor = c || "move"; return true; } else return false; } function handleMouse(e) { mx = e.offsetX; my = e.offsetY; if (!dragging) { var cdx = mx - cx; var cdy = my - cy; var cd = dist(mx, my, cx, cy); var cex = cx + cdx / cd * cr; var cey = cy + cdy / cd * cr; if (!((cd < cr - hr && hp(0, mx, my)) || hp(1, cex, cey) || hp(2, rx1, ry1, "nw-resize") || hp(3, rx2, ry1, "ne-resize") || hp(4, rx1, ry2, "sw-resize") || hp(5, rx2, ry2, "se-resize") || hp(6, clamp(mx, rx1, rx2), ry1, "n-resize") || hp(7, clamp(mx, rx1, rx2), ry2, "s-resize") || hp(8, rx1, clamp(my, ry1, ry2), "w-resize") || hp(9, rx2, clamp(my, ry1, ry2), "e-resize") || hp(10, clamp(mx, rx1, rx2), clamp(my, ry1, ry2)) )) { canvas.style.cursor = ""; over = -1; } } } canvas.onmousemove = function(e) { handleMouse(e); redraw = true; } canvas.onmousedown = function(e) { e.preventDefault(); handleMouse(e); if (over >= 0) { dragging = true; qx = mx - hx; qy = my - hy; redraw = true; } } canvas.onmouseup = function(e) { handleMouse(e); if (dragging) { dragging = false; over = -1; redraw = true; } } canvas.onmouseover = function(_) { if (interval == null) interval = setInterval(update, 10); } canvas.onmouseout = function(_) { if (interval != null) { clearInterval(interval); interval = null; } } render();