一、实现的功能

1、基于oop思想构建,支持坐标点、线条(由坐标点组成,包含方向)、多边形(由多个坐标点组成)、圆形(包含圆心坐标点和半径)等实体

2、原生JavaScript实现,不依赖任何第三方js库和插件

3、多图形绘制(支持画笔、线条、箭头、三角形、矩形、平行四边形、梯形以及多边形和圆形绘制)

4、拖拽式绘制(鼠标移动过程中不断进行canvas重绘)

5、图片绘制(作为背景图片时重绘会发生闪烁现象,暂时有点问题,后面继续完善)

5、清空绘制功能

6、新版本优化绘制性能(使用共享坐标变量数组,减少了大量的对象创建操作)

7、新版本支持箭头绘制功能

二、完整实现代码

DrawingTools =(function(){
//公共方法
      var getDom=function(id){return document.getElementById(id)};
      var isNull=function(s){return s==undefined||typeof(s)=='undefined'||s==null||s=='null'||s==''||s.length<1};
      var hideDefRM=function(){document.oncontextmenu=function(){return false}};//屏蔽浏览器默认鼠标事件
      /**绘图容器*/
      var cbtCanvas;
      /**绘图对象*/
      var cxt;
      /**绘制的图形列表*/
      var shapes=new Array();
      var graphkind={'cursor':0,'pen':1,'line':2,'trian':3,'rect':4,'poly':5,'circle':6,'arrow':21,'parallel':41,'trapezoid':42};
      //背景图片绘制配置
      var bgPictureConfig={
        pic:null,//背景图片地址或路径
        repaint:true,//是否作为永久背景图,每次清除时会进行重绘
      };
      //加载并绘制图片(src:图片路径或地址),默认重绘背景图
      var loadPicture=function(src){
        if(isNull(bgPictureConfig.repaint)||bgPictureConfig.repaint){bgPictureConfig.pic=src}
        var img = new Image();
        img.onload = function(){cxt.drawImage(img,0,0)}
        img.src =src;
      }
      //绘图基础配置
      var paintConfig={lineWidth:1,//线条宽度,默认1
        strokeStyle:'red',//画笔颜色,默认红色
        fillStyle:'red',//填充色
        lineJoin:"round",//线条交角样式,默认圆角
        lineCap:"round",//线条结束样式,默认圆角
      };
      //重新载入绘制样式
      var resetStyle=function(){
        cxt.strokeStyle=paintConfig.strokeStyle;
        cxt.lineWidth=paintConfig.lineWidth;
        cxt.lineJoin=paintConfig.lineJoin;
        cxt.lineCap=paintConfig.lineCap;
        cxt.fillStyle=paintConfig.fillStyle;
      }
      //鼠标图形
      var cursors=['crosshair','pointer'];
      /** 切换鼠标样式*/
      var switchCorser=function(b){
        cbtCanvas.style.cursor=((isNull(b)"选择:"+ctrlConfig.kind);
          //设置起始点
          switch(ctrlConfig.kind){
            case graphkind.pen://画笔(不松开鼠标按键一直画)
              beginDrawing();//开始绘制
              cxt.beginPath();
              cxt.moveTo(e.offsetX,e.offsetY);
              break;
            case graphkind.poly://多边形
              var p=new Point(e.offsetX,e.offsetY);
              if(isDrawing()){
                getCuGraph().add(p);//添加到
              }else{//第一次确定开始坐标
                beginDrawing();//开始绘制
                setStartPoint(p);
                var poly=new Poly();
                poly.add(p);
                setCuGraph(poly);//设置当前绘制图形
              }
              break;
            case graphkind.line://线条
            case graphkind.arrow://方向
            case graphkind.trian://三角形
            case graphkind.rect://矩形
            case graphkind.parallel://平行四边形
            case graphkind.trapezoid://梯形
              beginDrawing();//开始绘制
              var p=new Point(e.offsetX,e.offsetY);
              setStartPoint(p);
              var poly=new Poly();
              poly.add(p);
              setCuGraph(poly);//设置当前绘制图形
              break;
            case graphkind.circle://圆
              console.log("确定图形绘制开始坐标点:"+e.offsetX+","+e.offsetY);//点击确定图形的开始坐标点
              beginDrawing();//开始绘制
              var p=new Point(e.offsetX,e.offsetY);
              setStartPoint(p);
              var circle= new Circle({'start':p});
              setCuGraph(circle);
              break;
            case ctrlConfig.cursor: //手型鼠标
            default://默认是手型鼠标,不允许绘制
          }
        }else if(btnNum==2){
          console.log("右键由于结束多边形绘制");
          if(isDrawing()){
            if(ctrlConfig.kind==graphkind.poly){
              repaint();
              getCuGraph().draw();
              stopDrawing();//结束绘制
            }
          }
        }
        hideDefRM();//屏蔽浏览器默认事件
      }
      //鼠标移动(拖动,根据鼠标移动的位置不断重绘图形)
      var mouseMove = function(e){
        if(isDrawing()&&hasStartPoint()){//检查是否开始绘制,检查是否有开始坐标点
          //画笔不需要重绘
          if(ctrlConfig.kind>1){
            repaint();//重绘
          }
          var p=setCuPointXY(e.offsetX,e.offsetY,0);//设置共享的临时坐标点,用于防止重复创建对象
          switch(ctrlConfig.kind){
            case graphkind.pen://画笔(一直画)
              cxt.lineTo(e.offsetX,e.offsetY);
              cxt.stroke();
              break;
            case graphkind.poly://多边形
              var poly=getCuGraph(poly);
              var size=poly.getSize();
              poly.setPoint(p,(size-1));
              poly.draw();
              break;
            case graphkind.line://线条
              var line=new Line(getStartPoint(),p,false);
              ctrlConfig.cuGraph=line;
              line.draw();
              break;
            case graphkind.arrow://方向
              var line=new Line(getStartPoint(),p,true);
              ctrlConfig.cuGraph=line;
              line.draw();
              break;
            case graphkind.trian://三角形
              var lu=getStartPoint();
              var x2=p.getX();
              var x1=lu.getX();
              //三角形左边的点坐标计算方法:(x1-(x2-x1),y2)
              var x3=x1-(x2-x1);
              var l=setCuPointXY(x3,p.getY(),1);//设置共享的临时坐标点,用于防止重复创建对象
              var poly=getCuGraph();//获取当前图形
              poly.set([lu,p,l]);
              poly.draw();//即时绘制
              break;
            case graphkind.parallel://平行四边形
              var lu=getStartPoint();
              var x3=p.getX();
              var x1=lu.getX();
              //平行四边形两个未知坐标点计算方法:(x1-(x3-x1),y3),(x1+(x3-x1),y1)
              var x2=x3+(x3-x1);
              var x4=x1-(x3-x1);
              var ld=setCuPointXY(x2,lu.getY(),1);//设置共享的临时坐标点,用于防止重复创建对象
              var ru=setCuPointXY(x4,p.getY(),2);//设置共享的临时坐标点,用于防止重复创建对象
              var poly=getCuGraph();//获取当前图形
              poly.set([lu,ru,p,ld]);
              poly.draw();//即时绘制
              break;
            case graphkind.trapezoid://梯形
              var lu=getStartPoint();
              var x3=p.getX();
              var x1=lu.getX();
              //梯形两个未知坐标点计算方法:(x3-(x3-x1)/2,y1),(x1-(x3-x1)/2,y3)
              var x2=x3-(x3-x1)/2;
              var x4=x1-(x3-x1)/2;
              var ld=setCuPointXY(x2,lu.getY(),1);
              var ru=setCuPointXY(x4,p.getY(),2);
              var poly=getCuGraph();
              poly.set([lu,ru,p,ld]);
              poly.draw();
              break;
            case graphkind.rect://矩形
              var lu=getStartPoint();
              //矩形右上角和左上角坐标计算方法
              var ld=setCuPointXY(lu.getX(),p.getY(),1);
              var ru=setCuPointXY(p.getX(),lu.getY(),2);
              var poly=getCuGraph();
              poly.set([lu,ru,p,ld]);
              poly.draw();
              break;
            case graphkind.circle://圆
              var circle=getCuGraph();//获取当前图形
              circle.set({'start':getStartPoint(),'end':p});
              circle.draw();//即时绘制
              break;
          }
        }
      }
      //鼠标按键松开
      var mouseUp = function(e){
        if(isDrawing()){
          //console.log("松开鼠标按键:"+e.offsetX+","+e.offsetY);
          //画笔不需要重绘
          if(ctrlConfig.kind>1){
            repaint();
            getCuGraph().draw();
          }
          if(ctrlConfig.kind!=graphkind.poly){//多边形绘制鼠标按键松开不结束绘制,多边形只有右键点击才能结束绘制
            stopDrawing();//结束绘制
          }
        }
      }
      //鼠标移出
      var mouseOut = function(e){
        console.log("鼠标移出绘制区域"+e.offsetX+","+e.offsetY);
        if(isDrawing()){
          console.log("停止绘制");
          if(ctrlConfig.kind>1){
            repaint();
            getCuGraph().draw();
          }
          stopDrawing();//停止绘制
        }
      }
      return{
        isNull:isNull,
        getDom:getDom,
        clear:function(){
          stopDrawing();//停止绘制
          repaint();
        },
        /**初始化*/
        init:function(params){
          cbtCanvas=getDom(params.id);
          //浏览器是否支持Canvas
          if (cbtCanvas.getContext){
            /**绘图对象*/
            cxt=cbtCanvas.getContext("2d");
            cbtCanvas.onmousedown = mouseDown;
            cbtCanvas.onmouseup = mouseUp;
            cbtCanvas.onmousemove = mouseMove;
            cbtCanvas.onmouseout = mouseOut;
            resetStyle();//载入样式
            return true;
          }else{
            return false;
          }
        },
        /**设置背景图片*/
        setBgPic:loadPicture,
        /**选择图形类型*/
        begin:function(k){
          console.log("选择绘制图形:"+k);
          if(isNaN(k)){//如果不是数字,先转换为对应字符
            ctrlConfig.kind=kind[k];
          }else{
            ctrlConfig.kind=k;
          }
          switchCorser(true);//切换鼠标样式
        },
        /*手型,并停止绘图*/
        hand:function(){
          ctrlConfig.kind=0;
          stopDrawing();//停止绘制
          switchCorser(false);//切换鼠标样式
        }
      }
    })

三、使用方式

1、图形类型

0:鼠标,1:画笔,2:线条,3:三角形,4:矩形,5:多边形,6:圆形,21:箭头,41:平行四边形,42:梯形

var graphkind={'cursor':0,'pen':1,'line':2,'trian':3,'rect':4,'poly':5,'circle':6,'arrow':21,'parallel':41,'trapezoid':42};

2、初始化以及使用背景图片和画笔选择

var drawUtil=new DrawingTools();
//初始化,(如果浏览器不支持H5,会初始化失败,返回false)
if(drawUtil.init({'id':'calibrationCanvas'})){
//加载图片
var imgsrc='图片地址';
if(!drawUtil.isNull(imgsrc)){
  drawUtil.setBgPic(imgsrc,true);//设置背景图片(异步加载图片)
}
}
drawUtil.begin(1);//选择画笔

2、绘制箭头

drawUtil.begin(21);

总结

以上所述是小编给大家介绍的原生JS使用Canvas实现拖拽式绘图功能,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对网站的支持!
如果你觉得本文对你有帮助,欢迎转载,烦请注明出处,谢谢!

广告合作:本站广告合作请联系QQ:858582 申请时备注:广告合作(否则不回)
免责声明:本站资源来自互联网收集,仅供用于学习和交流,请遵循相关法律法规,本站一切资源不代表本站立场,如有侵权、后门、不妥请联系本站删除!

稳了!魔兽国服回归的3条重磅消息!官宣时间再确认!

昨天有一位朋友在大神群里分享,自己亚服账号被封号之后居然弹出了国服的封号信息对话框。

这里面让他访问的是一个国服的战网网址,com.cn和后面的zh都非常明白地表明这就是国服战网。

而他在复制这个网址并且进行登录之后,确实是网易的网址,也就是我们熟悉的停服之后国服发布的暴雪游戏产品运营到期开放退款的说明。这是一件比较奇怪的事情,因为以前都没有出现这样的情况,现在突然提示跳转到国服战网的网址,是不是说明了简体中文客户端已经开始进行更新了呢?