Calculate the bounding box's X, Y, Height and Width of a rotated element via JavaScript

浪子不回头ぞ 提交于 2019-11-27 13:57:18

I know this is a bit late, but I've written a fiddle for exactly this problem, on an HTML5 canvas:

http://jsfiddle.net/oscarpalacious/ZdQKg/

I hope somebody finds it useful!

I'm actually not calculating your x,y for the upper left corner of the container. It's calculated as a result of the offset (code from the fiddle example):

this.w = Math.sin(this.angulo) * rotador.h + Math.cos(this.angulo) * rotador.w;
this.h = Math.sin(this.angulo) * rotador.w + Math.cos(this.angulo) * rotador.h;
// The offset on a canvas for the upper left corner (x, y) is
// given by the first two parameters for the rect() method:
contexto.rect(-(this.w/2), -(this.h/2), this.w, this.h);

Cheers

Have you tried using getBoundingClientRect() ?

This method returns an object with current values of "bottom, height, left, right, top, width" considering rotations

Turn the four corners into vectors from the center, rotate them, and get the new min/max width/height from them.

EDIT:

I see where you're having problems now. You're doing the calculations using the entire side when you need to be doing them with the offsets from the center of rotation. Yes, this results in four rotated points (which, strangely enough, is exactly as many points as you started with). Between them there will be one minimum X, one maximum X, one minimum Y, and one maximum Y. Those are your bounds.

My gist can help you

Bounding box of a polygon (rectangle, triangle, etc.):

Live demo https://jsfiddle.net/Kolosovsky/tdqv6pk2/

let points = [
    { x: 125, y: 50 },
    { x: 250, y: 65 },
    { x: 300, y: 125 },
    { x: 175, y: 175 },
    { x: 100, y: 125 },
];
let minX = Math.min(...points.map(point => point.x));
let minY = Math.min(...points.map(point => point.y));
let maxX = Math.max(...points.map(point => point.x));
let maxY = Math.max(...points.map(point => point.y));
let pivot = {
    x: maxX - ((maxX - minX) / 2),
    y: maxY - ((maxY - minY) / 2)
};
let degrees = 90;
let radians = degrees * (Math.PI / 180);
let cos = Math.cos(radians);
let sin = Math.sin(radians);

function rotatePoint(pivot, point, cos, sin) {
    return {
        x: (cos * (point.x - pivot.x)) - (sin * (point.y - pivot.y)) + pivot.x,
        y: (sin * (point.x - pivot.x)) + (cos * (point.y - pivot.y)) + pivot.y
    };
}

let boundingBox = {
    x1: Number.POSITIVE_INFINITY,
    y1: Number.POSITIVE_INFINITY,
    x2: Number.NEGATIVE_INFINITY,
    y2: Number.NEGATIVE_INFINITY,
};

points.forEach((point) => {
    let rotatedPoint = rotatePoint(pivot, point, cos, sin);

    boundingBox.x1 = Math.min(boundingBox.x1, rotatedPoint.x);
    boundingBox.y1 = Math.min(boundingBox.y1, rotatedPoint.y);
    boundingBox.x2 = Math.max(boundingBox.x2, rotatedPoint.x);
    boundingBox.y2 = Math.max(boundingBox.y2, rotatedPoint.y);
});

Bounding box of an ellipse:

Live demo https://jsfiddle.net/Kolosovsky/sLc7ynd1/

let centerX = 350;
let centerY = 100;
let radiusX = 100;
let radiusY = 50;
let degrees = 200;

let radians = degrees * (Math.PI / 180);
let radians90 = radians + Math.PI / 2;
let ux = radiusX * Math.cos(radians);
let uy = radiusX * Math.sin(radians);
let vx = radiusY * Math.cos(radians90);
let vy = radiusY * Math.sin(radians90);

let width = Math.sqrt(ux * ux + vx * vx) * 2;
let height = Math.sqrt(uy * uy + vy * vy) * 2;
let x = centerX - (width / 2);
let y = centerY - (height / 2);
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!