《每週一點canvas動畫》——用戶交互

用戶交互也許是咱們學習canvas動畫中首先須要掌握的部分。畢竟,若是沒有交互或者向動畫中作一些動態的輸入,那麼這跟看電影有什麼區別呢?用戶交互基於事件,通常來講包括:鼠標事件觸摸事件鍵盤事件canvas

一、事件和事件執行

在理解事件以前,你須要明白什麼是listenerhandler
listener(即監聽器)決定當一個事件發生時是否作出反應。handler(即執行者)是一個函數,當事件發生時被調用。好了,扯了這麼多直接上代碼:瀏覽器

element.addEventListener(type, handler[, useCapture]);

    type: 事件類型
    handler: 事件執行函數
    useCapture: 可選,爲布爾值false/true, 表示在冒泡/捕獲階段執行

經過方法addEventListener來爲某一元素添加事件,具體到咱們的canvas上是什麼樣的呢?加入咱們如今想要在canvas上綁定一個mousedown事件,具體代碼以下:函數

canvas.addEventListener('mousedown', function(event){
        console.log("Mouse pressed on element");
    }, false)

這樣咱們就爲canvas綁定了鼠標點擊事件,當在canvas上按下鼠標是就會在控制檯看到打印出 "Mouse pressed on element"。工具

那麼既然有添加事件(addEventListener),就有移除事件(removeEventListener),使用方式與添加事件幾乎徹底同樣:學習

element.removeEventListener(type, handler[, useCapture]);
    type: 事件類型
    handler: 事件執行函數
    useCapture: 可選,爲布爾值false/true, 表示在冒泡/捕獲階段執行

惟一須要注意的是handler,即移除事件的函數,這裏只能寫函數名,而不能像添加事件同樣將整個功能函數所有寫入。也就是說,在添加某個事件的時候,咱們能夠將須要執行的函數寫在事件監聽以外並命名,這樣若是你想要在後續的代碼中移除該事件,直接將函數名傳入移除事件的handler中便可。動畫

如今讓咱們來實驗下先爲canvas添加一個事件,再將其移除code

<body>
  <canvas id="canvas" width="500" height="500"></canvas>
  <script></script>
   <script>
       window.onload = function(){
           var canvas = document.getElementById('canvas');
           
           //定義的執行函數add
           function add(event){
               console.log("mouse down");
           }
           canvas.addEventListener('mousedown', add, false);
           
           //移除事件mousedown
           canvas.removeEventListener('mousedown', add, false)
       }
   </script>
</body>

如今你能夠看看控制檯是否還能打印出「mouse down」!對象

2.鼠標事件

鼠標事件一共能夠分爲:seo

  • mousedown事件

  • mouseup

  • click

  • dbclick

  • mousewheel

  • mouseover

  • mouseout

每個鼠標事件都包含兩個屬性來決定當前鼠標的位置:pageXpageY。經過pageXpageY,還有canvas元素的偏移位置,咱們就可以計算出鼠標具體是在canvas元素的什麼位置。爲了考慮不一樣瀏覽器的兼容性,以防萬一你可使用clientXclientY。在這裏,咱們建立一個js文件,名爲**utils.js**,這個文件是咱們的一個工具函數,裏面會逐漸加入一些咱們重複使用的方法,那麼如今咱們向咱們的工具函數中添加第一個方法captureMouse,具體代碼以下:

utils.js文件

    //將utils定義爲window對象下的一個屬性,屬性值爲對象
    window.utils = {};

    //在utils對象上定義捕獲座標的方法
    window.utils.captureMouse = function(element){
            //定義一個名爲mouse的對象
            var mouse = {x:0,y:0};
            
            //爲元素綁定mousemove事件
            element.addEventListener('mousemove',function(event){
                var x,y;
                
                //獲取鼠標位於當前屏幕的位置, 並做兼容處理
                if(event.pageX||event.pageY){
                    x = event.pageX;
                    y = event.pageY;
                }else{
                    x = event.clientX + document.body.scrollLeft +document.documentElement.scrollLeft;
                    y = event.clientY + document.body.scrollTop +document.documentElement.scrollTop;
                }
                //將當前的座標值減去元素的偏移位置,即爲鼠標位於當前canvas的位置
                x -= element.offsetLeft;
                y -= element.offsetTop;

                mouse.x = x;
                mouse.y = y;
            },false);
             //返回值爲mouse對象
             return mouse;
        }

這個方法將DOM元素做爲參數傳入,這樣咱們只要將canvas傳入就能夠獲取到鼠標在當前canvas的位置。具體代碼以下:

<canvas id="canvas" width='500' height="500" style="background:#000">
           <p>you browser not support canvas!<p>
       </canvas>
       <script src='../js/utils.js'></script>
       <script>
           window.onload = function(){
              var canvas = document.getElementById('canvas'),
                  //將canvas傳入,該方法會返回一個包含屬性x和y的對象
                  mouse = utils.captureMouse(canvas);

              //爲canvas綁定mousedown事件,當鼠標按下的時候打印出當前鼠標相對於canvas的座標值
              canvas.addEventListener('mousedown',function(event){
                console.log("x:" +mouse.x +",y:" + mouse.y);
              });
       </script>

Have a try!!!看看可否成功。

getBoundingClientRect()

其實,關於canvas的鼠標位置獲取的方法還能夠應用它自身的一個方法getBoundingClientRect,這裏作一個介紹,你可使用,但本系列文章主要使用上面這種更具普遍性的方法。具體代碼能夠參考以下:

canvas.addEventListener('mousedown',function(event){
                       //event兼容處理
                       var event = event || window.event;
                       //兼容處理,獲取當前鼠標相對屏幕的座標
                       var winX = event.clientX+document.body.scrollLeft +document.documentElement.scrollLeft || event.pageX;
                       var winY = event.clientY+document.body.scrollTop +document.documentElement.scrollTop || event.pageY;
                       
                       //定義一個對象
                       var can = {x:0, y:0};
                       //調用getBoundingClientRect方法,該方法返回一個對象,包含canvas的left、 top、 width、 height等值
                       
                       var canBox = canvas.getBoundingClientRect();
                       
                   //(winX - canBox.left):與上面的含義同樣,是減去canvas的偏移量
                   //(canvas.width/canBox.width):通常來講canvas.width和canBox.width是同樣的,也就是說這兩個的比值爲1.但不排除你會爲canvas設置邊框,這是實際的座標位置就會有所變化,好比canvas.width = 500, 你可能設置了一個1px的邊框,那麼canBox.width = 502, 因此比值就不爲1了。這樣作只是讓數據更精確。
                   
                       can.x = (winX - canBox.left)*(canvas.width/canBox.width);
                       can.y = (winY - canBox.top)*(canvas.height/canBox.height);
                       
                       //輸出
                       console.log(can.x,can.y);
                   },false);

三、鍵盤事件

鍵盤事件就兩個:

  • keydown

  • keyup

咱們一樣能夠向綁定鼠標事件那樣爲canvas綁定鍵盤事件。好吧!如今咱們來看看,如何將一個鍵盤事件綁定到window(爲何不直接綁定到canvas上呢?想一想)上:

<body >
    <p>任意按下按鍵</p>
   <script>
       window.onload = function(){
       
              //定義鍵盤事件
           function onKeyboard(event){
              switch (event.keyCode){
                  case 38:
                      console.log('up!');
                      break;
                  case 40:
                      console.log('down!');
                      break;
                  case 37:
                      console.log('left!');
                      break;
                  case 39:
                      console.log('right!');
                      break;
                  default:
                      console.log(event.keyCode);
           }
        }
        //爲window對象綁定鍵盤事件
        window.addEventListener('keydown',onKeyboard,false);
       }
    </script>
</body>

試一試,當按下鼠標的方向鍵是是否在控制檯打印出了相應的信息!

四、觸摸事件

觸摸事件包括如下3種:

  • touchstart

  • touchend

  • touchmove

觸摸實踐中,手指就充當了鼠標的做用。一樣咱們最爲關心的是當前觸摸的位置。和captureMouse方法同樣,這裏在咱們的工具函數文件中,須要添加一新的方法來捕獲觸摸的位置,名爲captureTouch,如今在utils.js文件中添加以下方法:

utils.js文件

    window.utils.captureTouch = function (element) {
      var touch = {
                      x: null,
                    y: null,
                    isPressed: false,
                    event: null
                    };
      var body_scrollLeft = document.body.scrollLeft,
          element_scrollLeft = document.documentElement.scrollLeft,
          body_scrollTop = document.body.scrollTop,
          element_scrollTop = document.documentElement.scrollTop,
          offsetLeft = element.offsetLeft,
          offsetTop = element.offsetTop;
          
     // 綁定touchstart事件
      element.addEventListener('touchstart', function (event) {
        touch.isPressed = true;
        touch.event = event;
      }, false);
      
     // 綁定touchend事件
      element.addEventListener('touchend', function (event) {
        touch.isPressed = false;
        touch.x = null;
        touch.y = null;
        touch.event = event;
      }, false);
      
     //綁定touchmove事件
      element.addEventListener('touchmove', function (event) {
        var x, y,
            touch_event = event.touches[0]; //第一次touch

        if (touch_event.pageX || touch_event.pageY) {
          x = touch_event.pageX;
          y = touch_event.pageY;
        } else {
          x = touch_event.clientX + body_scrollLeft + element_scrollLeft;
          y = touch_event.clientY + body_scrollTop + element_scrollTop;
        }
        //剪去偏移量
        x -= offsetLeft;
        y -= offsetTop;

        touch.x = x;
        touch.y = y;
        touch.event = event;
      }, false);
      //返回touch對象
      return touch;
    };

總結

這一節主要介紹用戶與canvas交互的各類事件,重要的是你應該在你本身的工具函數文件中包含了如下兩個方法:utils.captureTouchutils.captureMouse這兩個方法都是爲了獲取當前相對於canvas元素的位置。咱們將在後面的章節中頻繁使用。固然,除了這兩個方法,因爲咱們使用的requestAnimationFrame方法一樣也涉及到兼容性的問題,咱們將它一同添加到utils.js中,具體代碼請查看utils.js文件。下一節,三角函數座標旋轉敬請期待!!!

相關文章
相關標籤/搜索