HTML5新增了Canvas API,允许js在标签识别的画布上绘制图形,创建动画,设置设计实时视频处理或渲染。借助一套编程接口,用户可以在页面上绘制出任何漂亮的图形。
【学习重点】
在HTML5文档中,使用标签可以在网页中创建一块画布。用法如下:
<canvas id="muCanvas" width="200" height="100">canvas>
该标签包括三个属性:
注意:与不同,
。如果结束标签不存在,则文档的其余部分会被认为是替代内容,将不会显示出来。
<canvas id="muCanvas" style="border:1px solid;" width="200" height="100">canvas>
使用js可以在canvas画布内绘画,或者设置动画。
【操作步骤】
标签,设置canvas的id属性值以便js调用。<canvas id="myCanvas" width="200" height="100">
var c = document.getElementById("myCanvas");
var context = c.getContext("2d");
getContext(“2d”)方法返回一个画布渲染上下文对象,使用该对象可以在canvas元素中绘制图形,参数2d表示二维绘图。
context.fillStyle = "pink";
context.fillRect(50, 25, 100, 50);
这两行代码中,fillStyle属性定义将要绘制的矩形的填充颜色为粉色,fillRect()方法制定了要绘制的矩形的位置和尺寸。图形的位置由前面的canvas坐标值决定,尺寸由后面的宽度和高度值决定。完整代码:
<script>
window.onload = function() {
var c = document.getElementById("myCanvas");
var context = c.getContext("2d");
context.fillStyle = "pink";
context.fillRect(50, 25, 100, 50);
}
script>
<body>
<canvas id="myCanvas" style="border: 1px solid;" width="200" height="100">canvas>
body>
fillRect(50, 25, 100, 50)方法可以用来绘制矩形图形,它的前两个参数用于绘制图形的x轴和y轴坐标,后面两个参数设置绘制矩形的宽度和高度。
本节将介绍一些基本图形的绘制,包括矩形、直线、圆形、曲线等形状或路径。
canvas提供了3种方法绘制矩形。
参数说明:
<script>
window.onload = function() {
draw();
function draw() {
var canvas = document.getElementById("canvas");
if (canvas.getContext) {
var ctx = canvas.getContext('2d');
ctx.fillRect(25, 25, 100, 100);
ctx.clearRect(45, 45, 60, 60);
ctx.strokeRect(50, 50, 50, 50);
}
}
}
script>
<body>
<canvas id="canvas" style="border: 1px solid #999;" width="300" height="200">canvas>
body>
使用路径绘制图形的步骤如下:
第一步,创建路径起始点。
第二布,使用画图命令绘制路径。
第三步,封闭路径。
第四步,生成路径之后,可以通过描边或填充路径区域来渲染图形。
需要调用的方法说明如下:
<script>
window.onload = function() {
draw();
function draw() {
var canvas = document.getElementById("canvas");
if (canvas.getContext) {
var ctx = canvas.getContext('2d');
ctx.beginPath();
ctx.arc(75, 75, 50, 0, Math.PI * 2, true);
ctx.moveTo(110, 75);
ctx.arc(75, 75, 35, 0, Math.PI, false);
ctx.moveTo(65, 65);
ctx.arc(60, 65, 5, 0, Math.PI * 2, true);
ctx.moveTo(95, 65);
ctx.arc(90, 65, 5, 0, Math.PI * 2, true);
ctx.stroke();
}
}
}
</script>
<body>
<canvas id="canvas" style="border: 1px solid #999;" width="300" height="200"></canvas>
</body>
上面代码中使用arc()方法,调用它可以绘制圆形,接下来详细讲解。
使用arc()方法可以绘制弧或者圆。用法如下:
context.arc(x,y,r,sAngle,eAngle,counterclockwise);
参数说明:
如果使用arc()创建圆,可以把起始点设置为0,结束角设置为2*Math.PI。
<script>
window.onload = function() {
draw();
function draw() {
var canvas = document.getElementById("canvas");
if (canvas.getContext) {
var ctx = canvas.getContext("2d");
for (var i = 0; i < 4; i++) {
for (var j = 0; j < 3; j++) {
ctx.beginPath();
var x = 25 + j * 50;
var y = 25 + i * 50;
var radius = 20;
var startAngle = 0;
var endAngle = Math.PI + (Math.PI * j) / 2;
var anticlockwise = i % 2 == 0 ? false : true;
ctx.arc(x, y, radius, startAngle, endAngle, anticlockwise);
if (i > 1) {
ctx.fill();
} else {
ctx.stroke();
}
}
}
}
}
}
script>
<body>
<canvas id="canvas" style="border: 1px solid #999;" width="300" height="200">canvas>
body>
使用lineTo()方法可以绘制直线。用法如下:
lineTo(x,y)
参数x和y分别表示终点位置的x坐标和y坐标。lineTo(x, y)将绘制一条从当前位置到指定(x, y)位置的直线。
<script>
window.onload = function() {
draw();
function draw() {
var canvas = document.getElementById("canvas");
if (canvas.getContext) {
var ctx = canvas.getContext('2d');
ctx.beginPath();
ctx.moveTo(25, 25);
ctx.lineTo(105, 25);
ctx.lineTo(25, 105);
ctx.fill();
ctx.beginPath();
ctx.moveTo(125, 125);
ctx.lineTo(125, 45);
ctx.lineTo(45, 125);
ctx.closePath();
ctx.stroke();
}
}
}
script>
<body>
<canvas id="canvas" style="border: 1px solid #999;" width="300" height="200">canvas>
body>
在上面实例代码中,从调用beginPath()方法准备绘制一个新的形状路径开始,使用movePath()方法移动到目标位置,两条线段绘制后构成三角形的两条边。当路径使用填充(fill)时路径会自动闭合。而使用描边(stroke)命令时则不会自动闭合路径。如果没有添加闭合路径closePath()到描边三角形中,则只绘制两条线段,并不是一个完整的三角形。
context.arcTo(x1, y1, x2, y2, r);
参数说明:
<script>
window.onload = function() {
draw();
function draw() {
var canvas = document.getElementById("canvas");
if (canvas.getContext) {
var ctx = canvas.getContext('2d');
ctx.beginPath();
ctx.moveTo(20, 20);
ctx.lineTo(100, 20);
ctx.arcTo(150, 20, 150, 70, 50);
ctx.lineTo(150, 120);
ctx.stroke();
}
}
}
script>
<body>
<canvas id="canvas" style="border: 1px solid #999;" width="300" height="200">canvas>
body>
canvas支持颜色和样式选项,如线性、渐变、图案、透明度和阴影。
使用fillStyle和strokeStyle属性可以给图形上色。其中,fillStyle设置图形的填充颜色,strokeStyle设置图形轮廓的颜色。
颜色值可以是表示CSS颜色值的字符串,那么这个新值机会成为新绘制的图形的默认值。如果要给每个图形定义不同的颜色,就需要重新设置fillStyle或strokeStyle的值。
<script>
window.onload = function() {
draw();
function draw() {
var canvas = document.getElementById("canvas");
if (canvas.getContext) {
var ctx = canvas.getContext('2d');
for (var i = 0; i < 6; i++) {
for (var j = 0; j < 6; j++) {
ctx.fillStyle = 'rgb(' + Math.floor(255 - 42.5 * i) + ',' + Math.floor(255 - 42.5 * j) + ', 0)';
ctx.fillRect(j * 25, i * 25, 25, 25);
}
}
}
}
}
</script>
<body>
<canvas id="canvas" style="border: 1px solid #999;" width="300" height="200"></canvas>
</body>
在嵌套for结构中,使用变量i和j为每一个方格产生唯一的RGB色彩值,其中仅修改红绿色通道的值,保持蓝色通道的值不变。
使用globalAlpha全局属性可以设置绘制图形的不透明度,另外也可以通过色彩的不透明度参数来为图形设置不透明度。相对与使用globalAlpha属性来说,这种方法更灵活些。使用rgba(R, G, B, A)方法可以设置具有不透明度的颜色。
rgba(R, G, B, A)
其中R、G、B将颜色的红色、绿色和蓝色分别指定为0~255之间的十进制整数;A把alpha(不透明)成分指定为0.0-1.0之间的一个浮点数值,0.0为完全透明,1.0表示完全不透明。
<script>
window.onload = function() {
draw();
function draw() {
var canvas = document.getElementById("canvas");
if (canvas.getContext) {
var ctx = canvas.getContext('2d');
ctx.fillStyle = '#FD0';
ctx.fillRect(0, 0, 75, 75);
ctx.fillStyle = '#6C0';
ctx.fillRect(75, 0, 75, 75);
ctx.fillStyle = '#09F';
ctx.fillRect(0, 75, 75, 75);
ctx.fillStyle = '#F30';
ctx.fillRect(75, 75, 75, 75);
ctx.globalAlpha = 0.2;
for (var i = 0; i < 7; i++) {
ctx.beginPath();
ctx.arc(75, 75, 10 + 10 * i, 0, Math.PI * 2, true);
ctx.fill();
}
}
}
}
script>
<body>
<canvas id="canvas" style="border: 1px solid #999;" width="300" height="200">canvas>
body>
使用lineWidth属性可以设置线条的粗细,取值必须为正值,默认为1.0。
<script>
window.onload = function() {
draw();
function draw() {
var canvas = document.getElementById("canvas");
if (canvas.getContext) {
var ctx = canvas.getContext('2d');
for (var i = 0; i < 12; i++) {
ctx.strokeStyle = "red";
ctx.lineWidth = 1 + i;
ctx.beginPath();
ctx.moveTo(5, 5 + i * 14);
ctx.lineTo(140, 5 + i * 14);
ctx.stroke();
}
}
}
}
script>
<body>
<canvas id="canvas" style="border: 1px solid #999;" width="300" height="200">canvas>
body>
lineCap属性用于设置线段端点的样式,包括三种:butt、round和square,默认为butt。
<script>
window.onload = function() {
draw();
function draw() {
var canvas = document.getElementById("canvas");
if (canvas.getContext) {
var ctx = canvas.getContext('2d');
var lineCap = ['butt', 'round', 'square'];
ctx.strokeStyle = 'red';
ctx.beginPath();
ctx.moveTo(10, 10);
ctx.lineTo(10, 150);
ctx.moveTo(150, 10);
ctx.lineTo(150, 150);
ctx.stroke();
ctx.strokeStyle = 'blue';
for (var i = 0; i < lineCap.length; i++) {
ctx.lineWidth = 20;
ctx.lineCap = lineCap[i];
ctx.beginPath();
ctx.moveTo(10, 30 + i * 50);
ctx.lineTo(150, 30 + i * 50);
ctx.stroke();
}
}
}
}
script>
<body>
<canvas id="canvas" style="border: 1px solid #999;" width="300" height="200">canvas>
body>
lineJoin属性用于设置两条线段连接处的样式。包括三种样式:round、bevel和miter,默认值为miter。
<script>
window.onload = function() {
draw();
function draw() {
var canvas = document.getElementById("canvas");
if (canvas.getContext) {
var ctx = canvas.getContext('2d');
var lineJoin = ['round', 'bevel', 'miter'];
ctx.strokeStyle = 'blur';
for (var i = 0; i < lineJoin.length; i++) {
ctx.lineWidth = 25;
ctx.lineJoin = lineJoin[i];
ctx.beginPath();
ctx.moveTo(10 + i * 150, 30);
ctx.lineTo(100 + i * 150, 30);
ctx.lineTo(100 + i * 150, 100);
ctx.stroke();
}
}
}
}
script>
<body>
<canvas id="canvas" style="border: 1px solid #999;" width="300" height="200">canvas>
body>
miterLimit属性用于设置两条线段连接处交点的绘制方式,其作用是为斜面的长度设置一个上限,默认为10,即规定斜面的长度不能超过线条宽度的10倍。当斜面的长度达到线条宽度的10倍时,就会变为斜角。如果lineJoin属性round或bevel时,miterLimit属性无效。
<script>
window.onload = function() {
draw();
function draw() {
var canvas = document.getElementById("canvas");
if (canvas.getContext) {
var ctx = canvas.getContext('2d');
for (var i = 1; i < 10; i++) {
ctx.strokeStyle = 'blue';
ctx.lineWidth = 10;
ctx.lineJoin = 'miter';
ctx.miterLimit = i * 10;
ctx.beginPath();
ctx.moveTo(10, i * 30);
ctx.lineTo(100, i * 30);
ctx.lineTo(10, 33 * i);
ctx.stroke();
}
}
}
}
</script>
<body>
<canvas id="canvas" style="border: 1px solid #999;" width="300" height="200"></canvas>
</body>
使用setLineDash()方法和lineDashOffset属性可以定义虚线样式。setLineDash()方法接受一个数组来指定线段与间隙的交替,lineDashOffset属性设置起始偏移量。
<script>
window.onload = function() {
var ctx = document.getElementById("canvas").getContext('2d');
var offset = 0;
function draw() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.setLineDash([4, 4]);
ctx.lineDashOffset = -offset;
ctx.strokeRect(50, 50, 200, 100);
}
function march() {
offset++;
if (offset > 16) {
offset = 0;
}
draw();
setTimeout(march, 100);
}
march();
}
script>
<body>
<canvas id="canvas" style="border: 1px solid #999;" width="300" height="200">canvas>
body>
要绘制线性渐变,首先使用createLinearGradient()方法创建canvasGradient对象,然后使用addColorStop()方法进行上色。
createLinearGradient()方法用法如下:
context.createLinearGradient(x0, y0, x1, y1);
参数说明:
addColorStop()方法用法如下:
gradient.addColorStop(stop, color);
参数说明:
<script>
window.onload = function() {
draw();
function draw() {
var ctx = document.getElementById("canvas").getContext('2d');
var lingrad = ctx.createLinearGradient(0, 0, 0, 200);
lingrad.addColorStop(0, '#ff0000');
lingrad.addColorStop(1 / 7, '#ff9900');
lingrad.addColorStop(2 / 7, '#ffff00');
lingrad.addColorStop(3 / 7, '#00ff00');
lingrad.addColorStop(4 / 7, '#00ffff');
lingrad.addColorStop(5 / 7, '#0000ff');
lingrad.addColorStop(6 / 7, '#ff00ff');
lingrad.addColorStop(1, '#ff0000');
ctx.fillStyle = lingrad;
ctx.strokeStyle = lingrad;
ctx.fillRect(0, 0, 300, 200);
}
}
script>
<body>
<canvas id="canvas" style="border: 1px solid #999;" width="300" height="200">canvas>
body>
使用addColorStop()可以添加多个色标,色标可以在0-1之间任意位置添加。
要绘制经向渐变,首先需要使用createRadialGradient()方法创建canvasGradient对象,然后使用addColorStop()方法进行上色。createRadialGradient()方法的用法:
context.createRadialGradinet(x0, y0, r0, x1, y1, r1);
参数说明:
<script>
window.onload = function() {
draw();
function draw() {
var ctx = document.getElementById("canvas").getContext('2d');
var radgrad = ctx.createRadialGradient(150, 100, 0, 150, 100, 100);
radgrad.addColorStop(0, '#A7D30C');
radgrad.addColorStop(0.9, '#019F62');
radgrad.addColorStop(1, 'rgba(1, 159, 98, 0)');
ctx.fillStyle = radgrad;
ctx.fillRect = (0, 0, 300, 200);
}
}
script>
<body>
<canvas id="canvas" style="border: 1px solid #999;" width="300" height="200">canvas>
body>
使用createPattern()方法可以绘制图案效果。用法如下:
context.createPattern(image, "repeat|repeat-x|repeat-y|no-repeat");
参数说明如下:
创建图案步骤与创建渐变有些类似,需要先创建一个pattern对象,然后将其赋予fillStyle属性或strokeStyle属性。
<script>
window.onload = function() {
draw();
function draw() {
var ctx = document.getElementById("canvas").getContext('2d');
var img = new Image();
img.src = '../img/doge.jpg';
img.onload = function() {
var ptrn = ctx.createPattern(img, 'repeat');
ctx.fillStyle = ptrn;
ctx.fillRect(0, 0, 600, 600);
}
}
}
script>
<body>
<canvas id="canvas" style="border: 1px solid #999;" width="600" height="400">canvas>
body>
创建阴影需要四个属性:
shadowColor:设置阴影颜色。
shadowBlur:设置阴影的模糊级别。
shadowOffsetX:设置阴影在x轴的偏移距离。
shadowOffsetY:设置阴影在y轴的偏移距离。
【实例】下面实例演示如何创建文字阴影效果。
<script>
window.onload = function() {
draw();
function draw() {
var ctx = document.getElementById("canvas").getContext('2d');
// 设置阴影
ctx.shadowOffsetX = 4;
ctx.shadowOffsetY = 4;
ctx.shadowBlur = 4;
ctx.shadowColor = "rgba(0, 0, 0, 0.5)";
// 绘制文本
ctx.font = "60px Times New Roman";
ctx.fillStyle = "pink";
ctx.fillText("你好佩琪", 5, 80);
}
}
script>
<body>
<canvas id="canvas" style="border: 1px solid #999;" width="300" height="200">canvas>
body>
前面介绍了fill()方法可以填充图形,该方法可以接受两个值,用来定义填充规则。
填充规则根据某处在路径的外面或者里面来决定是否被填充,这对于路径相交或者路径被嵌套的时候极为有用。
<script>
window.onload = function() {
draw();
function draw() {
var ctx = document.getElementById("canvas").getContext('2d');
ctx.beginPath();
ctx.arc(50, 50, 30, 0, Math.PI * 2, true);
ctx.arc(50, 50, 15, 0, Math.PI * 2, true);
ctx.fill("evenodd");
}
}
script>
<body>
<canvas id="canvas" style="border: 1px solid #999;" width="300" height="200">canvas>
body>
不设置与设置evenodd效果:
本节介绍如何对画布进行操作,进行变形以便设计复杂图形。
canvas状态存储在栈中,一个绘画状态包括两部分。
使用save()方法,可以将当前状态推送到栈中保存,使用restore()方法可以将上一个保存的状态从栈中弹出,恢复上一次所有的设置。
<script>
window.onload = function() {
draw();
function draw() {
var ctx = document.getElementById("canvas").getContext('2d');
// 开始绘制矩形
ctx.fillStyle = "#ff00ff";
ctx.strokeStyle = "blue";
ctx.fillRect(20, 20, 100, 100);
ctx.strokeRect(20, 20, 100, 100);
ctx.fill();
ctx.stroke();
ctx.save(); //保存当前canvas状态
// 绘制另一个矩形
ctx.fillStyle = "#ff0000";
ctx.strokeStyle = "green";
ctx.fillRect(140, 20, 100, 100);
ctx.strokeRect(140, 20, 100, 100);
ctx.fill();
ctx.stroke();
ctx.restore(); //恢复第一个矩形的状态
ctx.fillRect(20, 140, 50, 50);
ctx.strokeRect(80, 140, 50, 50);
}
}
script>
<body>
<canvas id="canvas" style="border: 1px solid #999;" width="300" height="200">canvas>
body>
使用clearRect()方法可以清除指定区域内的所有图形,显示画布背景。
context.clearRect(x, y, width, height);
参数说明如下。
x:要清除的矩形左上角的x坐标。
y:要清除的矩形左上角的y坐标。
width:要清除的矩形的宽度,以像素计。
height:要清除的矩形的高度,以像素计。
【实例】下面实例演示了如何使用clearRect()方法擦除画布中的绘图。
<script>
window.onload = function() {
draw();
function draw() {
var ctx = document.getElementById("canvas").getContext('2d');
ctx.strokeStyle = '#FF00FF';
ctx.beginPath();
ctx.arc(200, 150, 100, -Math.PI * 1 / 6, -Math.PI * 5 / 6, true);
ctx.stroke();
var btn = document.getElementsByTagName('input')[0];
btn.onclick = function() {
ctx.clearRect(0, 0, 300, 200);
}
}
}
script>
<body>
<canvas id="canvas" style="border: 1px solid #999;" width="300" height="200">canvas>
<input type="button" name="" value="清空画布">
body>
在默认状态下,画布以左上角(0, 0)为原点作为绘图参考。使用translate()方法可以移动坐标原点,这样新绘制的图形就以新的坐标原点作为参考进行绘制。其用法如下:
context.translate(dx, dy);
参数dx和dy分别为坐标原点沿水平和垂直两个方向的偏移量。
注意:在使用translate()方法之前,应该先使用save()方法保存画布的原始状态。当需要时可以使用restore()方法恢复原始状态,这在重复绘图时非常重要。
【实例】下面实例综合运用了save()、restore()、translate()方法绘制一个伞状图形。
<script>
window.onload = function() {
draw();
function draw() {
var ctx = document.getElementById("canvas").getContext('2d');
// 注意:所有移动都是基于这一上下文
ctx.translate(0, 80);
for (var i = 1; i < 10; i++) {
ctx.save();
ctx.translate(60 * i, 0);
drawTop(ctx, "rgb(" + (30 * i) + "," + (255 - 30 * i) + ",255)");
drawGrip(ctx);
ctx.restore();
}
// 绘制伞形顶部半圆
function drawTop(ctx, fillStyle) {
ctx.fillStyle = fillStyle;
ctx.beginPath();
ctx.arc(0, 0, 30, 0, Math.PI, true);
ctx.closePath();
ctx.fill();
}
// 绘制伞形底部手柄
function drawGrip(ctx) {
ctx.save();
ctx.fillStyle = "blue";
ctx.fillRect(-1.5, 0, 1.5, 40);
ctx.beginPath();
ctx.strokeStyle = "blue";
ctx.arc(-5, 40, 4, Math.PI, Math.PI * 2, true);
ctx.stroke();
ctx.closePath();
ctx.restore();
}
}
}
script>
<body>
<canvas id="canvas" style="border: 1px solid #999;" width="600" height="200">canvas>
body>
在浏览器中浏览效果如图,可见,canvas中图形移动的实现,其实是通过改变画布的坐标原点来实现的,所谓的”移动图形“,只是看上去的样子 ,实际移动的是坐标空间。
使用rotate()方法可以以原点为中心旋转canvas上下文对象的坐标空间。用法如下:
context.rotate(angle);
rotate()方法只有一个参数,即旋转角度angle,旋转角度以顺时针方向为正方向,以弧度为单位,旋转中心为canvas的原点。
<script>
window.onload = function() {
draw();
function draw() {
var ctx = document.getElementById("canvas").getContext('2d');
// 注意:所有移动都是基于这一上下文
ctx.translate(150, 150);
for (var i = 1; i < 9; i++) {
ctx.save();
ctx.rotate(Math.PI * (2 / 4 + i / 4));
ctx.translate(0, -100);
drawTop(ctx, "rgb(" + (30 * i) + "," + (255 - 30 * i) + ",255)");
drawGrip(ctx);
ctx.restore();
}
// 绘制伞形顶部半圆
function drawTop(ctx, fillStyle) {
ctx.fillStyle = fillStyle;
ctx.beginPath();
ctx.arc(0, 0, 30, 0, Math.PI, true);
ctx.closePath();
ctx.fill();
}
// 绘制伞形底部手柄
function drawGrip(ctx) {
ctx.save();
ctx.fillStyle = "blue";
ctx.fillRect(-1.5, 0, 1.5, 40);
ctx.beginPath();
ctx.strokeStyle = "blue";
ctx.arc(-5, 40, 4, Math.PI, Math.PI * 2, true);
ctx.stroke();
ctx.closePath();
ctx.restore();
}
}
}
script>
<body>
<canvas id="canvas" style="border: 1px solid #999;" width="300" height="300">canvas>
body>
使用scale()方法可以增减canvas上下文对象的像素数目,从而使吸纳图形的放大和缩小。
用法如下:
context.scale(x, y);
其中,x为横轴的缩放因子,y为纵轴的缩放因子,值必须是正值。如果需要放大图形,则将参数设置为大于1的数值,如果需要缩小图形,则将参数设置为小于1的数值,当参数值等于1时则没有任何效果。
<script>
window.onload = function() {
draw();
function draw() {
var ctx = document.getElementById("canvas").getContext('2d');
ctx.translate(200, 20);
for (var i = 1; i < 80; i++) {
ctx.save();
ctx.translate(30, 30);
ctx.scale(0.95, 0.95);
ctx.rotate(Math.PI / 12);
ctx.beginPath();
ctx.fillStyle = "red";
ctx.globalAlpha = "0.4";
ctx.arc(0, 0, 50, 0, Math.PI * 2, true);
ctx.closePath();
ctx.fill();
}
}
}
script>
<body>
<canvas id="canvas" style="border: 1px solid #999;" width="300" height="300">canvas>
body>
transform()方法可以同时缩放、旋转、移动和倾斜当前的上下文环境。
context.transform(a, b, c, d, e, f);
参数说明:
提示:
context.transform(0, 1, 1, 0, dx, dy);
或:
context.transform(1, 0, 0, 1, dx, dy);
其中dx为原点沿x轴移动的数值,dy为原点沿y轴移动的数值。
context.transform(m11, 0, 0, m22, 0, 0);
或:
context.transform(0, m12, m21, 0, 0, 0);
其中,dx、dy都为0表示坐标原点不变,m11、m22或m12、m21为沿x、y轴放大的倍数。
context.transform(cos0, sin0, -sin0, cos0, 0, 0);
其中,θ为旋转角度的弧度值,dx、dy都为0,表示坐标原点不变。
setTransform()方法用于将当前的变化矩阵重置为最初的矩阵,然后以相同的的参数调用transform()方法。用法如下:
context.setTransform(m11, m12, m21, m22, dx, dy);
<script>
window.onload = function() {
draw();
function draw() {
var ctx = document.getElementById("canvas").getContext('2d');
ctx.translate(200, 20);
for (var i = 1; i < 90; i++) {
ctx.save();
// ctx.translate(30, 30);
// ctx.scale(0.95, 0.95);
ctx.transform(0.95, 0, 0, 0.95, 30, 30);
ctx.rotate(Math.PI / 12);
ctx.beginPath();
ctx.fillStyle = "red";
ctx.globalAlpha = "0.4";
ctx.arc(0, 0, 50, 0, Math.PI * 2, true);
ctx.closePath();
ctx.fill();
}
ctx.setTransform(1, 0, 0, 1, 10, 10);
ctx.fillStyle = "blue";
ctx.fillRect(0, 0, 50, 50);
ctx.fill();
}
}
script>
<body>
<canvas id="canvas" style="border: 1px solid #999;" width="300" height="300">canvas>
body>
在本例中,使用scale(0.95, 0.95)来缩小图形到上次的0.95,共循环89次,同时移动和旋转做表空间,从而使吸纳图形成螺旋状由大到小的变化。
当两个或两个以上的图形存在重叠区域时,默认一个图形画在前一个图形之上。通过制定图形globalCompositeOperation属性的值可以改变图形的绘制顺序或绘制方式,从而实现更多的可能。
使用clip()方法能够从原始画布中剪切任意形状和尺寸。其原理与绘制普通canvas图形类似,只不过clip()的作用是形成一个蒙版,没有被蒙版的区域会被隐藏。
<script>
window.onload = function() {
draw();
function draw() {
var ctx = document.getElementById("canvas").getContext('2d');
// 绘制背景
ctx.fillStyle = "black";
ctx.fillRect(0, 0, 300, 300);
ctx.fill();
ctx.beginPath();
ctx.arc(150, 150, 100, 0, Math.PI * 2, true);
ctx.clip();
ctx.translate(200, 20);
for (var i = 1; i < 90; i++) {
ctx.save();
// ctx.translate(30, 30);
// ctx.scale(0.95, 0.95);
ctx.transform(0.95, 0, 0, 0.95, 30, 30);
ctx.rotate(Math.PI / 12);
ctx.beginPath();
ctx.fillStyle = "red";
ctx.globalAlpha = "0.4";
ctx.arc(0, 0, 50, 0, Math.PI * 2, true);
ctx.closePath();
ctx.fill();
}
}
}
script>
<body>
<canvas id="canvas" style="border: 1px solid #999;" width="300" height="300">canvas>
body>
使用fillText()和strokeText()方法,可以分别以填充方式和轮廓方式绘制文本。
fillText()方法能够在画布上绘制填色文本,默认颜色是黑色。其用法如下:
context.fillText(text, x, y, maxWidth);
参数说明:
<script>
window.onload = function() {
draw();
function draw() {
var ctx = document.getElementById("canvas").getContext('2d');
ctx.font = "40px Georgia"
ctx.fillText("Hi", 10, 50);
ctx.font = "50px Verdana";
// 创建渐变
var gradient = ctx.createLinearGradient(0, 0, canvas.width, 0);
gradient.addColorStop("0", "magenta");
gradient.addColorStop("0.5", "blue");
gradient.addColorStop("1.0", "red");
// 用渐变填色
ctx.fillStyle = gradient;
ctx.fillText("***!佩琪鸽王!", 10, 120);
}
}
script>
<body>
<canvas id="canvas" style="border: 1px solid #999;" width="400" height="300">canvas>
body>
使用strokeText()方法可以在画布上绘制描边文体,默认颜色是黑色。其用法如下:
context.strokeText(text, x, y, maxWidth);
参数说明:
text:规定在画布上输出的文本。
x:开始绘制文本的x坐标位置(相对于画布)。
y:开始绘制文本的y坐标位置(相对于画布)。
maxWidth:可选参数,允许的最大文本宽度,以像素计。
【实例】下面使用strokeText()方法绘制文本”Hi“和”Canvas API“。
<script>
window.onload = function() {
draw();
function draw() {
var ctx = document.getElementById("canvas").getContext('2d');
ctx.font = "40px Georgia"
ctx.fillText("Hi", 10, 50);
ctx.font = "50px Verdana";
// 创建渐变
var gradient = ctx.createLinearGradient(0, 0, canvas.width, 0);
gradient.addColorStop("0", "magenta");
gradient.addColorStop("0.5", "blue");
gradient.addColorStop("1.0", "red");
// 用渐变填色
ctx.stokeStyle = gradient;
ctx.strokeText("Canvas API", 10, 120);
}
}
script>
<body>
<canvas id="canvas" style="border: 1px solid #999;" width="400" height="300">canvas>
body>
下面简单介绍文本样式的相关属性。
<script>
window.onload = function() {
draw();
function draw() {
var ctx = document.getElementById("canvas").getContext('2d');
// 在位置150创建一条竖线
ctx.strokeStyle = "blue";
ctx.moveTo(150, 20);
ctx.lineTo(150, 170);
ctx.stroke();
ctx.font = "15px Arial";
// 显示不同的textAlign值
ctx.textAlign = "start";
ctx.fillText("textAlign = start", 150, 60);
ctx.textAlign = "end";
ctx.fillText("textAlign = end", 150, 80);
ctx.textAlign = "left";
ctx.fillText("textAlign = left", 150, 100);
ctx.textAlign = "center";
ctx.fillText("textAlign = center", 150, 120);
ctx.textAlign = "rigth";
ctx.fillText("textAlign = right", 150, 140);
}
}
script>
<body>
<canvas id="canvas" style="border: 1px solid #999;" width="400" height="300">canvas>
body>
<script>
window.onload = function() {
draw();
function draw() {
var ctx = document.getElementById("canvas").getContext('2d');
// 在位置 y=100 绘制蓝色线条
ctx.strokeStyle = "blue";
ctx.moveTo(5, 100);
ctx.lineTo(395, 100);
ctx.stroke();
ctx.font = "20px Arial";
// 在位置 y=100 以不同的textBaseline值放置每个单词
ctx.textBaseline = "top";
ctx.fillText("Top", 5, 100);
ctx.textBaseline = "bottom";
ctx.fillText("Bottom", 50, 100);
ctx.textBaseline = "middle";
ctx.fillText("Middle", 120, 100);
ctx.textBaseline = "alphabetic";
ctx.fillText("Alphabetic", 190, 100);
ctx.textBaseline = "hanging";
ctx.fillText("Hangin", 290, 100);
}
}
script>
<body>
<canvas id="canvas" style="border: 1px solid #999;" width="400" height="300">canvas>
body>
使用measureText()方法可以测量当前所绘制文字中指定文字的宽度,它返回一个TextMetrics对象,使用该对象的width属性可以得到指定文字参数后所有绘制文字的总宽度。用法如下:
metrics = context.measureText(text);
其中的参数text为要绘制的文字。
提示:如果需要在文本向画布输出之前就了解文本的宽度,应该使用该方法。
【实例】下面是测量文字宽度的一个实例。
<script>
window.onload = function() {
draw();
function draw() {
var ctx = document.getElementById("canvas").getContext('2d');
ctx.font = "blod 20px 楷体";
ctx.fillStyle = "Blue";
var txt1 = "HTML5 + CSS3";
ctx.fillText(txt1, 10, 40);
var txt2 = "以上字符串的宽度为:";
var mtxt1 = ctx.measureText(txt1);
var mtxt2 = ctx.measureText(txt2);
ctx.font = "blod 15px 宋体";
ctx.fillStyle = "Red";
ctx.fillText(txt2, 10, 80);
ctx.fillText(mtxt1.width, mtxt2.width, 80);
}
}
script>
<body>
<canvas id="canvas" style="border: 1px solid #999;" width="400" height="300">canvas>
body>
在canvas中可以导入图像。导入的图像可以改变大小、裁切或合成。canvas支持多种图像格式,如PNG、GIF、JPEG等。
在canvas中导入图像的步骤如下。
确定图像来源有以下4种方式,用户可以任选一种。
使用脚本创建image对象时,其方法如下:
var img = new Image(); //创建新的Image对象
img.src = 'image1.png'; //设置图像路径
如果要解决图片预装载问题,可以使用onload事件一边装载一边绘制图像函数。
var img = new Image();
img.onload = function(){
}
img.src = 'image1.png';
不管采用什么方法获取图像资源,之后的工作都是使用drawImage()方法将图像绘制到canvas中,drawImage()方法能够在画布上绘制图像、画布或视频。该方法也能够绘制图像的某些部分,以及增加或减小图像的尺寸。用法如下:
//语法1:在画布上定位图像
context.drawImage(img, x, y);
//语法2:在画布上定位图像,并规定图像的宽度和高度
context.drawImage(img, x, y, width, height);
//语法3:剪切图像,并在画布上定位被剪切的部分
context.drawImage(img, sx, sy, swidth, sheight, x, y, width, height);
参数说明:
img:规定要使用的图像、画布或视频。
sx:可选。开始剪切的x坐标位置。
sy:可选。开始剪切的y坐标位置。
swidth:可选。被剪切图像的宽度。
sheight:可选。被剪切图像的高度。
x:在画布上放置图像的x坐标位置。
y:在画布上放置图像的y坐标位置。
width:可选。要使用的图像的宽度,可以实现伸展或缩小图像。
height:可选。要使用的图像的高度,可以实现伸展或缩小图像。
【实例】下面实例演示了如何使用上述步骤将图像引入canvas中。
<script>
window.onload = function() {
draw();
function draw() {
var ctx = document.getElementById("canvas").getContext('2d');
var img = new Image();
img.onload = function() {
ctx.drawImage(img, 0, 0);
}
img.src = '../img/doge.jpg'
}
}
script>
<body>
<canvas id="canvas" style="border: 1px solid #999;" width="400" height="300">canvas>
body>
drawImage()方法的第2种方法可以用于使用图片按指定的大小显示。
context.drawImage(image, x, y, width, height);
其中width和height分别是图像在canvas中显示的宽度和高度。
<script>
window.onload = function() {
draw();
function draw() {
var ctx = document.getElementById("canvas").getContext('2d');
var img = new Image();
img.onload = function() {
ctx.drawImage(img, 0, 0, 400, 300);
}
img.src = '../img/doge.jpg'
}
}
script>
<body>
<canvas id="canvas" style="border: 1px solid #999;" width="400" height="300">canvas>
body>
drawImage()的第三种方法用于创建图像切片。用法如下:
context.drawImage(image, sx, sy, sw, sh, dx, dy, dw, dh);
sx、sy为原图像被切割区域,sw、sh为原图像被切下来的宽度和高度;dx、dy为被切割下来的原图像要方式到的位置,dw、dh为被切割下来的图像的宽度和高度。
<script>
window.onload = function() {
draw();
function draw() {
var ctx = document.getElementById("canvas").getContext('2d');
var img = new Image();
img.onload = function() {
ctx.drawImage(img, 0, 0, 200, 150, 50, 50, 100, 50);
}
img.src = '../img/doge.jpg'
}
}
script>
<body>
<canvas id="canvas" style="border: 1px solid #999;" width="400" height="300">canvas>
body>
图像平铺就是让图像铺满画布,有两种方法可以实现,下面结合实例进行说明。
<script>
window.onload = function() {
draw();
function draw() {
var ctx = document.getElementById("canvas").getContext('2d');
var image = new Image();
image.src = '../img/doge.jpg';
image.onload = function() {
var scale = 5;
var n1 = image.width / scale;
var n2 = image.heigth / scale;
var n3 = canvas.width / n1;
var n4 = canvas.height / n2;
for (var i = 0; i < n3; i++) {
for (var j = 0; j < n4; j++) {
ctx.drawImage(image, i * n1, j * n2, n1, n2);
}
}
}
}
}
script>
<body>
<canvas id="canvas" style="border: 1px solid #999;" width="400" height="300">canvas>
body>
context.createPattern(image, type);
参数image为要平铺的图像,参数type必须是下面的字符串之一。
<script>
window.onload = function() {
draw();
function draw() {
var ctx = document.getElementById("canvas").getContext('2d');
var image = new Image();
image.src = '../img/doge.jpg';
image.onload = function() {
var ptrn = ctx.createPattern(image, 'repeat');
ctx.fillStyle = ptrn;
ctx.fillRect(0, 0, 400, 300);
}
}
}
script>
<body>
<canvas id="canvas" style="border: 1px solid #999;" width="400" height="300">canvas>
body>