超酷的HTML5 Canvas网络画板教程

在今天的HTML教程里,我们要学习一下如何使用HTML5 Canvas实现一个超酷而又简单的网络画板功能。在这个教程中,我们可以选择笔刷的类型、笔刷的大小以及笔刷的颜色,当然作为画板还需要很多功能,这里只是最基本的绘制功能,大家可以自己实现类似矩形、椭圆等复杂元素的绘制。

demo演示

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

HTML代码:





  1.    

复制代码


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.     // Load images
  17.     // -----------
  18.     crayonImage.onload = function() { resourceLoaded(); 
  19.     };
  20.     crayonImage.src = "images/crayon-outline.png";
  21.     //context.drawImage(crayonImage, 0, 0, 100, 100);

  22.     markerImage.onload = function() { resourceLoaded(); 
  23.     };
  24.     markerImage.src = "images/marker-outline.png";

  25.     eraserImage.onload = function() { resourceLoaded(); 
  26.     };
  27.     eraserImage.src = "images/eraser-outline.png";    

  28.     crayonBackgroundImage.onload = function() { resourceLoaded(); 
  29.     };
  30.     crayonBackgroundImage.src = "images/crayon-background.png";

  31.     markerBackgroundImage.onload = function() { resourceLoaded(); 
  32.     };
  33.     markerBackgroundImage.src = "images/marker-background.png";

  34.     eraserBackgroundImage.onload = function() { resourceLoaded(); 
  35.     };
  36.     eraserBackgroundImage.src = "images/eraser-background.png";

  37.     crayonTextureImage.onload = function() { resourceLoaded(); 
  38.     };
  39.     crayonTextureImage.src = "images/crayon-texture.png";

  40.     outlineImage.onload = function() { resourceLoaded(); 
  41.     };
  42.     outlineImage.src = "images/watermelon-duck-outline.png";

  43.     // Add mouse events
  44.     // ----------------
  45.     $('#canvas').mousedown(function(e)
  46.     {
  47.         // Mouse down location
  48.         var mou** = e.pageX - this.offsetLeft;
  49.         var mouseY = e.pageY - this.offsetTop;

  50.         if(mou** < drawingAreaX) // Left of the drawing area
  51.         {
  52.             if(mou** > mediumStartX)
  53.             {
  54.                 if(mouseY > mediumStartY && mouseY < mediumStartY + mediumImageHeight){
  55.                     curColor = colorPurple;
  56.                 }else if(mouseY > mediumStartY + mediumImageHeight && mouseY < mediumStartY + mediumImageHeight * 2){
  57.                     curColor = colorGreen;
  58.                 }else if(mouseY > mediumStartY + mediumImageHeight * 2 && mouseY < mediumStartY + mediumImageHeight * 3){
  59.                     curColor = colorYellow;
  60.                 }else if(mouseY > mediumStartY + mediumImageHeight * 3 && mouseY < mediumStartY + mediumImageHeight * 4){
  61.                     curColor = colorBrown;
  62.                 }
  63.             }
  64.         }
  65.         else if(mou** > drawingAreaX + drawingAreaWidth) // Right of the drawing area
  66.         {
  67.             if(mouseY > toolHotspotStartY)
  68.             {
  69.                 if(mouseY > sizeHotspotStartY)
  70.                 {
  71.                     var sizeHotspotStartX = drawingAreaX + drawingAreaWidth;
  72.                     if(mouseY < sizeHotspotStartY + sizeHotspotHeight && mou** > sizeHotspotStartX)
  73.                     {
  74.                         if(mou** < sizeHotspotStartX + sizeHotspotWidthObject.huge){
  75.                             curSize = "huge";
  76.                         }else if(mou** < sizeHotspotStartX + sizeHotspotWidthObject.large + sizeHotspotWidthObject.huge){
  77.                             curSize = "large";
  78.                         }else if(mou** < sizeHotspotStartX + sizeHotspotWidthObject.normal + sizeHotspotWidthObject.large + sizeHotspotWidthObject.huge){
  79.                             curSize = "normal";
  80.                         }else if(mou** < sizeHotspotStartX + sizeHotspotWidthObject.small + sizeHotspotWidthObject.normal + sizeHotspotWidthObject.large + sizeHotspotWidthObject.huge){
  81.                             curSize = "small";                        
  82.                         }
  83.                     }
  84.                 }
  85.                 else
  86.                 {
  87.                     if(mouseY < toolHotspotStartY + toolHotspotHeight){
  88.                         curTool = "crayon";
  89.                     }else if(mouseY < toolHotspotStartY + toolHotspotHeight * 2){
  90.                         curTool = "marker";
  91.                     }else if(mouseY < toolHotspotStartY + toolHotspotHeight * 3){
  92.                         curTool = "eraser";
  93.                     }
  94.                 }
  95.             }
  96.         }
  97.         else if(mouseY > drawingAreaY && mouseY < drawingAreaY + drawingAreaHeight)
  98.         {
  99.             // Mouse click location on drawing area
  100.         }
  101.         paint = true;
  102.         addClick(mou**, mouseY, false);
  103.         redraw();
  104.     });

  105.     $('#canvas').mousemove(function(e){
  106.         if(paint==true){
  107.             addClick(e.pageX - this.offsetLeft, e.pageY - this.offsetTop, true);
  108.             redraw();
  109.         }
  110.     });

  111.     $('#canvas').mouseup(function(e){
  112.         paint = false;
  113.           redraw();
  114.     });

  115.     $('#canvas').mouseleave(function(e){
  116.         paint = false;
  117.     });
  118. }
复制代码


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


下面是draw的主要方法:



  1. function redraw()
  2. {
  3.     // Make sure required resources are loaded before redrawing
  4.     if(curLoadResNum < totalLoadResources){ return; }

  5.     clearCanvas();

  6.     var locX;
  7.     var locY;
  8.     if(curTool == "crayon")
  9.     {
  10.         // Draw the crayon tool background
  11.         context.drawImage(crayonBackgroundImage, 0, 0, canvasWidth, canvasHeight);

  12.         // Purple
  13.         locX = (curColor == colorPurple) ? 18 : 52;
  14.         locY = 19;

  15.         context.beginPath();
  16.         context.moveTo(locX + 41, locY + 11);
  17.         context.lineTo(locX + 41, locY + 35);
  18.         context.lineTo(locX + 29, locY + 35);
  19.         context.lineTo(locX + 29, locY + 33);
  20.         context.lineTo(locX + 11, locY + 27);
  21.         context.lineTo(locX + 11, locY + 19);
  22.         context.lineTo(locX + 29, locY + 13);
  23.         context.lineTo(locX + 29, locY + 11);
  24.         context.lineTo(locX + 41, locY + 11);
  25.         context.closePath();
  26.         context.fillStyle = colorPurple;
  27.         context.fill();    

  28.         if(curColor == colorPurple){
  29.             context.drawImage(crayonImage, locX, locY, mediumImageWidth, mediumImageHeight);
  30.         }else{
  31.             context.drawImage(crayonImage, 0, 0, 59, mediumImageHeight, locX, locY, 59, mediumImageHeight);
  32.         }

  33.         // Green
  34.         locX = (curColor == colorGreen) ? 18 : 52;
  35.         locY += 46;

  36.         context.beginPath();
  37.         context.moveTo(locX + 41, locY + 11);
  38.         context.lineTo(locX + 41, locY + 35);
  39.         context.lineTo(locX + 29, locY + 35);
  40.         context.lineTo(locX + 29, locY + 33);
  41.         context.lineTo(locX + 11, locY + 27);
  42.         context.lineTo(locX + 11, locY + 19);
  43.         context.lineTo(locX + 29, locY + 13);
  44.         context.lineTo(locX + 29, locY + 11);
  45.         context.lineTo(locX + 41, locY + 11);
  46.         context.closePath();
  47.         context.fillStyle = colorGreen;
  48.         context.fill();    

  49.         if(curColor == colorGreen){
  50.             context.drawImage(crayonImage, locX, locY, mediumImageWidth, mediumImageHeight);
  51.         }else{
  52.             context.drawImage(crayonImage, 0, 0, 59, mediumImageHeight, locX, locY, 59, mediumImageHeight);
  53.         }

  54.         // Yellow
  55.         locX = (curColor == colorYellow) ? 18 : 52;
  56.         locY += 46;

  57.         context.beginPath();
  58.         context.moveTo(locX + 41, locY + 11);
  59.         context.lineTo(locX + 41, locY + 35);
  60.         context.lineTo(locX + 29, locY + 35);
  61.         context.lineTo(locX + 29, locY + 33);
  62.         context.lineTo(locX + 11, locY + 27);
  63.         context.lineTo(locX + 11, locY + 19);
  64.         context.lineTo(locX + 29, locY + 13);
  65.         context.lineTo(locX + 29, locY + 11);
  66.         context.lineTo(locX + 41, locY + 11);
  67.         context.closePath();
  68.         context.fillStyle = colorYellow;
  69.         context.fill();    

  70.         if(curColor == colorYellow){
  71.             context.drawImage(crayonImage, locX, locY, mediumImageWidth, mediumImageHeight);
  72.         }else{
  73.             context.drawImage(crayonImage, 0, 0, 59, mediumImageHeight, locX, locY, 59, mediumImageHeight);
  74.         }

  75.         // Yellow
  76.         locX = (curColor == colorBrown) ? 18 : 52;
  77.         locY += 46;

  78.         context.beginPath();
  79.         context.moveTo(locX + 41, locY + 11);
  80.         context.lineTo(locX + 41, locY + 35);
  81.         context.lineTo(locX + 29, locY + 35);
  82.         context.lineTo(locX + 29, locY + 33);
  83.         context.lineTo(locX + 11, locY + 27);
  84.         context.lineTo(locX + 11, locY + 19);
  85.         context.lineTo(locX + 29, locY + 13);
  86.         context.lineTo(locX + 29, locY + 11);
  87.         context.lineTo(locX + 41, locY + 11);
  88.         context.closePath();
  89.         context.fillStyle = colorBrown;
  90.         context.fill();    

  91.         if(curColor == colorBrown){
  92.             context.drawImage(crayonImage, locX, locY, mediumImageWidth, mediumImageHeight);
  93.         }else{
  94.             context.drawImage(crayonImage, 0, 0, 59, mediumImageHeight, locX, locY, 59, mediumImageHeight);
  95.         }
  96.     }
  97.     else if(curTool == "marker")
  98.     {
  99.         // Draw the marker tool background
  100.         context.drawImage(markerBackgroundImage, 0, 0, canvasWidth, canvasHeight);

  101.         // Purple
  102.         locX = (curColor == colorPurple) ? 18 : 52;
  103.         locY = 19;

  104.         context.beginPath();
  105.         context.moveTo(locX + 10, locY + 24);
  106.         context.lineTo(locX + 10, locY + 24);
  107.         context.lineTo(locX + 22, locY + 16);
  108.         context.lineTo(locX + 22, locY + 31);
  109.         context.closePath();
  110.         context.fillStyle = colorPurple;
  111.         context.fill();    

  112.         if(curColor == colorPurple){
  113.             context.drawImage(markerImage, locX, locY, mediumImageWidth, mediumImageHeight);
  114.         }else{
  115.             context.drawImage(markerImage, 0, 0, 59, mediumImageHeight, locX, locY, 59, mediumImageHeight);
  116.         }

  117.         // Green
  118.         locX = (curColor == colorGreen) ? 18 : 52;
  119.         locY += 46;

  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 = colorGreen;
  127.         context.fill();    

  128.         if(curColor == colorGreen){
  129.             context.drawImage(markerImage, locX, locY, mediumImageWidth, mediumImageHeight);
  130.         }else{
  131.             context.drawImage(markerImage, 0, 0, 59, mediumImageHeight, locX, locY, 59, mediumImageHeight);
  132.         }

  133.         // Yellow
  134.         locX = (curColor == colorYellow) ? 18 : 52;
  135.         locY += 46;

  136.         context.beginPath();
  137.         context.moveTo(locX + 10, locY + 24);
  138.         context.lineTo(locX + 10, locY + 24);
  139.         context.lineTo(locX + 22, locY + 16);
  140.         context.lineTo(locX + 22, locY + 31);
  141.         context.closePath();
  142.         context.fillStyle = colorYellow;
  143.         context.fill();    

  144.         if(curColor == colorYellow){
  145.             context.drawImage(markerImage, locX, locY, mediumImageWidth, mediumImageHeight);
  146.         }else{
  147.             context.drawImage(markerImage, 0, 0, 59, mediumImageHeight, locX, locY, 59, mediumImageHeight);
  148.         }

  149.         // Yellow
  150.         locX = (curColor == colorBrown) ? 18 : 52;
  151.         locY += 46;

  152.         context.beginPath();
  153.         context.moveTo(locX + 10, locY + 24);
  154.         context.lineTo(locX + 10, locY + 24);
  155.         context.lineTo(locX + 22, locY + 16);
  156.         context.lineTo(locX + 22, locY + 31);
  157.         context.closePath();
  158.         context.fillStyle = colorBrown;
  159.         context.fill();    

  160.         if(curColor == colorBrown){
  161.             context.drawImage(markerImage, locX, locY, mediumImageWidth, mediumImageHeight);
  162.         }else{
  163.             context.drawImage(markerImage, 0, 0, 59, mediumImageHeight, locX, locY, 59, mediumImageHeight);
  164.         }
  165.     }
  166.     else if(curTool == "eraser")
  167.     {
  168.         context.drawImage(eraserBackgroundImage, 0, 0, canvasWidth, canvasHeight);
  169.         context.drawImage(eraserImage, 18, 19, mediumImageWidth, mediumImageHeight);    
  170.     }else{
  171.         alert("Error: Current Tool is undefined");
  172.     }

  173.     if(curSize == "small"){
  174.         locX = 467;
  175.     }else if(curSize == "normal"){
  176.         locX = 450;
  177.     }else if(curSize == "large"){
  178.         locX = 428;
  179.     }else if(curSize == "huge"){
  180.         locX = 399;
  181.     }
  182.     locY = 189;
  183.     context.beginPath();
  184.     context.rect(locX, locY, 2, 12);
  185.     context.closePath();
  186.     context.fillStyle = '#333333';
  187.     context.fill();    

  188.     // Keep the drawing in the drawing area
  189.     context.save();
  190.     context.beginPath();
  191.     context.rect(drawingAreaX, drawingAreaY, drawingAreaWidth, drawingAreaHeight);
  192.     context.clip();

  193.     var radius;
  194.     var i = 0;
  195.     for(; i < clickX.length; i++)
  196.     {        
  197.         if(clickSize[i] == "small"){
  198.             radius = 2;
  199.         }else if(clickSize[i] == "normal"){
  200.             radius = 5;
  201.         }else if(clickSize[i] == "large"){
  202.             radius = 10;
  203.         }else if(clickSize[i] == "huge"){
  204.             radius = 20;
  205.         }else{
  206.             alert("Error: Radius is zero for click " + i);
  207.             radius = 0;    
  208.         }

  209.         context.beginPath();
  210.         if(clickDrag[i] && i){
  211.             context.moveTo(clickX[i-1], clickY[i-1]);
  212.         }else{
  213.             context.moveTo(clickX[i], clickY[i]);
  214.         }
  215.         context.lineTo(clickX[i], clickY[i]);
  216.         context.closePath();

  217.         if(clickTool[i] == "eraser"){
  218.             //context.globalCompositeOperation = "destination-out"; // To erase instead of draw over with white
  219.             context.strokeStyle = 'white';
  220.         }else{
  221.             //context.globalCompositeOperation = "source-over";    // To erase instead of draw over with white
  222.             context.strokeStyle = clickColor[i];
  223.         }
  224.         context.lineJoin = "round";
  225.         context.lineWidth = radius;
  226.         context.stroke();

  227.     }
  228.     //context.globalCompositeOperation = "source-over";// To erase instead of draw over with white
  229.     context.restore();

  230.     // Overlay a crayon texture (if the current tool is crayon)
  231.     if(curTool == "crayon"){
  232.         context.globalAlpha = 0.4; // No IE support
  233.         context.drawImage(crayonTextureImage, 0, 0, canvasWidth, canvasHeight);
  234.     }
  235.     context.globalAlpha = 1; // No IE support

  236.     // Draw the outline image
  237.     context.drawImage(outlineImage, drawingAreaX, drawingAreaY, drawingAreaWidth, drawingAreaHeight);
  238. }
复制代码


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


代码下载


你可能感兴趣的:(HTML5)