Laya 縮放功能的實現
在 laya 中實現滾輪對選中對象的縮放,涉及到以下兩個模塊:
- 事件
- 容器座標
1. 事件
在 Laya 中, Event 是事件類型的集合。包含了常見的鼠標事件、鍵盤事件。<br>
- 1.1 事件的觸發<br> 觸發一個事件,需要設置一個事件接收區域. 如若未明確指定事件,事件觸發默認是冒泡模式。從子節點開始依次向父節點查詢,直到找到綁定了指定事件的容器後結束。 在對容器進行綁定時有下面兩種方式:<br>
方法一:根據事件對象獲取(不推薦使用)
mySprit.on(Laya.Event.MouseDOwn, this, this.Scale);
public Scale(e: Event)
{
// 此種形式獲取 sp, 並未明確指定綁定事件的 sp,觸發事件時,需冒泡查找, 不推薦使用
let sp = e.target as Laya.Sprite;
}
方法二: 直接傳入目標容器
mySprit.on(Laya.Event.MouseDOwn, this, this.Scale, [targetSp]);
public Scale(sp, e: Event)
{
// 直接用傳入的 sp 進行綁定
}
- 1.2 事件的綁定與解綁<br> 只有在需要時候事件時,才綁定事件方法。用完後,需要解除綁定。這樣可以避免同一個對象多次綁定的問題, 在 laya 中,事件管理器是允許同一個對象的同一個方法事件進行多次綁定的,這樣容易造成許多意向不到的 bug, 所以務必 只在使用時進行綁定,用完立馬解除綁定。注意,如鼠標移動事件、MouseUp 事件一般使用 Stage 來觸發。 如下例:<br>
// 下面的代碼爲按下鼠標左鍵,允許拖動目標容器,鬆開鼠標左鍵後,無法拖動目標容器
this.firstSp = new Laya.Sprite();
this.firstSp.graphics.drawRect(0, 0, 100, 100, null, "#ffffff"); // 繪製圖形
this.firstSp.on(Laya.Event.MOUSE_DOWN, this, this.MouseDown, [this.firstSp]); // 綁定 mouse_down 事件
this.firstSp.hitArea = this.firstSp.getGraphicBounds(); // 指定可觸發事件區域
this._rootSp.addChild(this.firstSp);
Laya.stage.addChild(this._rootSp);
// 在 mouse_down 事件後才綁定事件
private MouseDown(sp:Laya.Sprite, e:Laya.Event)
{
Laya.stage.on(Laya.Event.MOUSE_MOVE, this, this.MouseMove, [sp])
Laya.stage.on(Laya.Event.MOUSE_UP, this, this.MouseUp, [sp])
}
private MouseMove(sp:Laya.Sprite, e:Laya.Event)
{
sp.x += 5;
}
// 在 mouseup 事件後解除除了觸發事件外的其他一切事件
private MouseUp(sp:Laya.Sprite, e:Laya.Event)
{
Laya.stage.off(Laya.Event.MOUSE_MOVE, this, this.MouseMove)
Laya.stage.off(Laya.Event.MOUSE_UP, this, this.MouseUp)
}
- 1.3 可點擊區域的設置 容器要觸發交互事件,必須設置可點擊區域
// 將繪圖區域設置爲 點擊區域
this.firstSp.hitArea = this.firstSp.getGraphicBounds(); // 指定可觸發事件區域
// 用數值設定點擊區域
this.firstSp.hitArea = new Laya.Rectangle(0, 0, 10000, 10000)
容器座標
laya 2d 座標系座標單位爲像素, Stage 左上角爲左邊原點 (0,0)。向右爲 x 軸正向,向下爲 Y 軸正向。所有容器創建時座標原點默認爲 (0,0), 此處需要注意: 所有容器的原點座標都是相對於其父容器原點的座標,是局部座標,而非全局座標。 因此,對象在容器中的座標爲局部座標,轉換爲全局需要逐層向父容器變換,知道跟容器 Stage 爲止。 同時要注意: 在移動、縮放對象時不要改變對象座標,改變容器座標,實現對象的改變。
// 對容器對象進行縮放
///-------------- Scale Drawing Sprite --------------------------
public static MouseWheel(currentSp: Laya.Sprite, e: Laya.Event) {
let spriteX = 0, spriteY = 0;
if(currentSp.parent) // 考慮了父容器的偏差, TODO: 父容器與 stage 有偏差
{
spriteX = (currentSp.parent as Laya.Sprite).x
spriteY = (currentSp.parent as Laya.Sprite).y;
}
this.Zoom(currentSp, e.stageX - spriteX, e.stageY - spriteY, e.delta);
}
private static Zoom(sp: Laya.Sprite, x: number, y: number, delta: number) {
let oldScale = sp.scaleX;
let scale = delta > 0 ? WebCad.GlobalScaleRatio : 1 / WebCad.GlobalScaleRatio;
let newScale = sp.scaleX * scale;
// 設置最大最小縮放範圍
newScale = newScale < 0.1 ? 0.1 : (newScale > 50 ? 50 : newScale);
// 獲取在縮放比例下,光標相對偏移位置
sp.x = sp.x - (x - sp.x) * (newScale - oldScale) / oldScale;
sp.y = sp.y - (y - sp.y) * (newScale - oldScale) / oldScale;
sp.scale(newScale, newScale);
}
當有多個操作的時候,比如需要對象同時涉及到縮放,平移以及旋轉時候,我們應當遵循下面這個原則:<br> 先處理縮放,再旋轉,然後平移。 這裏涉及到一個矩陣組合運算的原則: **矩陣的組合
矩陣的乘法運算不遵守交換律,這意味着它們的順序很重要。當矩陣相乘時,在最右邊的矩陣是第一個與向量相乘的,所以我們應當從右向左來讀這個乘法。所以在組合時,先縮放操作,然後旋轉,最後纔是位移,否則它們會互相影響。比如,你先位移再縮放,位移的向量也會同樣縮放。
原文出處:https://www.cnblogs.com/yaolin1228/p/10596543.html