文章目录
- JavaScript绘图
- 使用canvas
- 绘制图形
-
- 定义样式和颜色
-
- 图形变形
- 保存和恢复状态
- 清除画布
- 移动坐标
- 旋转坐标
- 缩放图形
- 变换图形
- 图形合成
-
- 绘制文本
-
- 文本样式
-
JavaScript绘图
HTML5新增了Canvas API,允许js在<canvas>标签识别的画布上绘制图形,创建动画,设置设计实时视频处理或渲染。借助一套编程接口,用户可以在页面上绘制出任何漂亮的图形。
【学习重点】
- 使用canvas元素。
- 绘制图形。
- 设置图形样式。
- 灵活使用Canvas API设计网页动画。
使用canvas
在HTML5文档中,使用<canvas>标签可以在网页中创建一块画布。用法如下:
<canvas id="muCanvas" width="200" height="100"></canvas>
该标签包括三个属性:
- id:用来标识画布,以方便js脚本对其引用。
- width:设置canvas的宽度。
- height:设置canvas的高度。
注意:与<img>不同,<canvas>需要结束标签</canvas>。如果结束标签不存在,则文档的其余部分会被认为是替代内容,将不会显示出来。
<canvas id="muCanvas" style="border:1px solid;" width="200" height="100"></canvas>
使用js可以在canvas画布内绘画,或者设置动画。
【操作步骤】
- 第一步,在HTML页面中添加<canvas>标签,设置canvas的id属性值以便js调用。
<canvas id
="myCanvas" width
="200" height
="100">
- 第二步,在js脚本中使用document.getELementById()方法,根据canvas元素的id获取对canvas的应用。
var c
= document
.getElementById("myCanvas");
- 第三步,通过canvas元素的getContext()方法获取画布上下文(context),创建context对象,以获取允许进行绘制的2D环境。
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种方法绘制矩形。
- fillRect(x, y, width, height):绘制一个填充的矩形。
- strokeRect(x, y, width, height):绘制一个矩形的边框。
- clearRect(x, y, width, height):清除指定矩形区域,让清除部分完全透明。
参数说明:
- x:矩形左上角的x坐标。
- y:矩形左上角的y坐标。
- width:矩形的宽度,以像素为单位。
- height:矩形的高度,以像素为单位。
- 【实例】下面实例分别使用上面三种方法。
<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>
路径
使用路径绘制图形的步骤如下:
第一步,创建路径起始点。
第二布,使用画图命令绘制路径。
第三步,封闭路径。
第四步,生成路径之后,可以通过描边或填充路径区域来渲染图形。
需要调用的方法说明如下:
- beginPath():开始路径。
- closePath():闭合路径。闭合路径之后图形绘制命令又重新指向上下文。
- stroke():描边路径。通过线条来绘制图形轮廓。
- fill():填充路径。通过填充路径的内容区域生成实心的图形。
- 提示:生成路径的第一步是调用beginPath()方法。每次调用这个方法之后,表示开始重新绘制新的图形。闭合路径closePath()方法不是必需的;当调用fill()方法时,所有没有闭合的形状都会自动闭合,所以不需要调用closePath()方法;但是调用stroke()方法时不会自动闭合。
- 【实例】下面实例演示绘制一个笑脸。
<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
);
参数说明:
- x:圆心的x坐标。
- y:圆心的y坐标。
- r:圆的半径。
- sAngle:起始角,以弧度计。提示,弧的圆形的三点钟位置是0度。
- eAngle:结束角,以弧度计。
- counterclockwise:可选参数,定义绘图方法。false为顺时针,为默认值;true为逆时针。
如果使用arc()创建圆,可以把起始点设置为0,结束角设置为2*Math.PI。
- 【实例】下面实例绘制了12个不同的角度以及填充的圆弧。主要使用两个for循环,生成圆弧的行列坐标。每一段圆弧的开始都调用beginPath()方法。代码中,每个圆弧的参数都是可变的,(x,y)坐标是可变的,半径(radius)和开始角(startAngle)都是固定的。结束角度(endAngle)在第一列开始时是180度(半圆),然后每列增加90度。最后一列形成一个完整的圆。
<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)位置的直线。
- 【实例1】下面实例绘制两个三角形,一个是填充的,另一个是描边的。
<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()到描边三角形中,则只绘制两条线段,并不是一个完整的三角形。
- 使用arcTo()方法可以绘制曲线,该方法时lineTo()的曲线版,它能够创建两条切线之间的弧或曲线。用法如下:
context
.arcTo(x1
, y1
, x2
, y2
, r
);
参数说明:
- x1:弧的起点x坐标。
- y1:弧的起点y坐标。
- x2:弧的终点x坐标。
- y2:弧的终点y坐标。
- r:弧的半径。
- 【实例2】本实例用lineTo()和arcTo()方法绘制直线和曲线,再连成圆角弧线。
<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的值。
- 【实例1】本实例嵌套for循环绘制方阵列表,每个方格填充不同颜色。
<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表示完全不透明。
- 【实例】下面实例使用四色格作为背景,设置globalAlpha为0.2后,在上面画一系列半径递增的半透明圆,最终结果是一个经向渐变效果。圆叠加的越多,原来所画的圆的透明度就越低。通过增加循环次数,画更多的圆,背景图中心部分会完全消失。
<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。
- 【实例1】下面实例使用for循环绘制了12条线宽一次递增的线段。
<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。
- 【实例2】下面实例绘制了三条蓝色的直线段,并依次设置上述三种属性值,两侧有两条红色的参考线,以方便观察。
<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。
- 【实例3】下面实例绘制了三条蓝色的直线,并以此设置三个属性值,观察拐角处(即直角段连接处)样式的区别。
<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属性无效。
- 【实例4】通过下面实例可以观察到,当角度和miterLimit属性值发生变化时斜面长度的变化。在运行代码之前,也可以将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属性设置起始偏移量。
- 【实例】下面实例绘制一个矩形虚线框,然后使用定时器设计每隔0.5秒重新绘制一次,重绘时改变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
);
参数说明:
- x0:渐变开始点的x坐标。
- y0:渐变开始点的y坐标。
- x1:渐变结束点的x坐标。
- y1:渐变结束点的y坐标。
addColorStop()方法用法如下:
gradient
.addColorStop(stop
, color
);
参数说明:
- stop:介于0.0-1.0之间的值,表示渐变开始与结束之间的相对位置。渐变起点的偏移值为0,重点的偏移值为1.如果position值为0.5,则表示色标出现在渐变的正中间。
- color:在结束位置显示的css颜色值。
- 【实例】下面实例演示如何绘制线性渐变。
<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
);
参数说明:
- x0:渐变开始圆的x坐标。
- y0:渐变开始圆的y坐标。
- r0:开始圆的半径。
- x1:渐变结束圆的x坐标。
- y1:渐变结束圆的y坐标。
- 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");
参数说明如下:
- 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>
阴影
创建阴影需要四个属性:
<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()方法可以填充图形,该方法可以接受两个值,用来定义填充规则。
- nonzero:非零环绕数规则,为默认值。
- evenodd:奇偶规则。
填充规则根据某处在路径的外面或者里面来决定是否被填充,这对于路径相交或者路径被嵌套的时候极为有用。
<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状态存储在栈中,一个绘画状态包括两部分。
- 当前应用的变形,如移动、旋转、缩放。包括的样式属性:strokeStyle、fillStyle、globalAlpha、lineWidth、lineCap、lineJoin、miterLimit、shadowOffsetX、shadowOffsetY、shadowBlur、shadowColor、globalCompositeOperation。
- 当前裁切路径。
使用save()方法,可以将当前状态推送到栈中保存,使用restore()方法可以将上一个保存的状态从栈中弹出,恢复上一次所有的设置。
- 【实例】下面实例先绘制一个矩形,填充颜色为#ff00ff,轮廓颜色为蓝色,然后保存这个状态,再绘制另外一个矩形,填充颜色为#ff0000,轮廓颜色为绿色;最后恢复第一个矩形的状态,并绘制两个小的矩形,其中一个矩形填充颜色必为#ff00ff,另一个矩形轮廓颜色必为蓝色。因为此时已经恢复了原来保存的状态,所以会沿用最先设定的属性值。
<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(); 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
);
参数说明如下。
<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分别为坐标原点沿水平和垂直两个方向的偏移量。
<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的原点。
- 【实例】在上个实例的基础上,下面实例设计在每次开始绘制图形之前,现将做表空间旋转PI*(2/4+i/4),再将坐标空间沿y轴负方向移动100,然后开始绘制图形,从而实现图形沿以中心点平均旋转分布。
<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时则没有任何效果。
- 【实例】下面实例使用scale(0.95,0.95)来缩小图形到上次的0.95,共循环80次,同时移动和旋转坐标空间,从而实现图形呈螺旋状由大到小的变化。
<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
);
参数说明:
- a:水平缩放绘图。
- b:水平倾斜绘图。
- c:垂直倾斜绘图。
- d:垂直缩放绘图。
- e:水平移动绘图。
- f:垂直移动绘图。
提示:
- translate(x, y)可以用下面方法来代替。
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轴放大的倍数。
- rotate(angle)可以使用下面方法来代替。
context.transform(cos0, sin0, -sin0, cos0, 0, 0);
其中,θ为旋转角度的弧度值,dx、dy都为0,表示坐标原点不变。
setTransform()方法用于将当前的变化矩阵重置为最初的矩阵,然后以相同的的参数调用transform()方法。用法如下:
context
.setTransform(m11
, m12
, m21
, m22
, dx
, dy
);
- 【实例】下面实例使用setTransform()方法首先将前面已经发生变换的矩阵重置为最初的矩阵,即恢复最初的原点,然后再将坐标原点改为(10,10),并以新坐标为基准绘制蓝色矩阵。
<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.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()的作用是形成一个蒙版,没有被蒙版的区域会被隐藏。
- 提示:在使用clip()方法前,通过使用save()方法对当前画布区域进行保存,并可以在以后的任意时间通过restore()方法对其进行恢复。
- 【实例】如果绘制一个圆形,并进行裁切,则圆形之外的区域将不会绘制在canvas上。
<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.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
);
参数说明:
- text:规定在画布上输出的文本。
- x:开始绘制文本的x坐标位置(相对与画布)。
- y:开始绘制文本的y坐标位置(相对与画布)。
- maxWidth:可选参数,云溪的最大文本宽度,以像素计。
- 【实例】下面使用fillText()方法在画布上绘制文本”Hi“和”佩琪鸽王!“。
<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);
参数说明:
<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>
文本样式
下面简单介绍文本样式的相关属性。
- font:定义字体样式,语法与CSS字体样式相同。默认字体样式为10px sans-serif。
- textAlign:设置正在绘制的文本水平对齐方式,取值说明如下。
- start:默认值,文本在指定的位置开始。
- end:文本在指定的位置结束。
- center:文本的中心被放置在指定的位置。
- left:文本左对齐。
- right:文本右对齐。
- textBaseline:设置正在绘制的文本基线对齐方式,即文本垂直对齐方式,取值说明如下。
- alphabetic:默认值,文本基线是普通的子母基线。
- top:文本基线是en方框的顶端。
- hanging:文本基线是悬挂基线。
- middle:文本基线是em方框的正中间。
- ideographic:文本基线是表意基线。
- bottom:文本基线是em方框的底端。
- direction:设置文本方向,取值说明如下。
- ltr:从左到右。
- rtl:从右到左。
- inherit:默认值,继承文本方向。
- 【实例1】下面实例在x轴150px的位置创建一条竖线,位置150就被定义为所有文本的锚点。然后比较每种textAlign属性值对齐效果。
<script>window.onload = function() {draw();function draw() {var ctx = document.getElementById("canvas").getContext('2d');ctx.strokeStyle = "blue";ctx.moveTo(150, 20);ctx.lineTo(150, 170);ctx.stroke();ctx.font = "15px Arial";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>
- 【实例2】下面实例在y轴100px的位置创建一条水平线。位置100被定义为蓝色填充,然后比较每种textBaseline属性值对齐效果。
<script>window.onload = function() {draw();function draw() {var ctx = document.getElementById("canvas").getContext('2d');ctx.strokeStyle = "blue";ctx.moveTo(5, 100);ctx.lineTo(395, 100);ctx.stroke();ctx.font = "20px Arial";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种方式,用户可以任选一种。
- 页面内的图片:如果已知图片元素的ID,则可以通过document.images集合、document.getElementByTagName()或document.getElementById()等方法获取页面的图片元素。
- 其他canvas元素:可以通过document.getElmentByTagName()或document.getElementById()等方法获取已经设计好的canvas元素。例如,可以使用这种方法作为一个比较大的canvas生成缩略图。
- 用脚本创建一个新的Image对象:使用脚本可以从零点开始创建一个新的Image对象。不过这种方法存在一种缺点:如果图像文件来源于网络且较大,则会花费较长时间来装载。所以如果不希望因为图像文件装载时间过长而等待,就需要做好预装载的工作。
- 使用data:url方式引用图像:这种方法允许用Base64编码的字符串来定义一个图片;优点是图片可以即使使用,不必等待装载,而且迁移也非常容易;缺点是无法缓存图像,所以如果图片较大,则不太合适这种方法,因为这会导致嵌入的url数据相当庞大。
使用脚本创建image对象时,其方法如下:
var img
= new Image();
img
.src
= 'image1.png';
如果要解决图片预装载问题,可以使用onload事件一边装载一边绘制图像函数。
var img
= new Image();
img
.onload = function(){}
img
.src
= 'image1.png';
不管采用什么方法获取图像资源,之后的工作都是使用drawImage()方法将图像绘制到canvas中,drawImage()方法能够在画布上绘制图像、画布或视频。该方法也能够绘制图像的某些部分,以及增加或减小图像的尺寸。用法如下:
context
.drawImage(img
, x
, y
);
context
.drawImage(img
, x
, y
, width
, height
);
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>
平铺图像
图像平铺就是让图像铺满画布,有两种方法可以实现,下面结合实例进行说明。
- 【实例1】第一种方法是使用drawImage()方法。
<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>
- 【实例2】使用createPattern()方法,该方法只用了几个参数。
context.createPattern(image, type);
参数image为要平铺的图像,参数type必须是下面的字符串之一。
- no-repeat:不平铺。
- repeat-x:横方向平铺。
- repeat-y:纵方向平铺。
- repeat:全方向平铺。
<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>
总结
以上是生活随笔为你收集整理的js绘图的全部内容,希望文章能够帮你解决所遇到的问题。
如果觉得生活随笔网站内容还不错,欢迎将生活随笔推荐给好友。