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

Basically I'm asking this question for JavaScript: Calculate Bounding box coordinates from a rotat

Basically I'm asking this question for JavaScript: Calculate Bounding box coordinates from a rotated rectangle

In this case:

  • iX = Width of rotated (blue) HTML element
  • iY = Height of rotated (blue) HTML element
  • bx = Width of Bounding Box (red)
  • by = Height of Bounding Box (red)
  • x = X coord of Bounding Box (red)
  • y = Y coord of Bounding Box (red)
  • iAngle/t = Angle of rotation of HTML element (blue; not shown but used in code below), FYI: It's 37 degrees in this example (not that it matters for the example)

How does one calculate the X, Y, Height and Width of a bounding box (all the red numbers) surrounding a rotated HTML element (given its width, height, and Angle of rotation) via JavaScript? A sticky bit to this will be getting the rotated HTML element (blue box)'s original X/Y coords to use as an offset somehow (this is not represented in the code below). This may well have to look at CSS3's transform-origin to determine the center point.

I've got a partial solution, but the calculation of the X/Y coords is not functioning properly...

var boundingBox = function (iX, iY, iAngle) {
    var x, y, bx, by, t;

    //# Allow for negetive iAngle's that rotate counter clockwise while always ensuring iAngle's < 360
    t = ((iAngle < 0 ? 360 - iAngle : iAngle) % 360);

    //# Calculate the width (bx) and height (by) of the .boundingBox
    //#     NOTE: See 
    bx = (iX * Math.sin(iAngle) + iY * Math.cos(iAngle));
    by = (iX * Math.cos(iAngle) + iY * Math.sin(iAngle));

    //# This part is wrong, as it's re-calculating the iX/iY of the rotated element (blue)
    //# we want the x/y of the bounding box (red)
    //#     NOTE: See 
    x = (1 / (Math.pow(Math.cos(t), 2) - Math.pow(Math.sin(t), 2))) * (bx * Math.cos(t) - by * Math.sin(t));
    y = (1 / (Math.pow(Math.cos(t), 2) - Math.pow(Math.sin(t), 2))) * (-bx * Math.sin(t) + by * Math.cos(t));

    //# Return an object to the caller representing the x/y and width/height of the calculated .boundingBox
    return {
        x: parseInt(x), width: parseInt(bx),
        y: parseInt(y), height: parseInt(by)
    }
};

I feel like I am so close, and yet so far...

Many thanks for any help you can provide!

TO HELP THE NON-JAVASCRIPTERS...

Once the HTML element is rotated, the browser returns a "matrix transform" or "rotation matrix" which seems to be this: rotate(Xdeg) = matrix(cos(X), sin(X), -sin(X), cos(X), 0, 0); See this page for more info.

I have a feeling this will enlighten us on how to get the X,Y of the bounding box (red) based solely on the Width, Height and Angle of the rotated element (blue).

New Info

Humm... interesting...

Each browser seems to handle the rotation differently from an X/Y perspective! FF ignores it completely, IE & Opera draw the bounding box (but its properties are not exposed, ie: bx & by) and Chrome & Safari rotate the rectangle! All are properly reporting the X/Y except FF. So... the X/Y issue seems to exist for FF only! How very odd!

Also of note, it seems that $(document).ready(function () {...}); fires too early for the rotated X/Y to be recognized (which was part of my original problem!). I am rotating the elements directly before the X/Y interrogation calls in $(document).ready(function () {...}); but they don't seem to update until some time after(!?).

When I get a little more time, I will toss up a jFiddle with the example, but I'm using a modified form of "jquery-css-transform.js" so I have a tiny bit of tinkering before the jFiddle...

So... what's up, FireFox? That ain't cool, man!

The Plot Thickens...

Well, FF12 seems to fix the issue with FF11, and now acts like IE and Opera. But now I am back to square one with the X/Y, but at least I think I know why now...

It seems that even though the X/Y is being reported correctly by the browsers for the rotated object, a "ghost" X/Y still exists on the un-rotated version. It seems as though this is the order of operations:

  • Starting with an un-rotated element at an X,Y of 20,20
  • Rotate said element, resulting in the reporting of X,Y as 15,35
  • Move said element via JavaScript/CSS to X,Y 10,10
  • Browser logically un-rotates element back to 20,20, moves to 10,10 then re-rotates, resulting in an X,Y of 5,25

So... I want the element to end up at 10,10 post rotation, but thanks to the fact that the element is (seemingly) re-rotated post move, the resulting X,Y differs from the set X,Y.

This is my problem! So what I really need is a function to take the desired destination coords (10,10), and work backwards from there to get the starting X,Y coords that will result in the element being rotated into 10,10. At least I know what my problem is now, as thanks to the inner workings of the browsers, it seems with a rotated element 10=5!

Basically I'm asking this question for JavaScript: Calculate Bounding box coordinates from a rotated rectangle

In this case:

  • iX = Width of rotated (blue) HTML element
  • iY = Height of rotated (blue) HTML element
  • bx = Width of Bounding Box (red)
  • by = Height of Bounding Box (red)
  • x = X coord of Bounding Box (red)
  • y = Y coord of Bounding Box (red)
  • iAngle/t = Angle of rotation of HTML element (blue; not shown but used in code below), FYI: It's 37 degrees in this example (not that it matters for the example)

How does one calculate the X, Y, Height and Width of a bounding box (all the red numbers) surrounding a rotated HTML element (given its width, height, and Angle of rotation) via JavaScript? A sticky bit to this will be getting the rotated HTML element (blue box)'s original X/Y coords to use as an offset somehow (this is not represented in the code below). This may well have to look at CSS3's transform-origin to determine the center point.

I've got a partial solution, but the calculation of the X/Y coords is not functioning properly...

var boundingBox = function (iX, iY, iAngle) {
    var x, y, bx, by, t;

    //# Allow for negetive iAngle's that rotate counter clockwise while always ensuring iAngle's < 360
    t = ((iAngle < 0 ? 360 - iAngle : iAngle) % 360);

    //# Calculate the width (bx) and height (by) of the .boundingBox
    //#     NOTE: See https://stackoverflow.com/questions/3231176/how-to-get-size-of-a-rotated-rectangle
    bx = (iX * Math.sin(iAngle) + iY * Math.cos(iAngle));
    by = (iX * Math.cos(iAngle) + iY * Math.sin(iAngle));

    //# This part is wrong, as it's re-calculating the iX/iY of the rotated element (blue)
    //# we want the x/y of the bounding box (red)
    //#     NOTE: See https://stackoverflow.com/questions/9971230/calculate-rotated-rectangle-size-from-known-bounding-box-coordinates
    x = (1 / (Math.pow(Math.cos(t), 2) - Math.pow(Math.sin(t), 2))) * (bx * Math.cos(t) - by * Math.sin(t));
    y = (1 / (Math.pow(Math.cos(t), 2) - Math.pow(Math.sin(t), 2))) * (-bx * Math.sin(t) + by * Math.cos(t));

    //# Return an object to the caller representing the x/y and width/height of the calculated .boundingBox
    return {
        x: parseInt(x), width: parseInt(bx),
        y: parseInt(y), height: parseInt(by)
    }
};

I feel like I am so close, and yet so far...

Many thanks for any help you can provide!

TO HELP THE NON-JAVASCRIPTERS...

Once the HTML element is rotated, the browser returns a "matrix transform" or "rotation matrix" which seems to be this: rotate(Xdeg) = matrix(cos(X), sin(X), -sin(X), cos(X), 0, 0); See this page for more info.

I have a feeling this will enlighten us on how to get the X,Y of the bounding box (red) based solely on the Width, Height and Angle of the rotated element (blue).

New Info

Humm... interesting...

Each browser seems to handle the rotation differently from an X/Y perspective! FF ignores it completely, IE & Opera draw the bounding box (but its properties are not exposed, ie: bx & by) and Chrome & Safari rotate the rectangle! All are properly reporting the X/Y except FF. So... the X/Y issue seems to exist for FF only! How very odd!

Also of note, it seems that $(document).ready(function () {...}); fires too early for the rotated X/Y to be recognized (which was part of my original problem!). I am rotating the elements directly before the X/Y interrogation calls in $(document).ready(function () {...}); but they don't seem to update until some time after(!?).

When I get a little more time, I will toss up a jFiddle with the example, but I'm using a modified form of "jquery-css-transform.js" so I have a tiny bit of tinkering before the jFiddle...

So... what's up, FireFox? That ain't cool, man!

The Plot Thickens...

Well, FF12 seems to fix the issue with FF11, and now acts like IE and Opera. But now I am back to square one with the X/Y, but at least I think I know why now...

It seems that even though the X/Y is being reported correctly by the browsers for the rotated object, a "ghost" X/Y still exists on the un-rotated version. It seems as though this is the order of operations:

  • Starting with an un-rotated element at an X,Y of 20,20
  • Rotate said element, resulting in the reporting of X,Y as 15,35
  • Move said element via JavaScript/CSS to X,Y 10,10
  • Browser logically un-rotates element back to 20,20, moves to 10,10 then re-rotates, resulting in an X,Y of 5,25

So... I want the element to end up at 10,10 post rotation, but thanks to the fact that the element is (seemingly) re-rotated post move, the resulting X,Y differs from the set X,Y.

This is my problem! So what I really need is a function to take the desired destination coords (10,10), and work backwards from there to get the starting X,Y coords that will result in the element being rotated into 10,10. At least I know what my problem is now, as thanks to the inner workings of the browsers, it seems with a rotated element 10=5!

Share Improve this question edited May 23, 2017 at 11:47 CommunityBot 11 silver badge asked May 1, 2012 at 1:57 CampbelnCampbeln 2,9903 gold badges34 silver badges34 bronze badges 6
  • 1 Can you post a diagram of what you want? Pictures speak a thousand words and all. – Li-aung Yip Commented May 1, 2012 at 2:04
  • I second a picture, especially so that you can see what you're doing. – Ignacio Vazquez-Abrams Commented May 1, 2012 at 2:09
  • Thanks! The diagram really was necessary (rather then relying on the referenced Q's picture). – Campbeln Commented May 1, 2012 at 2:30
  • You should post a "before" picture for your benefit. – Ignacio Vazquez-Abrams Commented May 1, 2012 at 2:33
  • 1 My goal is to start with the "after". The "before" would be the blue box un-rotated. And thanks to CSS3's transform-origin property, the blue box could be rotated from any center point. See: w3schools.com/cssref/css3_pr_transform-origin.asp ... of course if this makes the question unpossible, then I'll re-evaluate =) – Campbeln Commented May 1, 2012 at 2:38
 |  Show 1 more comment

4 Answers 4

Reset to default 23

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);

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1737618157a3959315.html

相关推荐

  • JavaScript的基本知识点解析

    JavaScript是一种高级编程语言,广泛用于网页开发和构建现代Web应用程序。它是Web前端开发的核心技术之一,具有许多重要的基本知识点。以下是对JavaScript基本知识点的详细解析:变量与数据类型:JavaScript中的变量用

    2小时前
    10
  • Ubuntu 22.04版本中,root用户登录、硬盘挂载等新机器操作指南

    Ubuntu 2204版本是一个强大的操作系统,它提供了许多功能,包括root用户登录和硬盘挂载。以下是一些关于如何在Ubuntu 2204版本中进行这些操作的指南。首先,我们来谈谈如何以root用户身份登录。在Ubuntu中,root用户

    2小时前
    10
  • 【C++】第五节—类和对象(下)

    hello!云边有个稻草人-CSDN博客一、再探构造函数【自己下去敲代码把这些情况都体会一下】之前我们实现构造函数的时候,初始化成员变量主要使用函数体内赋值,构造函数初始化还有一种方式——初始化列表,初始化列表的使用方式是以一个冒号开始,

    2小时前
    00
  • 初识MySQl · 内置函数

    前言:在前文的学习我们已经简单了解了部分函数,比如count()函数什么的,今天我们主要是笼统的学习一下MySQL中的函数,仅仅从使用的角度来学习,如果要深究下去可能需要学习到事务部分了,那么因为事务还没有学习,所以我们这里就只讲怎么使用了

    2小时前
    00
  • 网络基本概念认识(2)

    前言:本文同样作为博主的二刷网络课程的文章,主要涵盖的主题还是网络基本概念的认识,从上一篇文章遗漏的点加上引入的一些知识点共同组成当前的知识点。在这篇文章收尾之后,我们就会开始愉快的TCP UDP IP ARP Cookie Session

    2小时前
    00
  • 【redis】缓存 更新策略(定期、实时生存),缓存预热、穿透、雪崩、击穿详解

    什么是缓存redis 最常用的场景核心思路就是把一些常用的数据,放到触手可及(访问速度更快)的地方 ⽐如我需要去⾼铁站坐⾼铁. 我们知道坐⾼铁是需要反复刷⾝份证的 (进⼊⾼铁站, 检票, 上⻋,乘⻋过程中, 出站…)正常来说, 我的⾝份证是

    2小时前
    00
  • centos 安装docker详细说明以及案例

    要在CentOS上安装Docker服务(包括容器运行器和Swarm),以下是详细的步骤说明:步骤说明1. 检查操作系统已安装的依赖项在安装Docker之前,首先检查系统是否已经安装了Docker所需的依赖项。这可以通过以下命令完成:代码语言

    1小时前
    00
  • 如何在Win7系统中使用ADB命令卸载Vivo自带浏览器

    如何在Win7系统中使用ADB命令卸载Vivo自带浏览器引言Vivo手机自带的浏览器虽然功能丰富,但有些用户可能更倾向于使用其他浏览器。本文将详细介绍如何在Win7系统中通过ADB命令卸载Vivo自带浏览器,帮助用户轻松移除不需要的应用。准

    1小时前
    00
  • Deepseek证明了“人工智能发展一日千里”!

    在科技的浩瀚星空中,人工智能(AI)无疑是最耀眼的星辰之一。近年来,AI技术以惊人的速度迭代演进,其中Deepseek的崛起更是将这一趋势推向了新的高潮。Deepseek以半年迭代13代模型的惊人速度,证明了人工智能发展正以前所未有的步伐一

    1小时前
    00
  • harmony OS NEXT

    1.任务一:构建Button组件,展示UI效果代码语言:ts复制@Entry@Componentstruct ButtonExample {按钮组件(Button) 常用于相应用户的点击操作,其类型包括胶囊按钮、圆形按钮、普通按钮

    1小时前
    00
  • harmony OS NEXT–状态管理器–@State详解

    鸿蒙Harmony--状态管理器--@State详解1.1 定义@State装饰的变量,或者称为状态变量,一旦变量拥有了状态属性,就可以触发其直接绑定UI组件的刷新。当状态改变时,UI会发生对应的渲染变化,@State装饰的变量,与声明

    1小时前
    00
  • 如果苹果上架审核7个工作日仍无反应如何向苹果官方询问进度和提交反馈

    如果苹果上架审核7个工作日仍无反应如何向苹果官方询问进度和提交反馈-App Store Connect方式和发送邮件询问方式-优雅草卓伊凡背景有个客户委托我的app的上架由于已经超过7天没有反应,7个自然日,因此比较焦急想要追寻问一下结果。

    53分钟前
    00
  • 【颠覆传统开发】AI 编程师 DeepSeek 让贪吃蛇脱胎换骨

    【颠覆传统开发】AI竟让贪吃蛇进化成星际争霸?手把手教你用DeepSeek打造史上最硬核贪吃蛇!【颠覆传统开发】AI编程师DeepSeek让贪吃蛇脱胎换骨你敢信?用AI写贪吃蛇游戏,代码量直接砍半!传统开发模式下,程序员需要手动编写碰撞检测

    52分钟前
    00
  • DeepSeek与全球AI格局:中国技术实力的新象征

    DeepSeek与全球AI格局:中国技术实力的新象征1. 全球AI格局概览大语言模型(LLM)已成为人工智能领域的战略高地,美国科技巨头长期占据主导地位。OpenAI的GPT系列、Anthropic的Claude、Google的Gemini

    50分钟前
    00
  • 【Java全栈学习笔记

    【Java全栈学习笔记-U1-day02】变量+数据类型+运算符**day02目标:1.掌握数据类型2.掌握变量3.运算符4.掌握Scanner类接收输入数据****引言:运行程序的过程:程序-安装硬盘-加载到内存(运行)硬盘作用:永久存储

    35分钟前
    00
  • 如何让AI更懂你?大模型个性化微调技术解析

    如何让AI更懂你?大模型个性化微调技术解析引言在人工智能领域,大型预训练模型(如GPT、BERT等)已经成为许多任务的核心工具。然而,这些模型虽然强大,但在处理特定领域的任务时,往往无法完全满足用户的需求。为了让AI更懂你,个性化微调技术成

    17分钟前
    00
  • Maven:解决&quot;Dependency &#x27;xxxx‘ not found&quot;

    报错原因引入依赖后报错,最终发现是将<dependencies>放入到<dependencyManagement>之中详细解释因为是多模块系统,所以在父 POM 的<dependencyManagement&g

    9分钟前
    00
  • 【转】向量数据库相关

    最近给研发部署pg+pgvector环境,这块还从未接触过。网上找到了下面这篇文章,讲的挺好转载过来。原文地址: 也许你最近可能听过这样的新闻,某向量数据库的初创公司刚写好 PPT,就获得了几千万的投资,某公司的开源的向量数据库因其代码的

    7分钟前
    00
  • HarmonyOS NEXT条件语句和循环迭代

    条件语句使用规则支持if、else和else if语句。if、else if后跟随的条件语句可以使用状态变量或者常规变量(状态变量:值的改变可以实时渲染UI,常规变量:值的改变不会实时渲染UI)。允许在容器组件内使用,通过条件渲染语句构建不

    4分钟前
    00
  • 鸿蒙开发:Canvas绘制之画笔对象Brush

    前言本文基于Api13在之前的文章中,我们主要针对Pen对象做了概述,知道了Pen对象主要用于修改绘制图形的轮廓信息,如果你想要实现一个实心的效果,那么就必须需要Brush对象了。我们还是拿着前边的案例代码做演示,使用Brush对象来实现一

    55秒前
    00

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信