Canvas的独特机制
说HTML5 Canvas之前,咱得知道这个跟平时操作DOM的方式可不同。比如那个SVG画图,直接用DOM节点输入网页,然后就能按DOM方法玩转。但Canvas,画在一张大屏幕(canvas)上,没法直接取出或给它加JavaScript事件。为啥?因为Canvas是个整体,画上去的图形只是Canvas的一部分,不能单独出来用。
Canvas上的涂鸦不能被轻易看到,JavaScript也没法直接知道我们画了什么。就是当你想看看Canvas标签内部情况时,空荡荡的什么也没有。那怎么办?想要给这些图案加点动作效果还需要特殊的编码才能实现。
cvs = document.getElementById('mycanvas'); ctx = canvas.getContext('2d'); theRect = ctx.rect(10, 10, 100, 100); ctx.stroke(); console.log(theRect); //undefined
给Canvas元素绑定事件
给画布加上点儿功能,必须得给它找点活儿干。比如说,想让图像一点就能动,那就要用画布这个神奇道具,给它安个监听器,这样以后图像覆盖到了啥地方,我们就能知道!
直接看看鼠标点哪儿,如果刚好落在特定图形区,那么就能自动触发那个图形的点击事件了。这种方法好用是好用,但有个小缺点哦——如果图形很多都堆在一起,速度就会受影响。
isPointInPath方法的局限性
在Canvas里用isPointInPath功能能知道你点击的地方是不是在已经画出的线上哈。不过,它只能查出我们当前看到的那根线,想查下以前画过的就不行!要是好几个图形叠起来的话,就是要按照最后画的那根线来判断。
cvs = document.getElementById('mycanvas'); cvs.addEventListener('click', function(e){ //... }, false);
要处理这个问题,咱们就把所有的图画全重画一次,再用 isPointInPath 瞧一眼点击位置到底在哪张图里面喽。时间上可能会花多点儿,但找准点击位置肯定没问题。
function getEventPosition(ev){ var x, y; if (ev.layerX || ev.layerX == 0) { x = ev.layerX; y = ev.layerY; } else if (ev.offsetX || ev.offsetX == 0) { // Opera x = ev.offsetX; y = ev.offsetY; } return {x: x, y: y}; }
循环重绘与事件代理
找毛病环节来了!画板事件处理得想想怎么让小刷子重复刷和智能代理帮忙。具体操作是这样滴,比如你按了左键就要重新画,然后挨个瞧瞧每个图形会不会挡住我们需要点击的地方呗。
cvs = document.getElementById('mycanvas'); ctx = canvas.getContext('2d'); ctx.rect(10, 10, 100, 100); ctx.stroke(); ctx.isPointInPath(50, 50); //true ctx.isPointInPath(5, 5); //false
直接来说,只要检测下每个位置在不在当前要处理的那幅图内,就能搞清到底哪里被点击了,然后把对应位置的编号保存到一个数组中就行。接着再用这个数组合成新的图像信号传递到画布那边,搞定!
优化与改进
cvs.addEventListener('click', function(e){ p = getEventPosition(e); if(ctx.isPointInPath(p.x, p.y)){ //点击了矩形 } }, false);
不止要搞定基本的事件处理,咱们还得多琢磨如何提高程序速度(比如优化下)、保存好图形参数、应对那些突然出现的问题(比如冒泡)等事。至于实际操作,记住鼠标移动轨迹啦、知道它进还是出,这些都得时刻留心。
我们要先把各种各样的点击、悬停和离开等事情分类处理。像鼠标移到啦、拖出来呀以及移动等等稍微复杂点的事情,就要记得动作是怎样的,然后还得弄清楚哪些地方能用哪些不能用什么的。只有这样,我们才能够准确地应付跟图形有关的事情嘛!
cvs = document.getElementById('mycanvas'); ctx = canvas.getContext('2d'); ctx.beginPath(); ctx.rect(10, 10, 100, 100); ctx.stroke(); ctx.isPointInPath(20, 20); //true ctx.beginPath(); ctx.rect(110, 110, 100, 100); ctx.stroke(); ctx.isPointInPath(150, 150); //true ctx.isPointInPath(20, 20); //false
总结与展望
今天我给大家科普下HTML5 Canvas事件处理的知识,首先介绍一些Canvas的特性。其实就像绑定事件,还有那个isPointInPath方法神马的。不过要小心,有时候它会失灵。当然还有Canvas不断重绘和用代理处理事件这些小技巧。就算有那么一点局限性或速度慢,但只要你懂得处理,Canvas事件处理就能变得很强大!
咱们要用实际操作,让商城红火起来;然后,别忘了发挥缓存和性能优化这两个神奇工具的作用,利用Canvas事件处理来提高效果。这样,才能不折不扣地掌控HTML5 Canvas,为大家带来超赞的互动体验哦!
arr = [ {x:10, y:10, width:100, height:100}, {x:110, y:110, width:100, height:100} ]; cvs = document.getElementById('mycanvas'); ctx = canvas.getContext('2d'); draw(); function draw(){ ctx.clearRech(0, 0, cvs.width, cvs.height); arr.forEach(function(v){ ctx.beginPath(); ctx.rect(v.x, v.y, v.width, v.height); ctx.stroke(); }); }
。
评论0