html5 Canvas drawing (二)


本篇主要讲html5 canvas中剪切区域(clip region)、分层、合成(compositing)、变换(Transformation)(旋转、缩放)功能如何应用。

先贴一个以下所有涉及到的实现运行的基本代码段: 

Base Code
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<script type="text/javascript" src="modernizr-latest.js"></script> <script type="text/javascript">
window.addEventListener(
"load", eventWindowLoaded, false);
var Debugger = function() {};
Debugger.log
= function(message) {
try {
console.log(message);
}
catch (exception) { return; }
}

function eventWindowLoaded() { canvasApp(); }

function canvasSupport() {
return Modernizr.canvas;
}

function canvasApp() {
//是否支持CANVAS判断
if(!canvasSupport()) {
return;
}
//取Canvas
var theCanvas = document.getElementById("canvasOne");
//获取绘图环境
contextvar context = theCanvas.getContext("2d");
//绘图方法的实现
function drawScreen() {}
//绘图方法调用执行
drawScreen();
}

</script>

</head>
<body>
<div style="position: absolute; top: 50px; left: 50px; border:1px solid #0000ff">
<canvas id="canvasOne" width="550" height="400">
Your browser does not support HTML5 Canvas.
</canvas>
</div>
</body>
</html>

以下所有实例代码,只要把上面的function drawScreen()替换掉即可! 

clip region 裁剪区域

在clip region中,我们利用.save 与 .restore来把当前绘图状态压入堆栈与从堆栈中恢复;

使用.save保证裁切前的绘图状态;

通过context.rect()来确定要裁切的区域在位置;

通过context.clip()来执行裁切动作;

在Canvas上画图,只有在裁切区域的图形才能显示出来;

使用context.restore()再恢复到裁切前的状态; 

clip region example
function drawScreen() {
context.fillStyle = "black";
context.fillRect(0, 0, 200, 200);
context.save();
//clip the canvas to a 50×50 square starting at 0,0
context.rect(0, 0, 100, 100);
context.clip();
//red circle
context.beginPath();
context.strokeStyle = "red";
context.lineWidth = 5;
context.arc(100, 100, 100, (Math.PI/180)*0, (Math.PI/180)*360, false);
//full circle
context.stroke();
context.closePath();
context.restore();

//reclip to the entire canvas
context.rect(0, 0, 300, 300);
context.clip();
//draw a blue line that is not clipped
context.beginPath();
context.strokeStyle = "blue"; //need list of available colors
context.lineWidth = 5;
context.arc(100, 100, 50, (Math.PI/180)*0, (Math.PI/180)*360, false);
//full circle
context.stroke();
context.closePath();
}

实例效果图:

 

 

Compositing 合成

在Canvas上图形合成,指更好的处理图形的透明度及在画布上的层效果;

compositing操作中有两个比较重要的属性我们先来认识一下: globalAlpha and globalCompositeOperation

globalAlpha:指Canvas的透明度,默认值为1.0,范围是[0.0-1.0];

globalCompositeOperation:应用了“alpha” 及"transformations"的多个图形,是如何绘制的Canvas上的。

共有11种类型: copy\ destination-atop\destination-in\destination-out\destination-over\ lighter\ source-atop\source-in\source-out\source-over\xor

这11种类型中有两个特殊的词"source" and "destination":

 "source":将要在Canvas上绘制的图形(新图形);

 "destination":Canvas上当前显示的图形(旧图形);

  1. copy:指新图形会被保留,其它都被清除掉
  2. destination-atop:指显示新图形与重叠部分的旧图形,旧图形(重叠部分)显示在上层
  3. destination-in:指只显示旧图形的重叠部分的图形
  4. destination-out:指只显示旧图形不重叠部分的图形
  5. destination-over:指新旧图形都显示,把旧图形显示在上层
  6. lighter:指新旧图形都显示,新旧图形重叠部分作加色处理
  7. source-atop:指显示旧图表与重叠部分的新图形,新图形(重叠部分)显示在上层
  8. source-in:指只显示新图形重叠部分的图形
  9. source-out:指只显示新图形中不重叠部分的图形
  10. source-over:指新旧图形都显示,新图形显示在上层
  11. xor:指新旧图形都显示,新旧图形重叠的部分会变成透明。
compositing
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>test</title>
<script type="text/javascript" src="../script/modernizr-latest.js"></script>
<script type="text/javascript">
window.addEventListener("load", eventWindowLoaded, false);
var Debugger = function() {
};
Debugger.log = function(message) {
try {
console.log(message);
} catch (exception) {
return;
}
}
function eventWindowLoaded() {
canvasApp();
}

function canvasSupport() {
return Modernizr.canvas;
}

function canvasApp() {

if(!canvasSupport()) {
return;
}

function drawScreen(compositing, num) {
var name = "c" + num;
var theCanvas = document.getElementById(name);
theCanvas.width=100;
theCanvas.height=100;
var context = theCanvas.getContext("2d");
context.fillStyle = "blue";
context.fillRect(10, 10, 50, 50);
context.globalCompositeOperation = compositing;
context.fillStyle = "red";
context.fillRect(30, 30, 50, 50);
}

drawScreen("copy", 1);
drawScreen("destination-atop", 2);
drawScreen("destination-in", 3);
drawScreen("destination-out", 4);
drawScreen("destination-over", 5);
drawScreen("lighter", 6);
drawScreen("source-atop", 7);
drawScreen("source-in", 8);
drawScreen("source-out", 9);
drawScreen("source-over", 10);
drawScreen("xor", 11);
}
</script>
<style>
td {
border: 1px solid #000000;
}
</style>
</head>
<body>
<div style="position: absolute; top: 50px; left: 50px; border:1px solid #0000ff">
<table>
<tr>
<td><canvas id="c1"></canvas></td>
<td><canvas id="c2"></canvas></td>
<td><canvas id="c3"></canvas></td>
<td><canvas id="c4"></canvas></td>
<td><canvas id="c5"></canvas></td>
</tr>
<tr>
<td><canvas id="c6"></canvas></td>
<td><canvas id="c7"></canvas></td>
<td><canvas id="c8"></canvas></td>
<td><canvas id="c9"></canvas></td>
<td><canvas id="c10"></canvas></td>
<td><canvas id="c11"></canvas></td>
</tr>
</table>
</div>
</body>
</html>

实例效果图:从左到右、从上到下,分别表示1,2,……11,这11种类型生成的效果图

 

Transformations 变换

变换的本质就是指从数学(矩阵)的角度来调整图形的物理属性;当然,这是原理;我们在实现的时候,只需要调用方法即可;

移动translate、旋转rotation  、缩放scale  、变换transforms

Transformations are applied to shapes and paths drawn after the setTransform() or other transformation function is called

只有在应用context.setTransform()方法后,对图形的各种变换才能生效;

实例:

 

Transform
function drawScreen() {
context.fillStyle = "blue";
context.fillRect(210,210,50,50);
context.setTransform(1,0,0,1,0,0);//启动变换
var angleInRadians = 45 * Math.PI / 180;
context.rotate(angleInRadians);//旋转(参数为弧度)
context.fillStyle = "red";
context.fillRect(0,0,200,200);
}

效果如图:

蓝色的box并没有发生旋转;红的box是以Canvas的原点为中心顺时针旋转了45度(为何没有以红色box中心为原点旋转呢?);

Canvas的旋转原点,默认为Canvas的坐标系的(0,0)点,若不进行原点平移就旋转,自然是像整个画布做了旋转;

We must “translate” the point of origin to the center of our shape to rotate it around its own center 

我们必须通地context.translate()方法来平移原点,才能按绘制的图形中心来旋转图形自身;

平移原理:

实例:

 

translate
function drawScreen() {
context.fillStyle = "blue";
context.fillRect(210,210,50,50);
context.setTransform(1,0,0,1,0,0);
var angleInRadians = 45 * Math.PI / 180;
var x = 0;
var y = 0;
var width = 200;
var height = 200;
context.translate(x+.5*width, y+.5*height);//平移
context.rotate(angleInRadians);
context.fillStyle = "red";
context.fillRect(-.5*width,-.5*height , width, height);
}

效果图:

 

context.scale()实现图形的缩放,

此方法有两个参数: 一个是对X轴方向的缩放,一个是对Y轴方向的缩放,正常的图形参数默认都为1;

例如,我们要对图形放大两倍,则使用context.scale(2,2);

以(25,25)为顶点,长宽为50的正方形,放大2倍
function drawScreen() {
context.fillStyle = "blue";
context.fillRect(0, 0, 50, 50);
context.fillRect(150, 50, 50, 50);
context.fillRect(50, 150, 50, 50);
context.setTransform(1, 0, 0, 1, 0, 0);
context.scale(2, 2);
context.fillStyle = "red";
context.fillRect(25, 25, 50, 50);
}

效果图:

 

scale与ratation也存在相似问题,就是原点的问题;

如果我们在变换前不进行原点的平移的话,scale功能默认的原点也是canvas的原点;

相当于对整个画布进行scale 默认是延x轴正向(left),y轴正向进行缩放(down);

如果想图形依然在原来的位置,从图形的中心位置进行scale,就需要先进行原点的平移context.translate();

以(25,25)为顶点,长宽为50的正方形,为其中心为原点,放大二倍
function drawScreen() {

context.setTransform(1, 0, 0, 1, 0, 0);
var x = 25;
var y = 25;
var width = 50;
var height = 50;
context.translate(x + .5 * width, y + .5 * height);
context.scale(2, 2);
context.fillStyle = "red";
context.fillRect(-.5 * width, -.5 * height, width, height);
}

 

 

祝愿大家龙年吉祥!!! 

 

 

posted @ 2012-01-16 11:33  folotus  阅读(4141)  评论(0编辑  收藏  举报