偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

圖形編輯器開(kāi)發(fā):以光標(biāo)為中心縮放畫(huà)布

開(kāi)發(fā) 前端
場(chǎng)景坐標(biāo)系 就是圖形所在的二維平面世界所使用的坐標(biāo)系。單位是像素(px)。坐標(biāo)系的原點(diǎn)在畫(huà)布(canvas 元素)的左上角,x 軸向右,y 軸向下。

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

畫(huà)布縮放是圖形設(shè)計(jì)工具中很重要的基礎(chǔ)能力。

通過(guò)它,我們可以像舉著一臺(tái)攝影機(jī),在圖形所在的世界到處游逛,透過(guò)鏡頭,可以只看自己想看的圖形;可以拉近攝影機(jī),看到圖形的細(xì)節(jié);也可以拉遠(yuǎn)攝影機(jī),總覽多個(gè)圖形之間的關(guān)系。

ok,那么我們看看如何實(shí)現(xiàn)縮放畫(huà)布功能。

文中的動(dòng)圖演示來(lái)自我正在開(kāi)發(fā)的圖形設(shè)計(jì)工具:

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

線上體驗(yàn):

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

場(chǎng)景坐標(biāo)系和視圖坐標(biāo)系

場(chǎng)景坐標(biāo)系 就是圖形所在的二維平面世界所使用的坐標(biāo)系。單位是像素(px)。坐標(biāo)系的原點(diǎn)在畫(huà)布(canvas 元素)的左上角,x 軸向右,y 軸向下。

圖形會(huì)被繪制到這個(gè)平面,理論上它的范圍是可以 無(wú)限延展 的。(不過(guò)實(shí)際上我們會(huì)給一個(gè)上限,但這個(gè)值也非常大。無(wú)限大的話沒(méi)有意義,且浮點(diǎn)數(shù)是有取值范圍的)

然而顯示器的寬高是有限的,只能看一個(gè)矩形范圍內(nèi)的內(nèi)容。

所以我們需要引入一個(gè) “攝影機(jī)”:視圖坐標(biāo)系,只看部分的區(qū)域。

其實(shí)就是將原來(lái)真實(shí)的圖形的坐標(biāo)做一個(gè)線性計(jì)算轉(zhuǎn)換。

首先是將特定區(qū)域 移動(dòng) 到視口中,就像攝影機(jī)從原點(diǎn)移動(dòng)我們想要觀察的某個(gè)物體上。不過(guò)實(shí)際上是物體所在的平面做了一個(gè)方向的移動(dòng)。

然后再做一個(gè)縮放,就像攝影機(jī)拉近或遠(yuǎn)離與目標(biāo)物體距離,效果是物體在鏡頭下變大或變小。

轉(zhuǎn)換就兩步,移動(dòng)然后縮放

視圖矩陣轉(zhuǎn)換

場(chǎng)景坐標(biāo)系到視圖坐標(biāo)系的轉(zhuǎn)換,我們通過(guò) 視圖矩陣 相乘來(lái)實(shí)現(xiàn)。

事實(shí)上,任意兩個(gè)坐標(biāo)系下坐標(biāo)的轉(zhuǎn)換,都可以通過(guò)一個(gè)矩陣乘法來(lái)實(shí)現(xiàn)。

首先是將坐標(biāo)進(jìn)行位移,x 方向位移 -viewport.x,y 方向位移 -viewport.y。這里是負(fù)數(shù),雖然我們想要移動(dòng) “攝影機(jī)”這是因?yàn)橐苿?dòng)的是畫(huà)布

<平移矩陣> * 坐標(biāo)

然后再縮放(縮放值我們會(huì)用 zoom 表示):

<縮放矩陣> * 平移后的坐標(biāo)

所有過(guò)程寫在一起,就是:

<縮放矩陣> * <平移矩陣> * 坐標(biāo)

矩陣乘法符合結(jié)合律,所以我們的視圖矩陣為:

<視圖矩陣>
= <縮放矩陣> * <平移矩陣>

矩陣表示為:

計(jì)算結(jié)果為:

對(duì)應(yīng)的 Canvas 2D 代碼:

ctx.scale(zoom, zoom);
ctx.translate(-viewport.x, -viewport.y);

寫成一個(gè)方法:

// 場(chǎng)景坐標(biāo)轉(zhuǎn)視圖坐標(biāo)
function sceneCoordsToViewport(x, y, zoom, scrollX, scrollY) {
  return {
  x: (x - scrollX) * zoom,
  y: (y - scrollY) * zoom
  };
}

至于反過(guò)來(lái),場(chǎng)景坐標(biāo)系轉(zhuǎn)視圖坐標(biāo),計(jì)算它的逆矩陣即可:

以光標(biāo)為中心縮放

首先我們來(lái)認(rèn)清本質(zhì),所謂以光標(biāo)為中心縮放,不變的是什么?

光標(biāo)所在點(diǎn)在視圖坐標(biāo)系距離視口左上角的相對(duì)位置,保持不變。

我們要做的事是,在 zoom 變化后,調(diào)整 viewport.x 和 viewport.y 的值,讓光標(biāo)在視圖坐標(biāo)系上相對(duì)視口左上角距離不變。

這里得補(bǔ)充一個(gè)知識(shí)點(diǎn)。就是兩個(gè)坐標(biāo)系中距離的轉(zhuǎn)換:

  1. 場(chǎng)景轉(zhuǎn)視圖,距離轉(zhuǎn)換為 dist * zoom;
  2. 視圖轉(zhuǎn)場(chǎng)景,距離的轉(zhuǎn)換是 dist / zoom,因?yàn)橐暱诳吹降膱D形都是縮放(乘以 zoom)后的結(jié)果,所以反過(guò)來(lái)就要除回去。

實(shí)現(xiàn)思路是:

  1. 記錄好縮放前,光標(biāo)所在位置的場(chǎng)景坐標(biāo);
  2. 計(jì)算 (cx, cy) 在舊縮放比(zoom)的場(chǎng)景坐標(biāo)。
  3. 計(jì)算 cx 在新的縮放比(zoom)下,(cx / zoom, cy / zoom)。
  4. 然后二者相減,即可得到新的適口左上角坐標(biāo)。

代碼實(shí)現(xiàn)為:

/**
 * 以某點(diǎn)為中心,進(jìn)行畫(huà)布縮放
 * @param {number} zoom 新的縮放比
 * @param {number} cx 縮放中心(使用視圖坐標(biāo))
 * @param {number} cy
 */
const setZoomAndUpdateViewport = (zoom, cx, cy) => {
  const prevZoom = this.zoom;
  this.zoom = zoom;

  // 計(jì)算縮放中點(diǎn)的場(chǎng)景坐標(biāo)
  const { x: sceneCX, y: sceneCY } = viewportCoordsToScene(
    cx,
    cy,
    prevZoom,
    this.viewport.x,
    this.viewport.y,
  );

  // 核心代碼
  const newViewportX = sceneCX - cx / zoom;
  const newViewportY = sceneCY - cy / zoom;

  this.viewport.x = newViewportX;
  this.viewport.y = newViewportY;

  this.renderScene();
};

以畫(huà)布為中心進(jìn)行縮放

如果縮放時(shí)光標(biāo)不在畫(huà)布上,比如通過(guò)手動(dòng)輸入縮放值時(shí),會(huì) 以畫(huà)布的中心位置進(jìn)行縮放。

實(shí)現(xiàn)同上,只是 cx 和 cy 改成傳入視口(即畫(huà)布)的寬高除以 2:(viewport.width / 2, , (viewport.height / 2)。

結(jié)尾

要實(shí)現(xiàn)畫(huà)布縮放,重點(diǎn)是理解場(chǎng)景坐標(biāo)和視圖坐標(biāo)之間的關(guān)系。

場(chǎng)景坐標(biāo)轉(zhuǎn)視圖坐標(biāo),首先需要將畫(huà)布進(jìn)行移動(dòng),讓場(chǎng)景坐標(biāo)的原點(diǎn)和視圖坐標(biāo)的原點(diǎn)對(duì)上(場(chǎng)景坐標(biāo)移動(dòng) -viewport.x 和 -viewport.x),然后再進(jìn)行縮放(乘以 zoom)。

責(zé)任編輯:姜華 來(lái)源: 前端西瓜哥
相關(guān)推薦

2023-10-19 10:12:34

圖形編輯器開(kāi)發(fā)縮放圖形

2024-01-08 08:30:05

光標(biāo)圖形編輯器開(kāi)發(fā)游標(biāo)

2024-01-03 08:43:17

圖形編輯器旋轉(zhuǎn)控制點(diǎn)縮放控制點(diǎn)

2023-08-31 11:32:57

圖形編輯器contain

2023-09-07 08:24:35

圖形編輯器開(kāi)發(fā)繪制圖形工具

2023-09-26 07:39:21

2023-09-11 09:02:31

圖形編輯器模塊間的通信

2023-08-28 08:10:50

Hex圖形編輯器

2023-10-10 16:04:30

圖形編輯器格式轉(zhuǎn)換

2023-10-08 08:11:40

圖形編輯器快捷鍵操作

2023-07-31 08:46:07

圖形編輯器圖形自動(dòng)對(duì)齊

2023-01-18 08:30:40

圖形編輯器元素

2023-02-01 09:21:59

圖形編輯器標(biāo)尺

2023-04-07 08:02:30

圖形編輯器對(duì)齊功能

2023-02-06 16:59:57

Canvas編輯器

2023-06-12 08:22:56

圖形編輯器工具

2023-04-10 08:45:44

圖形編輯器排列移動(dòng)功能

2023-05-09 08:15:32

圖形編輯器撤銷重做功能

2023-02-09 07:02:30

圖形編輯器修改圖形

2022-12-02 07:24:46

點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)