<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                ## 用戶交互 沒有用戶交互的動畫就跟電視上的動畫片一樣,不管誰看,都是一個樣,千年不變。顯然,這不是我們想要的,很多時候,我們需要用戶參與進來,這樣才能產生豐富的動畫效果,這就是專門用一章來了解用戶交互的原因。 用戶交互是基于用戶事件的,這些事件通常包括鼠標事件、鍵盤事件以及觸摸事件。 **1、事件綁定和事件取消** 在這里,并不會對JavaScript事件做過多的解析,如需詳細了解,可看這里:《[JavaScript學習筆記整理(10):Event事件](http://ghmagical.com/article/page/id/nXCnaSLsuyWd)》。 由于我們無法獲取到canvas上繪制的線和形狀,所以只能在canvas上綁定事件,然后根據鼠標相對canvas的位置而確定在哪個線或形狀上,比如要為canvas綁定鼠標點擊(mousedown)事件: ``` function MClick(event){ console.log('鼠標點擊了canvas'); }; canvas.addEventListener('mousedown',MClick,false); ``` 當鼠標在canvas上點擊時,每次都會在控制臺打印出"鼠標點擊了canvas"。 我們使用removeEventListener()還可以取消鼠標點擊事件: ``` canvas.removeEventListener('mousedown',MClick,false); ``` 上面的代碼就取消了canvas上的鼠標點擊事件,不過要注意的是,這里傳入的只能是函數名,而不能傳入函數體,而且只是取消了鼠標點擊事件中的MClick事件處理函數,如果還綁定了其他的鼠標點擊事件,依然有效。 **2、鼠標事件** 鼠標事件有很多種,常見的有下面這些: ``` mousedown mouseup click dblclick mousewheel mousemove mouseover mouseout ``` 當為元素注冊一個鼠標事件處理函數時,它還會為函數傳入一個MouseEvent對象,這個對象包含了多個屬性,比如我們接下來要用的`pageX`和`pageY`。 `pageX` 和 `pageY` 分別是觸點相對HTML文檔左邊沿的X坐標和觸點相對HTML文檔上邊沿的Y坐標。只讀屬性。 注意:當存在滾動的偏移時,pageX包含了水平滾動的偏移,pageY包含了垂直滾動的偏移。 顯然,通過pageX和pageY獲取到的只是相對于HTML文檔的鼠標位置,并不是我們想要的,我們需要的是相對于canvas的鼠標位置,如何得到呢? 只需用pageX和pageY分別減去canvas元素的左偏移和上偏移距離就可得到相對canvas的鼠標位置: ``` canvas.addEventListener('mousedown',function(event){ var x = (event.pageX || event.clientX + document.body.scrollLeft +document.documentElement.scrollLeft) - canvas.offsetLeft; var y = (event.pageY || event.clientY + document.body.scrollTop +document.documentElement.scrollTop) - canvas.offsetTop; },false); ``` 在上面的代碼中,還使用了clientX和clientY,這是為了兼容不同的瀏覽器。 注意:這里的canvas偏移位置是相對HTML文檔的。 為了避免后面重復寫代碼,我們先來造個輪子,創建一個tool.js文件(后續都會用到),在里面創建一個全局對象tool,然后將需要的方法傳入進去: ``` window.tool = {}; window.tool.captureMouse = function(element,mousedown,mousemove,mouseup){ /*傳入Event對象*/ function getPoint(event){ event = event || window.event; /*為了兼容IE*/ /*將當前的鼠標坐標值減去元素的偏移位置,返回鼠標相對于element的坐標值*/ var x = (event.pageX || event.clientX + document.body.scrollLeft + document.documentElement.scrollLeft); x -= element.offsetLeft; var y = (event.pageY || event.clientY + document.body.scrollTop + document.documentElement.scrollTop); y -= element.offsetTop; return {x:x,y:y}; }; if(!element) return; /*為element元素綁定mousedown事件*/ element.addEventListener('mousedown',function(event){ event.point = getPoint(event); mousedown && mousedown.call(this,event); },false); /*為element元素綁定mousemove事件*/ element.addEventListener('mousemove',function(event){ event.point = getPoint(event); mousemove && mousemove.call(this,event); },false); /*為element元素綁定mouseup事件*/ element.addEventListener('mouseup',function(event){ event.point = getPoint(event); mouseup && mouseup.call(this,event); },false); }; ``` 輪子已經造好了,使用方法也很簡單: ``` /*回調函數會傳入一個event對象,event.point中包含了x和y屬性,分別對應鼠標相對element的X坐標和Y坐標,函數內的this指向綁定元素element*/ function mousedown(event) { console.log(event.point.x,event.ponit.y); console.log(this); document.querySelector('.pointX').innerHTML = event.point.x; document.querySelector('.pointY').innerHTML = event.point.y; }; function mousemove(event) { console.log(event.point); document.querySelector('.pointX1').innerHTML = event.point.x; document.querySelector('.pointY1').innerHTML = event.point.y; var x = event.point.x; var y = event.point.y; var radius = 5; /*清除整個canvas畫布*/ ctx.clearRect(0,0,canvas.width,canvas.height); ctx.fillStyle = 'red'; ctx.beginPath(); /*繪制一個跟隨鼠標的圓*/ ctx.arc(x,y,radius,0,2*Math.PI,true); ctx.fill(); ctx.closePath(); }; function mouseup(event) { console.log(event.point); document.querySelector('.pointX2').innerHTML = event.point.x; document.querySelector('.pointY2').innerHTML = event.point.y; }; /*傳入canvas元素,后面是傳入三個函數,分別對應mousedown、mousemove和mouseup事件的事件處理函數*/ tool.captureMouse(canvas, mousedown, mousemove, mouseup); ``` 上面代碼中的mousedown、mousemove和mouseup三個方法都是自定義的,三個回調函數都會傳入一個event對象(element當前綁定事件的event對象), event.point 是我定義的,它包含了 x 和 y 屬性,分別對應鼠標相對element(也就是元素左上角)的X坐標和Y坐標,函數內的 this 指向綁定元素element。 實例(獲取鼠標坐標):canvas-demo/captureMousePoint.html **3、觸摸事件** 常用觸摸事件: touchstart touchmove touchend 觸摸事件和鼠標事件最大的區別在于,觸摸有可能會在同一時間有多個觸摸點,而鼠標永遠都是只有一個觸摸點。 要獲取觸摸點相對canvas的坐標,同樣是根據event對象中的pageX和pageY,還有canvas相對于HTML文檔的偏移位置來確定,不過由于觸摸點可能有多個,它傳遞給事件處理函數的是TouchEvent對象,使用方法稍微有一點區別: ``` canvas.addEventListener('touchstart',function(event){ var touchEvnet = event.changedTouches[0]; var x = (touchEvent.pageX || touchEvent.clientX + document.body.scrollLeft+ document.documentElement.scrollLeft ); x -= canvas.offsetLeft; var y = (touchEvent.pageY || touchEvent.clientY + document.body.scrollTop + document.documentElement.scrollTop ); y -= canvas.offsetTop; }); ``` 注意上面代碼中的 event.changedTouches[0] ,這是獲取當前觸摸事件引發的所有Touch對象中第一個觸摸點的Touch對象,當然還有 event.touches[0] 也可以獲取到,它是獲取所有仍然處于活動狀態的觸摸點中的第一個。 對于觸摸事件,我們也可以在tool這個輪子里添加一個captureTouch方法,你可以用手機或者打開瀏覽器控制臺模擬手機模式看看這個例子:觸摸例子(canvas-demo/captureTouchPoint.html) ``` window.tool.captureTouch = function(element,touchstart,touchmove,touchend){ /*傳入Event對象*/ function getPoint(event){ event = event || window.event; var touchEvent = event.changedTouches[0]; /*將當前的鼠標坐標值減去元素的偏移位置,返回鼠標相對于element的坐標值*/ var x = (touchEvent.pageX || touchEvent.clientX + document.body.scrollLeft + document.documentElement.scrollLeft); x -= element.offsetLeft; var y = (touchEvent.pageY || touchEvent.clientY + document.body.scrollTop + document.documentElement.scrollTop); y -= element.offsetTop; return {x:x,y:y}; }; if(!element) return; /*為element元素綁定touchstart事件*/ element.addEventListener('touchstart',function(event){ event.point = getPoint(event); touchstart && touchstart.call(this,event); },false); /*為element元素綁定touchmove事件*/ element.addEventListener('touchmove',function(event){ event.point = getPoint(event); touchmove && touchmove.call(this,event); },false); /*為element元素綁定touchend事件*/ element.addEventListener('touchend',function(event){ event.point = getPoint(event); touchend && touchend.call(this,event); },false); }; ``` 下面我會將鼠標事件和觸摸事件結合在一起,添加一個captureMT方法: ``` window.tool.captureMT = function(element, touchStartEvent, touchMoveEvent, touchEndEvent) { 'use strict'; var isTouch = ('ontouchend' in document); var touchstart = null; var touchmove = null var touchend = null; if(isTouch){ touchstart = 'touchstart'; touchmove = 'touchmove'; touchend = 'touchend'; }else{ touchstart = 'mousedown'; touchmove = 'mousemove'; touchend = 'mouseup'; }; /*傳入Event對象*/ function getPoint(event) { /*將當前的觸摸點坐標值減去元素的偏移位置,返回觸摸點相對于element的坐標值*/ event = event || window.event; var touchEvent = isTouch ? event.changedTouches[0]:event; var x = (touchEvent.pageX || touchEvent.clientX + document.body.scrollLeft + document.documentElement.scrollLeft); x -= element.offsetLeft; var y = (touchEvent.pageY || touchEvent.clientY + document.body.scrollTop + document.documentElement.scrollTop); y -= element.offsetTop; return {x: x,y: y}; }; if(!element) return; /*為element元素綁定touchstart事件*/ element.addEventListener(touchstart, function(event) { event.point = getPoint(event); touchStartEvent && touchStartEvent.call(this, event); }, false); /*為element元素綁定touchmove事件*/ element.addEventListener(touchmove, function(event) { event.point = getPoint(event); touchMoveEvent && touchMoveEvent.call(this, event); }, false); /*為element元素綁定touchend事件*/ element.addEventListener(touchend, function(event) { event.point = getPoint(event); touchEndEvent && touchEndEvent.call(this, event); }, false); }; ``` 在上面的代碼中,我們先檢測是移動還是PC('ontouchend' in document),然后將布爾值傳給變量 isTouch ,然后定義使用mouse事件還是touch事件,獲取坐標點時,也是根據 isTouch的值來絕對直接用 event還是用 event.changedTouches[0] 。 **4、鍵盤事件** 鍵盤事件只有三個: keydown 按下鍵盤時觸發該事件。 keyup 松開鍵盤時觸發該事件。 keypress 只要按下的鍵并非Ctrl、Alt、Shift和Meta,就接著觸發keypress事件(較少用到)。 只要用戶一直按鍵不松開,就會連續觸發鍵盤事件,觸發順序如下: ``` keydown keypress keydown keypress (重復以上過程) keyup ``` 在這里,我們只來了解keydown和keyup就足夠了。 我們會將事件綁定到window上,而不是canvas上,因為如果將鍵盤事件綁定到某個元素上,那么該元素只有在獲取到焦點時才會觸發鍵盤事件,而綁定到window上時,我們可以任何時候監聽到。 一般來說,我們比較關心鍵盤上的箭頭按鈕(上下左右): ``` function keyEvent(event){ switch (event.keyCode){ case 38: keybox.innerHTML = '你點擊了向上箭頭(↑)'; break; case 40: keybox.innerHTML = '你點擊了向下箭頭(↓)'; break; case 37: keybox.innerHTML = '你點擊了向左箭頭(←)'; break; case 39: keybox.innerHTML = '你點擊了向右箭頭(→)'; break; default: keybox.innerHTML = '你點擊了其他按鈕'; }; }; window.addEventListener('keydown',keyEvent,false); ``` String.fromCharCode(e.keyCode); 為了便利,我將keydown和keyup事件封裝成這樣: ``` window.tool.captureKeyDown = function(params) { function keyEvent(event) { params[event.keyCode](); }; window.addEventListener('keydown', keyEvent, false); }; window.tool.captureKeyUp = function(params) { function keyEvent(event) { params[event.keyCode](); }; window.addEventListener('keyup', keyEvent, false); }; ``` 需要時只需如下調用: ``` function keyLeft(){ keybox.innerHTML = '你點擊了向左箭頭(←)'; }; function keyRight(){ keybox.innerHTML = '你點擊了向右箭頭(→)'; }; window.tool.captureKeyEvent({"37":keyLeft,"39":keyRight}); ``` 傳入一個鍵值對形式的對象,鍵名是鍵碼,鍵值是調用函數。 實例(先點擊下面,讓其獲取到焦點): canvas-demo/keyboard.html 在后面會有個附錄,有完整的鍵碼值對應表。不過,我們不需要去死記硬背,你可以使用到再去查或者使用插件 keycode.js(可到這里下載:https://github.com/lamberta/html5-animation): ``` <script src="keycode.js"></script> <script> function keyEvent(event){ switch (event.keyCode){ case keycode.UP: keybox.innerHTML = '你點擊了向上箭頭(↑)'; break; }; }; window.addEventListener('keydown',keyEvent,false); </script> ``` 其實keycode.js里定義了一個全局變量keycode,然后以鍵值對的形式定義鍵名和鍵名值。 **總結** 用戶交互在游戲動畫中是很重要的一步,所以掌握用戶交互的各種事件是必須的,而且特別強調一點是,要學會制造輪子,避免重復的編寫相同的代碼,不過,初學者建議多敲 。 附錄: ![](https://box.kancloud.cn/4f4141060d2bc8c44739c7f01af1d650_800x1011.jpg)
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看