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) {
   ...