const canvas = document.querySelector( "canvas" );
const ctx = canvas.getContext( "2d" );
const width = canvas.width = 500;
const height = canvas.height = 180;
const text = "Hello world";
ctx.font = "800 40px sans-serif";
ctx.textAlign = "center";
ctx.textBaseline = "middle";
const text_pos = { x: width / 2, y: height / 2 };
const text_bbox = getTextBBox( ctx, text );
const bbox_path = drawBBoxPath( text_bbox, text_pos );
const start_time = performance.now();
ctx.strokeStyle = "red";
let viewport_point = new DOMPoint(0, 0);
onmousemove = ( { clientX, clientY } ) => {
const canvas_bbox = canvas.getBoundingClientRect();
viewport_point = new DOMPoint(
clientX - canvas_bbox.left,
clientY - canvas_bbox.top
);
};
anim();
function getTextBBox( ctx, text ) {
const metrics = ctx.measureText( text );
const left = metrics.actualBoundingBoxLeft * -1;
const top = metrics.actualBoundingBoxAscent * -1;
const right = metrics.actualBoundingBoxRight;
const bottom = metrics.actualBoundingBoxDescent;
const width = right - left;
const height = bottom - top;
return { left, top, right, bottom, width, height };
}
function drawBBoxPath( bbox, offset = { x: 0, y: 0 } ) {
const path = new Path2D();
const { left, top, width, height } = bbox;
path.rect( left + offset.x, top + offset.y, width, height );
return path;
}
function anim( t ) {
clear();
updateTransform( t );
checkCollision();
drawText();
drawBoundingBox();
requestAnimationFrame( anim );
}
function clear() {
ctx.setTransform( 1, 0, 0, 1, 0, 0 );
ctx.clearRect( 0, 0, width, height );
}
function updateTransform( t ) {
const dur = 10000;
const delta = (t - start_time) % dur;
const pos = Math.PI * 2 / dur * delta;
const angle = Math.cos( pos );
const scale = Math.sin( pos ) * 4;
ctx.translate( width / 2, height / 2 );
ctx.rotate( angle );
ctx.scale( scale, 1 );
ctx.translate( -width / 2, -height / 2 );
}
function checkCollision() {
const collides = ctx.isPointInPath( bbox_path, viewport_point.x, viewport_point.y );
ctx.fillStyle = collides ? "green" : "blue";
}
function drawText() {
ctx.fillText( text, text_pos.x, text_pos.y );
}
function drawBoundingBox() {
ctx.stroke( bbox_path );
}
<canvas></canvas>