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

html5-canvas-draw

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

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

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

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

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

复制代码
  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的网页画板就是一个很好的例子

版权声明:本文为axl234原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/axl234/p/3914875.html