《每周一点canvas动画》——用户交互

用户交互也许是我们学习canvas动画中首先需要掌握的部分。毕竟,如果没有交互或者向动画中做一些动态的输入,那么这跟看电影有什么区别呢?用户交互基于事件,一般来说包括:鼠标事件触摸事件键盘事件

1、事件和事件执行

在理解事件之前,你需要明白什么是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添加一个事件,再将其移除

<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.鼠标事件

鼠标事件一共可以分为:

  • 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);

3、键盘事件

键盘事件就两个:

  • 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>

试一试,当按下鼠标的方向键是是否在控制台打印出了相应的信息!

4、触摸事件

触摸事件包括以下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文件。
下一节,三角函数坐标旋转敬请期待!!!

原文地址:https://www.cnblogs.com/baimeishaoxia/p/12642012.html

时间: 2024-10-21 14:40:19

《每周一点canvas动画》——用户交互的相关文章

python变量及用户交互,用户名格式化输出

变量 name = wwjun Name2 = "wwjun" print ("name,Name2") 用户交互 Username = input ("username:") Password = input ("password:") Print(username,password) 用户名格式化输出 name = input ("name:") age = input ("age:"

python-FIrst1--变量赋值-注释-用户交互-条件判断与缩进

变量与赋值 name='mike'          #这里一定要注意,如果右边的值不是数字,就一定要加引号,否则系统会认为右边也是一个变量,而右边我们希望是一个值,所以这时候我们就需要给右边加上单引号或者双引号,以表示右边是一个字符串. age=39 把右边的值赋予左边,就是赋值,左边的name和age就叫做变量. 注释 可以用#符号来表示,也可以用一对三个连续的单引号和双引号来表示多行注释,当要注释的内容不多的时候用#比较方便,当要注释很多行内容尤其是超过三行的时候最好用,一对 三个单引号或

python-变量、用户交互、循环

如何在pycharm上创建一个工程 打开pycharm,在菜单栏点击file选项,选着New project,跳出一个New project的框,在左边一栏选择pure python,会在右边出现两行,第一行是选择工程创建的地址及工程的名字,第二行是选着使用的python的版本,选着好之后,点击右下角的creat.至此,工程就创建好了.然后在窗口右边的创建的工程名字点击鼠标右键,选择New,再选着Directory,一个目录就创建好了.将鼠标定位到刚创建的目录名出点击鼠标右键选择New,再选择p

控件不接收用户交互的情况以及事件响应顺序

开发中经常会遇到控件不接收用户交互了,可以从以下几个方面检查: 1. enable = NO 就不可以被点击 ->也会让按钮显示禁用状态 2. 设置了控件的 userInterActionEnabel = NO 3. hidden属性为YES 4. 控件的alpha < = 0.01 5. 如果一个父控件与用户的交互设置为NO ,那么它子控件将获取不到交互事件 6.如果子视图超出父视图范围,超出范围的部分也不能接收用户交互 7. 触发事件的过程 1). 交互事件,是先由父控件获取到,然后父控件

Kinect 开发 &mdash;&mdash; 用户交互设计的若干思考

Metro 风格 windows 8 Kinect Hub 手势原型设计 悬停选择     翻页控制 关节点重叠的处理方法 将箭靶设置在画面的边缘,这样玩家持弓的角度与屏幕保持一个大约45度的锐角,这样Kinect可以很精确的检测到拉弓射箭的动作 手势天生具有一定随意性,而且具有一定的文化背景差异性   手与设备的非接触性 虚拟触摸的界面 Kinect 使交互"柔软化"   确认操作保持简单一致 悬停选择 -- 将手停在想要选择的项目方块或按钮上,等待进度圆圈的填充,这个过程会在T时间

简明Python教程笔记(二)----用户交互raw_input()

raw_input() python内建函数 将所有输入看做字符串,返回字符串类型 input()对待纯数字输入时具有自己的特性,它返回所输入的数字的类型( int, float ) input() 本质上还是使用 raw_input() 来实现的,只是调用完 raw_input() 之后再调用 eval() 函数 例子: #!/usr/bin/env pythonthis_year = 2014name = raw_input('please input your name:')age1 =

赋值/用户交互/条件判断缩进

---恢复内容开始--- 变量起名 变量名只能是字母.数字.下划线的任意组合. 变量名的第一个字符不能是数字. 关键字不能声明为变量. 变量名不能有空格.特殊字符. 用户交互 name = input("please input your name:")   #3.0版本input输出为字符串格式. 2.0版本                         3.0版本 input             =           evel(input) raw_input      

菜鸟学Python Day1.4(导入模块Import、用户交互Raw_input)

导入模块      1.什么是模块? 2.导入模块 Import moduleName   (自带200多个模块,第三方模块上千) Python标准库 如下:导入模块os.system内的的df,查看内存 查看模块os可以导入很多方法os. tab健: 如何加tab健: /usr/lib/python2.7/dist-packages/tab.py   默认第三方库存放位置 Python寻找路径规则: 如果查询不到就会报错, 如何让某一个模块在python任何一个地方都可以导入: ①在sys.p

C# 通过服务启动窗体(把窗体添加到服务里)实现用户交互的windows服务[转发]

由于个人需要,想找一个键盘记录的程序,从网上下载了很多,多数都是需要注册的,另外也多被杀软查杀.于是决定自己写一个,如果作为一个windows应用程序,可以实现抓取键盘的记录.想要实现随系统启动的话,其中一种方法就是要作为windows服务,把代码直接写到服务里边并不能抓取到键盘的记录,从网上翻阅资料及查看msdn才知道: Windows 服务应用程序在不同于登录用户的交互区域的窗口区域中运行.窗口区域是包含剪贴板.一组全局原子和一组桌面对象的安全对象.由于 Windows 服务的区域不是交互区

Android SDK上手指南 3:用户交互

在这篇教程中,我们将对之前所添加的Button元素进行设置以实现对用户点击的检测与响应.为了达成这一目标,我们需要在应用程序的主Activity类中略微涉及Java编程内容.如果大家在Java开发方面的经验不太丰富也没必要担心,只要按步骤进行即可完成学习.我们将在本系列的下一篇文章中深入探讨Java语法,从而保证大家了解初步Android开发任务中所必需的编程语言知识. 大家可以在Android当中以多种不同方式实现用户交互.我们将学习两种最为典型的处理方案,从而实现应用按钮对用户点击的感应--