之前那篇Canvas画图-鼠标涂鸦已经可以实现与Canvas的简单交互,这篇会介绍Canvas中实现交互性的一个重要方法isPointInPath。
基本原理Cavnas的确能实现很多很酷炫狂拽\L炸天的效果,但是交互性要差很多,简单的鼠标单击选中某个图形,都要花费一番周折。
Canvas只是一个dom节点,所有监听的事件都只能绑定在这个节点上,但是我们可能需要对Canvas上的某个元素进行操作。基本的原理就是事件还是绑定在Canvas上,通过判断点击发生的位置是否在Canvas中某个图形的路径内 (这里注意,我没有说是某个图形的区域内) ,从而进一步确定是在哪个图形上戳来戳去。
isPointInPath为了让我们判断点击点到底是否在路径内,Canvas提供了 context.isPointInPath(x,y) 方法,参数自然是某个点的横竖坐标。
来个例子,先随便画三个矩形:
var rectList = [ [50,50,50,50], [120,120,80,60], [30,150,60,80] ]; var drawRect = function(x,y,w,h){ ctx.beginPath(); ctx.rect(x,y,w,h); } // init ctx.clearRect(0, 0,canvas.width(), canvas.height()); $.each(rectList, function(n,v){ drawRect(rectList[n][0],rectList[n][1],rectList[n][2],rectList[n][3]); ctx.stroke(); });另外再写个 getCanvasPoint 方法,主要把点击坐标换算成Canvas里面的坐标:
var getCanvasPoint = function(x,y) { var canvasOffset = canvas.offset(); return { x: x - canvasOffset.left, y: y - canvasOffset.top } }是时候该 isPointInPath 方法登场,实现点中某个矩形的时候改变矩形边框的颜色
canvas.on("mousedown", function(e){ moving = true; var point = getCanvasPoint(e.pageX, e.pageY); $.each(rectList, function(n, v) { drawRect(rectList[n][0],rectList[n][1],rectList[n][2],rectList[n][3]); if(ctx.isPointInPath(point.x, point.y)){ moveItem = n; startPos.x = point.x; startPos.y = point.y; ctx.strokeStyle = "#ff4444"; } else { ctx.strokeStyle = "#000"; } ctx.stroke(); }) });这里我们从预定义的 rectList 中依次拿出每个长方形参数,分表是左上角的x坐标,y坐标,长,宽。然后先画出长方形的路径,画完一个用 isPointInPath 方法判断一下点击点是否在当前路径中,如果在,就给当前的改颜色,如果不在就画出来然后继续画下一个长方形继续判断路径。
是不是很麻烦, isPointInPath 只对当前路径有效,也就说我们不能把三个长方形都画完了再判断某个点是否在第一个长方形路径中,而必须是每次画完一个长方形就要判断一次,而且Canvas中路径是不能保存的,要改变某一条路径,就必须把整个Canvas重新画一遍。
所以这里我们在循环中不单单是绘制了点中的长方形,还要绘制没点的长方形。
拖动元素基本原理就是上面那样,看到这里,你已经洞悉了Canvas实现点击等事件的小秘密。那我们就继续实现拖动其中的元素吧。
canvas.on("mousemove", function(e){ if( !moving && moveItem == null ) { return; } ctx.clearRect(0, 0,canvas.width(), canvas.height()); var point = getCanvasPoint(e.pageX, e.pageY); $.each(rectList, function(n, v) { var moveX = 0, moveY = 0; if(n !== moveItem ){ ctx.strokeStyle = "#000"; } else { moveX = point.x - startPos.x; moveY = point.y - startPos.y; ctx.strokeStyle = "#ff4444"; } drawRect(rectList[n][0] + moveX,rectList[n][1] + moveY,rectList[n][2],rectList[n][3]); ctx.stroke(); }) });依然是熟悉的味道,依然是熟悉的配方。我们还是依赖 mousemove 方法,移动端请用 touchmove 方法。
因为之前在点击的时候我们已经把是哪个长方形被选中给保存在变量 moveItem 中了,所以这里就直接判断就好了。是要拖动的元素就把长方形的x,y对应拖动的距离进行更新。同样是要把整个Canvas都绘制一遍。
另外在 mouseup 事件中保存下状态,方便下次绘画:
canvas.on("mouseup", function(e){ moving = false; $.each(rectList, function(n){ if (n == moveItem){ var point = getCanvasPoint(e.pageX, e.pageY); rectList[n][0] += point.x - startPos.x; rectList[n][1] += point.y - startPos.y; } }); startPos = {} moveItem = null });记住:在Canvas中不管你搞什么幺蛾子,都要按照之前的规则把所有路径绘制一遍。
上个效果图:
完整代码:
https://github.com/bob-chen/canvas-demo/blob/master/basic/movebymouse.html
参考
本文前端(javascript)相关术语:javascript是什么意思 javascript下载 javascript权威指南 javascript基础教程 javascript 正则表达式 javascript设计模式 javascript高级程序设计 精通javascript javascript教程
主题: 矩形、变量、
分页:12
转载请注明
本文标题:Canvas画图-鼠标移动图形
本站链接:
分享请点击:
1.凡CodeSecTeam转载的文章,均出自其它媒体或其他官网介绍,目的在于传递更多的信息,并不代表本站赞同其观点和其真实性负责;
2.转载的文章仅代表原创作者观点,与本站无关。其原创性以及文中陈述文字和内容未经本站证实,本站对该文以及其中全部或者部分内容、文字的真实性、完整性、及时性,不作出任何保证或承若;
3.如本站转载稿涉及版权等问题,请作者及时联系本站,我们会及时处理。
登录后可拥有收藏文章、关注作者等权限...
注册 登录