HTML5的功能非常强大,尤其是Canvas的应用更加广泛,Canvas画布上面不仅可以绘制任意的图形,而且可以实现多种多样的动画,甚至是一些交互式的应用,比如网页网版。这次我们要来看的就是一款基于HTML5 Canvas的网页画板,在这里仅对一些关键性的代码进行记录,大家也可以下载全部源代码研究。

你也可以再这里查看在线演示

下面我们来简单地分析一下实现这个HTML5网页画板的原理及代码,代码由HTML以及Javascript组成,主要还是Javascript代码。

HTML代码:

  1. <div style="width:530px;margin:10px auto">
  2. <div id="canvasDiv"></div>
  3. </div>

HTML代码非常简单,仅仅是构造了一个canvas容器,我们的画板就在这个地方生成。

Javascript代码:

首先我们通过一组变量来定义画板的样式,以及一些数据的初始化:

  1. var canvas;
  2. var context;
  3. var canvasWidth = 490;
  4. var canvasHeight = 220;
  5. var padding = 25;
  6. var lineWidth = 8;
  7. var colorPurple = "#cb3594";
  8. var colorGreen = "#659b41";
  9. var colorYellow = "#ffcf33";
  10. var colorBrown = "#986928";
  11. var outlineImage = new Image();
  12. var crayonImage = new Image();
  13. var markerImage = new Image();
  14. var eraserImage = new Image();
  15. var crayonBackgroundImage = new Image();
  16. var markerBackgroundImage = new Image();
  17. var eraserBackgroundImage = new Image();
  18. var crayonTextureImage = new Image();
  19. var clickX = new Array();
  20. var clickY = new Array();
  21. var clickColor = new Array();
  22. var clickTool = new Array();
  23. var clickSize = new Array();
  24. var clickDrag = new Array();
  25. var paint = false;
  26. var curColor = colorPurple;
  27. var curTool = "crayon";
  28. var curSize = "normal";
  29. var mediumStartX = 18;
  30. var mediumStartY = 19;
  31. var mediumImageWidth = 93;
  32. var mediumImageHeight = 46;
  33. var drawingAreaX = 111;
  34. var drawingAreaY = 11;
  35. var drawingAreaWidth = 267;
  36. var drawingAreaHeight = 200;
  37. var toolHotspotStartY = 23;
  38. var toolHotspotHeight = 38;
  39. var sizeHotspotStartY = 157;
  40. var sizeHotspotHeight = 36;
  41. var sizeHotspotWidthObject = new Object();
  42. sizeHotspotWidthObject.huge = 39;
  43. sizeHotspotWidthObject.large = 25;
  44. sizeHotspotWidthObject.normal = 18;
  45. sizeHotspotWidthObject.small = 16;
  46. var totalLoadResources = 8;
  47. var curLoadResNum = 0;

接下来开始准备画布,也就是初始化Canvas对象:

  1. function prepareCanvas()
  2. {
  3. // Create the canvas (Neccessary for IE because it doesn't know what a canvas element is)
  4. var canvasDiv = document.getElementById('canvasDiv');
  5. canvas = document.createElement('canvas');
  6. canvas.setAttribute('width', canvasWidth);
  7. canvas.setAttribute('height', canvasHeight);
  8. canvas.setAttribute('id', 'canvas');
  9. canvasDiv.appendChild(canvas);
  10. if(typeof G_vmlCanvasManager != 'undefined') {
  11. canvas = G_vmlCanvasManager.initElement(canvas);
  12. }
  13. context = canvas.getContext("2d"); // Grab the 2d canvas context
  14. // Note: The above code is a workaround for IE 8 and lower. Otherwise we could have used:
  15. // context = document.getElementById('canvas').getContext("2d");
  16.  
  17. // Load images
  18. // -----------
  19. crayonImage.onload = function() { resourceLoaded();
  20. };
  21. crayonImage.src = "images/crayon-outline.png";
  22. //context.drawImage(crayonImage, 0, 0, 100, 100);
  23.  
  24. markerImage.onload = function() { resourceLoaded();
  25. };
  26. markerImage.src = "images/marker-outline.png";
  27.  
  28. eraserImage.onload = function() { resourceLoaded();
  29. };
  30. eraserImage.src = "images/eraser-outline.png";
  31.  
  32. crayonBackgroundImage.onload = function() { resourceLoaded();
  33. };
  34. crayonBackgroundImage.src = "images/crayon-background.png";
  35.  
  36. markerBackgroundImage.onload = function() { resourceLoaded();
  37. };
  38. markerBackgroundImage.src = "images/marker-background.png";
  39.  
  40. eraserBackgroundImage.onload = function() { resourceLoaded();
  41. };
  42. eraserBackgroundImage.src = "images/eraser-background.png";
  43.  
  44. crayonTextureImage.onload = function() { resourceLoaded();
  45. };
  46. crayonTextureImage.src = "images/crayon-texture.png";
  47.  
  48. outlineImage.onload = function() { resourceLoaded();
  49. };
  50. outlineImage.src = "images/watermelon-duck-outline.png";
  51.  
  52. // Add mouse events
  53. // ----------------
  54. $('#canvas').mousedown(function(e)
  55. {
  56. // Mouse down location
  57. var mouseX = e.pageX - this.offsetLeft;
  58. var mouseY = e.pageY - this.offsetTop;
  59.  
  60. if(mouseX < drawingAreaX) // Left of the drawing area
  61. {
  62. if(mouseX > mediumStartX)
  63. {
  64. if(mouseY > mediumStartY && mouseY < mediumStartY + mediumImageHeight){
  65. curColor = colorPurple;
  66. }else if(mouseY > mediumStartY + mediumImageHeight && mouseY < mediumStartY + mediumImageHeight * 2){
  67. curColor = colorGreen;
  68. }else if(mouseY > mediumStartY + mediumImageHeight * 2 && mouseY < mediumStartY + mediumImageHeight * 3){
  69. curColor = colorYellow;
  70. }else if(mouseY > mediumStartY + mediumImageHeight * 3 && mouseY < mediumStartY + mediumImageHeight * 4){
  71. curColor = colorBrown;
  72. }
  73. }
  74. }
  75. else if(mouseX > drawingAreaX + drawingAreaWidth) // Right of the drawing area
  76. {
  77. if(mouseY > toolHotspotStartY)
  78. {
  79. if(mouseY > sizeHotspotStartY)
  80. {
  81. var sizeHotspotStartX = drawingAreaX + drawingAreaWidth;
  82. if(mouseY < sizeHotspotStartY + sizeHotspotHeight && mouseX > sizeHotspotStartX)
  83. {
  84. if(mouseX < sizeHotspotStartX + sizeHotspotWidthObject.huge){
  85. curSize = "huge";
  86. }else if(mouseX < sizeHotspotStartX + sizeHotspotWidthObject.large + sizeHotspotWidthObject.huge){
  87. curSize = "large";
  88. }else if(mouseX < sizeHotspotStartX + sizeHotspotWidthObject.normal + sizeHotspotWidthObject.large + sizeHotspotWidthObject.huge){
  89. curSize = "normal";
  90. }else if(mouseX < sizeHotspotStartX + sizeHotspotWidthObject.small + sizeHotspotWidthObject.normal + sizeHotspotWidthObject.large + sizeHotspotWidthObject.huge){
  91. curSize = "small";
  92. }
  93. }
  94. }
  95. else
  96. {
  97. if(mouseY < toolHotspotStartY + toolHotspotHeight){
  98. curTool = "crayon";
  99. }else if(mouseY < toolHotspotStartY + toolHotspotHeight * 2){
  100. curTool = "marker";
  101. }else if(mouseY < toolHotspotStartY + toolHotspotHeight * 3){
  102. curTool = "eraser";
  103. }
  104. }
  105. }
  106. }
  107. else if(mouseY > drawingAreaY && mouseY < drawingAreaY + drawingAreaHeight)
  108. {
  109. // Mouse click location on drawing area
  110. }
  111. paint = true;
  112. addClick(mouseX, mouseY, false);
  113. redraw();
  114. });
  115.  
  116. $('#canvas').mousemove(function(e){
  117. if(paint==true){
  118. addClick(e.pageX - this.offsetLeft, e.pageY - this.offsetTop, true);
  119. redraw();
  120. }
  121. });
  122.  
  123. $('#canvas').mouseup(function(e){
  124. paint = false;
  125. redraw();
  126. });
  127.  
  128. $('#canvas').mouseleave(function(e){
  129. paint = false;
  130. });
  131. }

看起来很复杂,前面主要是初始化canvas的背景图片,后面主要是初始化画笔事件,像click、mouseup、mouseleave等鼠标事件。

下面是draw的主要方法:

  1. function redraw()
  2. {
  3. // Make sure required resources are loaded before redrawing
  4. if(curLoadResNum < totalLoadResources){ return; }
  5.  
  6. clearCanvas();
  7.  
  8. var locX;
  9. var locY;
  10. if(curTool == "crayon")
  11. {
  12. // Draw the crayon tool background
  13. context.drawImage(crayonBackgroundImage, 0, 0, canvasWidth, canvasHeight);
  14.  
  15. // Purple
  16. locX = (curColor == colorPurple) ? 18 : 52;
  17. locY = 19;
  18.  
  19. context.beginPath();
  20. context.moveTo(locX + 41, locY + 11);
  21. context.lineTo(locX + 41, locY + 35);
  22. context.lineTo(locX + 29, locY + 35);
  23. context.lineTo(locX + 29, locY + 33);
  24. context.lineTo(locX + 11, locY + 27);
  25. context.lineTo(locX + 11, locY + 19);
  26. context.lineTo(locX + 29, locY + 13);
  27. context.lineTo(locX + 29, locY + 11);
  28. context.lineTo(locX + 41, locY + 11);
  29. context.closePath();
  30. context.fillStyle = colorPurple;
  31. context.fill();
  32.  
  33. if(curColor == colorPurple){
  34. context.drawImage(crayonImage, locX, locY, mediumImageWidth, mediumImageHeight);
  35. }else{
  36. context.drawImage(crayonImage, 0, 0, 59, mediumImageHeight, locX, locY, 59, mediumImageHeight);
  37. }
  38.  
  39. // Green
  40. locX = (curColor == colorGreen) ? 18 : 52;
  41. locY += 46;
  42.  
  43. context.beginPath();
  44. context.moveTo(locX + 41, locY + 11);
  45. context.lineTo(locX + 41, locY + 35);
  46. context.lineTo(locX + 29, locY + 35);
  47. context.lineTo(locX + 29, locY + 33);
  48. context.lineTo(locX + 11, locY + 27);
  49. context.lineTo(locX + 11, locY + 19);
  50. context.lineTo(locX + 29, locY + 13);
  51. context.lineTo(locX + 29, locY + 11);
  52. context.lineTo(locX + 41, locY + 11);
  53. context.closePath();
  54. context.fillStyle = colorGreen;
  55. context.fill();
  56.  
  57. if(curColor == colorGreen){
  58. context.drawImage(crayonImage, locX, locY, mediumImageWidth, mediumImageHeight);
  59. }else{
  60. context.drawImage(crayonImage, 0, 0, 59, mediumImageHeight, locX, locY, 59, mediumImageHeight);
  61. }
  62.  
  63. // Yellow
  64. locX = (curColor == colorYellow) ? 18 : 52;
  65. locY += 46;
  66.  
  67. context.beginPath();
  68. context.moveTo(locX + 41, locY + 11);
  69. context.lineTo(locX + 41, locY + 35);
  70. context.lineTo(locX + 29, locY + 35);
  71. context.lineTo(locX + 29, locY + 33);
  72. context.lineTo(locX + 11, locY + 27);
  73. context.lineTo(locX + 11, locY + 19);
  74. context.lineTo(locX + 29, locY + 13);
  75. context.lineTo(locX + 29, locY + 11);
  76. context.lineTo(locX + 41, locY + 11);
  77. context.closePath();
  78. context.fillStyle = colorYellow;
  79. context.fill();
  80.  
  81. if(curColor == colorYellow){
  82. context.drawImage(crayonImage, locX, locY, mediumImageWidth, mediumImageHeight);
  83. }else{
  84. context.drawImage(crayonImage, 0, 0, 59, mediumImageHeight, locX, locY, 59, mediumImageHeight);
  85. }
  86.  
  87. // Yellow
  88. locX = (curColor == colorBrown) ? 18 : 52;
  89. locY += 46;
  90.  
  91. context.beginPath();
  92. context.moveTo(locX + 41, locY + 11);
  93. context.lineTo(locX + 41, locY + 35);
  94. context.lineTo(locX + 29, locY + 35);
  95. context.lineTo(locX + 29, locY + 33);
  96. context.lineTo(locX + 11, locY + 27);
  97. context.lineTo(locX + 11, locY + 19);
  98. context.lineTo(locX + 29, locY + 13);
  99. context.lineTo(locX + 29, locY + 11);
  100. context.lineTo(locX + 41, locY + 11);
  101. context.closePath();
  102. context.fillStyle = colorBrown;
  103. context.fill();
  104.  
  105. if(curColor == colorBrown){
  106. context.drawImage(crayonImage, locX, locY, mediumImageWidth, mediumImageHeight);
  107. }else{
  108. context.drawImage(crayonImage, 0, 0, 59, mediumImageHeight, locX, locY, 59, mediumImageHeight);
  109. }
  110. }
  111. else if(curTool == "marker")
  112. {
  113. // Draw the marker tool background
  114. context.drawImage(markerBackgroundImage, 0, 0, canvasWidth, canvasHeight);
  115.  
  116. // Purple
  117. locX = (curColor == colorPurple) ? 18 : 52;
  118. locY = 19;
  119.  
  120. context.beginPath();
  121. context.moveTo(locX + 10, locY + 24);
  122. context.lineTo(locX + 10, locY + 24);
  123. context.lineTo(locX + 22, locY + 16);
  124. context.lineTo(locX + 22, locY + 31);
  125. context.closePath();
  126. context.fillStyle = colorPurple;
  127. context.fill();
  128.  
  129. if(curColor == colorPurple){
  130. context.drawImage(markerImage, locX, locY, mediumImageWidth, mediumImageHeight);
  131. }else{
  132. context.drawImage(markerImage, 0, 0, 59, mediumImageHeight, locX, locY, 59, mediumImageHeight);
  133. }
  134.  
  135. // Green
  136. locX = (curColor == colorGreen) ? 18 : 52;
  137. locY += 46;
  138.  
  139. context.beginPath();
  140. context.moveTo(locX + 10, locY + 24);
  141. context.lineTo(locX + 10, locY + 24);
  142. context.lineTo(locX + 22, locY + 16);
  143. context.lineTo(locX + 22, locY + 31);
  144. context.closePath();
  145. context.fillStyle = colorGreen;
  146. context.fill();
  147.  
  148. if(curColor == colorGreen){
  149. context.drawImage(markerImage, locX, locY, mediumImageWidth, mediumImageHeight);
  150. }else{
  151. context.drawImage(markerImage, 0, 0, 59, mediumImageHeight, locX, locY, 59, mediumImageHeight);
  152. }
  153.  
  154. // Yellow
  155. locX = (curColor == colorYellow) ? 18 : 52;
  156. locY += 46;
  157.  
  158. context.beginPath();
  159. context.moveTo(locX + 10, locY + 24);
  160. context.lineTo(locX + 10, locY + 24);
  161. context.lineTo(locX + 22, locY + 16);
  162. context.lineTo(locX + 22, locY + 31);
  163. context.closePath();
  164. context.fillStyle = colorYellow;
  165. context.fill();
  166.  
  167. if(curColor == colorYellow){
  168. context.drawImage(markerImage, locX, locY, mediumImageWidth, mediumImageHeight);
  169. }else{
  170. context.drawImage(markerImage, 0, 0, 59, mediumImageHeight, locX, locY, 59, mediumImageHeight);
  171. }
  172.  
  173. // Yellow
  174. locX = (curColor == colorBrown) ? 18 : 52;
  175. locY += 46;
  176.  
  177. context.beginPath();
  178. context.moveTo(locX + 10, locY + 24);
  179. context.lineTo(locX + 10, locY + 24);
  180. context.lineTo(locX + 22, locY + 16);
  181. context.lineTo(locX + 22, locY + 31);
  182. context.closePath();
  183. context.fillStyle = colorBrown;
  184. context.fill();
  185.  
  186. if(curColor == colorBrown){
  187. context.drawImage(markerImage, locX, locY, mediumImageWidth, mediumImageHeight);
  188. }else{
  189. context.drawImage(markerImage, 0, 0, 59, mediumImageHeight, locX, locY, 59, mediumImageHeight);
  190. }
  191. }
  192. else if(curTool == "eraser")
  193. {
  194. context.drawImage(eraserBackgroundImage, 0, 0, canvasWidth, canvasHeight);
  195. context.drawImage(eraserImage, 18, 19, mediumImageWidth, mediumImageHeight);
  196. }else{
  197. alert("Error: Current Tool is undefined");
  198. }
  199.  
  200. if(curSize == "small"){
  201. locX = 467;
  202. }else if(curSize == "normal"){
  203. locX = 450;
  204. }else if(curSize == "large"){
  205. locX = 428;
  206. }else if(curSize == "huge"){
  207. locX = 399;
  208. }
  209. locY = 189;
  210. context.beginPath();
  211. context.rect(locX, locY, 2, 12);
  212. context.closePath();
  213. context.fillStyle = '#333333';
  214. context.fill();
  215.  
  216. // Keep the drawing in the drawing area
  217. context.save();
  218. context.beginPath();
  219. context.rect(drawingAreaX, drawingAreaY, drawingAreaWidth, drawingAreaHeight);
  220. context.clip();
  221.  
  222. var radius;
  223. var i = 0;
  224. for(; i < clickX.length; i++)
  225. {
  226. if(clickSize[i] == "small"){
  227. radius = 2;
  228. }else if(clickSize[i] == "normal"){
  229. radius = 5;
  230. }else if(clickSize[i] == "large"){
  231. radius = 10;
  232. }else if(clickSize[i] == "huge"){
  233. radius = 20;
  234. }else{
  235. alert("Error: Radius is zero for click " + i);
  236. radius = 0;
  237. }
  238.  
  239. context.beginPath();
  240. if(clickDrag[i] && i){
  241. context.moveTo(clickX[i-1], clickY[i-1]);
  242. }else{
  243. context.moveTo(clickX[i], clickY[i]);
  244. }
  245. context.lineTo(clickX[i], clickY[i]);
  246. context.closePath();
  247.  
  248. if(clickTool[i] == "eraser"){
  249. //context.globalCompositeOperation = "destination-out"; // To erase instead of draw over with white
  250. context.strokeStyle = 'white';
  251. }else{
  252. //context.globalCompositeOperation = "source-over"; // To erase instead of draw over with white
  253. context.strokeStyle = clickColor[i];
  254. }
  255. context.lineJoin = "round";
  256. context.lineWidth = radius;
  257. context.stroke();
  258.  
  259. }
  260. //context.globalCompositeOperation = "source-over";// To erase instead of draw over with white
  261. context.restore();
  262.  
  263. // Overlay a crayon texture (if the current tool is crayon)
  264. if(curTool == "crayon"){
  265. context.globalAlpha = 0.4; // No IE support
  266. context.drawImage(crayonTextureImage, 0, 0, canvasWidth, canvasHeight);
  267. }
  268. context.globalAlpha = 1; // No IE support
  269.  
  270. // Draw the outline image
  271. context.drawImage(outlineImage, drawingAreaX, drawingAreaY, drawingAreaWidth, drawingAreaHeight);
  272. }

其实HTML5说白了还是需要很多Javascript支持,不过Canvas非常不错,可以让你在上面自由地绘制图形和动画。这款基于HTML5 Canvas的网页画板就是一个很好的例子

基于HTML5 Canvas的网页画板实现教程的更多相关文章

  1. 基于HTML5 Canvas的线性区域图表教程

    之前我们看到过很多用jQuery实现的网页图表,有些还是比较实用的.今天我们来介绍一款基于HTML5 Canvas的线性区域图表应用,这个图表应用允许你使用多组数据来同时展示,并且将数据结果以线性图的 ...

  2. 基于html5 canvas和js实现的水果忍者网页版

    今天爱编程小编给大家分享一款基于html5 canvas和js实现的水果忍者网页版. <水果忍者>是一款非常受喜欢的手机游戏,刚看到新闻说<水果忍者>四周年新版要上线了.网页版 ...

  3. 一款基于HTML5 Canvas的画板涂鸦动画

    今天给各网友分享一款基于HTML5 Canvas的画板涂鸦动画.记得之前我们分享过一款HTML5 Canvas画板工具,可以切换不同的笔刷,功能十分强大.本文今天要再来分享一款基于HTML5 Canv ...

  4. 基于html5 Canvas图表库 : ECharts

    ECharts开源来自百度商业前端数据可视化团队,基于html5 Canvas,是一个纯Javascript图表库,提供直观,生动,可交互,可个性化定制的数据可视化图表.创新的拖拽重计算.数据视图.值 ...

  5. 基于HTML5 Canvas和jQuery 的绘图工具的实现

    简单介绍 HTML5 提供了强大的Canvas元素.使用Canvas并结合Javascript 能够实现一些很强大的功能.本文就介绍一下基于HTML5 Canvas 的绘图工具的实现.废话少说,先看成 ...

  6. 18个基于 HTML5 Canvas 开发的图表库

    如今,HTML5 可谓如众星捧月一般,受到许多业内巨头的青睐.很多Web开发者也尝试着用 HTML 5 来制作各种各样的富 Web 应用.HTML 5 规范引进了很多新特性,其中之一就是 Canvas ...

  7. 基于HTML5 Canvas实现的图片马赛克模糊特效

    效果请点击下面网址: http://hovertree.com/texiao/html5/1.htm 一.开门见山受美国肖像画家Chuck Close的启发,此脚本通过使用HTML5 canvas元素 ...

  8. 基于HTML5 Canvas实现用户交互

    很多人都有这样的疑问,基于HTML5 Canvas实现的元素怎么和用户进行交互?在这里我们用到HT for Web(http://www.hightopo.com/guide/guide/core/b ...

  9. 基于html5 canvas 的客户端异步上传图片的插件,支持客户端压缩图片尺寸

    /** * Created by xx on 15-05-28. * 基于html5 canvas 的客户端异步上传画片的插件 * 在实际应用中,常常要用于上传图片的功能.在现在越来越多的手机weba ...

随机推荐

  1. 电子科大POJ "a^b"

    a ^ b Time Limit: 3000/1000MS (Java/Others)     Memory Limit: 65535/65535KB (Java/Others) C-sources: ...

  2. 杭电oj1236 排名

    Tips:此题比较简单,最好将每一个学生的信息构建一个结构体,另外需要注意的是,若分数相同,排序按姓名排序,我看网上很多都是使用<algorithm>中的sort算法,只需重写cmp函数即 ...

  3. H264 编码详解

    H264 编码详解(收集转载) (1)       x264_param_default( x264_param_t *param ) 作用: 对编码器进行参数设定 cqm:量化表相关信息 csp: ...

  4. TagBuilder 性能如此低下?

    本文来自:http://www.cnblogs.com/zhuisha/archive/2010/03/12/1684022.html 需要通过ASP.NET MVC生成一个列表,MVC里面根正苗红的 ...

  5. spark安装mysql与hive

    第一眼spark安装文件夹lib\spark-assembly-1.0.0-hadoop2.2.0.jar\org\apache\spark\sql下有没有hive文件夹,假设没有的话先下载支持hiv ...

  6. 超级强大的SVG SMIL animation动画详解

    本文花费精力惊人,具有先驱前瞻性,转载规则以及申明见文末,当心予以追究.本文地址:http://www.zhangxinxu.com/wordpress/?p=4333 //zxx: 本文的SVG在有 ...

  7. StringBuffer工具类整理(一)

    package com.gzcivil.utils; /** * 同StringBuffer * * @author Dragon * @time 2013-3-1 */ public class S ...

  8. UILabel头文件常见属性

    text : default is nil 文本属性,默认值是 nil @property(nullable, nonatomic,copy) NSString *text; font : defau ...

  9. 基于TcpDump和pcap文件分析的Android平台网络抓包程序设计与实现【随便】

    一.考虑使用Tcpdump,将抓到的包保存到cap文件中,然后手动分析.参考资料:1. http://www.cnblogs.com/tt-0411/archive/2012/09/23/269936 ...

  10. yii2 安装过程中的问题及解决方法

    一.php版本要求5.4+,如果使用wamp组合包,建议更换 二.各种模块的支持,一般只要修改php.ini文件,去掉相应模块前的注释即可. 注意,Intl extension模块的支持需要将     ...