JSFiddle - React, Tailwind, and code Playground
by Jake Cattrall
HTML
<div class="vector"></div>
<div class="edgePoint"></div>
<div class="position"></div>
<canvas id="myCanvas"></canvas>
CSS
html,
body {
margin: 0;
padding: 0;
}
#myCanvas {
position: absolute;
top: 0;
left: 0;
}
.vector {
width: 14px;
height: 14px;
position: absolute;
margin-left: -7px;
margin-top: -7px;
left: 50%;
top: 50px;
background-color: lightblue;
}
.edgePoint {
width: 14px;
height: 14px;
margin-left: -7px;
margin-top: -7px;
background-color: lightgreen;
position: absolute;
}
.position {
color: black;
padding: 20px;
font-size: 16px;
}
JavaScript
const $ = selector => document.querySelectorAll(selector)[0];
const position = $('.position');
const edgePoint = $('.edgePoint');
const vector = $('.vector').getBoundingClientRect();
const vectorCenter = {
x: vector.left + (vector.width / 2),
y: vector.top + (vector.height / 2)
};
const viewport = {
width: window.innerWidth,
height: window.innerHeight,
};
var canvas = document.getElementById("myCanvas");
canvas.width = viewport.width;
canvas.height = viewport.height;
var ctx = canvas.getContext("2d");
window.addEventListener('mousemove', (e) => {
const mouse = {
x: e.pageX,
y: e.pageY,
};
const angle = Math.atan2(mouse.y - vectorCenter.y, mouse.x - vectorCenter.x);
const cosAngle = Math.abs(Math.cos(angle));
const sinAngle = Math.abs(Math.sin(angle));
const vx = (viewport.width - vectorCenter.x) * sinAngle;
const vy = (viewport.height - vectorCenter.y) * cosAngle;
const vpMagnitude = vx <= vy ?
(viewport.width - vectorCenter.x) / cosAngle :
(viewport.height - vectorCenter.y) / sinAngle;
const viewportX = vectorCenter.x + Math.cos(angle) * vpMagnitude;
const viewportY = vectorCenter.y + Math.sin(angle) * vpMagnitude;
const viewPortEdge = {
x: viewportX,
y: viewportY,
};
edgePoint.style.left = viewPortEdge.x + 'px';
edgePoint.style.top = viewPortEdge.y + 'px';
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.beginPath();
ctx.moveTo(vectorCenter.x,vectorCenter.y);
ctx.lineTo(viewPortEdge.x, viewPortEdge.y);
ctx.stroke();
position.innerHTML = `X: ${Math.round(viewPortEdge.x)}<br />Y: ${Math.round(viewPortEdge.y)}`;
position.style.color = viewPortEdge.y >= 0 ? 'black' : 'red';
});