移动端的touch事件(四)

前面对touch的一些基本信息都有了一些了解,现在就来看看touch来完成的一些小的东西吧,这个示例,其实就是来自MDN中给的示例(懒了一把)。

代码集合

该示例是利用canvas画布,来展示触摸点的运动轨迹。原文查看:MDN Touch events

1:首先,我们先创建一个画布


<div>
    <canvas id="canvas" width="300" height="300" style="border:solid black 1px;">
	Your browser does not support canvas element.
    </canvas>
</div>
<div>
    <button onclick="startup()">Initialize</button>
</div>


上面的就是代码的结构了,一个宽高都是300canvas画布,和一个用于初始化的按钮。

首先,我们先看下按钮进行初始化时,需要做的工作。


function startup() {
    var el = document.getElementById("canvas");

    el.addEventListener("touchstart", handleStart, false);
    el.addEventListener("touchend", handleEnd, false);
    el.addEventListener("touchcancel", handleCancel, false);
    //el.addEventListener("touchleave", handleEnd, false);
    el.addEventListener("touchmove", handleMove, false);
}


很简单,就是对画布部分进行绑定各种touch事件,包括:touchstarttouchendtouchcanceltouchmove等,为什么这里我把touchleave给注释掉了?如果您有看过前面的接触介绍,应该会记得,touchleavetouchenter是两个被废弃的事件类型,是没有意义的,所以这里给注释掉了。

关于touchleavetouchenter被废弃,可以查看:移动端的touch事件(二)中“对前一章节的补充”部分,或者 W3C List of TouchEvent typesMDN touchenterMDN touchleave

在初始化函数中,又有几个回调函数,是我们必须要完成的,一个一个的看,但是,首先我们先要看看的是,一些公用的基本处理函数:


var ongoingTouches = new Array();
//定义的一个全局数组,用来保存触摸点的移动轨迹。

function copyTouch(touch) {
    //把对应的touch值,保存下来
    //返回的新的对象,用于保存到ongoingTouches数组中
    //后面就把这个新对象,称之为对应的touch对象的映象
    return { identifier: touch.identifier, pageX: touch.pageX, pageY: touch.pageY };
}

function colorForTouch(touch) {
    //对每一个touch对象,根据identifier值生成一个随机的颜色
    var r = touch.identifier % 16;
    var g = Math.floor(touch.identifier / 3) % 16;
    var b = Math.floor(touch.identifier / 7) % 16;
	
    r = r.toString(16); // make it a hex digit
    g = g.toString(16); // make it a hex digit
    b = b.toString(16); // make it a hex digit
    var color = "#" + r + g + b;
	
    return color;
}

function ongoingTouchIndexById(idToFind) {
    //查看idToFind是否存在于ongoingTouches数组中
    //对应copyTouch函数中,生成的identifier的属性值进行判断比较
    //也就是,查看在该touch对象在ongoingTouches数组中
    //是否有一个自己的映象存在
	
    for (var i=0; i < ongoingTouches.length; i++) {
	var id = ongoingTouches[i].identifier;
    
	if (id == idToFind) {
	    return i;
	}
    }
	
    //如果需要查找的touch对象,存在于ongoingTouches数组中
    //则返回其所在的位置
    //如果没有,则返回-1

    return -1;    // not found
}


OK,上面的说完了,那么接下来,再看看各个事件的回调函数的相关处理吧,首先是touchstart的回调函数handleStart


function handleStart(evt) {
    //touchstart事件的回调函数
	
    //阻止默认动作,也就是,touch事件不再会滚动页面
    evt.preventDefault();
	
    //获取对应的canvas对象
    var el = document.getElementById("canvas");
	
    //canvas对象的上下文
    var ctx = el.getContext("2d");
	
    //这里就是获取触点的信息
    //上一篇文章中,也有说到touches,targetTouches,changedTouches
    //这三者的区别,当我们要获取一些触点的信息时,
    //changedTouches是最佳的属性获取
    var touches = evt.changedTouches;
        
    for (var i=0; i < touches.length; i++) {
	
	//copyTouch函数把touches[i]对象中的信息取出,返回一个新的对象
	//并把新返回的对象保存到ongoingTouches数组中
	ongoingTouches.push(copyTouch(touches[i]));
		
	//通过colorForTouch函数,使用touches[i]生成一个颜色值
	var color = colorForTouch(touches[i]);
		
	//开始画图
	ctx.beginPath();
		
	//arc画圆
	//中心为touches[i].pageX, touches[i].pageY
	//半径为4,
	//起始角度为0,2*Math.PI
	//画圆方向false,表示顺时针画圆
	ctx.arc(touches[i].pageX, touches[i].pageY, 4, 0,2*Math.PI, false);  // a circle at the start
		
	//设置ctx的fillStyle的值,也就是之后画圆时的颜色
	ctx.fillStyle = color;
		
	//执行画圆操作。
	ctx.fill();
    }
}


OK,继续看handleMove,在接下来的代码中,对于与handleStart函数中执行的相同功能的代码,则不会再添加注释。


function handleMove(evt) {
	
    evt.preventDefault();
	
    var el = document.getElementById("canvas");
    var ctx = el.getContext("2d");
    var touches = evt.changedTouches;

    for (var i=0; i < touches.length; i++) {
	var color = colorForTouch(touches[i]);
		
	//使用ongoingTouchIndexById函数,根据touches[i].identifier属性
	//查看该touch事件是否在ongoingTouches数组中有一个自己的映象
	//如果有,才会进行下面的操作
	var idx = ongoingTouchIndexById(touches[i].identifier);
	//其实,touchmove事件一般都是跟随在touchstart事件之后出现的
	//所以,按正常情况,这个地方使不需要进行判断的
	//maybe是为了以防万一吧
		
	if(idx >= 0) {
	    //如果当前的touch对象存在于ongoingTouches数组中
	    //则进行画图
	    ctx.beginPath();
			
	    //把起始点,移动到ongoingTouches数组中touch对象对应的映象中
	    //保存的pageX,pageY的位置,从上次结束的位置,
	    //开始画直线。
	    ctx.moveTo(ongoingTouches[idx].pageX, ongoingTouches[idx].pageY);
			
	    //以上一个点为基点,以touches[i].pageX, touches[i].pageY点为终点,画直线。
	    ctx.lineTo(touches[i].pageX, touches[i].pageY);
			
	    //设置线宽
	    ctx.lineWidth = 4;
			
	    //设置显得颜色
	    ctx.strokeStyle = color;
			
	    //画线
	    ctx.stroke();

	    //因为此时的touch对象的新的都有了变化
	    //所以,更新ongoingTouches数组中对应映象的信息
	    //splice方法,从第idx位置,删除1个元素,
	    //然后插入一个新的copyTouch(touches[i])对象
	    ongoingTouches.splice(idx, 1, copyTouch(touches[i])); 
            // swap in the new touch record
	} else {
	}
    }
}


OK,接下来是handleEnd方法


function handleEnd(evt) {
    evt.preventDefault();
	
    var el = document.getElementById("canvas");
    var ctx = el.getContext("2d");
    var touches = evt.changedTouches;

    for (var i=0; i < touches.length; i++) {
	var color = colorForTouch(touches[i]);
	var idx = ongoingTouchIndexById(touches[i].identifier);

	if(idx >= 0) {
	    ctx.lineWidth = 4;
	    ctx.fillStyle = color;
	    ctx.beginPath();
	    ctx.moveTo(ongoingTouches[idx].pageX, ongoingTouches[idx].pageY);
	    ctx.lineTo(touches[i].pageX, touches[i].pageY);
			
	    //touchend时,是以一个一个正方形结束的,
	    //fillRect为画长方形的方法
	    //起始点为touches[i].pageX-4, touches[i].pageY-4
	    //长宽都是8
	    ctx.fillRect(touches[i].pageX-4, touches[i].pageY-4, 8, 8); 
            // and a square at the end
			
	    //touchend时,把在ongoingTouches保存的touch对象的映象同时删掉
	    ongoingTouches.splice(idx, 1);  // remove it; we're done
	} else {
	}
    }
}


touchcancel时的回调函数handleCancel方法:


function handleCancel(evt) {
    evt.preventDefault();
	
    var touches = evt.changedTouches;
  
    for (var i=0; i < touches.length; i++) {
	ongoingTouches.splice(i, 1);  // remove it; we're done
    }
}


OK,这样的话,这个简单的小示例,也就算是结束了,您可以扫描下面的二维码查看对应的页面,小玩一下,也可以直接点击下面的链接,然后查看源文件:

静态页网址二维码:
源代码查看网址:http://www.zhangyunling.com/study/2014/20140921/touch-canvas.html

上述的代码,看起来有些杂乱,并且都使用的全局变量,所以对代码进行了一些改写,确切的说,进行了一下封装,使代码更具独立性,减少全局变量的个数,并且调用的方法也会变得更简单,比如:如果当前页面有多个canvas区域需要处理的话,只需要执行以下代码即可:


zyl.init("canvas");
zyl.init("canvas2");


更改后的页面,有兴趣请按下面的方式进行查看:

静态页网址二维码:
源代码查看网址:http://www.zhangyunling.com/study/2014/20140921/touch-canvas-1.html

总结

这个。。。

本文地址:http://www.zhangyunling.com/?p=240

发表评论

电子邮件地址不会被公开。 必填项已用*标注

您可以使用这些HTML标签和属性: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>