I found that there's a tool that can calculate the intersection of two lines. If I treated the rectangle as a set of 4 lines I can use the line-intersect npm project to get the point of intersection on one of those 4 lines. The solution was found in the SO question below.
calculating the point of intersection of two lines
This is an example of my code:
// first, get the sizes of the element.
// here we use getBoundingClientRect for an SVG
const clientRect = svgRectElement.getBoundingClientRect();
// extract the width and height
const w = clientRect.width;
const h = clientRect.height;
// trg represents the target point from the element above
// the x and y for trg relate to the center of the element
const top = trg.y - h / 2;
const bottom = trg.y + h / 2;
const left = trg.x - w / 2;
const right = trg.x + w / 2;
// a line extends from src{x,y} to trg{x,y} at the center of both rectangles
// another line extends from left to right at the top of the rectangle
const topIntersect = lineIntersect.checkIntersection(src.x, src.y, trg.x, trg.y, left, top, right, top);
// another line extends from top to bottom at the right of the rectangle
const rightIntersect = lineIntersect.checkIntersection(src.x, src.y, trg.x, trg.y, right, top, right, bottom);
// another line extends from left to right at the bottom of the rectangle
const bottomIntersect = lineIntersect.checkIntersection(src.x, src.y, trg.x, trg.y, left, bottom, right, bottom);
// another line extends from top to bottom at the left of the rectangle
const leftIntersect = lineIntersect.checkIntersection(src.x, src.y, trg.x, trg.y, left, top, left, bottom);
// only one of the intersect variables above will have a value
if (topIntersect.type !== 'none' && topIntersect.point != null) {
// topIntersect.point is the x,y of the line intersection with the top of the rectangle
} else if (rightIntersect.type !== 'none' && rightIntersect.point != null) {
// rightIntersect.point is the x,y of the line intersection with the right of the rectangle
} else if (bottomIntersect.type !== 'none' && bottomIntersect.point != null) {
// bottomIntersect.point is the x,y of the line intersection with the bottom of the rectangle
} else if (leftIntersect.type !== 'none' && leftIntersect.point != null) {
// leftIntersect.point is the x,y of the line intersection with the left of the rectangle
}
To get the intersection of the source node I would pass that as the trg
parameter to my function and the target node would represent the src
parameter, essentially tricking the system into thinking the line is drawn backwards. This would provide the intersection of the source node, which is represented in the variable trg
above.