计算画布内旋转元素的边界坐标
Posted 庞永胜
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了计算画布内旋转元素的边界坐标相关的知识,希望对你有一定的参考价值。
svg,dom类的图形编辑器,在画布内编辑元素完成后,为了得到只包含元素的部分,去掉画布的留白,或者进行编组时,往往需要计算元素在画布内的边界坐标,重新生成输出元素的坐标
1、对于无旋转等几何变化的基本元素,计算元素的边界坐标是很容易的(以屏幕坐标为准)
如下图,只需遍历每个元素的四个顶点坐标比较即可;
假设已知元素css属性 left = x,top = y ,width = w ,height = h;
对于任意元素四个顶点坐标分别为,(左上,右上,左下,右下)
代码为
let minX = Infinity, minY = Infinity, maxX = -Infinity , maxY = -Infinity;
elements.forEach(ele=>
const points = [pointLT,pointRT, pointLB, pointRB ];
points.forEach(point=>
minX = Math.min(minX, xx);
maxX = Math.max(maxX, xx);
minY = Math.min(minY, yy);
maxY = Math.max(maxY, yy);
)
)
实际开发中,编辑器往往会对元素会有旋转反转裁剪等几何变化,如下图为实验仪器的组合,其边界可能为最左侧的旋转的玻璃棒和右侧旋转的试管决定
为了需重 新计算单个仪器旋转后的坐标和边界,从而 那么变化后的坐标如何计算呢
2、带有旋转属性的元素坐标计算
以元素中心E点为中心建立坐标系
A\'B\'C\'D\'为ABCD旋转θ ,后的矩形,已A点为例,连接EA,EA\',根据向量的旋转角度公式有
以上坐标是基于中心点坐标的,so可以用中心点的坐标E表示A\'坐标,从而换算会屏幕坐标,(注意屏幕坐标的基是(0,1)(-1,0),故y需取负值)
更新上一段代码为:
let minX = Infinity, minY = Infinity, maxX = -Infinity , maxY = -Infinity;
elements.forEach(ele=>
const vertices = [pointLT,pointRT, pointLB, pointRB ];
// ...
vertices.forEach((x,y)=>
let xm = cx + (x - cx) * cos - (cy - y) * sin;
let ym = cy - ((x - cx) * sin + (cy - y) * cos);
minX = Math.min(minX, xm);
maxX = Math.max(maxX, xm);
minY = Math.min(minY, ym);
maxY = Math.max(maxY, ym);
)
)
HTML5 Canvas 中旋转矩形内的鼠标位置
【中文标题】HTML5 Canvas 中旋转矩形内的鼠标位置【英文标题】:Mouse position within rotated rectangle in HTML5 Canvas 【发布时间】:2012-03-01 09:37:18 【问题描述】:html5 画布中矩形的旋转以弧度存储。为了确定随后的鼠标点击是否在任何给定的矩形内,我将鼠标 x 和 y 平移到矩形的旋转原点,将旋转的反向应用于鼠标坐标,然后将鼠标坐标平移回来。
这根本行不通 - 鼠标坐标没有按预期转换(也就是说,在旋转矩形的可见边界内单击时,鼠标坐标不在原始矩形的边界内),并且针对矩形边界的测试失败.鼠标点击的检测仅在矩形的最中心区域内起作用。请查看下面的代码 sn-p 并告诉我您是否可以看到这里有什么问题。
// Our origin of rotation is the center of the rectangle
// Our rectangle has its upper-left corner defined by x,y, its width
// defined in w, height in h, and rotation(in radians) in r.
var originX = this.x + this.w/2, originY = this.y + this.h/2, r = -this.r;
// Perform origin translation
mouseX -= originX, mouseY -= originY;
// Rotate mouse coordinates by opposite of rectangle rotation
mouseX = mouseX * Math.cos(r) - mouseY * Math.sin(r);
mouseY = mouseY * Math.cos(r) + mouseX * Math.sin(r);
// Reverse translation
mouseX += originX, mouseY += originY;
// Bounds Check
if ((this.x <= mouseX) && (this.x + this.w >= mouseX) && (this.y <= mouseY) && (this.y + this.h >= mouseY))
return true;
【问题讨论】:
这个问题同:***.com/questions/28706989/… 【参考方案1】:经过一些进一步的工作,得出了以下解决方案,我想我会在这里为将来可能需要它的任何人转录:
// translate mouse point values to origin
var dx = mouseX - originX, dy = mouseY - originY;
// distance between the point and the center of the rectangle
var h1 = Math.sqrt(dx*dx + dy*dy);
var currA = Math.atan2(dy,dx);
// Angle of point rotated around origin of rectangle in opposition
var newA = currA - this.r;
// New position of mouse point when rotated
var x2 = Math.cos(newA) * h1;
var y2 = Math.sin(newA) * h1;
// Check relative to center of rectangle
if (x2 > -0.5 * this.w && x2 < 0.5 * this.w && y2 > -0.5 * this.h && y2 < 0.5 * this.h)
return true;
【讨论】:
以上是关于计算画布内旋转元素的边界坐标的主要内容,如果未能解决你的问题,请参考以下文章