PHP前端开发

超级炫酷的HTML5 Canvas网络画板代码示例详解

百变鹏仔 3个月前 (10-18) #H5教程
文章标签 画板

超级炫酷的HTML5 Canvas网络画板代码示例详解

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

你也可以再这里查看DEMO演示

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

HTML代码:

<p style="width:530px;margin:10px auto">    <p id="canvasp"></p></p>

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

Javascript代码:

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

立即学习“前端免费学习笔记(深入)”;

var canvas;var context;var canvasWidth = 490;var canvasHeight = 220;var padding = 25;var lineWidth = 8;var colorPurple = "#cb3594";var colorGreen = "#659b41";var colorYellow = "#ffcf33";var colorBrown = "#986928";var outlineImage = new Image();var crayonImage = new Image();var markerImage = new Image();var eraserImage = new Image();var crayonBackgroundImage = new Image();var markerBackgroundImage = new Image();var eraserBackgroundImage = new Image();var crayonTextureImage = new Image();var clickX = new Array();var clickY = new Array();var clickColor = new Array();var clickTool = new Array();var clickSize = new Array();var clickDrag = new Array();var paint = false;var curColor = colorPurple;var curTool = "crayon";var curSize = "normal";var mediumStartX = 18;var mediumStartY = 19;var mediumImageWidth = 93;var mediumImageHeight = 46;var drawingAreaX = 111;var drawingAreaY = 11;var drawingAreaWidth = 267;var drawingAreaHeight = 200;var toolHotspotStartY = 23;var toolHotspotHeight = 38;var sizeHotspotStartY = 157;var sizeHotspotHeight = 36;var sizeHotspotWidthObject = new Object();sizeHotspotWidthObject.huge = 39;sizeHotspotWidthObject.large = 25;sizeHotspotWidthObject.normal = 18;sizeHotspotWidthObject.small = 16;var totalLoadResources = 8;var curLoadResNum = 0;

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

function prepareCanvas(){    // Create the canvas (Neccessary for IE because it doesn&#39;t know what a canvas element is)    var canvasp = document.getElementById(&#39;canvasp&#39;);    canvas = document.createElement(&#39;canvas&#39;);    canvas.setAttribute(&#39;width&#39;, canvasWidth);    canvas.setAttribute(&#39;height&#39;, canvasHeight);    canvas.setAttribute(&#39;id&#39;, &#39;canvas&#39;);    canvasp.appendChild(canvas);    if(typeof G_vmlCanvasManager != &#39;undefined&#39;) {        canvas = G_vmlCanvasManager.initElement(canvas);    }    context = canvas.getContext("2d"); // Grab the 2d canvas context    // Note: The above code is a workaround for IE 8 and lower. Otherwise we could have used:    //     context = document.getElementById(&#39;canvas&#39;).getContext("2d");    // Load images    // -----------    crayonImage.onload = function() { resourceLoaded();     };    crayonImage.src = "images/crayon-outline.png";    //context.drawImage(crayonImage, 0, 0, 100, 100);    markerImage.onload = function() { resourceLoaded();     };    markerImage.src = "images/marker-outline.png";    eraserImage.onload = function() { resourceLoaded();     };    eraserImage.src = "images/eraser-outline.png";        crayonBackgroundImage.onload = function() { resourceLoaded();     };    crayonBackgroundImage.src = "images/crayon-background.png";    markerBackgroundImage.onload = function() { resourceLoaded();     };    markerBackgroundImage.src = "images/marker-background.png";    eraserBackgroundImage.onload = function() { resourceLoaded();     };    eraserBackgroundImage.src = "images/eraser-background.png";    crayonTextureImage.onload = function() { resourceLoaded();     };    crayonTextureImage.src = "images/crayon-texture.png";    outlineImage.onload = function() { resourceLoaded();     };    outlineImage.src = "images/watermelon-duck-outline.png";    // Add mouse events    // ----------------    $(&#39;#canvas&#39;).mousedown(function(e)    {        // Mouse down location        var mouseX = e.pageX - this.offsetLeft;        var mouseY = e.pageY - this.offsetTop;        if(mouseX < drawingAreaX) // Left of the drawing area        {            if(mouseX > mediumStartX)            {                if(mouseY > mediumStartY && mouseY < mediumStartY + mediumImageHeight){                    curColor = colorPurple;                }else if(mouseY > mediumStartY + mediumImageHeight && mouseY < mediumStartY + mediumImageHeight * 2){                    curColor = colorGreen;                }else if(mouseY > mediumStartY + mediumImageHeight * 2 && mouseY < mediumStartY + mediumImageHeight * 3){                    curColor = colorYellow;                }else if(mouseY > mediumStartY + mediumImageHeight * 3 && mouseY < mediumStartY + mediumImageHeight * 4){                    curColor = colorBrown;                }            }        }        else if(mouseX > drawingAreaX + drawingAreaWidth) // Right of the drawing area        {            if(mouseY > toolHotspotStartY)            {                if(mouseY > sizeHotspotStartY)                {                    var sizeHotspotStartX = drawingAreaX + drawingAreaWidth;                    if(mouseY < sizeHotspotStartY + sizeHotspotHeight && mouseX > sizeHotspotStartX)                    {                        if(mouseX < sizeHotspotStartX + sizeHotspotWidthObject.huge){                            curSize = "huge";                        }else if(mouseX < sizeHotspotStartX + sizeHotspotWidthObject.large + sizeHotspotWidthObject.huge){                            curSize = "large";                        }else if(mouseX < sizeHotspotStartX + sizeHotspotWidthObject.normal +                         sizeHotspotWidthObject.large + sizeHotspotWidthObject.huge){                            curSize = "normal";                        }else if(mouseX < sizeHotspotStartX + sizeHotspotWidthObject.small +                         sizeHotspotWidthObject.normal + sizeHotspotWidthObject.large + sizeHotspotWidthObject.huge){                            curSize = "small";                                                }                    }                }                else                {                    if(mouseY < toolHotspotStartY + toolHotspotHeight){                        curTool = "crayon";                    }else if(mouseY < toolHotspotStartY + toolHotspotHeight * 2){                        curTool = "marker";                    }else if(mouseY < toolHotspotStartY + toolHotspotHeight * 3){                        curTool = "eraser";                    }                }            }        }        else if(mouseY > drawingAreaY && mouseY < drawingAreaY + drawingAreaHeight)        {            // Mouse click location on drawing area        }        paint = true;        addClick(mouseX, mouseY, false);        redraw();    });    $(&#39;#canvas&#39;).mousemove(function(e){        if(paint==true){            addClick(e.pageX - this.offsetLeft, e.pageY - this.offsetTop, true);            redraw();        }    });    $(&#39;#canvas&#39;).mouseup(function(e){        paint = false;          redraw();    });    $(&#39;#canvas&#39;).mouseleave(function(e){        paint = false;    });}

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

下面是draw的主要方法:

function redraw(){    // Make sure required resources are loaded before redrawing    if(curLoadResNum < totalLoadResources){ return; }    clearCanvas();    var locX;    var locY;    if(curTool == "crayon")    {        // Draw the crayon tool background        context.drawImage(crayonBackgroundImage, 0, 0, canvasWidth, canvasHeight);        // Purple        locX = (curColor == colorPurple) ? 18 : 52;        locY = 19;        context.beginPath();        context.moveTo(locX + 41, locY + 11);        context.lineTo(locX + 41, locY + 35);        context.lineTo(locX + 29, locY + 35);        context.lineTo(locX + 29, locY + 33);        context.lineTo(locX + 11, locY + 27);        context.lineTo(locX + 11, locY + 19);        context.lineTo(locX + 29, locY + 13);        context.lineTo(locX + 29, locY + 11);        context.lineTo(locX + 41, locY + 11);        context.closePath();        context.fillStyle = colorPurple;        context.fill();            if(curColor == colorPurple){            context.drawImage(crayonImage, locX, locY, mediumImageWidth, mediumImageHeight);        }else{            context.drawImage(crayonImage, 0, 0, 59, mediumImageHeight, locX, locY, 59, mediumImageHeight);        }        // Green        locX = (curColor == colorGreen) ? 18 : 52;        locY += 46;        context.beginPath();        context.moveTo(locX + 41, locY + 11);        context.lineTo(locX + 41, locY + 35);        context.lineTo(locX + 29, locY + 35);        context.lineTo(locX + 29, locY + 33);        context.lineTo(locX + 11, locY + 27);        context.lineTo(locX + 11, locY + 19);        context.lineTo(locX + 29, locY + 13);        context.lineTo(locX + 29, locY + 11);        context.lineTo(locX + 41, locY + 11);        context.closePath();        context.fillStyle = colorGreen;        context.fill();            if(curColor == colorGreen){            context.drawImage(crayonImage, locX, locY, mediumImageWidth, mediumImageHeight);        }else{            context.drawImage(crayonImage, 0, 0, 59, mediumImageHeight, locX, locY, 59, mediumImageHeight);        }        // Yellow        locX = (curColor == colorYellow) ? 18 : 52;        locY += 46;        context.beginPath();        context.moveTo(locX + 41, locY + 11);        context.lineTo(locX + 41, locY + 35);        context.lineTo(locX + 29, locY + 35);        context.lineTo(locX + 29, locY + 33);        context.lineTo(locX + 11, locY + 27);        context.lineTo(locX + 11, locY + 19);        context.lineTo(locX + 29, locY + 13);        context.lineTo(locX + 29, locY + 11);        context.lineTo(locX + 41, locY + 11);        context.closePath();        context.fillStyle = colorYellow;        context.fill();            if(curColor == colorYellow){            context.drawImage(crayonImage, locX, locY, mediumImageWidth, mediumImageHeight);        }else{            context.drawImage(crayonImage, 0, 0, 59, mediumImageHeight, locX, locY, 59, mediumImageHeight);        }        // Yellow        locX = (curColor == colorBrown) ? 18 : 52;        locY += 46;        context.beginPath();        context.moveTo(locX + 41, locY + 11);        context.lineTo(locX + 41, locY + 35);        context.lineTo(locX + 29, locY + 35);        context.lineTo(locX + 29, locY + 33);        context.lineTo(locX + 11, locY + 27);        context.lineTo(locX + 11, locY + 19);        context.lineTo(locX + 29, locY + 13);        context.lineTo(locX + 29, locY + 11);        context.lineTo(locX + 41, locY + 11);        context.closePath();        context.fillStyle = colorBrown;        context.fill();            if(curColor == colorBrown){            context.drawImage(crayonImage, locX, locY, mediumImageWidth, mediumImageHeight);        }else{            context.drawImage(crayonImage, 0, 0, 59, mediumImageHeight, locX, locY, 59, mediumImageHeight);        }    }    else if(curTool == "marker")    {        // Draw the marker tool background        context.drawImage(markerBackgroundImage, 0, 0, canvasWidth, canvasHeight);        // Purple        locX = (curColor == colorPurple) ? 18 : 52;        locY = 19;        context.beginPath();        context.moveTo(locX + 10, locY + 24);        context.lineTo(locX + 10, locY + 24);        context.lineTo(locX + 22, locY + 16);        context.lineTo(locX + 22, locY + 31);        context.closePath();        context.fillStyle = colorPurple;        context.fill();            if(curColor == colorPurple){            context.drawImage(markerImage, locX, locY, mediumImageWidth, mediumImageHeight);        }else{            context.drawImage(markerImage, 0, 0, 59, mediumImageHeight, locX, locY, 59, mediumImageHeight);        }        // Green        locX = (curColor == colorGreen) ? 18 : 52;        locY += 46;        context.beginPath();        context.moveTo(locX + 10, locY + 24);        context.lineTo(locX + 10, locY + 24);        context.lineTo(locX + 22, locY + 16);        context.lineTo(locX + 22, locY + 31);        context.closePath();        context.fillStyle = colorGreen;        context.fill();            if(curColor == colorGreen){            context.drawImage(markerImage, locX, locY, mediumImageWidth, mediumImageHeight);        }else{            context.drawImage(markerImage, 0, 0, 59, mediumImageHeight, locX, locY, 59, mediumImageHeight);        }        // Yellow        locX = (curColor == colorYellow) ? 18 : 52;        locY += 46;        context.beginPath();        context.moveTo(locX + 10, locY + 24);        context.lineTo(locX + 10, locY + 24);        context.lineTo(locX + 22, locY + 16);        context.lineTo(locX + 22, locY + 31);        context.closePath();        context.fillStyle = colorYellow;        context.fill();            if(curColor == colorYellow){            context.drawImage(markerImage, locX, locY, mediumImageWidth, mediumImageHeight);        }else{            context.drawImage(markerImage, 0, 0, 59, mediumImageHeight, locX, locY, 59, mediumImageHeight);        }        // Yellow        locX = (curColor == colorBrown) ? 18 : 52;        locY += 46;        context.beginPath();        context.moveTo(locX + 10, locY + 24);        context.lineTo(locX + 10, locY + 24);        context.lineTo(locX + 22, locY + 16);        context.lineTo(locX + 22, locY + 31);        context.closePath();        context.fillStyle = colorBrown;        context.fill();            if(curColor == colorBrown){            context.drawImage(markerImage, locX, locY, mediumImageWidth, mediumImageHeight);        }else{            context.drawImage(markerImage, 0, 0, 59, mediumImageHeight, locX, locY, 59, mediumImageHeight);        }    }    else if(curTool == "eraser")    {        context.drawImage(eraserBackgroundImage, 0, 0, canvasWidth, canvasHeight);        context.drawImage(eraserImage, 18, 19, mediumImageWidth, mediumImageHeight);        }else{        alert("Error: Current Tool is undefined");    }    if(curSize == "small"){        locX = 467;    }else if(curSize == "normal"){        locX = 450;    }else if(curSize == "large"){        locX = 428;    }else if(curSize == "huge"){        locX = 399;    }    locY = 189;    context.beginPath();    context.rect(locX, locY, 2, 12);    context.closePath();    context.fillStyle = &#39;#333333&#39;;    context.fill();        // Keep the drawing in the drawing area    context.save();    context.beginPath();    context.rect(drawingAreaX, drawingAreaY, drawingAreaWidth, drawingAreaHeight);    context.clip();    var radius;    var i = 0;    for(; i < clickX.length; i++)    {                if(clickSize[i] == "small"){            radius = 2;        }else if(clickSize[i] == "normal"){            radius = 5;        }else if(clickSize[i] == "large"){            radius = 10;        }else if(clickSize[i] == "huge"){            radius = 20;        }else{            alert("Error: Radius is zero for click " + i);            radius = 0;            }        context.beginPath();        if(clickDrag[i] && i){            context.moveTo(clickX[i-1], clickY[i-1]);        }else{            context.moveTo(clickX[i], clickY[i]);        }        context.lineTo(clickX[i], clickY[i]);        context.closePath();        if(clickTool[i] == "eraser"){            //context.globalCompositeOperation = "destination-out"; // To erase instead of draw over with white            context.strokeStyle = &#39;white&#39;;        }else{            //context.globalCompositeOperation = "source-over";    // To erase instead of draw over with white            context.strokeStyle = clickColor[i];        }        context.lineJoin = "round";        context.lineWidth = radius;        context.stroke();    }    //context.globalCompositeOperation = "source-over";// To erase instead of draw over with white    context.restore();    // Overlay a crayon texture (if the current tool is crayon)    if(curTool == "crayon"){        context.globalAlpha = 0.4; // No IE support        context.drawImage(crayonTextureImage, 0, 0, canvasWidth, canvasHeight);    }    context.globalAlpha = 1; // No IE support    // Draw the outline image    context.drawImage(outlineImage, drawingAreaX, drawingAreaY, drawingAreaWidth, drawingAreaHeight);}

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