Ch19 全局阴影与图像合成

阴影效果

创建阴影效果需要操作以下4个属性:

  • context.shadowColor:阴影颜色。
  • context.shadowOffsetX:阴影x轴位移。正值向右,负值向左。
  • context.shadowOffsetY:阴影y轴位移。正值向下,负值向上。
  • context.shadowBlur:阴影模糊滤镜。数据越大,扩散程度越大。

这四个属性只要设置了第一个和剩下三个中的任意一个就有阴影效果。不过通常情况下,四个属性都要设置。

例如,创建一个向右下方位移各5px的红色阴影,模糊2px,可以这样写。

  1. context.shadowColor = "red";
  2. context.shadowOffsetX = 5;
  3. context.shadowOffsetY = 5;
  4. context.shadowBlur= 2;

需要注意的是,这里的阴影同其他属性设置一样,都是基于状态的设置。因此,如果只想为某一个对象应用阴影而不是全局阴影,需要在下次绘制前重置阴影的这四个属性。

下面的例子摘抄自《HTML5 Canvas开发详解》第二版,案例名为 textArranger,是一个交互的网页。结合了上两节所说的 文本API 和本节的阴影属性。大家可以自己打开链接尝试一下,看看每个属性的效果是什么。本例代码过长,在此不贴。

演示 19-1

运行结果:

textArranger

全局透明globalAlpha

这个也是很简单的一个属性,默认值为1.0,代表完全不透明,取值范围是0.0(完全透明)~1.0。这个属性与阴影设置是一样的,如果不想针对全局设置不透明度,就得在下次绘制前重置globalAlpha

总结一下:基于状态的属性有哪些?

——globalAlpha

——globalCompositeOpeartion

——strokeStyle

——textAlign,textBaseline

——lineCap,lineJoin,lineWidth,miterLimit

——fillStyle

——font

——shadowBlur,shadowColor,shadowOffsetX,shadowOffsetY

我们通过一个代码,来体验一下globalAlpha的神奇之处~

  1. <!DOCTYPE html>
  2. <html lang="zh">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>全局透明</title>
  6. <style>
  7. body { background: url("./images/bg3.jpg") repeat; }
  8. #canvas { border: 1px solid #aaaaaa; display: block; margin: 50px auto; }
  9. </style>
  10. </head>
  11. <body>
  12. <div id="canvas-warp">
  13. <canvas id="canvas">
  14. 你的浏览器居然不支持Canvas?!赶快换一个吧!!
  15. </canvas>
  16. </div>
  17. <script>
  18. window.onload = function(){
  19. var canvas = document.getElementById("canvas");
  20. canvas.width = 800;
  21. canvas.height = 600;
  22. var context = canvas.getContext("2d");
  23. context.fillStyle = "#FFF";
  24. context.fillRect(0,0,800,600);
  25. context.globalAlpha = 0.5;
  26. for(var i=0; i<=50; i++){
  27. var R = Math.floor(Math.random() * 255);
  28. var G = Math.floor(Math.random() * 255);
  29. var B = Math.floor(Math.random() * 255);
  30. context.fillStyle = "rgb(" + R + "," + G + "," + B + ")";
  31. context.beginPath();
  32. context.arc(Math.random() * canvas.width, Math.random() * canvas.height, Math.random() * 100, 0, Math.PI * 2);
  33. context.fill();
  34. }
  35. };
  36. </script>
  37. </body>
  38. </html>

演示 19-2

运行结果:

globalAlpha

是不是非常的酷?终于有点艺术家的范儿了吧。

图像合成globalCompositeOperation

两个图像重合的时候,就涉及到了对这两个图像的合成处理。globalCompositeOperation属性设置或返回如何将一个源(新的)图像绘制到目标(已有)的图像上。

源图像 = 您打算放置到画布上的绘图。

目标图像 = 您已经放置在画布上的绘图。

描述
source-over 默认。在目标图像上显示源图像。
source-atop 在目标图像顶部显示源图像。源图像位于目标图像之外的部分是不可见的。
source-in 在目标图像中显示源图像。只有目标图像内的源图像部分会显示,目标图像是透明的。
source-out 在目标图像之外显示源图像。只会显示目标图像之外源图像部分,目标图像是透明的。
destination-over 在源图像上方显示目标图像。
destination-atop 在源图像顶部显示目标图像。源图像之外的目标图像部分不会被显示。
destination-in 在源图像中显示目标图像。只有源图像内的目标图像部分会被显示,源图像是透明的。
destination-out 在源图像外显示目标图像。只有源图像外的目标图像部分会被显示,源图像是透明的。
lighter 显示源图像 + 目标图像。
copy 显示源图像。忽略目标图像。
xor 使用异或操作对源图像与目标图像进行组合。

下面我用一段代码来说明一下这些值的意义。

  1. <!DOCTYPE html>
  2. <html lang="zh">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>图像合成</title>
  6. <style>
  7. #canvas { border: 1px solid #aaaaaa; display: block; margin: 50px auto; }
  8. </style>
  9. </head>
  10. <body>
  11. <div id="canvas-warp">
  12. <canvas id="canvas">
  13. 你的浏览器居然不支持Canvas?!赶快换一个吧!!
  14. </canvas>
  15. </div>
  16. <script>
  17. window.onload = function(){
  18. var canvas = document.getElementById("canvas");
  19. canvas.width = 800;
  20. canvas.height = 600;
  21. var context = canvas.getContext("2d");
  22. context.globalCompositeOperation = "source-out";
  23. context.globalAlpha = 0.5;
  24. for(var i=0; i<=50; i++){
  25. var R = Math.floor(Math.random() * 255);
  26. var G = Math.floor(Math.random() * 255);
  27. var B = Math.floor(Math.random() * 255);
  28. context.fillStyle = "rgb(" + R + "," + G + "," + B + ")";
  29. context.beginPath();
  30. context.arc(Math.random() * canvas.width, Math.random() * canvas.height, Math.random() * 100, 0, Math.PI * 2);
  31. context.fill();
  32. }
  33. };
  34. </script>
  35. </body>
  36. </html>

演示 19-3

运行结果:

globalCompositeOperation

我这个代码相对比较简单,这里推荐一下laijieyao的专栏——【HTML5】Canvas之globalCompositeOperation属性详解,这篇博客里面介绍了该属性的11值的不同效果,大家可以看一下有一个直观的感受。

这里的代码和上面的一样,但是用到了图像合成,所以把背景和空白矩形去掉了,不然的话所有的图像都是合成图像,因为他们都是建立在那个空白矩形之上的。虽然只加了context.globalCompositeOperation = "source-out";一句而已,其他的圆都不见了,有时候只会显示1~2个圆。因为source-out就是图像合成处理时,保留没有被叠加的图像。因此可以推出,在随机生成的50个圆中,有49个都重叠了。

还有其他的属性,童鞋们私下也可以自己尝试一下,都能带来不一样的神奇效果。


这一小节介绍了阴影、透明与图像合成,大家消化一下,建议其他属性值都自己尝试一下加深理解。我们继续向着终点前进!~😋