使用HTML 5和Javascript设计绘图程序

开发 前端
在本文中,将会介绍如何使用HTML5和Javascript去设计一个简单的绘图程序。HTML5的一个新的特性是canvas画布功能,通过canvas画布的强大功能可以实现绘画不少图形和其他绚丽的功能。

在本文中,将会介绍如何使用HTML5和Javascript去设计一个简单的绘图程序。HTML5的一个新的特性是canvas画布功能,通过canvas画布的强大功能可以实现绘画不少图形和其他绚丽的功能。在本文中,读者将学习到如下几个知识点:

1) 如何动态在canvas画布上绘画图形

2) HTML 5 canvas的前景特性探讨

3) 目前浏览器对HTML5的兼容情况

本文的读者对象为,对HTML 5 Canvas有初步认识及熟悉Javascript的读者。

设计目标

首先,我们来设计下这个绘图程序将会拥有什么功能。在这个简单的绘图程序中,首先要有的是一块能给用户涂鸦的画布区域,上面有一只可爱的小鸭,然后我们准备了4种不同颜色的蜡笔,可以给用户给这只小鸭上色,同时也要提供橡皮擦的功能,以方便随时擦除这个小鸭。而除了蜡笔外,也提供了普通的油画笔的效果,当然也指定了每次绘画时笔触范围的大小,这里设定了4个选择。设计好后的绘图应用,效果如下图:

在这个应用中,用户点左边的四种颜色笔,就可以在指定的矩形框中随便涂鸦,也可而已点右面两种不同的笔触效果(crayon蜡笔)和普通笔,也可以使用橡皮擦,也可以使用右下角四种不同的笔触大小。

开始使用Canvas画布

首先,要声明一个canvas画布,使用如下代码声明:

目前,对canvas支持的最好的浏览器依然是FireFox,Chrome等非IE的浏览器,在本文的这个例子中,也兼顾了对IE浏览器的支持,使用的是一个开源的JS文件,其中提供了一些对canvas的基本支持脚本(在附件下载中包含了该脚本,名称为excanvas.js)。因此,我们可以同时也为了兼顾IE,所以这里改用了

的方式,如下代码:

接下来,为了要使用canvas画布的功能,必须如下调用:

  1. context = document.getElementById('canvasInAPerfectWorld').getContext("2d"); 

然而,同样为了兼顾在IE下的使用,我们改用以下的代码段实现:

  1. var canvasDiv = document.getElementById('canvasDiv');  
  2.   canvas = document.createElement('canvas');  
  3.   canvas.setAttribute('width', canvasWidth);  
  4.   canvas.setAttribute('height', canvasHeight);  
  5.   canvas.setAttribute('id''canvas');  
  6.   canvasDiv.appendChild(canvas);  
  7.   if(typeof G_vmlCanvasManager != 'undefined') {  
  8.   canvas = G_vmlCanvasManager.initElement(canvas);  
  9.   }  
  10. context = canvas.getContext("2d"); 

可以看到,在上面的代码中,通过document.createElement创建了一个标签元素canvas,然后再用setAttribute方法设置了画布的高度和宽度等属性(这些都可以通过设置常量属性值进行设置)。然后通过

  1. canvasDiv.appendChild(canvas); 

为canvasDiv增加了一个子元素canvas。然后利用excanvas.js这个专门为IE扩展的canvas元素包中提供的处理方法initElement进行相应的判断处理,即:

  1. if(typeof G_vmlCanvasManager != 'undefined') {  
  2.   canvas = G_vmlCanvasManager.initElement(canvas);  
  3.   } 

最后,要使用canvas的绘图功能的话,必须调用canvas的上下文,这里使用的语句是:

  1. context = canvas.getContext("2d"); 

在画布上绘画图形

接下来,我们开始在canvas上绘制图形。这里我们要对4个鼠标的相关事件进行编码,并且要编写两个相关的方法addClick和redraw。addClick方法记录鼠标移动的点,而redraw方法则将已记录的数据点在canvas画布中绘画出来。

先来看下鼠标按下时的mouse down事件,代码如下:

  1. $('#canvas').mousedown(function(e){  
  2.   var mouseX = e.pageX - this.offsetLeft;  
  3.   var mouseY = e.pageY - this.offsetTop;  
  4.   paint = true;  
  5.   addClick(e.pageX - this.offsetLeft, e.pageY - this.offsetTop);  
  6.   redraw();  
  7.   }); 

其中设置的变量paint为true时,表明当前正在绘制图形,patint为false时,表示鼠标已经松开。

再看下鼠标移动时的事件,代码如下:

  1. $('#canvas').mousemove(function(e){  
  2.   if(paint){//是不是按下了鼠标  
  3.   addClick(e.pageX - this.offsetLeft, e.pageY - this.offsetTop, true);  
  4.   redraw();  
  5.   }  
  6.  }); 

鼠标松开时的事件代码为:

  1. $('#canvas').mouseup(function(e){  
  2.   paint = false;  
  3.   }); 

鼠标移开的事件代码为:

  1. $('#canvas').mouseleave(function(e){  
  2.   paint = false;  
  3.   }); 

下面是addClick方法的代码如下:

  1. var clickX = new Array();  
  2.   var clickY = new Array();  
  3.   var clickDrag = new Array();  
  4.   var paint;  
  5.   function addClick(x, y, dragging)  
  6.   {  
  7.   clickX.push(x);  
  8.   clickY.push(y);  
  9.   clickDrag.push(dragging);  
  10.   } 

可以看到,这里分别用三个数组clickX,clickY及clickDrag记录了鼠标移动的点的X,Y坐标,以及判断是否鼠标松开的标志。

再来看下redraw这个方法,其作用为每次都清空画板,然后重新把所有的点都画过,效率不高,但作为本例子来说还是可以接受,代码如下:

  1. function redraw(){  
  2.   canvas.width = canvas.width; // Clears the canvas  
  3.   context.strokeStyle = "#df4b26";  
  4.   context.lineJoin = "round";  
  5.   context.lineWidth = 5;  
  6.   for(var i=0; i < clickX.length; i++)  
  7.   {  
  8.   context.beginPath();  
  9.   if(clickDrag[i] && i){//当是拖动而且i!=0时,从上一个点开始画线。  
  10.   context.moveTo(clickX[i-1], clickY[i-1]);  
  11.   }else{  
  12.   context.moveTo(clickX[i]-1, clickY[i]);  
  13.   }  
  14.   context.lineTo(clickX[i], clickY[i]);  
  15.   context.closePath();  
  16.   context.stroke();  
  17.  }  
  18.   }  

接下来,再定义四种不同的颜色:紫色,绿色,棕色和黄色,分别用四个不同的变量表示,并且用变量curColor保存当前正在使用的颜色,并且也用一个数组clickColor来记录用户每次选择的颜色。代码如下:

  1. var colorPurple = "#cb3594";  
  2.   var colorGreen = "#659b41";  
  3.   var colorYellow = "#ffcf33";  
  4.   var colorBrown = "#986928";  
  5.   var curColor = colorPurple;  
  6.   var clickColor = new Array();  

同样,在addClick方法中,也必须加入对用户每次选择颜色的记录,所以更新后的addclick代码如下:

  1. function addClick(x, y, dragging)  
  2.   {  
  3.   clickX.push(x);  
  4.   clickY.push(y);  
  5.   clickDrag.push(dragging);  
  6.   clickColor.push(curColor);  
  7.   } 

而在redraw的方法中,我们去掉context.strokeStyle一句,将绘画笔的颜色设置到for循环中去设置,更新后的redraw代码如下:

  1. function redraw(){  
  2.   /* context.strokeStyle = "#df4b26"; */ 
  3.   context.lineJoin = "round";  
  4.   context.lineWidth = 5;  
  5.   for(var i=0; i < clickX.length; i++)  
  6.   {  
  7.   context.beginPath();  
  8.   if(clickDrag[i] && i){  
  9.   contex.moveTo(clickX[i-1], clickY[i-1]);  
  10.   }else{  
  11.   context.moveTo(clickX[i]-1, clickY[i]);  
  12.   }  
  13.   context.lineTo(clickX[i], clickY[i]);  
  14.   context.closePath();  
  15.   context.strokeStyle = clickColor[i];  
  16.   context.stroke();  
  17.   }  
  18.   } 

我们再设置画笔每次绘画笔触范围的大小,同样,有四种选择,分别为小,中,大和很大,并用clickSize数组记录用户的选择,默认的笔触范围大小用curSize进行记录。并且也要更新redraw方法,更新后的addClick,redraw代码如下:

  1. function addClick(x, y, dragging)  
  2.   {  
  3.   clickX.push(x);  
  4.   clickY.push(y);  
  5.   clickDrag.push(dragging);  
  6.   clickColor.push(curColor);  
  7.   clickSize.push(curSize);  
  8.   }  
  9.   var radius;  
  10.   var i = 0;  
  11.   for(; i < clickX.length; i++)  
  12.   {  
  13.   if(clickSize[i] == "small"){  
  14.   radius = 2;  
  15.   }else if(clickSize[i] == "normal"){  
  16.  radius = 5;  
  17.   }else if(clickSize[i] == "large"){  
  18.   radius = 10;  
  19.   }else if(clickSize[i] == "huge"){  
  20.   radius = 20;  
  21.   }else{  
  22.   alert("Error: Radius is zero for click " + i);  
  23.   radius = 0;  
  24.   }  
  25.   function redraw(){  
  26.   ........ 
  27.   context.strokeStyle = clickColor[i];  
  28.   context.lineWidth = radius;  
  29.   context.stroke();  
  30.   }  
  31.   }  
  32.  
  33.   

最后,我们设置不同笔的绘画效果,分别是蜡笔和普通笔以及橡皮擦功能。用clickTool记录用户选择的工具种类,curTool则为当前用户选择的工具,addClick的方法如下:

  1. function addClick(x, y, dragging)  
  2.   {  
  3.   clickX.push(x);  
  4.   clickY.push(y);  
  5.   clickDrag.push(dragging);  
  6.   if(curTool == "eraser"){  
  7.   clickColor.push("white");  
  8.   }else{  
  9.   clickColor.push(curColor);  
  10.   }  
  11.   clickColor.push(curColor);  
  12.   clickSize.push(curSize);  
  13.   }  

注意,这里判断如果用户选择的工具是橡皮擦,则将白色加入到clickColor数组中。同样要在redraw的方法中对新的两个绘图工具进行处理,代码如下:

  1. function redraw(){  
  2.   context.lineJoin = "round";  
  3.   for(var i=0; i < clickX.length; i++)  
  4.   {  
  5.   context.beginPath();  
  6.   if(clickDrag[i] && i){  
  7.   context.moveTo(clickX[i-1], clickY[i-1]);  
  8.   }else{  
  9.   context.moveTo(clickX[i]-1, clickY[i]);  
  10.   }  
  11.   context.lineTo(clickX[i], clickY[i]);  
  12.   context.closePath();  
  13.   context.strokeStyle = clickColor[i];  
  14.   context.lineWidth = radius;  
  15.   context.stroke();  
  16.   }  
  17.   if(curTool == "crayon") {  
  18.   context.globalAlpha = 0.4;  
  19.   context.drawImage(crayonTextureImage, 0, 0, canvasWidth, canvasHeight);  
  20.   }  
  21.   context.globalAlpha = 1;  
  22.   } 

这里针对当用户选择“crazyon”蜡笔效果时,对绘画的效果进行了透明度的处理。

最后,我们要把小鸭子的图在画布中画上,首先要声明一个图片对象如下:

  1.  var outlineImage = new Image(); 

然后在prepareCanvas()方法中加载事先准备好的图片:

  1. function prepareCanvas(){  
  2.   ...  
  3.   outlineImage.src = "images/watermelon-duck-outline.png";  
  4.  
  5.   } 

最后在redraw的绘画方法中,要使用canvas画布的drawImage方法进行绘画,代码为:

  1. function redraw(){  
  2.   ...  
  3.   context.drawImage(outlineImage, drawingAreaX, drawingAreaY, drawingAreaWidth, drawingAreaHeight);  
  4.   }  

其中drawingAreaX, drawingAreaY为要在哪个具体位置绘画图形,drawingAreaWidth和

drawingAreaHeight则为具体图片的宽度和高度。

我们还要把绘图的区域限制在一个矩形框里,这要用到画布的save和clip方法。其中save用来保存Canvas的状态,而clip方法则是指定一个区域进行剪裁,规定了绘画的区域,代码如下:

  1.  function redraw()  
  2.   {  
  3.   ...  
  4.   context.save();  
  5.   context.beginPath();  
  6.   context.rect(drawingAreaX, drawingAreaY, drawingAreaWidth, drawingAreaHeight);  
  7.   context.clip(); //剪裁出指定的绘画区域  
  8.   var radius;  
  9.   var i = 0;  
  10.   for(; i < clickX.length; i++)  
  11.   {  
  12.   ...  
  13.   }  
  14.   context.restore(); //使用restore方法,恢复每次保存的canvas状态  
  15.   ...  
  16.   } 

总结

本文中只是对如何使用HTML5和javascript绘制小绘图应用进行了思路和基本技术点的分析,其中着重介绍了画布canvas的各种使用方法,完整的代码请到这里下载

(http://www.williammalone.com/articles/create-html5-canvas-javascript-drawing-app/downloads/html5-canvas-drawing-app.zip ),代码中完成实现了相关的各种功能,并加入了一些逻辑判断等操作,由于篇幅关系,不再在文中详细描述。

原文:http://tech.it168.com/a2011/1104/1269/000001269250_all.shtml

【编辑推荐】

  1. HTML 5 VS Flash 谁是海贼王
  2. HTML 5新特性与技巧
  3. HTML 5特效页面及js测试页面汇总推荐
  4. 学习HTML 5的10个顶级资源
  5. 49个超炫的HTML 5示例
责任编辑:陈贻新 来源: it168
相关推荐

2011-05-25 09:34:30

HTML5cssjavascript

2013-08-26 17:41:43

JavaScriptWindows 8.1

2012-09-19 15:21:48

Worklight

2011-01-27 13:08:57

HTML5JavascriptWeb

2011-04-07 11:33:00

HTML 5JavaScript

2011-12-15 01:01:16

ibmdw

2014-10-21 17:34:11

HTML5移动设计

2012-01-09 13:24:27

2012-05-30 09:22:56

Hybrid App助HTML5JavaScript

2013-08-30 10:02:48

2014-04-17 09:54:47

HTML5JavaScript

2013-09-16 10:19:08

htmlcssJavaScript

2014-02-11 11:21:00

html5工具

2015-06-26 11:51:26

HTML5JavaScript

2011-03-08 10:15:08

HTML 5

2012-06-13 14:19:27

2012-02-01 09:30:54

HTML 5

2013-01-18 10:59:44

IBMdW

2016-05-27 15:44:12

H5LeanCloudWex5

2010-07-28 08:41:17

HTML5Web移动应
点赞
收藏

51CTO技术栈公众号