日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問(wèn)題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷解決方案
圖形編輯器:旋轉(zhuǎn)選中的元素

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

成都創(chuàng)新互聯(lián)公司長(zhǎng)期為千余家客戶提供的網(wǎng)站建設(shè)服務(wù),團(tuán)隊(duì)從業(yè)經(jīng)驗(yàn)10年,關(guān)注不同地域、不同群體,并針對(duì)不同對(duì)象提供差異化的產(chǎn)品和服務(wù);打造開(kāi)放共贏平臺(tái),與合作伙伴共同營(yíng)造健康的互聯(lián)網(wǎng)生態(tài)環(huán)境。為武鄉(xiāng)企業(yè)提供專業(yè)的成都網(wǎng)站建設(shè)、網(wǎng)站制作,武鄉(xiāng)網(wǎng)站改版等技術(shù)服務(wù)。擁有十余年豐富建站經(jīng)驗(yàn)和眾多成功案例,為您定制開(kāi)發(fā)。

最近更文比較少,是因?yàn)楸救嗽谧鰝€(gè)人開(kāi)源項(xiàng)目,用 Canvas 做一個(gè)設(shè)計(jì)工具,做個(gè)乞丐版 figma。期間遇到了不少問(wèn)題,在這里記錄一下。

今天開(kāi)始會(huì)恢復(fù)高頻更新的,一兩天一更。內(nèi)容主要會(huì)圍繞我打造的設(shè)計(jì)工具遇到的一些問(wèn)題和解決方案,也會(huì)有其他主題。

項(xiàng)目地址:

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

線上體驗(yàn):

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

元素和它的包圍盒(bBox)

元素指的是一些圖形,比如矩形、橢圓。

為了方便描述,后面都會(huì)用矩形作為例子。

元素有一個(gè)包圍盒(Bounding Box),是能包裹元素的最小矩形。當(dāng)然大一點(diǎn)也行,但必須能包裹元素。

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

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

另外元素一個(gè) rotation 屬性,表示元素以其中心位置(即包圍盒的正中心)的旋轉(zhuǎn)弧度。

bBox 是考慮旋轉(zhuǎn)的(最外層的矩形):

bBox

還有一種不考慮旋轉(zhuǎn),我暫且稱其為 bBoxWithoutRotation。它會(huì)忽視 rotation 的存在,得到一個(gè)旋轉(zhuǎn)前的 bBox。我們使用它配合渲染層(ctx.rotate(angle)),繪制一個(gè)進(jìn)行了旋轉(zhuǎn)的盒子。

bBoxWithoutRotation

選中元素

選中的元素需要分兩種情況討論,一種是選中單個(gè)元素,一種是選中多個(gè)元素。

對(duì)于單個(gè)元素,要繪制 bBoxWithoutRotation。原因是只有一個(gè)元素,也就一個(gè)旋轉(zhuǎn)角度,旋轉(zhuǎn)起來(lái)更能表現(xiàn)這個(gè)元素的情況。見(jiàn)下圖:

對(duì)于多個(gè)元素,情況則不同了,因?yàn)椴煌脑赜胁煌男D(zhuǎn)角度,所以要計(jì)算所有元素的 bBox,然后取出其中最小的 x、y 和最大的 x、y,組成包圍所有元素的選中框:

旋轉(zhuǎn)元素

旋轉(zhuǎn)元素同樣分兩種情況討論:旋轉(zhuǎn)單個(gè)元素,以及旋轉(zhuǎn)多個(gè)元素。

先講解 旋轉(zhuǎn)單個(gè)元素。我們看看效果:

旋轉(zhuǎn)單個(gè)元素

首先,從圖形的中點(diǎn)連接光標(biāo)位置,得到一個(gè)向量。我們的旋轉(zhuǎn)角度就是這個(gè)向量和向上向量(即 [0, -1])的夾角。

求向量角度

這里我們可以用 點(diǎn)積公式 來(lái)計(jì)算這個(gè)夾角。

計(jì)算好這個(gè)夾角,將其賦值給選中的元素的 rotation 屬性,然后進(jìn)行渲染,讓渲染引擎根據(jù)新的角度進(jìn)行繪制。

然后是 旋轉(zhuǎn)多個(gè)元素。效果:

旋轉(zhuǎn)多個(gè)元素

旋轉(zhuǎn)多個(gè)元素則復(fù)雜一些。

我們需要改變每個(gè)元素的旋轉(zhuǎn)角度 rotation,以及 x、y 值。

這里我們需要知道一個(gè)很重要的信息:元素上所有的點(diǎn)的旋轉(zhuǎn)結(jié)果坐標(biāo),都是根據(jù)大包圍盒中心旋轉(zhuǎn) rotation 得到的。

首先是 rotation,旋轉(zhuǎn)中心是這個(gè)大 bBox 的中心。

我們從元素的中點(diǎn)畫(huà)一個(gè)向上的向量,這個(gè)向量是跟隨著多元素旋轉(zhuǎn)角度改變的。

所以,和單元素直接賦值不同,多元素旋轉(zhuǎn)情況下,拖拽中產(chǎn)生的旋轉(zhuǎn)角度需要作為增量,加在每個(gè)旋轉(zhuǎn)前的元素起始角度上,即:

element.rotation = prevElementRotation + dRotation;

然后是計(jì)算每個(gè)元素 新的 x 和 y 值。

也很簡(jiǎn)單,對(duì)旋轉(zhuǎn)前的中點(diǎn) cx 和 cy,使用旋轉(zhuǎn)算法,計(jì)算出新的 cx 和 cy ,然后減去寬高/2即可。

需要實(shí)現(xiàn)的算法

在這個(gè)過(guò)程中你需要實(shí)現(xiàn)的算法有:

  1. 求向量夾角,需要用點(diǎn)積公式。
  2. 旋轉(zhuǎn)算法,需要考慮旋轉(zhuǎn)中心。
  3. 計(jì)算 bBox,其實(shí)就是將 bBox 轉(zhuǎn)換為 4 個(gè)邊角的坐標(biāo),然后取最小的 x、y 和最大的 x、y 重新組合成一個(gè) box。

然后其他就是繁瑣的交互邏輯了。

結(jié)尾

至此,我們就實(shí)現(xiàn)了元素的旋轉(zhuǎn)邏輯。晚點(diǎn)我會(huì)再出一篇縮放元素的文章。


分享名稱:圖形編輯器:旋轉(zhuǎn)選中的元素
網(wǎng)頁(yè)路徑:http://www.5511xx.com/article/coecsop.html