HTML5 Canvas实践(二)Canvas 高级功能

2.1 保存和恢复绘图状态

          在绘制复杂canvas图像时,经常在各种样式之间切换,甚至有时候会在不同颜色之间反复切换。这种重复很麻烦,它意味着如果要返回之前使用的一些样式,必须重写大量的代码。画布能够记住一些样式和属性,这样就可以再次使用。

    2.1.1 保存绘画状态

          使用save方法可以保存画布状态。代码如下:

 var canvas=$(“#myCanvas”);
 var context = canvas.get(0).getContext(“2d”);
 context.fillStyle=”rgb(255,0,0)”;
 context.save(); //保存画布状态
 context.fillRect(50,50,100,100); //红色正方形

          2D渲染上下文会保存一个绘图状态栈,实际上是一组之前保存的状态,其中最近保存的状态位于顶部。绘图状态的默认栈是空的,调用save方法,就会有一个新状态被放入这个栈,这意味着,你完全可以多次调用save方法,将多个绘图状态逐一保存在栈中,其中最早的状态在底部。然而,无法将任何绘图状态后移,因为这个过程是有严格顺序的。


    2.1.2 恢复绘图状态



          现在,绘制另一个蓝色正方形,使用如下代码:


 context.fillStyle=”rgb(0,0,255)”;
 context.fillRect(200,50,100,100); //蓝色正方形

使用restore方法恢复原先的状态。

context.restore(); //恢复画布状态
context.fillRect(350,50,100,100); //红色正方形

          效果如下:


2.2 变形


        2D渲染上下文的变形功能支持的功能是非常强大的。


    2.2.1 平移


          将2D渲染上下文的原点从一个位置移动到另一个位置。在画布中进行平移使用translate方法,实际上它移动的是2D渲染上下文的坐标原点,而不是所绘制的对象。 通过移动2D渲染上下文的原点,画布中的所有对象都将移动相应的距离,代码如下:

 context.fillRect(150,150,100,100);
 context.translate(150,150);
 context.fillStyle=”rgb(255,0,0)”;
 context.fillRect(150,150,100,100);


          效果如下所示:



          一般情况下,第二次调用fillRect时,所绘制的正方形的原点坐标是(150,150),但是由于执行了一次平移,这个正方形的原点现在变成(300,300)。



    2.2.2 缩放


          另一个变形方法是缩放,它是调整2D渲染上下文的尺寸。它与平移的区别在于(x,y)参数是缩放倍数,而不是像素值。 


 context.scale(2,2);
 context.fillRect(150,150,100,100);




          效果如下所示:



                                          这个例子将2D渲染上下文的x和y方向都乘以2。



    2.2.3 旋转


          如果想将画出的图形旋转,可以使用rotate方法。


 context.rotate(0.7854); //旋转45度
 context.fillRect(150,150,100,100);


          结果如下图所示,这个旋转结果可能并不是所期望的:



          出现这种结果,是因为rotate方法是把2D渲染上下文绕其原点(0,0)进行旋转,原点是屏幕的左上角,所绘制的正方形本身是不会旋转的,它实际上是以45度角绘制到画布中。下图可以帮助理解。



2.3 合成


        本节将介绍两个全局合成属性都会影响到2D渲染上下文的绘图效果。


    2.3.1 全局阿尔法值


          在画布上进行绘画之前,它会应用一个与globalAlpha属性相匹配的阿尔法值。赋给globalAlpha的值必须在0.0(全透明)与1.0(不透明)之间,默认值为1.0。globalAlpha属性会影响将要绘制的对象的透明度。看下面的例子:


 context.fillStyle=”rgb(63,169,245)”;
 context.fillRect(50,50,100,100);
 context.globalAlpha=0.5;
 context.fillStyle=”rgb(255,123,172)”;
 context.fillRect(100,100,100,100);


          效果如下图所示:



          图中,由于我们在绘制了蓝色正方形后才设置globalAlpha属性,所以只有粉色正方形才会受到阿尔法值的影响。



    2.3.2 合成操作



          如果一个图形叠加在另一个图形之上,2D渲染上下文会使用一个名为globalCompositeOperation属性来处理重叠,共有11种可选方法。这种合成称为源覆盖于目标之上,源是绘制的新图形,而目标是可能已经绘制了图形的2D渲染上下文。 使用下面的代码作为模板,了解这11种方法的效果。


 context.fillStyle=”rgb(63,169,245)”;
 context.fillRect(50,50,100,100);
 context.globalCompositeOperation=”source-over”;
 context.fillStyle=”rgb(255,123,172)”;
 context.fillRect(100,100,100,100);


          source-over


          这是默认值,它表示绘制的图形(源)将画在现有画布之上。效果如下图所示:


          destination-over


          这个操作的值与前一个相反,目标绘制在源之上,效果如下图:



          source-top


          这个操作会将源绘制在目标之上,但是在重叠区上两者都是不透明的,绘制在其他位置的源是透明的。效果如下图:



          destination-atop


          这个操作与source-atop相反,在重叠区域上两者都是不透明的,但绘制在其他位置的目标变为透明。效果如下:



          source-in


          在源于目标重叠的区域只绘制源。而不重叠的部分变成透明。如下所示:



          destination-in


          这个操作与source-in相反,在源于目标重叠的区域保留目标。而不重叠的部分都变为透明。如下所示:



          source-out


          在于目标不重叠的区域上绘制源。其他部分都变成透明的。如下所示:



          destination-out


          在于源不重叠的区域上保留目标。其他部分都变为透明的。如下所示:






          lighter


          如果源于目标重叠,将两者的颜色值相加,得到的颜色值的最大值为255,结果就是白色。如下所示:


          copy


          只绘制源,覆盖掉目标。如下所示:


          xor


          只绘制出不重叠的源与目标区域。所有重叠的部分都变成透明的。如下所示:



2.4 阴影


        阴影效果是被人们普遍喜欢,应用最广泛的效果,如果操作正确,它们实际上能够增加图像真实感。在画布中创建阴影效果相对较简单,它通过4个全局属性进行控制。这些属性是shadowBlur、shadowOffsetX、shadowOffsetY和shadowColor。默认情况下,2D渲染上下文是不会绘制阴影效果的。创建阴影效果的方法是将shadowColor修改为不透明值,同时将shadowBlur、shadowOffsetX、shadowOffsetY都设置为非0值。代码如下:


 context.shadowBlur=20;
 context.shadowColor=”rgb(0,0,0)”;
 context.fillRect(50,50,100,100);



          效果如下所示:



          修改shadowBlur、shadowOffsetX或shadowOffsetY属性,能够创建不同的阴影效果。例如:


 cotext.shadowBlur=0;
 context.shadowOffsetX=10;
 context.shadowOffsetY=10;
 context.shadowColor="rgba(100,100,100,0.5)"
 context.fillRect(200,50,100,100);




          效果如下:


2.5 渐变



        有时候,简单的颜色并不够用,画布的渐变颜色是一个不错的方法,fillStyle和strokeStyle都可以接受以CanvasGradient对象表示的渐变颜色值。 画布支持两种类型的渐变:线性渐变(createLinearGradient)和放射性渐变(createRadialGradient)。下面是一个基本的线性渐变的例子。

 var gradient=context.createLinearGradient(0,0,0,canvas.height());
 gradient.addColorStop(0,”rgb(0,0,0)”);
 gradient.addColorStop(1,”rgb(255,255,255)”);
 context.fillStyle=gradient;
 context.fillRect(0,0,canvas.width(),canvas.height());


          效果如下:


          createLinearGradient方法有4个参数:渐变起点的(x,y)坐标,渐变终点的(x,y)坐标。定义一个CanvasGradient对象还不够,需要给它指定一种颜色,调用addColorStop方法,传入两个参数:颜色的偏移量(0表示渐变起点,1表示渐变终点),以及该偏移的颜色值。


2.6 将画布导出为图像


         如果想将画布中绘制的图形导出为图像在其他地方使用,可以使用toDataURL方法,它能够将画布绘图转换为一个数据URL,可以通过它在浏览器上显示一个图像。看下面的例子。


 context.save();
 context.fillRect(50,50,100,100); 
 context.fillStyle=”rgb(255,0,0)”;
 context.fillRect(100,100,100,100);
 context.restore();
 context.fillRect(150,150,100,100);
 var dataURL=canvas.get(0).toDataURL();

          注意,toDataURL是canvas的方法,不是2D渲染上下文的方法。dataURL中记录的值为data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAfQAAAH0CAYAAADL1t+KAAAXvElEQVR4Ae3XQQ4dNxYDwPkD3//KPZMDRItA0ovI8tINS81iG8T/fd/3H38IECBAgACBtwX++/bre3sCBAgQIEDgLwGD7jsgQIAAAQIBAgY9oEQRCBAgQICAQfcNECBAgACBAAGDHlCiCAQIECBAwKD7BggQIECAQICAQQ8oUQQCBAgQIGDQfQMECBAgQCBAwKAHlCgCAQIECBAw6L4BAgQIECAQIGDQA0oUgQABAgQIGHTfAAECBAgQCBAw6AElikCAAAECBAy6b4AAAQIECAQIGPSAEkUgQIAAAQIG3TdAgAABAgQCBAx6QIkiECBAgAABg+4bIECAAAECAQIGPaBEEQgQIECAgEH3DRAgQIAAgQABgx5QoggECBAgQMCg…。前面3个单词是data:image/png,它们表示后续内容是一个PNG格式的图像的数据URL,第4个单词是base64,表示数据采用base64编码格式,剩下的内容是以文本表示的画布图像。效果如下:







          可以将dataURL变量中的字符串赋值给img作为其src,如下面的例子:


 var dataURL=canvas.get(0).toDataURL();
 var img=$(“<img></img>”);
 img.attr(“src”,dataURL);
 canvas.replaceWith(img);




          现在画布上的内容是一副图像,单击右键能够出现”图片另存为…”。如下所示:




  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值