閑聊js16: 動(dòng)畫沮趣、數(shù)學(xué)與碰撞檢測(cè)2(實(shí)現(xiàn)一個(gè)簡單的事件分發(fā)和處理框架)

技術(shù)具有"繼承性务傲、延展性"

修正為:

技術(shù)具有"延續(xù)性狈癞,延展性"

寫生.jpg

本篇目的:

  • 為什么不能使用DOM內(nèi)置的事件分發(fā)系統(tǒng)
  • 暫時(shí)先選擇鼠標(biāo)事件
  • 實(shí)現(xiàn)一個(gè)簡單的鼠標(biāo)事件分發(fā)和處理框架
  • demo演示與驗(yàn)證

由于動(dòng)畫履羞,數(shù)學(xué)峦萎,碰撞等demo演示,需要進(jìn)行事件交互忆首。
目前還沒有事件分發(fā)系統(tǒng)骨杂,因此今天我們來實(shí)現(xiàn)一個(gè)簡單的事件分發(fā)系統(tǒng)以及事件處理的流程

為什么不能使用DOM內(nèi)置的冒泡事件系統(tǒng)

很簡單,因?yàn)镈OM事件系統(tǒng)僅能分發(fā)到canvas元素雄卷。

而我們的2D精靈系統(tǒng)是直接通過canvas2D繪制出來的搓蚪,并沒有并入到DOM文檔樹中,因此DOM 事件分發(fā)到canvas后丁鹉,就結(jié)束了妒潭。

所以我們要在事件分發(fā)到canvas后,繼續(xù)進(jìn)行分發(fā)給每個(gè)精靈揣钦,讓他們有機(jī)會(huì)接受到事件并進(jìn)行處理雳灾。這就是今天的任務(wù)!冯凹!

暫時(shí)先選擇鼠標(biāo)事件

原因:

  • 在手機(jī)端谎亩,豎屏顯示范圍太小了,查了一些資料宇姚,發(fā)現(xiàn)h5目前沒有一個(gè)通用的進(jìn)入頁面直接橫屏的功能匈庭,需要研究一下變通的實(shí)現(xiàn)方式。

  • 如果一旦實(shí)現(xiàn)手機(jī)端自動(dòng)橫屏效果浑劳,我會(huì)將mouse事件更改為touch事件阱持,也就是幾句代碼的事情

  • touch/mouse事件最大區(qū)別是move事件。只要鼠標(biāo)移動(dòng)就會(huì)產(chǎn)生mousemove事件魔熏。而touchmove事件必須按下移動(dòng)才產(chǎn)生衷咽。后面我一些例子,建立在mousemove基礎(chǔ)上

  • 關(guān)鍵原因就是我現(xiàn)在還沒實(shí)現(xiàn)h5頁面自動(dòng)橫屏效果蒜绽。導(dǎo)致手機(jī)演示不是很爽镶骗。

實(shí)現(xiàn)一個(gè)簡單的鼠標(biāo)事件分發(fā)和處理系統(tǒng)

  1. 需要一個(gè)函數(shù),將窗口客戶區(qū)坐標(biāo)轉(zhuǎn)換到canvas2D坐標(biāo)表示,該函數(shù)就加在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)
        };
    }

原因和如何使用躲雅,等會(huì)demo會(huì)演示和解釋

  1. BLFSprite基類中增加鼠標(biāo)事件處理方法:
   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;
    }

關(guān)于返回值true/false鼎姊,請(qǐng)看下面的代碼注釋

  1. BLFSpriteManager中增加事件分發(fā)函數(shù):
dispatchMouseDownEvent(x, y) {
        //超級(jí)簡單,用于演示用的事件分發(fā)體系
        //事件分發(fā)是核心之一
        //目前比較流行的有:dom3 level3事件系統(tǒng)
        //                ios responder 職責(zé)鏈?zhǔn)录到y(tǒng)
        //                android中那個(gè)復(fù)雜無比,效率底下的事件分發(fā)系統(tǒng)(會(huì)被罵嗎?哈哈)

        for (let i = this.sprites.length - 1; i >= 0; i--) {
            //如果i指向的精靈事件處理完成(true)此蜈,就中斷事件分發(fā)
            if (this.sprites[i].onMouseDown(x, y))
                return;
        }
    }

    dispatchMouseUpEvent(x, y) {
        for (let i = this.sprites.length - 1; i >= 0; i--) {
            //如果i指向的精靈事件處理完成(true)即横,就中斷事件分發(fā)
            if (this.sprites[i].onMouseUp(x, y))
                return;
        }
    }

    dispatchMouseMoveEvent(x, y) {
        for (let i = this.sprites.length - 1; i >= 0; i--) {
            //如果i指向的精靈事件處理完成(true)噪生,就中斷事件分發(fā)
            if (this.sprites[i].onMouseMove(x, y))
                return;
        }
    }
  • 如果循環(huán)中當(dāng)前i指向的精靈事件處理完成(true)裆赵,就中斷事件分發(fā),退出函數(shù)
  • 事件分發(fā)循環(huán)是從后到前方式(let i = this.sprites.length - 1; i >= 0; i--),這是因?yàn)楫?dāng)兩個(gè)精靈重疊時(shí),肯定是上面的精靈進(jìn)行事件處理跺嗽,而不是被遮擋住的精靈(先前景战授,后背景)
  • 而繪制時(shí),肯定是先背景桨嫁,后前景(昨天孩子寫生油畫植兰,老師講解也強(qiáng)調(diào)如此,經(jīng)典的畫家算法)
  1. 最后璃吧,在BLFEngine2D的構(gòu)造函數(shù)中將DOM 事件轉(zhuǎn)發(fā)到各個(gè)精靈上:
       canvas.addEventListener("mousedown", (e) => {
            //先將客戶區(qū)的點(diǎn)轉(zhuǎn)換為相對(duì)canvas坐標(biāo)系的點(diǎn)表示
            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) => {
            //先將客戶區(qū)的點(diǎn)轉(zhuǎn)換為相對(duì)canvas坐標(biāo)系的點(diǎn)表示
            let pt = this.render.ToCanvasCoord(e.clientX, e.clientY);
            this.sprMgr.dispatchMouseUpEvent(pt.x, pt.y);
        }, false);

        canvas.addEventListener("mousemove", (e) => {
            //先將客戶區(qū)的點(diǎn)轉(zhuǎn)換為相對(duì)canvas坐標(biāo)系的點(diǎn)表示
            let pt = this.render.ToCanvasCoord(e.clientX, e.clientY);
            this.sprMgr.dispatchMouseMoveEvent(pt.x, pt.y);
        }, false);         
  • 關(guān)鍵的一步是將客戶區(qū)的點(diǎn)轉(zhuǎn)換為相對(duì)canvas坐標(biāo)系的點(diǎn)表示楣导。可能的情況是你的canvs畫布的原點(diǎn)和客戶區(qū)的原點(diǎn)沒有重合時(shí)畜挨,如果不進(jìn)行坐標(biāo)變換筒繁,會(huì)出現(xiàn)非常大的問題

  • 關(guān)于DOM3 level3 冒泡事件,我個(gè)人是非常喜歡的一種事件分發(fā)體系巴元。其實(shí)使用中有很多訣竅毡咏。本系列中,我會(huì)專門抽一章來聊一聊冒泡事件逮刨。實(shí)際上呕缭,我從webkit中抽取了很多超級(jí)有用的代碼,包括冒泡事件系統(tǒng)(webkit我個(gè)人感覺應(yīng)該是超過100萬行代碼的龐大c++程序)

demo演示與驗(yàn)證:
以前我們的demo都是canvs畫布與客戶區(qū)原點(diǎn)對(duì)齊的
現(xiàn)在我們改變一下:將canvas右移100個(gè)像素

    <style>
        .canvas {
            position: absolute;
            left: 100px;
        }
    </style>
  • 使用絕對(duì)定位修己,left設(shè)置為100px,css一定要用單位哦

添加畫布恢总,使用canvas樣式:

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

客戶區(qū): 649 392
canvas: 549 384

丈量.png

紅色框部分左右差100 px
藍(lán)色框部分上下差8 px

問題: 為什么客戶區(qū)和canvas上下差8px?(有興趣可以留言回答)

本篇結(jié)束,下一篇我們進(jìn)入鼠標(biāo)hitTest方面的內(nèi)容

附:
昨天晚上聽了一堂視聽課睬愤,關(guān)于mysql MyISAM/InnoDB 索引底層實(shí)現(xiàn)(B+樹)离熏。收獲是巨大的。只有了解了原理戴涝,才能有效的使用滋戳!。

其實(shí)我個(gè)人一直很努力的學(xué)習(xí)各種樹結(jié)構(gòu)啥刻,它太重要了<檠臁!

  • quake3中實(shí)現(xiàn)的自適應(yīng)哈夫曼樹(用于網(wǎng)絡(luò)傳輸數(shù)據(jù)最小化)

  • quake3 BSP樹(整個(gè)quake引擎之所以如此高效可帽,就是因?yàn)槭褂昧薭inary space partitioning tree,空間二叉分割樹)

  • 分割空間娄涩,加快渲染,與碰撞檢測(cè)的quadtree(二維分割,四叉樹蓄拣,廣泛用于地形渲染和碰撞檢測(cè))扬虚,octree(三維分割,八叉樹)

  • kd樹(四叉/八叉都是kd的特殊形式)

  • 用于ui/2d/3d中組成場(chǎng)景用的通用樹結(jié)構(gòu)

  • 用于加快室內(nèi)場(chǎng)景管理球恤,動(dòng)態(tài)光影計(jì)算的portal樹

  • 各種加快碰撞檢測(cè)的包圍體層次樹

  • 還有就是數(shù)據(jù)結(jié)構(gòu)中各種經(jīng)典的樹結(jié)構(gòu):二叉樹辜昵,紅黑樹,還有昨天的b樹/b+樹......

樹是非常非常非常重要的數(shù)據(jù)結(jié)構(gòu)咽斧,如果想深入了解圖形堪置,數(shù)據(jù)庫,游戲引擎等,那么各種樹的數(shù)據(jù)結(jié)構(gòu)一定要了解,并且知道用在哪些方面

設(shè)計(jì)模式在UI系統(tǒng)開發(fā)中的應(yīng)用(導(dǎo)讀)這篇文章中幽崩,提供了一個(gè)通用樹結(jié)構(gòu)相關(guān)圖,很值得研究

樹1.png
遍歷策略.png
遍歷策略2.png
遍歷策略3.png

在閑聊c++系列中坎匿,我的文章以基礎(chǔ)知識(shí)為主。別看現(xiàn)在外面的新技術(shù)層出不窮雷激,但本質(zhì)都是很基礎(chǔ)的知識(shí)替蔬。
一個(gè)新技術(shù)不可能是憑空出來的,技術(shù)都是具有:
繼承性 : 從上到下
延展性 : 從左到右
突然發(fā)現(xiàn)侥锦,好有哲理哦=浴!恭垦!

修正為:
一個(gè)新技術(shù)不可能是憑空出來的快毛,技術(shù)都是具有:
延續(xù)性 : 從上到下
延展性 : 從左到右

這樣比較押韻!番挺!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末唠帝,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子玄柏,更是在濱河造成了極大的恐慌襟衰,老刑警劉巖,帶你破解...
    沈念sama閱讀 223,126評(píng)論 6 520
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件粪摘,死亡現(xiàn)場(chǎng)離奇詭異瀑晒,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)徘意,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,421評(píng)論 3 400
  • 文/潘曉璐 我一進(jìn)店門苔悦,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人椎咧,你說我怎么就攤上這事玖详。” “怎么了?”我有些...
    開封第一講書人閱讀 169,941評(píng)論 0 366
  • 文/不壞的土叔 我叫張陵蟋座,是天一觀的道長拗踢。 經(jīng)常有香客問我,道長向臀,這世上最難降的妖魔是什么巢墅? 我笑而不...
    開封第一講書人閱讀 60,294評(píng)論 1 300
  • 正文 為了忘掉前任,我火速辦了婚禮飒硅,結(jié)果婚禮上砂缩,老公的妹妹穿的比我還像新娘作谚。我一直安慰自己三娩,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,295評(píng)論 6 398
  • 文/花漫 我一把揭開白布妹懒。 她就那樣靜靜地躺著雀监,像睡著了一般。 火紅的嫁衣襯著肌膚如雪眨唬。 梳的紋絲不亂的頭發(fā)上会前,一...
    開封第一講書人閱讀 52,874評(píng)論 1 314
  • 那天,我揣著相機(jī)與錄音匾竿,去河邊找鬼瓦宜。 笑死,一個(gè)胖子當(dāng)著我的面吹牛岭妖,可吹牛的內(nèi)容都是我干的临庇。 我是一名探鬼主播,決...
    沈念sama閱讀 41,285評(píng)論 3 424
  • 文/蒼蘭香墨 我猛地睜開眼昵慌,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼假夺!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起斋攀,我...
    開封第一講書人閱讀 40,249評(píng)論 0 277
  • 序言:老撾萬榮一對(duì)情侶失蹤已卷,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后淳蔼,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體侧蘸,經(jīng)...
    沈念sama閱讀 46,760評(píng)論 1 321
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,840評(píng)論 3 343
  • 正文 我和宋清朗相戀三年鹉梨,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了讳癌。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,973評(píng)論 1 354
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡俯画,死狀恐怖析桥,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤泡仗,帶...
    沈念sama閱讀 36,631評(píng)論 5 351
  • 正文 年R本政府宣布埋虹,位于F島的核電站,受9級(jí)特大地震影響娩怎,放射性物質(zhì)發(fā)生泄漏搔课。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,315評(píng)論 3 336
  • 文/蒙蒙 一截亦、第九天 我趴在偏房一處隱蔽的房頂上張望爬泥。 院中可真熱鬧,春花似錦崩瓤、人聲如沸袍啡。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,797評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽境输。三九已至,卻和暖如春颖系,著一層夾襖步出監(jiān)牢的瞬間嗅剖,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,926評(píng)論 1 275
  • 我被黑心中介騙來泰國打工嘁扼, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留信粮,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 49,431評(píng)論 3 379
  • 正文 我出身青樓趁啸,卻偏偏與公主長得像强缘,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子莲绰,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,982評(píng)論 2 361

推薦閱讀更多精彩內(nèi)容