服务粉丝

我们一直在努力
当前位置:首页 > 财经 >

图形编辑器:旋转选中的元素

日期: 来源:前端西瓜哥收集编辑:西瓜

大家好,我是前端西瓜哥。

最近更文比较少,是因为本人在做个人开源项目,用 Canvas 做一个设计工具,做个乞丐版 figma。期间遇到了不少问题,在这里记录一下。

今天开始会恢复高频更新的,一两天一更。内容主要会围绕我打造的设计工具遇到的一些问题和解决方案,也会有其他主题。

项目地址:

https://github.com/F-star/suika

线上体验:

https://blog.fstars.wang/app/suika/

元素和它的包围盒(bBox)

元素指的是一些图形,比如矩形、椭圆。

为了方便描述,后面都会用矩形作为例子。

元素有一个包围盒(Bounding Box),是能包裹元素的最小矩形。当然大一点也行,但必须能包裹元素。

const bBox = {
  x: 100,
  y: 100,
  width: 30,
  height: 40
}

x 和 y 代表包围盒的位置,width 和 height 代表盒子的尺寸。

另外元素一个 rotation 属性,表示元素以其中心位置(即包围盒的正中心)的旋转弧度。

bBox 是考虑旋转的(最外层的矩形):

bBox

还有一种不考虑旋转,我暂且称其为 bBoxWithoutRotation。它会忽视 rotation 的存在,得到一个旋转前的 bBox。我们使用它配合渲染层(ctx.rotate(angle)),绘制一个进行了旋转的盒子。

bBoxWithoutRotation

选中元素

选中的元素需要分两种情况讨论,一种是选中单个元素,一种是选中多个元素。

对于单个元素,要绘制 bBoxWithoutRotation。原因是只有一个元素,也就一个旋转角度,旋转起来更能表现这个元素的情况。见下图:

对于多个元素,情况则不同了,因为不同的元素有不同的旋转角度,所以要计算所有元素的 bBox,然后取出其中最小的 x、y 和最大的 x、y,组成包围所有元素的选中框:

旋转元素

旋转元素同样分两种情况讨论:旋转单个元素,以及旋转多个元素。

先讲解 旋转单个元素。我们看看效果:

旋转单个元素

首先,从图形的中点连接光标位置,得到一个向量。我们的旋转角度就是这个向量和向上向量(即 [0, -1])的夹角。

求向量角度

这里我们可以用 点积公式 来计算这个夹角。

计算夹角的实现可以看我这篇文章:

求向量的角度

计算好这个夹角,将其赋值给选中的元素的 rotation 属性,然后进行渲染,让渲染引擎根据新的角度进行绘制。

然后是 旋转多个元素。效果:

旋转多个元素

旋转多个元素则复杂一些。

我们需要改变每个元素的旋转角度 rotation,以及 x、y 值。

这里我们需要知道一个很重要的信息:元素上所有的点的旋转结果坐标,都是根据大包围盒中心旋转 rotation 得到的

首先是 rotation,旋转中心是这个大 bBox 的中心。

我们从元素的中点画一个向上的向量,这个向量是跟随着多元素旋转角度改变的。

所以,和单元素直接赋值不同,多元素旋转情况下,拖拽中产生的旋转角度需要作为增量,加在每个旋转前的元素起始角度上,即:

element.rotation = prevElementRotation + dRotation;

然后是计算每个元素 新的 x 和 y 值

也很简单,对旋转前的中点 cx 和 cy,使用旋转算法,计算出新的 cx 和 cy ,然后减去宽高/2即可。

需要实现的算法

在这个过程中你需要实现的算法有:

  1. 求向量夹角,需要用点积公式;
  2. 旋转算法,需要考虑旋转中心;
  3. 计算 bBox,其实就是将 bBox 转换为 4 个边角的坐标,然后取最小的 x、y 和最大的 x、y 重新组合成一个 box;

然后其他就是繁琐的交互逻辑了。

结尾

至此,我们就实现了元素的旋转逻辑。晚点我会再出一篇缩放元素的文章。

我是前端西瓜哥,欢迎关注我,学习更多前端知识。



相关阅读,

图形编辑器:场景坐标、视口坐标以及它们之间的转换

图形编辑器——矩形选区是如何实现选中多个图形的?

在容器内显示图片的五种方案:contain、cover、fill、none、scale-down

计算机图形学:变换矩阵

快速检索碰撞图形:四叉树碰撞检测

Canvas 性能优化:脏矩形渲染

如何在 Canvas 上实现图形拾取?

来,教你开发一款图形编辑器


关注公众号,后台回复 「字节」,即可获得字节前端面试资料

相关阅读

  • 图形编辑器:标尺功能的实现

  • 大家好,我是前端西瓜哥。今天我们来实现图形编辑器的标尺功能。项目地址:https://github.com/F-star/suika线上体验:https://blog.fstars.wang/app/suika/标尺指的是画布上边和
  • 图形编辑器:图形和辅助线绘制的坐标问题

  • 大家好,我是前端西瓜哥。今天看看绘制图形和辅助线时,坐标转换的一些注意点。项目地址,欢迎 star:https://github.com/F-star/suika线上体验:https://blog.fstars.wang/app/suika
  • 回顾 2022 / 展望 2023

  • 其实不想写的,因为今年挺糟心的,下不动笔。但快过年了,思前想后,最后还是写一下吧。回顾 2022先过一下 2022 立下的 flag。1、每个月至少三篇文章,再尝试看能不能投稿。这个对我
  • 图形编辑器:工具管理和切换

  • 大家好,我是前端西瓜哥。今天我们看看对于一款图形编辑器,应该怎么去实现工具,比如绘制矩形、选中工具,以及如何去管理它们的。项目地址,欢迎 star:https://github.com/F-star/sui
  • WebSocket 入门:简易聊天室

  • 大家好,我是前端西瓜哥,今天我们用 WebSocket 来实现一个简单的聊天室。WebSocket 是一个应用层协议,有点类似 HTTP。但和 HTTP 不一样的是,它支持真正的全双工,即不仅客户端可以
  • 在 VSCode 中像写 TypeScript 一样写 JavaScript

  • 大家好,我是前端西瓜哥。我们在 VSCode 编辑器中编写 js 代码,是会提供类型提示的。VSCode 会推断一个变量是什么类型,并在你输入内容的时候,提供对应的 API 属性或方法补全。如
  • 一起学 pixijs(2):修改图形属性

  • 大家好,我是前端西瓜哥。我们做动画、游戏、编辑器,需要根据用户的交互等操作,去实时地改变图形的属性,比如位置,颜色等信息。今天西瓜哥带大家来看看在 pixijs 怎么修改图形的属
  • Amazing!如何根据背景色自动切换黑白文字?

  • 在项目中,经常会碰到背景色不确定的场景,为了让内容文字足够清晰可见,文字和背景之间需要有足够的对比度。换句话说,当背景是深色时,文字为白色,当背景是浅色时,文字为黑色,就像这样
  • 巧用视觉障眼法,还原 3D 文字特效

  • 最近群里有这样一个有意思的问题,大家在讨论,使用 CSS 3D 能否实现如下所示的效果:这里的核心难点在于,如何利用 CSS 实现一个立体的数字?CSS 能做到吗?不是特别好实现,但是,如果仅
  • 那些炫酷的 CSS 文字效果之诗词《兔》

  • 不知不觉已经迈入2023年,今年是兔年,想到兔子就会联想到玉兔,中秋,胡萝卜,兔子不吃窝边草,这就越扯越远了,今天的主题是用纯CSS来实现各种不错的文字效果,文字则摘录古诗词中有关《

热门文章

  • “复活”半年后 京东拍拍二手杀入公益事业

  • 京东拍拍二手“复活”半年后,杀入公益事业,试图让企业捐的赠品、家庭闲置品变成实实在在的“爱心”。 把“闲置品”变爱心 6月12日,“益心一益·守护梦想每一步”2018年四

最新文章

  • 图形编辑器:旋转选中的元素

  • 大家好,我是前端西瓜哥。最近更文比较少,是因为本人在做个人开源项目,用 Canvas 做一个设计工具,做个乞丐版 figma。期间遇到了不少问题,在这里记录一下。今天开始会恢复高频更新
  • 图形编辑器:标尺功能的实现

  • 大家好,我是前端西瓜哥。今天我们来实现图形编辑器的标尺功能。项目地址:https://github.com/F-star/suika线上体验:https://blog.fstars.wang/app/suika/标尺指的是画布上边和
  • 图形编辑器:图形和辅助线绘制的坐标问题

  • 大家好,我是前端西瓜哥。今天看看绘制图形和辅助线时,坐标转换的一些注意点。项目地址,欢迎 star:https://github.com/F-star/suika线上体验:https://blog.fstars.wang/app/suika
  • 回顾 2022 / 展望 2023

  • 其实不想写的,因为今年挺糟心的,下不动笔。但快过年了,思前想后,最后还是写一下吧。回顾 2022先过一下 2022 立下的 flag。1、每个月至少三篇文章,再尝试看能不能投稿。这个对我
  • 图形编辑器:工具管理和切换

  • 大家好,我是前端西瓜哥。今天我们看看对于一款图形编辑器,应该怎么去实现工具,比如绘制矩形、选中工具,以及如何去管理它们的。项目地址,欢迎 star:https://github.com/F-star/sui
  • WebSocket 入门:简易聊天室

  • 大家好,我是前端西瓜哥,今天我们用 WebSocket 来实现一个简单的聊天室。WebSocket 是一个应用层协议,有点类似 HTTP。但和 HTTP 不一样的是,它支持真正的全双工,即不仅客户端可以