圖形編輯器:場(chǎng)景坐標(biāo)、視口坐標(biāo)以及它們之間的轉(zhuǎn)換
大家好,我是前端西瓜哥。
圖形編輯器的坐標(biāo)系有兩種。
一個(gè)是場(chǎng)景(scene)坐標(biāo)系,一個(gè)是 視口(viewport)坐標(biāo)系。視口就是場(chǎng)景的一個(gè)子區(qū)域。
假設(shè)我們的視口的原點(diǎn),離場(chǎng)景原點(diǎn)的坐標(biāo)水平和垂直距離分別為 scrollX 和 scrollY。
先 不考慮縮放,假設(shè)我們?cè)谝暱谧鴺?biāo)上的某個(gè)地方點(diǎn)擊了一下,這個(gè)坐標(biāo)是 ??(x, y)?
?。這個(gè)坐標(biāo)在場(chǎng)景坐標(biāo)系中,就是:
挺簡(jiǎn)單。
視口坐標(biāo)轉(zhuǎn)換為場(chǎng)景坐標(biāo)
下面我們引入畫布縮放,即畫布可以縮小和放大,對(duì)應(yīng)的一個(gè)比例值 zoom。
視口中的某個(gè)坐標(biāo) (x, y) 在場(chǎng)景坐標(biāo)系,則是 :
之所以要用 x 除以 zoom,是因?yàn)榇藭r(shí)視口中展示的是縮放后的圖形,里面的坐標(biāo)都是縮放后的值。所以需要先轉(zhuǎn)換為 zoom 值為 1 對(duì)應(yīng)的真實(shí)值。
場(chǎng)景坐標(biāo)轉(zhuǎn)換為視口坐標(biāo)
然后我們反過(guò)來(lái),如何從場(chǎng)景坐標(biāo) (x, y) 轉(zhuǎn)換為視口坐標(biāo)?將前面的公式做等式變換即可:
我們通常是使用按鍵加滾輪的方式讓畫布以光標(biāo)為中心進(jìn)行縮放,或按按鈕進(jìn)行縮放,
為了讓縮放后的場(chǎng)景還能對(duì)上縮放前光標(biāo)的位置,我們需要計(jì)算縮放后的 scrollX 和 scrollY,進(jìn)行校準(zhǔn)。
核心思路是 保持縮放前點(diǎn)到視口左上角距離(視口坐標(biāo)系)相同。
再說(shuō)點(diǎn)別的。
可能會(huì)有這么一種情況,就是實(shí)際的視口區(qū)域的原點(diǎn)坐標(biāo)有一些偏移,偏移了 offsetX 和 offsetY,見(jiàn)下圖。
我們只需要將前面代碼中的 scrollX 變成 (scrollX + offsetX),scrollY 變成 (scrollY + offsetY),其他不變。
就這些了。
總結(jié)一下,視口坐標(biāo)是場(chǎng)景坐標(biāo)平移并縮放后的結(jié)果,所以視口轉(zhuǎn)場(chǎng)景,需要除以 zoom 再加上偏移值。在圖形編輯器中,會(huì)有相當(dāng)多的坐標(biāo)系轉(zhuǎn)換邏輯,這兩個(gè)坐標(biāo)系的關(guān)系需要好好消化理解。