• Laya 中缩放的实现


    Laya 缩放功能的实现

    在 laya 中实现滚轮对选中对象的缩放,涉及到以下两个模块:

    • 事件
    • 容器坐标

    1. 事件

    在 Laya 中, Event 是事件类型的集合。包含了常见的鼠标事件、键盘事件。

    • 1.1 事件的触发

        触发一个事件,需要设置一个事件接收区域.
      如若未明确指定事件,事件触发默认是冒泡模式。从子节点开始依次向父节点查询,直到找到绑定了指定事件的容器后结束。
      在对容器进行绑定时有下面两种方式:
    方法一:根据事件对象获取(不推荐使用)
    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 事件的绑定与解绑

        只有在需要时候事件时,才绑定事件方法。用完后,需要解除绑定。这样可以避免同一个对象多次绑定的问题,
      在 laya 中,事件管理器是允许同一个对象的同一个方法事件进行多次绑定的,这样容易造成许多意向不到的 bug, 所以务必
      只在使用时进行绑定,用完立马解除绑定。注意,如鼠标移动事件、MouseUp 事件一般使用 Stage 来触发。
      如下例:
    // 下面的代码为按下鼠标左键,允许拖动目标容器,松开鼠标左键后,无法拖动目标容器
    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);
    }
    

    当有多个操作的时候,比如需要对象同时涉及到缩放,平移以及旋转时候,我们应当遵循下面这个原则:

    先处理缩放,再旋转,然后平移。
    这里涉及到一个矩阵组合运算的原则:
    **矩阵的组合

    矩阵的乘法运算不遵守交换律,这意味着它们的顺序很重要。当矩阵相乘时,在最右边的矩阵是第一个与向量相乘的,所以我们应当从右向左来读这个乘法。所以在组合时,先缩放操作,然后旋转,最后才是位移,否则它们会互相影响。比如,你先位移再缩放,位移的向量也会同样缩放。

  • 相关阅读:
    mkdir命令
    pwd命令
    chmod命令
    chown命令
    chgrp命令
    687. Longest Univalue Path
    HYSBZ 1036 树的统计Count (水题树链剖分)
    POJ 3709 K-Anonymous Sequence (斜率优化DP)
    LightOJ 1065 Island of Survival (概率DP?)
    LightOJ 1248 Dice (III) (水题,期望DP)
  • 原文地址:https://www.cnblogs.com/yaolin1228/p/10596543.html
Copyright © 2020-2023  润新知