JSFiddle - React, Tailwind, and code Playground
by m1erickson
HTML
<p>Move the mouse: find "near-ish" point on ellipse</p>
<div id="wrapper">
<canvas id="canvas2" width=300 height=300></canvas>
<canvas id="canvas" width=300 height=300></canvas>
</div>
CSS
body {
background-color: ivory;
padding:20px;
}
#wrapper {
position:relative;
width:300px;
height:300px;
}
#canvas {
position:absolute;
top:0px;
left:0px;
border:1px solid green;
width:100%;
height:100%;
}
#canvas2 {
position:absolute;
top:0px;
left:0px;
border:1px solid red;
width:100%;
height:100%;
}
JavaScript
// get canvas references
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var canvas2 = document.getElementById("canvas2");
var ctx2 = canvas2.getContext("2d");
// calc canvas position on page
var canvasOffset = $("#canvas").offset();
var offsetX = canvasOffset.left;
var offsetY = canvasOffset.top;
// define the ellipse
var cx = 150;
var cy = 150;
var radiusX = 50;
var radiusY = 25;
var halfPI = Math.PI / 2;
var steps = 8; // larger == greater accuracy
drawEllipse();
// get mouse position
// calc a point on the ellipse that is "near-ish"
// display a line between the mouse and that ellipse point
function handleMouseMove(e) {
mouseX = parseInt(e.clientX - offsetX);
mouseY = parseInt(e.clientY - offsetY);
// Put your mousemove stuff here
var pt = getEllipsePt(mouseX, mouseY);
// testing: draw results
drawResults(mouseX, mouseY, pt.x, pt.y);
}
// calc a point on the ellipse that is "near-ish" the target point
// uses "brute force"
function getEllipsePt(targetPtX, targetPtY) {
// calculate which ellipse quadrant the targetPt is in
var q;
if (targetPtX > cx) {
q = (targetPtY > cy) ? 0 : 3;
} else {
q = (targetPtY > cy) ? 1 : 2;
}
// calc beginning and ending radian angles to check
var r1 = q * halfPI;
var r2 = (q + 1) * halfPI;
var dr = halfPI / steps;
var minLengthSquared = 200000000;
var minX, minY;
// walk the ellipse quadrant and find a near-point
for (var r = r1; r < r2; r += dr) {
// get a point on the ellipse at radian angle == r
var ellipseX = cx + radiusX * Math.cos(r);
var ellipseY = cy + radiusY * Math.sin(r);
// calc distance from ellipsePt to targetPt
var dx = targetPtX - ellipseX;
var dy = targetPtY - ellipseY;
var lengthSquared = dx * dx + dy * dy;
// if new length is shortest, save this ellipse point
if (lengthSquared < minLengthSquared) {
...