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

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

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

HTML代码:

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

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't know what a canvas element is)
var canvasDiv = document.getElementById('canvasDiv');
canvas = document.createElement('canvas');
canvas.setAttribute('width', canvasWidth);
canvas.setAttribute('height', canvasHeight);
canvas.setAttribute('id', 'canvas');
canvasDiv.appendChild(canvas);
if(typeof G_vmlCanvasManager != 'undefined') {
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('canvas').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
// ----------------
$('#canvas').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();
}); $('#canvas').mousemove(function(e){
if(paint==true){
addClick(e.pageX - this.offsetLeft, e.pageY - this.offsetTop, true);
redraw();
}
}); $('#canvas').mouseup(function(e){
paint = false;
redraw();
}); $('#canvas').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 = '#333333';
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 = 'white';
}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的网页画板就是一个很好的例子

基于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. 解决未能启动服务“VMware Authorization Service”

    计算机-管理-服务--服务列表找到VMware Authorization Service 并双击 打开服务.

  2. Dictionary到List转换中的性能问题 转

    本文来自:http://www.cnblogs.com/353373440qq/p/3488367.html 在应用泛型中,我们经常使用Dictionary,经常会用到Dictionary到List的 ...

  3. PHP 多input file文件上传

    前台html jquery代码 后台PHP处理 前台html <form id="form" method="post" enctype="mu ...

  4. 聚类算法初探(五)DBSCAN

    最近由于工作需要,对聚类算法做了一些相关的调研.现将搜集到的资料和自己对算法的一些理解整理如下,供大家参考. 另外在算法代码方面,我也做了一些实现(包括串行和并行),欢迎感兴趣的朋友探讨和交流. 第一 ...

  5. stage.width/height和stage.stageWidth/stageHeight的区别

    stage.stageWidth和stage.stageHeight就是舞台的宽带和高度 一般默认打开宽带是550,高度是400 那么stage.stageWidth=550,stage.stageH ...

  6. 一个loader加载多个swf

    var _swfLoader:Loader; var _swfRequest:URLRequest; var _swfPathArr:Array = new Array("00.swf&qu ...

  7. XML是什么,它能够做什么?——写给XML入门者

    XML就可以扩展标记语言(eXtensible Markup Language).标记是指计算机所能理解的信息符号,通过此种标记,计算机之间能够处理包括各种信息的文章等.怎样定义这些标记,既能够选择国 ...

  8. Android学习之菜单

    android中包含多种菜单,本例带来的是选项菜单和上下文菜单. 1.选项菜单 在android中,开发者可以在xml文档中部署所要添加的菜单,在后台调用即可. <menu xmlns:andr ...

  9. hibernate-annotation CascadeType.PERSIST不起作用的解决方法

    有如下两个实体类 , Student和Grade 为多对一关系. Student.java @Entity public class Student { private Integer id; pri ...

  10. mysql和VS2010 C++链接过程中出现的问题

    PS:二者连接的过程主要参考这篇博客园文章,http://www.cnblogs.com/justinzhang/archive/2011/09/23/2185963.html 这篇博客园的文章中的代 ...