web前端入门(四)-canvas图形拖拽事件

概述

  在 canvas 中绘制图形后,可以给 canvas 添加事件响应函数,并判断事件是否发生在canvas内部所绘制的图形中,从而给 canvas 中绘制图形添加事件处理。
  很多情况下有鼠标拖拽图形的需求,如果是单个图形、不重叠图形,鼠标拖拽功能还较易实现。但在 canvas 中有图形存在重叠的情况下,鼠标点击的图形以及绘制区域的清除等操作,都不容易实现。此文首先讲解基本的鼠标拖拽功能的实现,再进一步说明如何处理 canvas 图形重叠时的鼠标拖拽功能。

鼠标拖拽canvas中的图形

要实现鼠标拖拽 canvas 中的图形功能,整个逻辑为:

  1. canvas响应 mousedown 事件,判断鼠标点击点是否在canvas绘制的图形内,如不在则不处理;
  2. 用一个全局变量标记当前为拖拽状态,并记录被点击图形当前位置和鼠标当前位置。
var curMouseX;//记录当前鼠标X坐标
var curMouseY;//记录当前鼠标Y坐标
var curId;//当前被拖拽的图形所属的 canvas 的ID;
 if(ctx.isPointInPath(e.clientX-$(this).offset().left,e.clientY-$(this).offset().top))//需要计算鼠标在canvas中的位置
     {
             bDrag=true;
             curId=$(this).attr("id");
             return false;
      }
  1. document 监听 mousemove 事件,清除 canvas 中的图形,并在鼠标当前位置重新绘制。
 $(document).mousemove(function (e) {
        if(bDrag)
        {
            var $item=$("#"+curId);
            var item=document.getElementById(curId);
            var ctx=item.getContext('2d');
            ctx.clearRect(0,0,item.width,item.height);//清除 canvas 区域
            var posX=e.clientX-$item.offset().left; //获取鼠标在canvas中的X坐标
            var posY=e.clientY-$item.offset().top;//获取鼠标在canvas中的Y坐标
           	ctx.save();
		    ctx.translate(posX,posY);//posX,posY为需要绘制的图形的坐标,根据实际情况赋值
		    ctx.beginPath();
		    ctx.moveTo(0,0);
		    ctx.arc(0,0,r,s,e);//此处为绘制弧形,相关参数详细含义和查询手册
		    ctx.closePath();
		    ctx.restore();
            ctx.fillStyle=curColor;
            ctx.fill();
        }
    });

其中第1步已在上一篇中讲解,在此不赘述;由于很多控件能够响应 document 的事件,因此要第2步操作,标记当前为拖拽状态;并记录当前鼠标和图形位置,在鼠标点击后第一次拖拽时重绘图形不出现“闪动”的效果;第3步中,通过清除旧图形,跟随鼠标移动重绘新图形,实现鼠标拖拽图形的效果。

多个图形、重叠图形的拖拽

以上基于一个canvas里面的一个图形讲解了鼠标拖拽功能的实现,但如果有多个图形,则主要有两种实现方式:
1.所有图形都在1个canvas中绘制,并实现拖拽功能;
2.每个图形都有1个canvas,在各自的canvas内实现图形的操作。

web前端入门(四)-canvas图形拖拽事件_第1张图片1个canvas内绘制所有图形
web前端入门(四)-canvas图形拖拽事件_第2张图片每个图形都在单独canvas中绘制
对于第1种方法,在图形不移动,只需要判断鼠标是否在图形内时更方便。而当需要拖拽图形时则不易处理,因为拖拽是通过清除区域并重绘来实现的,当两个图形重叠时,即使只清除图形所在的最小区域,也会影响到其他图形。如下图所示,若要重绘矩形,即使清除红色区域,也会同时清除圆形的一部分。 web前端入门(四)-canvas图形拖拽事件_第3张图片图形重叠时清除区域 下面采用第2种方法,讲解图形重叠时的事件操作。 web前端入门(四)-canvas图形拖拽事件_第4张图片图形重叠 在此种情况下,图形重叠即是canvas重叠。本希望鼠标点击处的圆形响应事件,但由于是canvas响应事件,且2在3之上,因此圆形区域不会响应该点击事件。我们通过一下步骤来处理:
  1. 每个canvas都绑定鼠标点击事件;
  2. 在canvas的点击事件响应函数中,遍历全部canvas,计算鼠标坐标,先判断鼠标是否在canvas内,再判断鼠标是否在所绘制的图形内;
$("#id").mousedown(function (e) {		//每个canvas都绑定事件
        $(".canvas").each(function () {	//当有canvas被点击时,遍历全部的canvas
            var canvaLeft=$(this).offset().left;//计算鼠标在该canvas内的相对坐标
            var canvaTop=$(this).offset().top;//计算鼠标在该canvas内的相对坐标
            if((e.clientXcanvaLeft+$(this).width())//判断鼠标是否在该canvas内
                || (e.clientYcanvaTop+$(this).height()))
                {
                    return; //鼠标点击点不在当前canvas内,则跳出,判断下一个canvas
                    		//return相当于continue的功能
                }

                var ctx=this.getContext('2d');
                
             /*
             处理代码
			*/
				//判断鼠标是否在绘制的图形内
                if(ctx.isPointInPath(e.clientX-$(this).offset().left,e.clientY-$(this).offset().top))
                {
                     /*
             			处理代码
					*/
                    return false;//鼠标点击点在当前canvas内,且在所绘制的图形上,执行完毕后停止循环
                    			//return false 相当于 break
                }
            }
        });

你可能感兴趣的:(web前端开发)