HTML5 JS 画图板

     最近在研究下 html5 的 canvas 想写个小项目,练练手,结果写了一个画图板,功能点有 绘制、直线、圆、方形、涂鸦、线条粗细、颜色切换、撤销、回退、保存、下载、外部图片拖入等 , 用的技术是包含 html5 中的本地存储、下载、canvas 等技术,上图。 

 

演示地址:http://chengxinwei.github.io/html5/2013/06/20/HTML5_CANVAS_%E7%94%BB%E5%9B%BE%E6%9D%BF/ 

这个项目中用到了 canvas 的很多基础功能 。在这里解释一下核心代码的思路。 

在这个项目中 我用到了 2 层 canvas , 原因是当用户在画部分图形的时候希望看到绘画的过程,比如在画圆的时候,而canvas 目前支持的就是清空 和 绘制操作, 所以在这里我用了 bak 层做了一个 假象。用户一开始的所有绘制都是在 bak 层做的绘制 , 之后当鼠标松开的时候 才会到 真正的 canvas 层保存。这个是核心思路。 

接下来我们来看一下代码的构造。 

1.首先第一部。是做对象初始化, 包括有 初始化canvas , context , height, width  这个很简单就不做多的解释了 代码如下。 

Javascript代码 

 收藏代码

  1. //初始化  
  2.         var initCanvas = function(){  
  3.             canvas =  document.getElementById("canvas");  
  4.             canvas.width = canvasWidth;  
  5.             canvas.height = canvasHeight;  
  6.             context = canvas.getContext('2d');  
  7.             canvasTop = $(canvas).offset().top  
  8.             canvasLeft = $(canvas).offset().left;  
  9.       
  10.   
  11.             canvas_bak =  document.getElementById("canvas_bak");  
  12.             canvas_bak.width = canvasWidth;  
  13.             canvas_bak.height = canvasHeight;  
  14.             context_bak = canvas_bak.getContext('2d');        
  15.         }     




2. 第二部 就是绘制了 , 思路是当鼠标点下得时候 确定一个初始点, 当鼠标移动的时候开始绘制。之前说过 鼠标移动只是在bak 层绘制 , 当松开鼠标时把bak层的 添加到 canvas 层 。 那么这里就包含三个事件 。 点击,移动,松开 , 对应了三个不同的方法 。代码如下: 

Javascript代码 

 收藏代码

  1. //鼠标按下获取 开始xy开始画图  
  2.     var mousedown = function(e){  
  3.         context.strokeStyle= color;  
  4.         context_bak.strokeStyle= color;  
  5.         context_bak.lineWidth = size;  
  6.         e=e||window.event;  
  7.         startX = e.clientX - canvasLeft;  
  8.         startY = e.clientY - canvasTop;  
  9.         context_bak.moveTo(startX ,startY );  
  10.         canDraw = true;           
  11.           
  12.         if(graphType == 'pencil'){  
  13.             context_bak.beginPath();  
  14.         }else if(graphType == 'circle'){  
  15.             context.beginPath();  
  16.             context.moveTo(startX ,startY );  
  17.             context.lineTo(startX +2 ,startY+2);  
  18.             context.stroke();     
  19.               
  20.         }else if(graphType == 'rubber'){                              
  21.             context.clearRect(startX - size * 10 ,  startY - size * 10 , size * 20 , size * 20);                  
  22.         }     
  23.     };    
  24.   
  25.     //鼠标离开 把蒙版canvas的图片生成到canvas中  
  26.     var mouseup = function(e){  
  27.         e=e||window.event;  
  28.         canDraw = false;  
  29.         var image = new Image();  
  30.         if(graphType!='rubber'){      
  31.               
  32.             image.src = canvas_bak.toDataURL();  
  33.             image.onload = function(){  
  34.                 context.drawImage(image , 0 ,0 , image.width , image.height , 0 ,0 , canvasWidth , canvasHeight);  
  35.                 clearContext();  
  36.                 saveImageToAry();  
  37.             }  
  38.             var x = e.clientX   - canvasLeft;  
  39.             var y = e.clientY  - canvasTop;   
  40.             context.beginPath();  
  41.             context.moveTo(x ,y );  
  42.             context.lineTo(x +2 ,y+2);  
  43.             context.stroke();     
  44.         }  
  45.     };  
  46.   
  47.     // 鼠标移动  
  48.     var  mousemove = function(e){  
  49.         e=e||window.event;  
  50.         var x = e.clientX   - canvasLeft;  
  51.         var y = e.clientY  - canvasTop;   
  52.         //方块  4条直线搞定  
  53.         if(graphType == 'square'){  
  54.             if(canDraw){  
  55.                 context_bak.beginPath();  
  56.                 clearContext();  
  57.                 context_bak.moveTo(startX , startY);                          
  58.                 context_bak.lineTo(x  ,startY );  
  59.                 context_bak.lineTo(x  ,y );  
  60.                 context_bak.lineTo(startX  ,y );  
  61.                 context_bak.lineTo(startX  ,startY );  
  62.                 context_bak.stroke();  
  63.             }  
  64.         //直线  
  65.         }else if(graphType =='line'){                         
  66.             if(canDraw){  
  67.                 context_bak.beginPath();  
  68.                 clearContext();  
  69.                 context_bak.moveTo(startX , startY);  
  70.                 context_bak.lineTo(x  ,y );  
  71.                 context_bak.stroke();  
  72.             }  
  73.         //画笔  
  74.         }else if(graphType == 'pencil'){  
  75.             if(canDraw){  
  76.                 context_bak.lineTo(e.clientX   - canvasLeft ,e.clientY  - canvasTop);  
  77.                 context_bak.stroke();                         
  78.             }  
  79.         //圆 未画得时候 出现一个小圆  
  80.         }else if(graphType == 'circle'){                          
  81.             clearContext();  
  82.             if(canDraw){  
  83.                 context_bak.beginPath();              
  84.                 var radii = Math.sqrt((startX - x) *  (startX - x)  + (startY - y) * (startY - y));  
  85.                 context_bak.arc(startX,startY,radii,0,Math.PI * 2,false);                                     
  86.                 context_bak.stroke();  
  87.             }else{    
  88.                 context_bak.beginPath();                      
  89.                 context_bak.arc(x,y,20,0,Math.PI * 2,false);  
  90.                 context_bak.stroke();  
  91.             }  
  92.         //涂鸦 未画得时候 出现一个小圆  
  93.         }else if(graphType == 'handwriting'){                                             
  94.             if(canDraw){  
  95.                 context_bak.beginPath();      
  96.                 context_bak.strokeStyle = color;  
  97.                 context_bak.fillStyle  = color;  
  98.                 context_bak.arc(x,y,size*10,0,Math.PI * 2,false);         
  99.                 context_bak.fill();  
  100.                 context_bak.stroke();  
  101.                 context_bak.restore();  
  102.             }else{    
  103.                 clearContext();  
  104.                 context_bak.beginPath();                      
  105.                 context_bak.fillStyle  = color;  
  106.                 context_bak.arc(x,y,size*10,0,Math.PI * 2,false);  
  107.                 context_bak.fill();  
  108.                 context_bak.stroke();  
  109.             }  
  110.         //橡皮擦 不管有没有在画都出现小方块 按下鼠标 开始清空区域  
  111.         }else if(graphType == 'rubber'){      
  112.             context_bak.lineWidth = 1;  
  113.             clearContext();  
  114.             context_bak.beginPath();              
  115.             context_bak.strokeStyle =  '#000000';                         
  116.             context_bak.moveTo(x - size * 10 ,  y - size * 10 );                          
  117.             context_bak.lineTo(x + size * 10  , y - size * 10 );  
  118.             context_bak.lineTo(x + size * 10  , y + size * 10 );  
  119.             context_bak.lineTo(x - size * 10  , y + size * 10 );  
  120.             context_bak.lineTo(x - size * 10  , y - size * 10 );      
  121.             context_bak.stroke();         
  122.             if(canDraw){                              
  123.                 context.clearRect(x - size * 10 ,  y - size * 10 , size * 20 , size * 20);  
  124.                                           
  125.             }             
  126.         }  
  127.     };  




顺便提一下撤销和回退的做法。之前有提过在鼠标松开的时候,我们会把 bak 层的内容绘制到 canvas 层中, 那么在这个时候,同步的会把一份 图片信息 存到一个 数组中去,用于回滚 , 当点击撤销的时候 只需要把上一个的 图片信息取出来,在绘制一遍canvas即可。撤销回退同理 



4.接下来讲一下保存功能实现。保存图片使用得 是html5 的 storage 的功能实现的。storage 是浏览器开辟了一个5M 的控件提供方开发者使用 存放key value 的键值对, 有点类似于 cookie ,那么women保存的实现就很简单了,当点击保存按钮的时候 , 获取图片的 dataUrl 保存与 storage  中即可,下次打开浏览器 获取再放入canvas中就可以了。代码如下: 
 

Javascript代码 

 收藏代码

  1. //保存  
  2. var save = function(){  
  3.     for(var i = 1;i<=8;i++){  
  4.         var dataUrl = getStorage(i);  
  5.         if(dataUrl == null || dataUrl == ''){  
  6.             putStorage(i,canvas.toDataURL());  
  7.             $("#history_"+i).attr("src",canvas.toDataURL());  
  8.   
  9.             initHistorty();  
  10.             return ;  
  11.         }  
  12.     }             
  13. }  




5.最后说一下 下载,可能很多人因为这个头疼,因为没有后台的处理,怎么能做到下载图片呢。其实在html5中 对于 a 标签提供了一个新的属性 【download】 如: 

Java代码 

 收藏代码

  1. <a href="javascript:void(0);" id="history_download_1" download="picture.png">下载</a></td>  


浏览器默认会把他当做一个下载链接去处理,下载的文件名就是 download 中的 picture.png 下载的内容对应的是src 中的值。所以我们只需要把 图片的dataUrl 动态赋值上去 即可。 

今天就先讲到这里哈,有问题可以给我留言。 


--------------//2013-06-258 --------------- 

昨天新加了 拖拽图片的功能, 从文件夹中 拖到画图板里面可以直接覆盖。 
代码页很简单 如下: 

Javascript代码 

 收藏代码

  1. // 处理文件拖入事件,防止浏览器默认事件带来的重定向    
  2.        function handleDragOver(evt) {    
  3.         evt.stopPropagation();    
  4.         evt.preventDefault();    
  5.         }  
  6.        
  7.   
  8.     // 判断是否图片    
  9.     function isImage(type) {    
  10.         switch (type) {    
  11.         case 'image/jpeg':    
  12.         case 'image/png':    
  13.         case 'image/gif':    
  14.         case 'image/bmp':    
  15.         case 'image/jpg':    
  16.             return true;    
  17.         default:    
  18.             return false;    
  19.         }    
  20.     }    
  21.   
  22.   
  23.      // 处理拖放文件列表    
  24.     function handleFileSelect(evt) {    
  25.         evt.stopPropagation();    
  26.         evt.preventDefault();    
  27.    
  28.         var files = evt.dataTransfer.files;    
  29.    
  30.         for (var i = 0, f; f = files[i]; i++) {      
  31.             var t = f.type ? f.type : 'n/a';  
  32.             reader = new FileReader();  
  33.             isImg = isImage(t);  
  34.                 
  35.             // 处理得到的图片    
  36.             if (isImg) {    
  37.                 reader.onload = (function (theFile) {    
  38.                     return function (e) {    
  39.                         var  image = new Image();   
  40.                         image.src =  e.target.result ;  
  41.                         image.onload = function(){  
  42.                             context.drawImage(image , 0 ,0 , image.width , image.height , 0 ,0 , canvasWidth , canvasHeight);  
  43.                         }  
  44.   
  45.                     };    
  46.                 })(f)    
  47.                 reader.readAsDataURL(f);    
  48.             }     
  49.         }      
  50.     }    
  51.   
  52.     //初始化拖入效果  
  53.     var initDrag= function(){  
  54.         var dragDiv  = document.getElementById("canvas_bak");  
  55.         dragDiv.addEventListener('dragover', handleDragOver, false);    
  56.         dragDiv.addEventListener('drop', handleFileSelect, false);    
  57.     }  



简单解释一下 , 在html5支持的浏览器中, 有drop的回调函数 , 在其中获得event之后 里面有一个对象 dataTransfer.files , 获取的是 file 文件信息 , 最后通过 FileReader.readAsDataURL  的函数读入,可以获取到 html5 支持的图片信息 , 最后通过创建 image 对象,把图片绘制进去就可以了。 

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值