Laya 中縮放的實現

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章