让前端飞Web前端之路程序员

闲聊js16: 动画、数学与碰撞检测2(实现一个简单的事件分发和

2017-08-22  本文已影响121人  随风而行之青衫磊落险峰行

技术具有"继承性、延展性"

修正为:

技术具有"延续性,延展性"

写生.jpg

本篇目的:

由于动画,数学,碰撞等demo演示,需要进行事件交互。
目前还没有事件分发系统,因此今天我们来实现一个简单的事件分发系统以及事件处理的流程

为什么不能使用DOM内置的冒泡事件系统

很简单,因为DOM事件系统仅能分发到canvas元素。

而我们的2D精灵系统是直接通过canvas2D绘制出来的,并没有并入到DOM文档树中,因此DOM 事件分发到canvas后,就结束了。

所以我们要在事件分发到canvas后,继续进行分发给每个精灵,让他们有机会接受到事件并进行处理。这就是今天的任务!!

暂时先选择鼠标事件

原因:

实现一个简单的鼠标事件分发和处理系统

  1. 需要一个函数,将窗口客户区坐标转换到canvas2D坐标表示,该函数就加在BLFRender2D中去吧:
   ToCanvasCoord(x, y) {
        var bbox = this.context.canvas.getBoundingClientRect();
        return {
            x: x - bbox.left * (this.context.canvas.width / bbox.width),
            y: y - bbox.top * (this.context.canvas.height / bbox.height)
        };
    }

原因和如何使用,等会demo会演示和解释

  1. BLFSprite基类中增加鼠标事件处理方法:
   onMouseDown(x, y) {
        console.log("deal mouseDown event");
        return false;
    }

    onMouseUp(x, y) {
        console.log("deal mouseUp event");
        return false;
    }

    onMouseMove(x, y) {
        console.log("deal mouseMove event");
        return false;
    }

关于返回值true/false,请看下面的代码注释

  1. BLFSpriteManager中增加事件分发函数:
dispatchMouseDownEvent(x, y) {
        //超级简单,用于演示用的事件分发体系
        //事件分发是核心之一
        //目前比较流行的有:dom3 level3事件系统
        //                ios responder 职责链事件系统
        //                android中那个复杂无比,效率底下的事件分发系统(会被骂吗?哈哈)

        for (let i = this.sprites.length - 1; i >= 0; i--) {
            //如果i指向的精灵事件处理完成(true),就中断事件分发
            if (this.sprites[i].onMouseDown(x, y))
                return;
        }
    }

    dispatchMouseUpEvent(x, y) {
        for (let i = this.sprites.length - 1; i >= 0; i--) {
            //如果i指向的精灵事件处理完成(true),就中断事件分发
            if (this.sprites[i].onMouseUp(x, y))
                return;
        }
    }

    dispatchMouseMoveEvent(x, y) {
        for (let i = this.sprites.length - 1; i >= 0; i--) {
            //如果i指向的精灵事件处理完成(true),就中断事件分发
            if (this.sprites[i].onMouseMove(x, y))
                return;
        }
    }
  1. 最后,在BLFEngine2D的构造函数中将DOM 事件转发到各个精灵上:
       canvas.addEventListener("mousedown", (e) => {
            //先将客户区的点转换为相对canvas坐标系的点表示
            let pt = this.render.ToCanvasCoord(e.clientX, e.clientY);
            console.log("e.clientX = " + e.clientX + " e.clientY = " + e.clientY);
            console.log("canvasX = " + pt.x + " canvasY = " + pt.y);
            this.sprMgr.dispatchMouseDownEvent(pt.x, pt.y);
        }, false);

        canvas.addEventListener("mouseup", (e) => {
            //先将客户区的点转换为相对canvas坐标系的点表示
            let pt = this.render.ToCanvasCoord(e.clientX, e.clientY);
            this.sprMgr.dispatchMouseUpEvent(pt.x, pt.y);
        }, false);

        canvas.addEventListener("mousemove", (e) => {
            //先将客户区的点转换为相对canvas坐标系的点表示
            let pt = this.render.ToCanvasCoord(e.clientX, e.clientY);
            this.sprMgr.dispatchMouseMoveEvent(pt.x, pt.y);
        }, false);         

demo演示与验证:
以前我们的demo都是canvs画布与客户区原点对齐的
现在我们改变一下:将canvas右移100个像素

    <style>
        .canvas {
            position: absolute;
            left: 100px;
        }
    </style>

添加画布,使用canvas样式:

<canvas id="myCanvas" class="canvas" width="800" height="600" style="border: 1px solid black">你的浏览器还不支持哦</canvas>
mousedown.png

客户区: 649 392
canvas: 549 384

丈量.png

红色框部分左右差100 px
蓝色框部分上下差8 px

问题: 为什么客户区和canvas上下差8px?(有兴趣可以留言回答)

本篇结束,下一篇我们进入鼠标hitTest方面的内容

附:
昨天晚上听了一堂视听课,关于mysql MyISAM/InnoDB 索引底层实现(B+树)。收获是巨大的。只有了解了原理,才能有效的使用!。

其实我个人一直很努力的学习各种树结构,它太重要了!!

树是非常非常非常重要的数据结构,如果想深入了解图形,数据库,游戏引擎等,那么各种树的数据结构一定要了解,并且知道用在哪些方面

设计模式在UI系统开发中的应用(导读)这篇文章中,提供了一个通用树结构相关图,很值得研究

树1.png 遍历策略.png 遍历策略2.png 遍历策略3.png

在闲聊c++系列中,我的文章以基础知识为主。别看现在外面的新技术层出不穷,但本质都是很基础的知识。
一个新技术不可能是凭空出来的,技术都是具有:
继承性 : 从上到下
延展性 : 从左到右
突然发现,好有哲理哦!!!

修正为:
一个新技术不可能是凭空出来的,技术都是具有:
延续性 : 从上到下
延展性 : 从左到右

这样比较押韵!!

上一篇下一篇

猜你喜欢

热点阅读