JSFiddle - React, Tailwind, and code Playground
HTML
Move mouse over canvas to control the red dot.<br/>
Click on canvas to start/stop animation.<br/>
Green is the closest point on the curve.<br/>
Light red/blue is the closest point on each segment.<br/>
<canvas width="400" height="400"/>
JavaScript
function nearest_point(v, w, p) {
var l2 = (v.x-w.x)*(v.x-w.x) + (v.y-w.y)*(v.y-w.y);
if (l2 === 0.0) return v;
var t = ((p.x-v.x)*(w.x-v.x) + (p.y-v.y)*(w.y-v.y)) / l2;
if (t < 0.0) return v;
else if (t > 1.0) return w;
var projection = {};
projection.x = v.x + t * (w.x - v.x);
projection.y = v.y + t * (w.y - v.y);
return projection;
}
var cvs = document.getElementsByTagName('canvas')[0];
var ctx = cvs.getContext('2d');
var width = cvs.width, height = cvs.height;
function LineSegment() {
this.x0 = this.y0 = this.x1 = this.y1 = 0.0;
}
LineSegment.prototype.Set = function(x0, y0, x1, y1) {
this.x0 = x0;
this.y0 = y0;
this.x1 = x1;
this.y1 = y1;
}
var numSegs = 6;
var lineSegs = [];
for (var i = 0; i < numSegs; i++) lineSegs.push(new LineSegment());
ctx.lineCap = ctx.lineJoin = 'round';
var mouseX = width / 2.0, mouseY = width / 2.0;
var mouseRadius = 10.0;
var lastTime = new Date();
var animTime = 0.0;
var animate = true;
function doFrame() {
// We record what time it is for animation purposes
var time = new Date();
var dt = (time - lastTime) / 1000; // deltaTime in seconds for animating
lastTime = time;
if (animate) animTime += dt;
// Here we create a list of animated line segments
for (var i = 0; i < numSegs; i++) {
lineSegs[i].Set(
width * i / numSegs,
Math.sin(4.0 * i / numSegs + animTime) * height / 4.0 + height / 2.0,
width * (i + 1.0) / numSegs,
Math.sin(4.0 * (i + 1.0) / numSegs + animTime) * height / 4.0 + height / 2.0
);
}
// Clear the background
ctx.fillStyle = '#cdf';
ctx.beginPath();
ctx.rect(0, 0, width, height);
ctx.fill();
// Compute the closest point on the curve.
var closestSeg = 0;
var closestDistSquared = 1e100;
var closestPoint = {};
for (var i = 0; i < numSegs; i++) {
var lineSeg = lineSegs[i];
var np =...