javascript--15使用canvas绘图

一、基本用法
1.要使用canvas元素,需要先给定其width和height来设置绘图区域的大小。canvas中间的文本会在浏览器不支持canvas的情况下显示出来。
<canvas width="1500px"height="1500px"id='drawing'>do not support.</canvas>
2.绘图上下文:
要在canvas绘图,需要通过getContext方法来获取上下文。传入参数“2d”,就可以获取2d上下文。在调用getContext方法之前要先判断一下该方法是否存在。
vardrawing=document.getElementById("drawing");
if(drawing.getContext){//判断方法是否存在
varcontext=drawing.getContext('2d');//创建上下文
}
二、常用2D上下文绘图方法
1.填充矩形:
使用指定的颜色、图片等对图形进行填充。
fillStyle:可以是字符串、渐变对象、模式对象等,用来设置填充区域的效果;
fillRect(x,y,w,d):在画布上填充指定的矩形区域,效果使用fillStyle中的设定。方法有四个参数:x坐标、y坐标、宽度、高度。
clearRect(x,y,w,d):清除画布上的指定区域。方法有四个参数:x坐标、y坐标、宽度、高度。
//绘制红色矩形
context.fillStyle="red"; context.fillRect(10,10,50,50);
//绘制蓝色半透明举行
context.fillStyle="rgba(0,0,255,0.5)"; context.fillRect(30,30,50,50);
//清除中间小矩形块
context.clearRect(35,40,10,10);
运行效果:
2.绘制矩形
lineWidth:设置边框线条的宽度;
lineJoin:设置图形的线条相交处是round、bevel、mitel;
shadowColor:用CSS颜色设置阴影颜色;
shadowOffsetX:形状或阴影X轴方向偏移值,默认为0;
shadowOffsetY:形状或阴影X轴方向偏移值,默认为0;
shadowBlur:模糊的像素数,默认为0。
//边框宽度
context.lineWidth=10; //设置阴影
context.shadowOffsetX=5; context.shadowOffsetY=5; ontext.shadowColor="rgba(0,0,0,0.5)"; context.shadowBlur=4;
//线条拐角处
context.lineJoin="round";
//绘制红色矩形
context.strokeStyle="red"; context.strokeRect(10,100,100,100);
//绘制绿色矩形
context.strokeStyle="green"; context.strokeRect(30,130,100,100);
3.绘制路径
可以通过绘制路径来画出复杂的线条和形状。几个常用方法:
准备绘制:
beginPath():绘制路径前要先调用该方法,表示即将绘制路径;
绘制:
moveTo(x,y):从当前点将绘图游标移动到(x,y)而不画线;
lineTo(x,y):从上一条开始绘制一条线,到(x,y)为止。
arc(x,y,radius,start,end,counterclockwise):绘制以(x,y)为圆心,半径为radius,起始角度为start,结束角度为end的圆弧。最后一个参数表示是否按逆时针方向计算。
结束绘制:
context.closePath();//结束绘制
context.fill();//填充区域
context.stroke();//描边
//坐标原点移动
context.translate(400,110); context.lineWidth=1;
//复杂线条
context.beginPath(); context.arc(0,0,100,0,2*Math.PI,false); context.moveTo(102,0); context.arc(0,0,103,0,2*Math.PI,false); context.closePath();//结束绘制
4.绘制文本
设置文本格式:
font:设置文本的字体、颜色、大小;
textAlign:文本对齐方式,包括start,end,center;
textBaseline:文本的基线。
绘制文本:
fillText(text,x,y):使用fillStyle属性绘制文本,其中参数text是要绘制的文本内容,x,y表示坐标位置。
//绘制文本
context.font="bold 14px"; context.textBaseline="middle"; context.textAlign="center"; context.fillText("12",0,-90); context.fillText("3",90,0); context.fillText("6",0,90); context.fillText("9",-90,0);
//绘制表盘指针
context.moveTo(0,0); context.lineTo(70,0); context.moveTo(0,0); context.lineTo(0,-80); context.stroke();
5.绘制图像
要将图像绘制到画布上,需要调用drawImage方法。该方法最多有9个参数:
drawImage(image,源图像x坐标,源图像y坐标,源图像宽度,源图像高度,目标图像x坐标,目标图像y坐标,目标图像宽度,目标图像高度)。
//绘制图像
varimg=document.getElementById("img"); context.drawImage(img,0,0,112,150,300,100,112,150); context.drawImage(img,0,0,112,150,390,220,56,75);
6.模式
模式就是使用重复的图像进行填充或者描边效果。
createPattern(image,pattern):该方法用来创建一个新模式。第一个参数时一个image对象,第二个参数表示图像的重复方式:repeat,repeat-x,repeat-y,no-repeat.
varpattern=context.createPattern(img,"repeat"); context.fillStyle=pattern; context.fillRect(0,400,300,300);
7.渐变 CanvasGradient
①创建线性渐变:
线性渐变先调用方法创建渐变对象:createLinearGradient(起点x坐标,起点y坐标,终点x坐标,终点y坐标);
然后调用方法指定色标:addColorStop(x,y)其中x是色标位置是0-1之间的数值,y是css表示的颜色。
然后调用fillStyle或者strokeStyle设置成渐变对象,就可以了。
//线性渐变
vargradient=context.createLinearGradient(-200,200,-100,300); gradient.addColorStop(0,'white'); gradient.addColorStop(1,'black'); context.fillStyle=gradient; context.fillRect(-200,200,100,100);
②创建放射渐变:
创建渐变对象:调用createRadialGradient(起点圆心x坐标,起点圆心y坐标,起点圆半径,终点圆x坐标,终点圆y坐标,终点圆半径);
调用addColorStop()方法设置色标;
将fillStyle或者strokeStype设置成放射渐变对象。
//放射渐变
vargradientR=context.createRadialGradient(200,200,10,200,200,100); gradientR.addColorStop(0,'white'); gradientR.addColorStop(1,'blue'); context.fillStyle=gradientR; context.fillRect(100,100,200,200);
背景:与浏览器环境中的其他组件类似,<canvas>由几组API组成,但并非所有浏览器都支持所有这些API。除了几倍基本绘图能力的2D上下文,<canvas>还建议了一个名为WebGL的3D上下文。目前,所有支持该元素的浏览器都支持2D上下文及文本API。因此我们这篇文章就只讲2D上下文。
兼容性:IE9+以及主流浏览器

1.基本用法
要使用<canvas>元素,必须先设置其width和height属性,指定可以绘图的区域大小(也能通过CSS属性添加样式)。出现在开始和结束标签的内容是必备信息,如果浏览器不支持<canvas>元素,就会显示这些信息,类似于<img>中的alt属性。
<canvas id="drawing" width="200" height="100">Your browser doesn't support canvas tag</canvas>

要在这块画布canvas绘图,需要取得绘图上下文。传入"2d",就可以取得2D上下文
var drawing  = document.getElementById("drawing");

if(drawing.getContext){
  var context = drawing.getContext("2d");
  ....
}

使用toDataURL()方法,可以导出在<canvas>元素上绘制的元素。这个方法接受一个参数,即图像耳MIME类似格式("image/png"),而且适合于创建图像的任何上下文,
var drawing = document.getElementById("drawing");

if(drawing.getContext){
  //取得图像的数据URL
  var imgURL = drawing.toDataURL("image/png");
 
  //显示图像
  var image = document.createElement("img");
  image.src=imgURL;  //imgURL:data:image/png;base64,
  document.body.appendChild(img);

}
默认情况下,浏览器会将图像编码为PNG格式,除非另行指定。例如"image/jpeg";
如果绘制到画布上的图像源自不同的域,toDataURL()方法会抛出错误

2.2D上下文
①2D上下文的两种基本绘图操作时填充和描边。填充,就是用指定的样式(颜色、渐变或图像)填充图形;描边,就是只在图形的边缘划线。操作的结果取决于两个属性:fillStyle和StrokeStyle。这个属性的值可以是字符串、渐变对象或模式对象,而且他们的默认值都是“#000000”;字符串可以是颜色值的任何格式,包括颜色明、十六进制码、rgb、rgba、hsl或hsla
context.strokeStyle = "red";
context.fillStyle = "#0000ff"

②绘制矩形
与矩形有关的方法包括fillRect()、strokeRect和clearRect()。这三个方法都能接收4个参数:矩形的x坐标、矩形的y坐标、矩形的宽度和矩形高度。这些参数的单位都是像素
//绘制红色矩形
context.fillStyle = "#ff0000";
conetxt.fillRect(10, 10, 50, 50);

//绘制半透明的蓝色矩形
context.fillStyle = "rgba(0, 0, 255, 0.5)";
context.fillRect(30, 30, 50, 50);
描边线条的宽度:lineWidth,该属性的值可以是任意整数
线条末端的形状:lineCap,这属性的值方头"butt"、源头"round"、方头"square"
线条相交的方式:lineJoin,这属性的值"round"圆交、"bevel"斜交、“miter”斜接

clearRect()方法用于清除画布上的矩形区域(经典例子:刮刮乐)

③绘制路径
首先:beginPath()方法,表示要开始绘制新路径
然后:调用下列方法来实际绘制路径
           rect(x, y, width, height):从点(x,y)开始绘制一个矩形路径,宽度和高度分别由width和height决定
           arc(x, y, radius, startAngle, endAngle, counterClockwIse):以(x,y)为圆心,半径为radius,startAngle和endAngle分别为起始和结束角度。最后一个参数表示startAngle和endAngle是否                 按逆时针计算,值为false表示按顺时针计算,绘制成一条弧线
           arcTo(x1, y1, x2, y2, radius):从上一点开始绘制一条弧线,到(x2, y2)为止,兵器以给定的半径radius穿过(x1, y1).
           lineTo(x, y):从上一点开始绘制一条直线,到(x, y)为止
           moveTo(x, y):将绘图游标移动到(x, y),就不是从上一点了
接下来: 调用closePath()绘制一条连接到路径起点的线条
               调用fill()方法或者stroke()对路径进行填充或者描边,这取决于画笔用的是fillStyle还是strokeStyle。
最后:调用clip(),可以在路径上创建一个剪切区域
//开始路径
context.beginPath();

//绘制外圆,角度转弧度 PI /180 * 角度
context.arc(100, 100, 99, 0, 2 * Math.PI, false);

//绘制内圆,这里必须要先使用moveTo,因为画笔默认是从上一点开始画的,不使用会绘制出多余的线条
context.moveTo(194, 100);
context.arc(100, 100, 94 , 0, 2* Math.PI, false);

④绘制文本
绘制文本主要由两个方法:fillText() 和 strokeText(),使用fillText()更好,因为文字实心更好看,模拟了在网页中正常显示文本
两个方法都可以接收4个参数:要绘制的文本字符串、x坐标、y坐标和可选的最大像素宽度
这两个方法都以下列3个属性为基础,都是上下文的属性
font:表示文本样式、大小及字体,用CSS中指定字体的格式来写,例如"bold 14px Arial"
textAlign:表示文本对齐方式。可能的值有"start"、"end"、"left"、"right"、"center"。建议使用"start"和"end"而不是"left"和"right"
textBaseLine:表示文本的基线,可能的值有"top"、"hanging"、"middle"、“alphabetic”字母的、"ideographic"表意的和"bottom"
context.font = "bold 14px Arial";
context.textAlign = "center";
contetx.textBaseLine = "middle";
context.fillText("12",  100, 20);
这里把textAlign设置为"center",把textBaseLine设置为"middle",所以坐标(100, 20)表示的是文本水平和垂直重点的坐标。
当textBaseLine值为"hanging"、"ideographic"、"alphabetic"时分别指向字体的特定基线坐标

由于绘制文本比较复杂,特定是需要把文本控制在某一区域中的时候,2D上下文提供了辅助确定文本大小的方法measureText()。这个方法接受一个参数,即要绘制的文本。返回一个TextMetrics对象,目前只有一个width属性。例如,你想再一个140px款的矩形区域上绘制hello word!可以从100px的字体大小开始递减,最终找到合适的字体大小

⑤变换
通过上下文的变换,可以把处理后的图像绘制到画布上。
rotate(angle):围绕原点旋转图像angle弧度
scale(scaleX, scaleY):缩放图像
translate(x, y):将坐标原点移动到(x, y)。执行后,坐标(0, 0)会变成之前由(x, y)表示的点
transform(m1_1, m1_2, m2_1, m2_2, dx, dy): 直接修改变换矩阵

如果你知道将来还要返回某组属性与变换的组合,可以对上下文对象调用save()方法。调用这个方法后,当时的所有设置都会进入一个栈结构,得以妥善保管。然会对上下文进行其他修改。等想要回到之前保存的设置时,可以调用restore()方法,在保存设置的栈结构中向前返回一级,恢复之前的状态。其实我觉得重新设置也不麻烦。save()方法保存的只是对绘图上下文的设置与包换,不会保存绘图上下文的内容

⑥绘制图像
对上下文对象使用drawImage()方法。可以使用三种不同参数组合。
1.传入一个HTML<img>元素,以及绘制该图像的起点的x和y坐标。
2.如果你想要改变绘制后图像的大小,可以再多传入两个参数,分别表示目标宽度和目标高度。通过这种方法来缩放图像并不影响上下文的变换矩阵。
3.再复杂一点,可以选择把图像的某个区域绘制到上下文。这种调用方法需要传入9个参数:要绘制的图像、源图像的x坐标、源图像的y坐标、源图像的宽度、源图像的高度、目标图像的x坐标、目标图像的y坐标、目标图像的宽度、目标图像的高度。

除了给drawImage()方法传入<img>元素外,还可以传入另一个<canvas>元素作为第一个参数。这样,就可以把另一个画布内容绘制到当前画布上。

⑦阴影
2D上下文会根据以下几个属性的值,自动为形状或路径绘制出阴影
shadowColor、shadowOffsetX、shadowOffsetY、shadowBlur

⑧渐变
对上下文使用createLinearGradient()方法创建线性渐变对象。该方法接收4个参数:起点的x坐标、起点的y坐标、终点的x坐标、重点的y坐标
创建线性渐变对象后,下一部就是使用addColorStop()来指定色标。这个方法接收两个参数:色标位置和CSS颜色值。色标位置是一个0到1之间的数字。
var gradient = context.createLinearGradient(30, 30, 70, 70);
gradient.addColorStop(0, "white");
gradient.addColorStop(1, "black");

//绘制渐变矩形
context.fillStyle = gradient;
context.fillRect(30, 30, 50, 50)
如果没把渐变坐标和绘制矩形匹配的话,就会只显示一部分渐变

创建放射渐变,可以使用createRadialGradient()方法。该方法接收6个参数,对应着两个圆的圆心和半径。因为创建比较麻烦,所以径向渐变并不是那么容易控制。不过一般来说,让起点圆和重点圆保持为同心圆的情况比较多。

⑨模式
模式其实就是重复的图像,可以用来填充或描边图形。调用上下文对象的createPattern()方法并传入两个参数:一个HTML<img>元素和一个表示如何重复图像的字符串。其中,第二个参数的值与CSS的background-repeat属性值相同,包括"repeat"、"repeat-x"、"repeat-y"和"no-repeat";
var image = document.images[0],
       pattern = context.createPattern(image,"repeat");

//绘制矩形
context.fillStyle = pattern;
context.fillRect(10, 10, 150, 150);
需要注意的是,模式与渐变一样,都是从画布的原点(0,, 0)开始的。

10.合成
2D上下文对象还有两个属性,可以应道到2D上下文中所有绘制操作的属性:globalAlpha和globalComposition-Operation
其中globalAlpha是一个介于0到1之间的值,包括0和1,用于指定所有绘制的透明度。默认为0

第二个属性globalCompositionOperation表示后绘制的图形怎样与先绘制的图形结合,可能的值很多,只列几个,详情,戳globalCompositionOperation
source-over(默认值):后绘制的图形位于绘制的图形上方

2D上下文的使用就先讲到这里,3D就不讲了,毕竟支持度不高
首页 > JavaScript高级程序设计 > JavaScript高级程序设计:学习笔记9--使用Canvas绘图和HTML5脚本编程

JavaScript高级程序设计:学习笔记9--使用Canvas绘图和HTML5脚本编程

1. 使用Canvas绘图
1. 基本用法
要使用<canvas>元素,必须先设置其width和height属性,指定可以绘图的区域大小.出现在开始和结束标签中的内容是后备信息,如果浏览器不支持就显示这些信息.
要在这块画布上绘图,需要取得绘图上下文,则需要调用getContext()方法并传入上下文的名字,例如传入"2d".
我们可以使用toDataURL()方法导出在<canvas>元素上绘制的图像.一个具体实例如下:
<!DOCTYPE html>
<html>
<head>
    <title>Canvas Fill Rect Example</title>
</head>
<body>
    <canvas id="drawing" width="200" height="200">Your browser doesn't support the canvas tag.</canvas>
    <input type="button" value="Export" id="export-btn" >
    <script type="text/javascript">
        window.onload = function(){
            var drawing = document.getElementById("drawing"),
                btn     = document.getElementById("export-btn");

            //make sure <canvas> is completely supported
            if (drawing.getContext){

                var context = drawing.getContext("2d");

                //draw a red rectangle
                context.fillStyle = "#ff0000";
                context.fillRect(10, 10, 50, 50);

                //draw a blue rectangle that's semi-transparent
                context.fillStyle = "rgba(0,0,255,0.5)";
                context.fillRect(30, 30, 50, 50);
            }               

            btn.onclick = function(){
                //get data URI of the image
                var imgURI = drawing.toDataURL();

                //display the image
                var image = document.createElement("img");
                image.src = imgURI;
                document.body.appendChild(image);   

            };
        };

    </script>
    </body>
</html>
浏览器显示如下:


2. 2D上下文
1. 填充和描边
填充,就是用指定的样式填充图形;描边,就是只在图形的边缘画线,分别涉及到两个属性:fillStyle和strokeStyle:
if (drawing.getContext){
     var context = drawing.getContext("2d");

     context.strokeStyle = "red";
     context.fillStyle = "#0000ff";
}
备注:这里是预先设定格式,然后绘制图形(而并非将这个绘制区域的填充改为#0000ff,描边改为red)参考下一节:绘制矩形.
2. 绘制矩形
矩形是唯一一种可以在2D上下文中绘制的形状.与矩形有关的方法包括fillRect(),strokeRect()和clearRect().这三个方法都能接收4个参数:矩形的x坐标,矩形的y坐标,矩形的宽度和矩形的高度.这些参数的单位都是像素.
2.1 fllRect()方法在画布上绘制的矩形会填充指定的颜色,而填充的颜色通过fillStyle属性指定:
        window.onload = function(){
            var drawing = document.getElementById("drawing");

            //make sure <canvas> is completely supported
            if (drawing.getContext){
                var context = drawing.getContext("2d");

                //绘制红色矩形
                context.fillStyle = "#ff0000";
                context.fillRect(10, 10, 50, 50);

                //绘制半透明的蓝色矩形
                context.fillStyle = "rgba(0, 0, 255, 0.5)";
                context.fillRect(30, 30, 50, 50);
            }
        };
浏览器显示如下:


2.2 strokeRect()方法在画布上绘制的矩形会使用指定的颜色描边.描边的颜色通过strokeStyle属性指定:
            var drawing = document.getElementById("drawing");

            //make sure <canvas> is completely supported
            if (drawing.getContext){

                var context = drawing.getContext("2d");

                //绘制红色描边矩形
                context.strokeStyle = "#ff0000";
                context.strokeRect(10, 10, 50, 50);

                //绘制半透明的蓝色描边矩形
                context.strokeStyle = "rgba(0, 0, 255, 0.5)";
                context.strokeRect(30, 30, 50, 50);
            }
浏览器显示如下:


2.3 clearRect()方法用于清除画布上的矩形区域:
var drawing = document.getElementById("drawing");

            //make sure <canvas> is completely supported
            if (drawing.getContext){

                var context = drawing.getContext("2d");

                //绘制红色矩形
                context.fillStyle = "#ff0000";
                context.fillRect(10, 10, 50, 50);

                //绘制半透明的蓝色矩形
                context.fillStyle = "rgba(0, 0, 255, 0.5)";
                context.fillRect(30, 30, 50, 50);

                //在两个矩形重叠的地方清除一个小矩形
                context.clearRect(40, 40, 10, 10);
               }
浏览器显示如下:
3. 绘制路径
要绘制路径,首先必须调用beginPath()方法,表示要开始绘制新路径.然后,再通过调用下列方法来实际的绘制路径
1. arc(x, y, radius, startAngle, endAngle, counterclockwise):以(x,y)为圆心绘制一条弧线,弧线的半径为radius,起始和结束角度(用弧度表示)分别为startAngle和endAngle.最后一个参数表示startAngle和endAngle是否按逆时针方向计算,值为false表示按顺时针方向计算.
2. arcTo(x1, y1, x2, y2, radius):从上一点开始绘制一条弧线,到(x2, y2)为止,并且以给定的半径radius穿过(x1, y1)
3. bezierCurveTo(c1x, c1y, c2x, c2y, x, y):从上一点开始绘制一条曲线,到(x,y)为止,并且以(c1x, c1y)和(c2x, c2y)为控制点.
4. lineTo(x, y):从上一点开始绘制一条直线,到(x, y)为止.
5. moveTo(x, y):将绘图游标移动到(x, y),不画线.
6. quadraticCurveTo(cx, cy, x, y):从上一点开始绘制一条二次曲线,到(x, y)为止,并且以(cx, cy)作为控制点.
7. rect(x, y, width, height):从点(x, y)开始绘制一个矩形,宽度和高度分别由width和height指定.这个方法绘制的是矩形路径,而不是strokeRect()和fillRect()所绘制的独立的形状.
实例如下:绘制一个不带数字的时钟表盘:
            var drawing = document.getElementById("drawing");

            //make sure <canvas> is completely supported
            if (drawing.getContext){
                var context = drawing.getContext("2d");

                //开始路径
                context.beginPath();

                //绘制外圆
                context.arc(100, 100, 99, 0, 2 * Math.PI, false);

                //绘制内圆
                context.moveTo(194, 100);   //如果没有这句话,则图形将从(200,0)开始绘制内圆
                context.arc(100, 100, 94, 0, 2 * Math.PI, false);

                //绘制分针
                context.moveTo(100, 100);
                context.lineTo(100, 15);

                //绘制时针
                context.moveTo(100, 100);
                context.lineTo(35, 100);

                //描边路径--显示所绘制的钟表
                context.stroke();
              }
浏览器显示如下:

4. 绘制文本
绘制文本通常有两个方法:fillText()和strokeText().这两个方法都可以接收4个参数:要绘制的文本字符串,x坐标,y坐标和可选的最大像素值.而且这三个方法都以下列3个属性为基础:
1. font:表示文本样式,大小及字体,用CSS中指定字体的格式来指定.
2. textAlign:表示文本对其方式.可能的值有"start","end","left","right"和"center".不推荐使用"left"和"right".
3. textBaseline:表示文本的基线.可能的值有"top","hanging","middle","alphabetic","ideographic"和"bottom".值为top,y坐标表示文本顶端,值为"bottom",y坐标表示文本底端,值为hanging,alphabetic和ideographic,则y坐标分别指向字体的特定基线坐标.
fillText()方法使用fillStyle属性绘制文本,而strokeText()方法是用strokeStyle属性为文本描边.
实例如下:
               context.font = "bold 14px Arial";
                context.textAlign = "center";
                context.textBaseline = "middle";
                context.fillText("12", 100, 20);
浏览器显示如下:

5. 变换
1. rotate(angle):围绕远点旋转图像angle弧度.
2. scale(scaleX, scaleY):缩放图像,在X方向乘以scaleX,在y方向乘以scaleY.scaleX和scaleY的默认值是1.0
3. translate(x, y):将坐标原定移动到(x, y).执行这个变换之后,坐标(0,0)会变成之前由(x,y)表示的点.
4. transform(m1_1, m1_2, m2_1, m2_2, dx, dy):直接修改变换矩阵,方法是乘以如下矩阵:
m1_1 m1_2 dx
m2_1 m2_2 dy
0 0 1
5. setTransform(m1_1, m1_2, m2_1, m2_2, dx, dy):将变换矩阵重置为默认状态,然后再调用transform
实例如下:
            var drawing = document.getElementById("drawing");

            if (drawing.getContext) {
                var context = drawing.getContext("2d");

                //开始路径
                context.beginPath();

                //绘制外圆
                context.arc(100, 100, 99, 0, 2 * Math.PI, false);

                //绘制内圆
                context.moveTo(194, 100);   //如果没有这句话,则图形将从(200,0)开始绘制内圆
                context.arc(100, 100, 94, 0, 2 * Math.PI, false);

                //变换原点
                context.translate(100, 100);

                //旋转表针
                context.rotate(1);

                //绘制分针
                context.moveTo(0, 0);
                context.lineTo(0, -85);

                //绘制时针
                context.moveTo(0, 0);
                context.lineTo(-65, 0);

                context.stroke();
            }
浏览器显示如下:

而我们可以通过save()在堆栈中保存设置,而通过restore()方法恢复上一级状态.我们可以连续使用save()和restore()方法:
               var context = drawing.getContext("2d");

                context.fillStyle = "#ff0000";
                context.save();

                context.fillStyle = "#00ff00";
                context.translate(100, 100);
                context.save();

                context.fillStyle = "#0000ff";
                context.fillRect(0, 0, 100, 200);   //从点(100, 100)开始绘制蓝色矩形

                context.restore();  //注意:这里坐标位置的变换仍然起作用
                context.fillRect(10, 10, 100, 200); //从点(110, 110)开始绘制绿色矩形

                context.restore();
                context.fillRect(0, 0, 100, 200);   //从点(0, 0)开始绘制红色矩形
浏览器显示如下:

6. 绘制图像
使用drawImage()方法来绘制图像.有三种不同的参数组合:
1. 传入一个HTML<img>元素,以及绘制该图像的起点的x和y坐标.
2. 再多传两个参数,分别表示目标宽度和目标高度(进行缩放)
3. 再多传4个参数,表示目标图像的x,y坐标和目标图像的宽度和高度(并没有进行缩放):
实例如下:
        window.onload = function(){
            var drawing = document.getElementById("drawing");

            if (drawing.getContext) {
                var context = drawing.getContext("2d");
                var image = document.getElementById("smiley");

                //draw regular size
                context.drawImage(image, 10, 10);

                //draw smaller
                context.drawImage(image, 50, 10, 20, 30);

                //draw just part of the image
                context.drawImage(image, 0, 10, 50, 50, 0, 100, 40, 60);
            }
        };
浏览器显示如下:

7. 阴影
1. shadowColor:用CSS颜色格式表示的阴影颜色,默认为黑色
2. shadowOffsetX:形状或路径x轴方向的阴影偏移量,默认为0
3. shadowOffsetY:形状或路径y轴方向的阴影偏移量,默认为0
4. shadowBlur:模糊的像素数,默认0,即不模糊
实例如下:
               var context = drawing.getContext("2d");

                //设置阴影
                context.shadowOffsetX = 5;
                context.shadowOffsetY = 5;
                context.shadowBlur = 4;
                context.shadowColor = "rgba(0, 0, 0, 0.5)";

                //绘制红色矩形
                context.fillStyle = "#ff0000";
                context.fillRect(10, 10, 50, 50);

                //绘制蓝色矩形
                context.fillStyle = "rgba(0, 0, 255, 1)";
                context.fillRect(30, 30, 50, 50);
浏览器显示如下:


8. 渐变
渐变由CanvasGradient实例表示,调用createLinearGradient()方法,此方法接收4个参数:起点的x坐标,起点的y坐标,终点的x坐标,终点的y坐标.调用这个方法后,它就会创建一个指定大小的渐变,并返回CanvasGradient对象实例.
创建了渐变对象后,下一步就是使用addColorStop()方法来指定色标.接收两个参数:色标位置和CSS颜色值.色标位置是一个0(开始的颜色)到1(结束的颜色)之间的数字.
实例如下:
               var context = drawing.getContext("2d");

                var gradient = context.createLinearGradient(30, 30, 70, 70);
                gradient.addColorStop(0, "white");
                gradient.addColorStop(1, "red");

                //绘制红色矩形
                context.fillStyle = "#00ff00";
                context.fillRect(10, 10, 50, 50);

                //绘制渐变矩形
                context.fillStyle = gradient;
                context.fillRect(30, 30, 50, 50);
浏览器显示如下:


9. 模式
模式就是重复的图像,可以用来填充或描边图形.要创建一个新模式,可以调用createPattern()方法并传入两个参数:一个HTML<img>元素和一个表示如何重复图像的字符串.其中,第二个参数的值与CSS的background-repeat属性值相同,包括"repeat","repeat-x","repeat-y","no-repeat":
实例如下:
       var context = drawing.getContext("2d"),
                    image = document.images[0],
                    pattern = context.createPattern(image, "repeat");

                //draw a rectangle
                context.fillStyle = pattern;
                context.fillRect(10, 10, 150, 150);
浏览器显示如下:


10. 使用图像数据
通过getImageData()取得原始图像数据.这个方法接收4个参数:要取得其数据的画面区域的x和y坐标以及该区域的像素宽度和高度:
var imageData = context.getImageData(10, 5, 50, 50);
这里返回的对象是ImageData的实例,每个ImageData对象有三个属性:width,height和data.其中data是一个数组,保存着图像中每一个像素的数据.在data数组中,每一个像素用4个元素来保存,分别表示红,绿,蓝和透明度值.
以下代码创建一个简单的灰阶过滤器:
window.onload = function(){
            var drawing = document.getElementById("drawing");

            //make sure <canvas> is completely supported
            if (drawing.getContext){

                var context = drawing.getContext("2d"),
                    image = document.images[0],
                    imageData, data,
                    i, len, average,
                    red, green, blue, alpha;

                //draw regular size
                context.drawImage(image, 0, 0);   

                //get the image data
                imageData = context.getImageData(0, 0, image.width, image.height);
                data = imageData.data;

                for (i=0, len=data.length; i < len; i+=4){

                    red = data[i];
                    green = data[i+1];
                    blue = data[i+2];
                    alpha = data[i+3];

                    //get the average of rgb
                    average = Math.floor((red + green + blue) / 3);

                    //set the colors, leave alpha alone
                    data[i] = average;
                    data[i+1] = average;
                    data[i+2] = average;

                }

                //assign back to image data and display
                imageData.data = data;
                context.putImageData(imageData, 0, 0);
            }
        };
浏览器显示如下:


2. HTML5脚本编程
1. 跨文档消息传递
跨文档消息传递(也简称为XDM),指的是在来自不同域的页面间传递消息.
XDM的核心是postMessage()方法,作用是向另一个地方传递数据.另一个地方指的是包含在当前页面中的<iframe>元素,或者由当前页面弹出的窗口.
postMessage方法接收两个参数:一条消息和一个表示消息接收方来自哪个域的字符串.第二个参数对保障安全通信非常重要,可以防止浏览器把消息发送到不安全的地方.
//注意:所有支持XDM的浏览器也支持iframe的contentWindow属性
var iframeWindow = document.getElementById("myframe").contentWindow;
iframeWindow.postMessage("a secret", "http://www.wrox.com");
接收到XDM消息时,会触发window对象的message事件.这个事件是以异步形式触发的,所以会存在延迟.触发message事件后,传递给onmessage处理程序的事件对象包含以下三方面的重要信息:
1. data:作为postMessage()第一个参数传入的字符串数据.
2. origin:发送消息的文档所在的域.
3. source:发送消息的文档的window对象的代理.如果来自同一个域,就是window.
接收到消息后验证发送窗口的来源是至关重要的:
EventUtil.addHandler(window, "message", function(event) {
    //确保发送消息的域是已知的域
    if (event.origin == "http://www.wrox.com") {
        //处理接收到的数据
        processMessage(event.data);

        //可选:向来源窗口发送回执
        event.source.postMessage("received!", "http://p2p.wrox.com");
    }
});
2. 原生拖放
1. 拖放事件
拖动某元素时,会依次触发以下事件:
1. dragstart:按下鼠标键并开始移动鼠标时触发
2. drag:拖动期间触发
3. dragend:停止拖动时候触发
当某个元素被拖动到一个有效的放置目标上时,下列事件会依次发生:
1. dragenter:元素被拖动到放置目标上
2. dragover:在放置目标上移动
3. dragleave或drop:拖出了放置目标触发dragleave,放到了放置目标触发drop.
2. 自定义放置目标
对于无效的放置目标,我们通过取消dragenter和dragover的默认行为,来使目标变为有效:
var droptarget = document.getElementById("droptarget");

EventUtil.addHandler(droptarget, "dragover", function(event){
    EventUtil.preventDefault(event);
});

EventUtil.addHandler(droptarget, "dragenter", function(event){
    EventUtil.preventDefault(event);
});

//firefox3.5+中,放置时间的默认行为是打开其URL,所以也得取消drop事件的默认行为
EventUtil.addHandler(droptarget, "drop", function(event){
    EventUtil.preventDefault(event);
});
3. dataTransfer对象
dataTransfer是事件对象的属性,所以只能在拖放事件的事件处理程序中访问dataTransfer对象.它有两个主要方法:getData()和setData():getData可以取得由setData保存的值,而setData方法的第一个参数,也是getData()方法唯一的一个参数,是一个字符串,表示保存的数据类型,取值为"text"或"URL":
//设置和接收文本数据
event.dataTransfer.setData("text", "some text");
var text = event.dataTransfer.getData("text");

//设置和接收URL
event.dataTransfer.setData("URL", "http://www.wrox.com");
var url = event.dataTransfer.getData("URL");
保存在dataTransfer对象中的数据只能在drop事件处理程序中读取.如果在ondrop处理程序中没有读到数据,那就是dataTransfer对象已经被销毁,数据也丢失了.
在拖动文本框中的文本时,浏览器会调用setData()方法,将拖动的文本以"text"格式保存在dataTransfer对象中.类似的,在拖放链接或图像时,会调用setData()方法并保存URL.然后,在这些元素被拖放到放置目标时,就可以通过getData()读到这些数据.
实例如下:
<!DOCTYPE html>
<html>
<head>
    <title>Data Transfer Example</title>
    <script type="text/javascript" src="EventUtil.js"></script>
</head>
<body>
    <p>Try dragging the link over to the red square. This won't work correctly in Opera.</p>
    <a href="http://www.wrox.com">Wrox homepage</a>
    <div style="width: 100px; height: 100px; float: middle; background: red" id="droptarget"></div>
    <div id="output"></div>
    <script type="text/javascript">
        var droptarget = document.getElementById("droptarget");

        function handleEvent(event){
            document.getElementById("output").innerHTML += event.type + "<br>";
            switch(event.type){
                case "drop":
                case "dragdrop":
                    droptarget.innerHTML = event.dataTransfer.getData("url") || event.dataTransfer.getData("text/uri-list");
                    /* falls through */

                case "dropenter":
                case "dragover":
                    EventUtil.preventDefault(event);
                    break;
            }

        }

        EventUtil.addHandler(droptarget, "dragenter", handleEvent);
        EventUtil.addHandler(droptarget, "dragover", handleEvent);
        EventUtil.addHandler(droptarget, "dragleave", handleEvent);
        EventUtil.addHandler(droptarget, "drop", handleEvent);

    </script>
</body>
</html>
浏览器显示如下:

4. dropEffect与effectAllowed
通过dataTransfer对象,可以确定被拖动的元素以及作为放置目标的元素能够接收什么操作,额外的两个属性为:dropEffect和effectAllowed:
1. dropEffect属性可以知道被拖动的元素能够执行哪些放置行为:
"none":不能把拖放元素放在这里,这是除文本框之外所哟元素的默认值.
"move":应该把拖放的元素移动到放置目标.
"copy":应该把拖放的元素复制到放置目标.
"link":表示放置目标会打开拖动的元素.
要使用dropEffect属性,必须在ondragenter事件处理程序中针对放置目标来设置它.
2. effectAllowed属性表示允许拖动元素的哪种dropEffect:
"uninitialized":没有给被拖动的元素设置任何放置行为
"none":被拖动元素不能有任何行为
"copy":只允许值为"copy"的dropEffect
"link":只允许值为"link"的dropEffect
"move":只允许值为"move"的dropEffect
"copyLink":只允许值为"copy"和"link"的dropEffect
"copyMove":只允许值为"copy"和"move"的dropEffect
"linkMove":只允许值为"link"和"move"的dropEffect
"all":允许任意dropEffect
必须在ondragstart事件处理程序中设置effectAllowed属性.
5. 可拖动
HTML5为所有HTML元素规定了一个draggable属性,为true表示可以拖动,为false表示不能拖动.

、基本用法

1.要使用canvas元素,需要先给定其width和height来设置绘图区域的大小。canvas中间的文本会在浏览器不支持canvas的情况下显示出来。

<canvas width="1500px" height="1500px" id='drawing'>do not support.</canvas>
2.绘图上下文:

要在canvas绘图,需要通过getContext方法来获取上下文。传入参数“2d”,就可以获取2d上下文。在调用getContext方法之前要先判断一下该方法是否存在。

var drawing=document.getElementById("drawing");
if(drawing.getContext){//判断方法是否存在
          var context=drawing.getContext('2d');//创建上下文

}
二、常用2D上下文绘图方法

1.填充矩形:

使用指定的颜色、图片等对图形进行填充。

fillStyle:可以是字符串、渐变对象、模式对象等,用来设置填充区域的效果;
fillRect(x,y,w,d):在画布上填充指定的矩形区域,效果使用fillStyle中的设定。方法有四个参数:x坐标、y坐标、宽度、高度。
clearRect(x,y,w,d):清除画布上的指定区域。方法有四个参数:x坐标、y坐标、宽度、高度。

//绘制红色矩形
context.fillStyle="red";        
context.fillRect(10,10,50,50);   
//绘制蓝色半透明举行      
context.fillStyle="rgba(0,0,255,0.5)";
context.fillRect(30,30,50,50);
//清除中间小矩形块
context.clearRect(35,40,10,10);

运行效果:



2.绘制矩形

lineWidth:设置边框线条的宽度;
lineJoin:设置图形的线条相交处是round、bevel、mitel;
shadowColor:用CSS颜色设置阴影颜色;
shadowOffsetX:形状或阴影X轴方向偏移值,默认为0;
shadowOffsetY:形状或阴影X轴方向偏移值,默认为0;
shadowBlur:模糊的像素数,默认为0。

//边框宽度
context.lineWidth=10;        
//设置阴影
context.shadowOffsetX=5;
context.shadowOffsetY=5;
ontext.shadowColor="rgba(0,0,0,0.5)";
context.shadowBlur=4;
//线条拐角处
context.lineJoin="round";
//绘制红色矩形
context.strokeStyle="red";
context.strokeRect(10,100,100,100);
//绘制绿色矩形   
context.strokeStyle="green";
context.strokeRect(30,130,100,100);



3.绘制路径

可以通过绘制路径来画出复杂的线条和形状。几个常用方法:

准备绘制:

beginPath():绘制路径前要先调用该方法,表示即将绘制路径;
绘制:

moveTo(x,y):从当前点将绘图游标移动到(x,y)而不画线;
lineTo(x,y):从上一条开始绘制一条线,到(x,y)为止。
arc(x,y,radius,start,end,counterclockwise):绘制以(x,y)为圆心,半径为radius,起始角度为start,结束角度为end的圆弧。最后一个参数表示是否按逆时针方向计算。
结束绘制:

context.closePath();//结束绘制
context.fill();//填充区域
context.stroke();//描边

//坐标原点移动
context.translate(400,110);
context.lineWidth=1;
//复杂线条
context.beginPath();
context.arc(0,0,100,0,2*Math.PI,false);
context.moveTo(102,0);
context.arc(0,0,103,0,2*Math.PI,false);
context.closePath();//结束绘制

4.绘制文本

设置文本格式:

font:设置文本的字体、颜色、大小;
textAlign:文本对齐方式,包括start,end,center;
textBaseline:文本的基线。
绘制文本:

fillText(text,x,y):使用fillStyle属性绘制文本,其中参数text是要绘制的文本内容,x,y表示坐标位置。


//绘制文本
context.font="bold 14px";
context.textBaseline="middle";
context.textAlign="center";
context.fillText("12",0,-90);
context.fillText("3",90,0);
context.fillText("6",0,90);
context.fillText("9",-90,0);
//绘制表盘指针
context.moveTo(0,0);
context.lineTo(70,0);
context.moveTo(0,0);
context.lineTo(0,-80);
context.stroke();

 


5.绘制图像

要将图像绘制到画布上,需要调用drawImage方法。该方法最多有9个参数:

drawImage(image,源图像x坐标,源图像y坐标,源图像宽度,源图像高度,目标图像x坐标,目标图像y坐标,目标图像宽度,目标图像高度)。

//绘制图像
var img=document.getElementById("img");
context.drawImage(img,0,0,112,150,300,100,112,150);
context.drawImage(img,0,0,112,150,390,220,56,75);


6.模式

模式就是使用重复的图像进行填充或者描边效果。

createPattern(image,pattern):该方法用来创建一个新模式。第一个参数时一个image对象,第二个参数表示图像的重复方式:repeat,repeat-x,repeat-y,no-repeat.

var pattern=context.createPattern(img,"repeat");
context.fillStyle=pattern;
context.fillRect(0,400,300,300);


7.渐变 CanvasGradient

①创建线性渐变:

线性渐变先调用方法创建渐变对象:createLinearGradient(起点x坐标,起点y坐标,终点x坐标,终点y坐标);

然后调用方法指定色标:addColorStop(x,y)其中x是色标位置是0-1之间的数值,y是css表示的颜色。

然后调用fillStyle或者strokeStyle设置成渐变对象,就可以了。


//线性渐变
var gradient=context.createLinearGradient(-200,200,-100,300);
gradient.addColorStop(0,'white');
gradient.addColorStop(1,'black');
context.fillStyle=gradient;
context.fillRect(-200,200,100,100);



②创建放射渐变:

创建渐变对象:调用createRadialGradient(起点圆心x坐标,起点圆心y坐标,起点圆半径,终点圆x坐标,终点圆y坐标,终点圆半径);

调用addColorStop()方法设置色标;

将fillStyle或者strokeStype设置成放射渐变对象。


//放射渐变
var gradientR=context.createRadialGradient(200,200,10,200,200,100);
gradientR.addColorStop(0,'white');
gradientR.addColorStop(1,'blue');
context.fillStyle=gradientR;
context.fillRect(100,100,200,200);
新的特性是canvas画布功能,通过canvas画布的强大功能可以实现绘画不少图形和其他绚丽的功能。在本文中,读者将学习到如下几个知识点:
  1) 如何动态在canvas画布上绘画图形
  2) HTML 5 canvas的前景特性探讨
  3) 目前浏览器对HTML5的兼容情况
  本文的读者对象为,对HTML 5 Canvas有初步认识及熟悉Javascript的读者。
  设计目标
  首先,我们来设计下这个绘图程序将会拥有什么功能。在这个简单的绘图程序中,首先要有的是一块能给用户涂鸦的画布区域,上面有一只可爱的小鸭,然后我们准备了4种不同颜色的蜡笔,可以给用户给这只小鸭上色,同时也要提供橡皮擦的功能,以方便随时擦除这个小鸭。而除了蜡笔外,也提供了普通的油画笔的效果,当然也指定了每次绘画时笔触范围的大小,这里设定了4个选择。设计好后的绘图应用,效果如下图:
  在这个应用中,用户点左边的四种颜色笔,就可以在指定的矩形框中随便涂鸦,也可而已点右面两种不同的笔触效果(crayon蜡笔)和普通笔,也可以使用橡皮擦,也可以使用右下角四种不同的笔触大小。
  开始使用Canvas画布
  首先,要声明一个canvas画布,使用如下代码声明:
  目前,对canvas支持的最好的浏览器依然是FireFox,Chrome等非IE的浏览器,在本文的这个例子中,也兼顾了对IE浏览器的支持,使用的是一个开源的JS文件,其中提供了一些对canvas的基本支持脚本(在附件下载中包含了该脚本,名称为excanvas.js)。因此,我们可以同时也为了兼顾IE,所以这里改用了
  的方式,如下代码:
  接下来,为了要使用canvas画布的功能,必须如下调用:
context = document.getElementById('canvasInAPerfectWorld').getContext("2d");
  然而,同样为了兼顾在IE下的使用,我们改用以下的代码段实现:
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");

 
  可以看到,在上面的代码中,通过document.createElement创建了一个标签元素canvas,然后再用setAttribute方法设置了画布的高度和宽度等属性(这些都可以通过设置常量属性值进行设置)。然后通过
canvasDiv.appendChild(canvas);
  为canvasDiv增加了一个子元素canvas。然后利用excanvas.js这个专门为IE扩展的canvas元素包中提供的处理方法initElement进行相应的判断处理,即:
  
if(typeof G_vmlCanvasManager != 'undefined') {

  canvas = G_vmlCanvasManager.initElement(canvas);

  }
 
  最后,要使用canvas的绘图功能的话,必须调用canvas的上下文,这里使用的语句是:
  
context = canvas.getContext("2d");
 
  在画布上绘画图形
  接下来,我们开始在canvas上绘制图形。这里我们要对4个鼠标的相关事件进行编码,并且要编写两个相关的方法addClick和redraw。addClick方法记录鼠标移动的点,而redraw方法则将已记录的数据点在canvas画布中绘画出来。
  先来看下鼠标按下时的mouse down事件,代码如下:
  
$('#canvas').mousedown(function(e){

  var mouseX = e.pageX - this.offsetLeft;

  var mouseY = e.pageY - this.offsetTop;

  paint = true;

  addClick(e.pageX - this.offsetLeft, e.pageY - this.offsetTop);

  redraw();

  });

 
  其中设置的变量paint为true时,表明当前正在绘制图形,patint为false时,表示鼠标已经松开。
  再看下鼠标移动时的事件,代码如下:
  
$('#canvas').mousemove(function(e){

  if(paint){//是不是按下了鼠标

  addClick(e.pageX - this.offsetLeft, e.pageY - this.offsetTop, true);

  redraw();

  }

  });

 
  鼠标松开时的事件代码为:
 
 $('#canvas').mouseup(function(e){

  paint = false;

  });

 
  鼠标移开的事件代码为:
  
$('#canvas').mouseleave(function(e){

  paint = false;

  });
 
  下面是addClick方法的代码如下:
  
var clickX = new Array();

  var clickY = new Array();

  var clickDrag = new Array();

  var paint;

  function addClick(x, y, dragging)

  {

  clickX.push(x);

  clickY.push(y);

  clickDrag.push(dragging);

  }

 
  可以看到,这里分别用三个数组clickX,clickY及clickDrag记录了鼠标移动的点的X,Y坐标,以及判断是否鼠标松开的标志。
  再来看下redraw这个方法,其作用为每次都清空画板,然后重新把所有的点都画过,效率不高,但作为本例子来说还是可以接受,代码如下:
function redraw(){

  canvas.width = canvas.width; // Clears the canvas

  context.strokeStyle = "#df4b26";

  context.lineJoin = "round";

  context.lineWidth = 5;

  for(var i=0; i < clickX.length; i++)

  {

  context.beginPath();

  if(clickDrag[i] && i){//当是拖动而且i!=0时,从上一个点开始画线。

  context.moveTo(clickX[i-1], clickY[i-1]);

  }else{

  context.moveTo(clickX[i]-1, clickY[i]);

  }

  context.lineTo(clickX[i], clickY[i]);

  context.closePath();

  context.stroke();

  }

  }

 
  接下来,再定义四种不同的颜色:紫色,绿色,棕色和黄色,分别用四个不同的变量表示,并且用变量curColor保存当前正在使用的颜色,并且也用一个数组clickColor来记录用户每次选择的颜色。代码如下:
 
  var colorPurple = "#cb3594";

  var colorGreen = "#659b41";

  var colorYellow = "#ffcf33";

  var colorBrown = "#986928";

  var curColor = colorPurple;

  var clickColor = new Array();

 
 

 同样,在addClick方法中,也必须加入对用户每次选择颜色的记录,所以更新后的addclick代码如下:
  
function addClick(x, y, dragging)

  {

  clickX.push(x);

  clickY.push(y);

  clickDrag.push(dragging);

  clickColor.push(curColor);

  }

 
  而在redraw的方法中,我们去掉context.strokeStyle一句,将绘画笔的颜色设置到for循环中去设置,更新后的redraw代码如下:
 
function redraw(){

  /* context.strokeStyle = "#df4b26"; */

  context.lineJoin = "round";

  context.lineWidth = 5;

  for(var i=0; i < clickX.length; i++)

  {

  context.beginPath();

  if(clickDrag[i] && i){

  contex.moveTo(clickX[i-1], clickY[i-1]);

  }else{

  context.moveTo(clickX[i]-1, clickY[i]);

  }

  context.lineTo(clickX[i], clickY[i]);

  context.closePath();

  context.strokeStyle = clickColor[i];

  context.stroke();

  }

  }

 
    我们再设置画笔每次绘画笔触范围的大小,同样,有四种选择,分别为小,中,大和很大,并用clickSize数组记录用户的选择,默认的笔触范围大小用curSize进行记录。并且也要更新redraw方法,更新后的addClick,redraw代码如下:
 
function addClick(x, y, dragging)

  {

  clickX.push(x);

  clickY.push(y);

  clickDrag.push(dragging);

  clickColor.push(curColor);

  clickSize.push(curSize);

  }

  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;

  }

  function redraw(){

  。。。。。。。。

  context.strokeStyle = clickColor[i];

  context.lineWidth = radius;

  context.stroke();

  }

  }

 
  最后,我们设置不同笔的绘画效果,分别是蜡笔和普通笔以及橡皮擦功能。用clickTool记录用户选择的工具种类,curTool则为当前用户选择的工具,addClick的方法如下:
 
function addClick(x, y, dragging)

  {

  clickX.push(x);

  clickY.push(y);

  clickDrag.push(dragging);

  if(curTool == "eraser"){

  clickColor.push("white");

  }else{

  clickColor.push(curColor);

  }

  clickColor.push(curColor);

  clickSize.push(curSize);

  }

 
  注意,这里判断如果用户选择的工具是橡皮擦,则将白色加入到clickColor数组中。同样要在redraw的方法中对新的两个绘图工具进行处理,代码如下:
function redraw(){

  context.lineJoin = "round";

  for(var i=0; i < clickX.length; i++)

  {

  context.beginPath();

  if(clickDrag[i] && i){

  context.moveTo(clickX[i-1], clickY[i-1]);

  }else{

  context.moveTo(clickX[i]-1, clickY[i]);

  }

  context.lineTo(clickX[i], clickY[i]);

  context.closePath();

  context.strokeStyle = clickColor[i];

  context.lineWidth = radius;

  context.stroke();

  }

  if(curTool == "crayon") {

  context.globalAlpha = 0.4;

  context.drawImage(crayonTextureImage, 0, 0, canvasWidth, canvasHeight);

  }

  context.globalAlpha = 1;

  }

 
  这里针对当用户选择“crazyon”蜡笔效果时,对绘画的效果进行了透明度的处理。
  最后,我们要把小鸭子的图在画布中画上,首先要声明一个图片对象如下:
 
 var outlineImage = new Image();
 
  然后在prepareCanvas()方法中加载事先准备好的图片:
  
function prepareCanvas(){

  ...

  outlineImage.src = "images/watermelon-duck-outline.png";

  }

 
  最后在redraw的绘画方法中,要使用canvas画布的drawImage方法进行绘画,代码为:
  
function redraw(){

  ...

  context.drawImage(outlineImage, drawingAreaX, drawingAreaY, drawingAreaWidth, drawingAreaHeight);

  }

 
  其中drawingAreaX, drawingAreaY为要在哪个具体位置绘画图形,drawingAreaWidth和
  drawingAreaHeight则为具体图片的宽度和高度。
  我们还要把绘图的区域限制在一个矩形框里,这要用到画布的save和clip方法。其中save用来保存Canvas的状态,而clip方法则是指定一个区域进行剪裁,规定了绘画的区域,代码如下:
 
 function redraw()

  {

  ...

  context.save();

  context.beginPath();

  context.rect(drawingAreaX, drawingAreaY, drawingAreaWidth, drawingAreaHeight);

  context.clip(); //剪裁出指定的绘画区域

  var radius;

  var i = 0;

  for(; i < clickX.length; i++)

  {

  ...

  }

  context.restore(); //使用restore方法,恢复每次保存的canvas状态

  ...

  }








猜你喜欢

转载自zhyp29.iteye.com/blog/2304412
今日推荐