成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

圖形編輯器:修改圖形X、Y、Width、Height、Rotation

開發 前端
開發者理解底層,理解一個圖形是先有基本的物理信息(x、y、width、height),然后再做變換(旋轉、縮放等)后得到新的坐標再進行繪制。

大家好,我是前端西瓜哥。圖形編輯器的一個需求,就是可以通過屬性面板的輸入框設置選中元素的屬性值。

項目地址,歡迎 star:

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

線上體驗:

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

最終效果如下:

圖片

元素對象的結構:

interface IGraph {
x: number;
y: number;
width: number;
height: number;
rotation: number; // 旋轉角度,單位為弧度
}

設置 x / y

UI 界面顯示上說的 x / y,指的是旋轉后的 x(即 rotatedX / rotatedY)。

圖片

為什么不是對應真正的 x 和 y 呢?因為需要對應用戶的視角。

開發者理解底層,理解一個圖形是先有基本的物理信息(x、y、width、height),然后再做變換(旋轉、縮放等)后得到新的坐標再進行繪制。

而用戶看到的則是直觀的繪制出來的圖形,并希望圖形的左上角坐標能夠對上他設置的坐標。旋轉前的 x 和 y 是無法直觀體現在畫布上的,用戶也不會在意。

OK,先看看怎么修改 rotatedX。圖形對象上沒有 rotatedX 屬性,本質還是要修改 x 值。

先看看 rotatedX 和 rotatedY 是怎么計算出來的,其實就是計算 x 和 y 基于圖形的中點旋轉后的結果:

// 對坐標做旋轉
function transformRotate(x, y, radian, cx ,cy) {
if (!radian) {
return [x, y];
}
const cos = Math.cos(radian);
const sin = Math.sin(radian);
return [
(x - cx) * cos - (y - cy) * sin + cx,
(x - cx) * sin + (y - cy) * cos + cy,
];
}

// 計算旋轉后的 x 和 y
const [rotatedX, rotatedY] = transformRotate(x, y, rotation, cx, cy);

計算一個元素 rotatedX / rotatedY 的方法實現:

// 計算中點
function getRectCenterPoint({x, y, width, height}) {
return [x + width / 2, y + height / 2];
}

// 計算 rotatedX / rotatedY
export function getElementRotatedXY(element) {
const [cx, cy] = getRectCenterPoint(element);
return transformRotate(element.x, element.y, element.rotation || 0, cx, cy);
}

所以,設置新的 rotatedX,其實就是加上一個移動前后 rotatedX 的偏移值,將其加到 x 上就行了。

class Graph {
// ...
setRotatedX(rotatedX) {
const [prevRotatedX] = getElementRotatedXY(this);
const dx = rotatedX - prevRotatedX;
this.x += dx;
}
}

rotatedY 同理:

class Graph {
// ...
setRotatedY(rotatedY: number) {
const [, prevRotatedY] = getElementRotatedXY(this);
const dy = rotatedY - prevRotatedY;
this.y += dy;
}
}

設置 width / height

首先修改width 和 height。

但是這樣會導致 rotatedX 和 rotatedY 發生偏移,我們需要修正一下。

修正方式有兩種思路:

思路 1:計算修改 width 前后的 rotatedX / rotatedY 之間的差值,給元素進行修正。

const [preRotatedX, preRotatedY] = getElementRotatedXY(el); // 修改 width 前的
el.width = width;
const [rotatedX, rotatedY] = getElementRotatedXY(el); // 修改 width 后的
const dx = rotatedX - preRotatedX;
const dy = rotatedY - preRotatedY;
el.x -= dx; // "-" 是因為要復原狀態
el.y -= dy;

思路 2:確定后最終的 rotatedX / rotatedY,然后對之前的 transformRotate 方法中的等式,進行逆推導,通過  rotatedX、rotatedY、radian、width、height 計算出對應的 x 和 y。這個思路比上一個思路有點復雜。

const [rotatedX, rotatedY] = getElementRotatedXY(el);
el.width = width;
const [x, y] = getOriginXY(
rotatedX,
rotatedY,
el.rotation || 0,
width,
el.height
);
el.x = x;
el.y = y;

/**
* 計算旋轉前的 x、y
* transformRotate 的反推
*/
function getOriginXY(rotatedX, rotatedY, radian, width, height) {
if (!radian) {
return [rotatedX, rotatedY];
}
const cos = Math.cos(radian);
const sin = Math.sin(radian);
const halfWidth = width / 2;
const halfHeight = height / 2;
return [
rotatedX - halfWidth - halfHeight * sin + halfWidth * cos,
rotatedY - halfHeight + halfHeight * cos + halfWidth * sin,
];
}

我一開始用的思路 2 實現的,后面寫這篇文章梳理時,相處了思路 1 的解法,因為更簡單更好理解,就換成思路 1 的實現了。

修改 rotation

修改 rotation 就很簡單了,直接改就好了。

但需要注意將度數轉成弧度,以及通過取余來限定弧度范圍。

// 角度轉弧度
function degree2Radian(degree: number) {
return (degree * Math.PI) / 180;
}

/**
* 標準化角度
*/
const PI_DOUBLE = 2 * Math.PI;
export const normalizeAngle = (angle) => {
return angle % PI_DOUBLE;
};


element.rotation = normalizeAngle(degree2Radian(rotation));

結尾

算法實現上并不復雜。

責任編輯:姜華 來源: 前端西瓜哥
相關推薦

2023-10-19 10:12:34

圖形編輯器開發縮放圖形

2023-08-31 11:32:57

圖形編輯器contain

2023-09-07 08:24:35

圖形編輯器開發繪制圖形工具

2023-09-26 07:39:21

2023-01-18 08:30:40

圖形編輯器元素

2023-02-01 09:21:59

圖形編輯器標尺

2023-02-06 16:59:57

Canvas編輯器

2023-04-07 08:02:30

圖形編輯器對齊功能

2023-02-02 14:07:00

圖形編輯器Canvas

2023-04-10 08:45:44

圖形編輯器排列移動功能

2023-09-11 09:02:31

圖形編輯器模塊間的通信

2023-05-09 08:15:32

圖形編輯器撤銷重做功能

2024-01-08 08:30:05

光標圖形編輯器開發游標

2023-07-31 08:46:07

圖形編輯器圖形自動對齊

2023-08-28 08:10:50

Hex圖形編輯器

2023-10-10 16:04:30

圖形編輯器格式轉換

2023-03-03 10:24:51

2023-10-08 08:11:40

圖形編輯器快捷鍵操作

2024-01-03 08:43:17

圖形編輯器旋轉控制點縮放控制點

2023-07-07 13:56:01

圖形編輯器畫布縮放
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: www成人免费视频 | 欧美电影大全 | re久久 | www.日本国产 | 亚洲高清视频在线 | 成人精品一区二区三区 | 精品无码三级在线观看视频 | 国产精品日韩欧美一区二区 | 97高清国语自产拍 | 青春草91 | 国产成人精品一区二区三 | 91传媒在线播放 | 欧美h视频 | 成人福利电影 | 亚洲乱码一区二区三区在线观看 | 国产精品久久久久久久久久久久久 | 99re视频在线观看 | 国产激情小视频 | 久久亚洲精品视频 | 久久九精品 | 一区二区国产精品 | 精品美女在线观看视频在线观看 | 国产精品久久久久无码av | 精品久久香蕉国产线看观看亚洲 | 亚州精品天堂中文字幕 | 久久久久国产精品午夜一区 | 91色视频在线 | 欧美一区二区三区在线观看视频 | 国产婷婷在线视频 | 成人午夜免费网站 | 国产精品一区二区在线免费观看 | aa级毛片毛片免费观看久 | 久草精品在线 | 免费视频一区二区三区在线观看 | 国产精品久久av | 国产乱码精品一区二区三区中文 | 国产精品欧美一区二区三区不卡 | 久久久久久免费精品一区二区三区 | 日韩综合在线 | 91精品国产欧美一区二区成人 | 日韩视频精品在线 |