Assuming you don't have the transform matrix for the rectangle.
If you do have the matrix then multiply the point by the inverse transform matrix. Then just test the point against the bounds of the rectangle top,left, right, and bottom
Point inside convex polygon
Consider a convex polygon with points going around in a clockwise direction.
A point is inside that polygon if it is to the left of every edge (line) of the polygon.
If the point is right of one or more edges it is outside the polygon.
Left is defined as your left as if standing at the start of the line looking along its length. Or looking at a clock face with minute hand at 3 then left of minute hand is at 4 and right is at 2.
Cross product
To find out which side a point is of a line you get the cross product of the vector from the line start to end, and the vector from the line start to the point. If the cross product is positive the point is to the left, if zero it is on the line, else it is to the right.
Is left
const Point = (x, y) => ({x, y});
const Line = (p1, p2) => ({p1, p2});
function isPointLeft(l, p) { // l is line, p is point
return 0 < (l.p2.x - l.p1.x) * (p.y - l.p1.y) - (l.p2.y - l.p1.y) * (p.x - l.p1.x);
}
Clockwise check
Thus give a set of points in clockwise order that represent a rectangle check each side against the point. If all left you are inside.
Function returns true if point is inside polygon. Assumes points for polygon are in clockwise order
function isPointInsidePoly(point, poly) {
var i = 0;
const line = Line(poly[poly.length - 1]);
while (i < poly.length) {
line.p2 = poly[i++];
if (!isPointLeft(line, point)) { return false }
line.p1 = line.p2;
}
return true;
}
Demo
Simple demo creates a set of points and rotates a rectangle.
Renders each point. If point is inside rectangle then point is drawn a little larger.
const Point = (x = 0, y = 0) => ({x, y});
const Line = (p1, p2) => ({p1, p2});
function isPointLeft(l, p) { // l is line, p is point
return 0 < (l.p2.x - l.p1.x) * (p.y - l.p1.y) - (l.p2.y - l.p1.y) * (p.x - l.p1.x);
}
function isPointInsidePoly(point, poly) {
var i = 0;
const line = Line(poly[poly.length - 1]);
while (i < poly.length) {
line.p2 = poly[i++];
if (!isPointLeft(line, point)) { return false }
line.p1 = line.p2;
}
return true;
}
requestAnimationFrame(renderLoop);
const ctx = canvas.getContext("2d");
const [W, H] = [canvas.width, canvas.height];
const rand = (m, M) => Math.random() * (M - m) + m;
const setOf = (count, cb, i = 0, a = []) => {while (i < count) { a.push(cb(i++)) } return a}
function drawPoint(p, size) {
ctx.strokeStyle = "#000";
ctx.beginPath();
ctx.arc(p.x, p.y, size, 0, Math.PI * 2);
ctx.stroke();
}
const rect = {
x: W / 2, y: H / 2,// x,y center of rectangle
w: 80, h: 20, // w h from center
points: [Point(), Point(), Point(), Point()],
update(angle) {
const transform = (x, y, res) => {
res.x = x * ax - y * ay + this.x;
res.y = x * ay + y * ax + this.y;
}
const [ax, ay] = [Math.cos(angle), Math.sin(angle)];
const p = this.points;
transform( this.w, this.h, p[0]);
transform(-this.w, this.h, p[1]);
transform(-this.w, -this.h, p[2]);
transform( this.w, -this.h, p[3]);
},
draw(ctx) {
ctx.lineWidth = 1;
ctx.strokeStyle = "red";
ctx.beginPath();
for (const p of this.points) { ctx.lineTo(p.x, p.y) }
ctx.closePath();
ctx.stroke();
}
};
const testPoints = setOf(20, () => Point(rand(20, W - 20), rand(20, H - 20)));
function renderLoop(time) {
ctx.clearRect(0, 0, W, H);
rect.update(time / 2300);
rect.draw(ctx);
for (const p of testPoints) {
if (isPointInsidePoly(p, rect.points)) { drawPoint(p, 3) }
drawPoint(p, 1);
}
requestAnimationFrame(renderLoop);
}
<canvas id="canvas" width="200" height="200"></canvas>
getBoundingClientRect()might be useful depending on how you create the element. - GeshodegetBoundingClientRect()is not a solution, imagine that the pointEis out side the box betweenAandB; usinggetBoundingClientRectwill falsely indicate that the pointEis within the box, because it will return overall dimension. - cyrus-d