赞
踩
目录
<canvas>元素是HTML5新增的,一个可以使用脚本(通常为JavaScript)在其中绘制图像的HTML元素。它可以用来制作照片集或者制作简单的动画,甚至可以进行实时视频处理和渲染。
<canvas>由几组API构成,除了具备基本绘图能力的2D上下文,<canvas>还具备一个名为WebGL的3D上下文。
使用<canvas>元素之前,必须先设置其width和height属性,指定可以绘图的区域大小。
出现在开始和结束标签中的内容是后备信息,如果浏览器不支持<canvas>元素,就会显示这些信息。
<canvas id="drawing" width="200" height="200">A drawing of something.</canvas>
要在这块画布上绘图,需要使用getContext()方法传入参数"2d"取得2D上下文对象。
- var drawing = document.getElementById("drawing");
-
- //确定浏览器支持<canvas>元素
- if(drawing.getContext){
- var context = drawing.getContext("2d"); //取得2D上下文对象
- //更多代码
- }
使用2D绘图上下文提供的方法,可以绘制简单的2D图形,比如矩形、弧线和路径。
2D上下文的坐标开始于<canvas>元素的左上角,原点坐标是(0,0)。
所有坐标值都基于这个原点计算,x值越大表示越靠右,y值越大表示越靠下。
2D上下文的两种基本绘图操作是填充和描边。
填充就是用指定的样式(颜色、渐变或图像)填充图形,fillStyle属性设置填充样式。
描边就是只在图形的边缘画线,strokeStyle属性设置描边样式。
这两个属性的值可以是字符串、渐变对象或模式对象,例如:
- var drawing = document.getElementById("drawing");
-
- //确定浏览器支持<canvas>元素
- if(drawing.getContext){
-
- var context = drawing.getContext("2d"); //取得2D上下文对象
- context.strokeStyle = "red";
- context.fillStyle = "#0000FF";
- }
与绘制矩形有关的方法包括:
这三个方法都能接收4个参数:矩形的x坐标、矩形的y坐标、矩形的宽度和矩形高度。参数单位都是像素。
示例1:
- var drawing = document.getElementById("drawing");
-
- //确定浏览器支持<canvas>元素
- if(drawing.getContext){
-
- var context = drawing.getContext("2d"); //取得2D上下文对象
-
- //绘制红色矩形
- context.fillStyle = "#F00";
- context.fillRect(10, 10, 50, 50);
-
- //绘制半透明的蓝色矩形
- context.fillStyle = "rgba(0, 0, 255, 0.5)";
- context.fillRect(30, 30, 50, 50);
- }
示例2:
- var drawing = document.getElementById("drawing");
-
- //确定浏览器支持<canvas>元素
- if(drawing.getContext){
-
- var context = drawing.getContext("2d"); //取得2D上下文对象
-
- //绘制红色描边矩形
- context.strokeStyle = "#F00";
- context.strokeRect(10, 10, 50, 50);
-
- //绘制半透明的蓝色描边矩形
- context.strokeStyle = "rgba(0, 0, 255, 0.5)";
- context.strokeRect(30, 30, 50, 50);
- }
示例3:
- var drawing = document.getElementById("drawing");
-
- //确定浏览器支持<canvas>元素
- if(drawing.getContext){
-
- var context = drawing.getContext("2d"); //取得2D上下文对象
-
- //绘制红色矩形
- context.fillStyle = "#F00";
- context.fillRect(10, 10, 50, 50);
-
- //绘制半透明的蓝色描边矩形
- context.fillStyle = "rgba(0, 0, 255, 0.5)";
- context.fillRect(30, 30, 50, 50);
-
- //在两个矩形重叠的地方清除一个小矩形
- context.clearRect(40, 40, 10, 10);
- }
绘制路径的方法:
- var drawing = document.getElementById("drawing");
-
- //确定浏览器支持<canvas>元素
- if(drawing.getContext){
-
- var context = drawing.getContext("2d"); //取得2D上下文对象
-
- context.beginPath(); //开始绘制新路径
- context.moveTo(50, 50); //把画笔移动到指定的坐标
- context.lineTo(200, 50); //绘制一条从当前位置到指定坐标(200, 50)的直线
- context.stroke(); //绘制
- }
绘制三角形边框:
- var drawing = document.getElementById("drawing");
-
- //确定浏览器支持<canvas>元素
- if(drawing.getContext){
-
- var context = drawing.getContext("2d"); //取得2D上下文对象
-
- context.beginPath(); //开始绘制新路径
- context.moveTo(50, 50); //把画笔移动到指定的坐标
- context.lineTo(200, 50); //绘制一条从坐标(50, 50)到坐标(200, 50)的直线
- context.lineTo(200, 200); //绘制一条从坐标(200, 50)到坐标(200, 200)的直线
- context.closePath(); //闭合路径,绘制一条从路径起点到路径终点的直线
- context.stroke() //为路径描边
- }
填充三角形:
- var drawing = document.getElementById("drawing");
-
- //确定浏览器支持<canvas>元素
- if(drawing.getContext){
-
- var context = drawing.getContext("2d"); //取得2D上下文对象
-
- context.beginPath(); //开始绘制新路径
- context.moveTo(50, 50); //把画笔移动到指定的坐标
- context.lineTo(200, 50); //绘制一条从坐标(50, 50)到坐标(200, 50)的直线
- context.lineTo(200, 200); //绘制一条从坐标(200, 50)到坐标(200, 200)的直线
- context.closePath(); //闭合路径,绘制一条从路径起点到路径终点的直线
- context.fill() //填充三角形
- }
- var drawing = document.getElementById("drawing");
-
- //确定浏览器支持<canvas>元素
- if(drawing.getContext){
-
- var context = drawing.getContext("2d"); //取得2D上下文对象
-
- context.beginPath(); //开始绘制新路径
- context.arc(100, 100, 99, 0, Math.PI, false);
- context.stroke();
- }
二次贝塞尔曲线:
- var drawing = document.getElementById("drawing");
-
- //确定浏览器支持<canvas>元素
- if(drawing.getContext){
-
- var context = drawing.getContext("2d"); //取得2D上下文对象
-
- context.beginPath();
- context.moveTo(10, 200); //起始点
- var x1 = 40, y1 = 100; //控制点
- var x2 = 200, y2 = 200; //结束点
- //绘制贝塞尔曲线
- context.quadraticCurveTo(x1, y1, x2, y2);
- context.stroke();
-
- context.beginPath();
- context.rect(10, 200, 10, 10);
- context.rect(x1, y1, 10, 10);
- context.rect(x2, y2, 10, 10);
- context.fill();
-
- }
三次贝塞尔曲线:
- var drawing = document.getElementById("drawing");
-
- //确定浏览器支持<canvas>元素
- if(drawing.getContext){
-
- var context = drawing.getContext("2d"); //取得2D上下文对象
-
- context.beginPath();
- context.moveTo(40, 200); //起始点
- var x1 = 20, y1 = 100; //控制点1
- var x2 = 100, y2 = 120; //控制点2
- var x3 = 200, y3 = 200; //结束点
- //绘制三次贝塞尔曲线
- context.bezierCurveTo(x1, y1, x2, y2, x3, y3);
- context.stroke();
-
- context.beginPath();
- context.rect(40, 200, 10, 10);
- context.rect(x1, y1, 10, 10);
- context.rect(x2, y2, 10, 10);
- context.rect(x3, y3, 10, 10);
- context.fill();
- }
lineWidth属性用于设置线宽
- var drawing = document.getElementById("drawing");
-
- //确定浏览器支持<canvas>元素
- if(drawing.getContext){
-
- var context = drawing.getContext("2d"); //取得2D上下文对象
-
- context.beginPath();
- context.moveTo(10, 10);
- context.lineTo(100, 10);
- context.lineWidth = 10;
- context.stroke();
-
- context.beginPath();
- context.moveTo(110, 10);
- context.lineTo(160, 10);
- context.lineWidth = 20;
- context.stroke();
- }
lineCap属性用于设置线条末端样式,可以设置为三个值:
- var drawing = document.getElementById("drawing");
-
- //确定浏览器支持<canvas>元素
- if(drawing.getContext){
-
- var context = drawing.getContext("2d"); //取得2D上下文对象
-
- var lineCaps = ["butt", "round", "square"]
- for(var i = 0; i < 3; i++){
- context.beginPath();
- context.moveTo(20 + 30 * i, 30);
- context.lineTo(20 + 30 * i, 100);
- context.lineWidth = 20;
- context.lineCap = lineCaps[i];
- context.stroke();
- }
-
- context.beginPath();
- context.moveTo(0, 30);
- context.lineTo(300, 30);
-
- context.moveTo(0, 100);
- context.lineTo(300, 100);
-
- context.strokeStyle = "red";
- context.lineWidth = 1;
- context.stroke();
- }
lineJoin属性用于设置线条与线条间接合处的样式,可以设置为三个值:
- var drawing = document.getElementById("drawing");
-
- //确定浏览器支持<canvas>元素
- if(drawing.getContext){
-
- var context = drawing.getContext("2d"); //取得2D上下文对象
-
- var lineJoin = ['round', 'bevel', 'miter'];
- context.lineWidth = 20;
-
- for (var i = 0; i < lineJoin.length; i++){
- context.lineJoin = lineJoin[i];
- context.beginPath();
- context.moveTo(50, 50 + i * 50);
- context.lineTo(100, 100 + i * 50);
- context.lineTo(150, 50 + i * 50);
- context.lineTo(200, 100 + i * 50);
- context.lineTo(250, 50 + i * 50);
- context.stroke();
- }
- }
globalAlpha属性用于指定所有绘制的透明度,默认值为0。
示例:
- var drawing = document.getElementById("drawing");
-
- //确定浏览器支持<canvas>元素
- if(drawing.getContext){
-
- var context = drawing.getContext("2d"); //取得2D上下文对象
-
- //绘制红色矩形
- context.fillStyle = "#F00";
- context.fillRect(10, 10, 50, 50);
-
- //修改全局透明度
- context.globalAlpha = 0.5;
-
- //绘制蓝色矩形
- context.fillStyle = "rgba(0, 0, 255, 1)";
- context.fillRect(30, 30, 50, 50);
-
- //重置全局透明度
- context.globalAlpha = 0;
-
- }
translate(x, y)用于将坐标原点移动到(x, y),执行这个变换后,坐标(0, 0)会变成之前由(x, y)表示的点。
示例:
- var drawing = document.getElementById("drawing");
-
- //确定浏览器支持<canvas>元素
- if(drawing.getContext){
-
- var context = drawing.getContext("2d"); //取得2D上下文对象
-
- //开始路径
- context.beginPath();
-
- //绘制外圆
- context.arc(100, 100, 99, 0, 2 * Math.PI, false);
-
- //绘制内圆
- context.moveTo(194, 100);
- context.arc(100, 100, 94, 0, 2 * Math.PI, false);
-
- //变换原点
- context.translate(100, 100);
-
- //绘制分针
- context.moveTo(0, 0);
- context.lineTo(0, -85);
-
- //绘制时针
- context.moveTo(0, 0);
- context.lineTo(-65, 0);
-
- //描边路径
- context.stroke();
-
- }
rotate(angle)方法能够旋转坐标轴。
示例:
- var drawing = document.getElementById("drawing");
-
- //确定浏览器支持<canvas>元素
- if(drawing.getContext){
-
- var context = drawing.getContext("2d"); //取得2D上下文对象
-
- //开始路径
- context.beginPath();
-
- //绘制外圆
- context.arc(100, 100, 99, 0, 2 * Math.PI, false);
-
- //绘制内圆
- context.moveTo(194, 100);
- context.arc(100, 100, 94, 0, 2 * Math.PI, false);
-
- //变换原点
- context.translate(100, 100);
-
- //旋转表针
- context.rotate(Math.PI / 6);
-
- //绘制分针
- context.moveTo(0, 0);
- context.lineTo(0, -85);
-
- //绘制时针
- context.moveTo(0, 0);
- context.lineTo(-65, 0);
-
- //描边路径
- context.stroke();
-
- }
scale(scaleX, scaleY)方法用于缩放图像,在x方向乘以scaleX,在y方向乘以scaleY。
scaleX和scaleY的默认值都是1.0
示例:
- var drawing = document.getElementById("drawing");
-
- //确定浏览器支持<canvas>元素
- if(drawing.getContext){
-
- var context = drawing.getContext("2d"); //取得2D上下文对象
-
- //开始路径
- context.beginPath();
-
- //绘制外圆
- context.arc(100, 100, 99, 0, 2 * Math.PI, false);
-
- //绘制内圆
- context.moveTo(194, 100);
- context.arc(100, 100, 94, 0, 2 * Math.PI, false);
-
- //变换原点
- context.translate(100, 100);
-
- //旋转表针
- context.rotate(Math.PI / 6);
-
- //绘制分针
- context.moveTo(0, 0);
- context.lineTo(0, -85);
-
- //绘制时针
- context.moveTo(0, 0);
- context.lineTo(-65, 0);
-
- //放大路径
- context.scale(5, 5);
-
- //描边路径
- context.stroke();
-
- }
直接修改变换矩阵,方式是乘以如下矩阵:
将变换矩阵重置为默认状态,然后再调用transform()。
调用save()方法,当时所有的设置都会进入一个栈结构,得以妥善保管。
然后可以对上下文进行其他修改,等想要回到之前保存的设置时,可以调用restore()方法,在保存设置的栈结构中向前返回一级,恢复之前的状态。
连续调用save()可以把更多设置保存到栈结构中,之后再连续调用restore()则可以一级一级返回。
示例:
- var drawing = document.getElementById("drawing");
-
- //确定浏览器支持<canvas>元素
- if(drawing.getContext){
-
- var context = drawing.getContext("2d"); //取得2D上下文对象
-
- context.fillStyle = "#F00";
- context.save();
-
- context.fillStyle = "#0F0";
- context.translate(100, 100);
- context.save();
-
- context.fillStyle = "#00F";
- //从点(100, 100)开始绘制蓝色矩形
- context.fillRect(0, 0, 100, 200);
-
- context.restore();
- //从点(110, 110)开始绘制绿色矩形
- context.fillRect(10, 10, 100, 200);
-
- context.restore();
- //从点(0, 0)开始绘制红色矩形
- context.fillRect(0, 0, 100, 200);
- }
绘制文本主要有两个方法:
这两个方法都可以接收4个参数:要绘制的文本字符串、x坐标、y坐标和可选的最大像素宽度。
这两个方法都以下列3个属性为基础:
示例:
- var drawing = document.getElementById("drawing");
-
- //确定浏览器支持<canvas>元素
- if(drawing.getContext){
-
- var context = drawing.getContext("2d"); //取得2D上下文对象
-
- //开始路径
- context.beginPath();
-
- //绘制分针
- context.moveTo(100, 100);
- context.lineTo(100, 15);
-
- //描边路径
- context.stroke();
-
- context.font = "bold 14px Arial";
- context.textAlign = "center";
- context.textBaseline = "middle";
- context.fillText("12", 100, 20);
-
- //起点对齐
- context.textAlign = "start";
- context.fillText("12", 100, 40);
-
- //终点对齐
- context.textAlign = "end";
- context.strokeText("12", 100, 60);
fillText()和strokeText()方法都可以接收第四个参数,也就是文本的最大像素宽度。提供这个参数后,调用fillText()或strokeText()时如果传入的字符串大于最大宽度,则绘制的文本字符的高度正确,但宽度会收缩以适应最大宽度。
2D绘图上下文内置了对图像的支持,可以使用drawImage()方法。
drawImage()有9个参数:要素绘制的图像、源图像的x坐标、源图像的y坐标、源图像的宽度、源图像的高度、目标图像的x坐标、目标图像的y坐标、目标图像的宽度、目标图像的高度。
①绘制图像简单示例:
- var drawing = document.getElementById("drawing");
-
- var img = new Image(); //创建Image对象
- img.src = 'https://avatar.csdn.net/6/4/D/1_qq_35732147.jpg?1539065138'; //设置图片源
-
- //确定浏览器支持<canvas>元素
- if(drawing.getContext){
-
- var context = drawing.getContext("2d"); //取得2D上下文对象
-
- img.addEventListener("load", function(){
- context.drawImage(img, 0, 0); //图像加载完之后才会执行这条语句
- },false);
-
- }
使用DOM0级的Image对象可以在客户端预先加载图像,可以像使用<img>元素一样使用Image对象,但无法将其添加到DOM树中。
考虑到图片是从网络加载,所以应该保证图像加载完之后再调用drawImage()方法绘制图像。
②缩放图片简单示例:
- var drawing = document.getElementById("drawing");
-
- var img = new Image(); //创建Image对象
- img.src = 'https://avatar.csdn.net/6/4/D/1_qq_35732147.jpg?1539065138'; //设置图片源
-
- //确定浏览器支持<canvas>元素
- if(drawing.getContext){
-
- var context = drawing.getContext("2d"); //取得2D上下文对象
-
- img.addEventListener("load", function(){
- context.drawImage(img, 0, 0, 400, 400); //图像加载完之后才会执行这条语句
- },false);
-
- }
③切片
切片示例:
- var drawing = document.getElementById("drawing");
-
- //确定浏览器支持<canvas>元素
- if(drawing.getContext){
-
- var context = drawing.getContext("2d"); //取得2D上下文对象
-
- var img = new Image();
- img.src = "https://avatar.csdn.net/6/4/D/1_qq_35732147.jpg?1539071828";
-
- img.addEventListener("load", function(){
- context.drawImage(img, 50, 50, 200, 200, 0, 0, 200, 200);
- }, false);
-
- }
模式其实就是重复的图像,可以用来填充或描边图形。
要创建一个新模式,可以调用createPattern()方法并传入两个参数:
- var drawing = document.getElementById("drawing");
-
- //确定浏览器支持<canvas>元素
- if(drawing.getContext){
-
- var context = drawing.getContext("2d"); //取得2D上下文对象
-
- var img = new Image();
- img.src = "https://avatar.csdn.net/E/9/8/3_weixin_42058532.jpg";
-
- img.addEventListener("load", function(){
- var pattern = context.createPattern(img, "repeat");
-
- //绘制矩形
- context.fillStyle = pattern;
- context.fillRect(10, 10, 200, 200);
- }, false);
-
- }
canvas操作图像数据使用的几个方法:
①getImageData() —— 用于取得画布上指定矩形的像素数据。
具体是这个方法会返回ImageData对象,ImageData对象中包含图像数据。
getImageData()方法接收4个参数:
例如要取得左上角坐标为(10,5)、大小为50*50像素的区域的图像数据:
var imageData = context.getImageData(10, 5, 50, 50);
返回的对象是ImageData的实例,每个ImageData对象都有三个属性:
②putImageData() —— 把图像数据(从指定的ImageData对象)放回画布上。
这个方法接收以下参数:
下面的代码通过getImageData()取得画布上指定矩形的像素数据,然后通过putImageData()将图像数据放回画布:
- var c=document.getElementById("myCanvas");
- var ctx=c.getContext("2d");
- ctx.fillStyle="green";
- ctx.fillRect(10,10,50,50);
-
- var imgData=ctx.getImageData(10,10,50,50);
- ctx.putImageData(imgData,10,70);
③createImageData() —— 创建新的、空白的ImageData对象
这个方法接收的参数:
以下代码创建100*100像素的ImageData对象,其中每个像素都是红色的,然后把它放到画布上:
- var c=document.getElementById("myCanvas");
- var ctx=c.getContext("2d");
- var imgData=ctx.createImageData(100,100);
- for (var i=0;i<imgData.data.length;i+=4)
- {
- imgData.data[i+0]=255;
- imgData.data[i+1]=0;
- imgData.data[i+2]=0;
- imgData.data[i+3]=255;
- }
- ctx.putImageData(imgData,10,10);
效果:
示例:
创建一个简单的灰阶过滤器:
- var drawing = document.getElementById("drawing");
-
- //确定浏览器支持<canvas>元素
- if(drawing.getContext){
-
- var context = drawing.getContext("2d"); //取得2D上下文对象
-
- var image = new Image();
- image.src = "liyangqiao.jpg";
-
- image.addEventListener("load", function(event){
- var red, green, blue, alpha, average;
-
- //绘制原始图像
- context.drawImage(image, 0, 0);
-
- //取得图像数据
- imageData = context.getImageData(0, 0, image.width, image.height);
- data = imageData.data;
-
- for(var i = 0, len = data.length; i < len; i += 4){
- red = data[i];
- green = data[i + 1];
- blue = data[i + 2];
- alpha = data[i + 3];
-
- //求得rgb平均值
- average = Math.floor((red + green + blue) / 3);
-
- //设置颜色值,透明度不变
- data[i] = average;
- data[i + 1] = average;
- data[i + 2] = average;
- }
-
- //回写图像数据并显示结果
- imageData.data = data;
- context.putImageData(imageData, 0, 0);
- }, false);
-
- }
注意:只有在画布“干净”的情况下(即图像并非来自其他域),才可以取得图像数据。如果画布”不干净“,那么访问图像数据时会导致JavaScript错误。
2D上下文会根据以下几个属性的值,自动为形状或路径绘制出阴影。
- var drawing = document.getElementById("drawing");
-
- //确定浏览器支持<canvas>元素
- if(drawing.getContext){
-
- var context = drawing.getContext("2d"); //取得2D上下文对象
-
- //设置阴影
- context.shadowOffsetX = 5;
- context.shadowOffsetY = 5;
- context.shadowBlur = 5;
- context.shadowColor = "rgba(0, 0, 0, 0.5)";
-
- //绘制红色矩形
- context.fillStyle = "#F00";
- context.fillRect(10, 10, 50, 50);
-
- //绘制蓝色矩形
- context.fillStyle = "rgba(0, 0, 255, 1)";
- context.fillRect(30, 30, 50, 50);
-
- }
渐变由CanvasGradient实例表示,很容易通过2D上下文来创建和修改。
要创建一个新的线性渐变对象,可以调用createLinearGradient()方法。
这个方法接受4个参数:起点的x坐标、起点的y坐标、终点的x坐标、终点的y坐标。
创建了渐变对象后,下一步就是使用addColorStop()方法来指定色标。
这个方法接收两个参数:色标位置和CSS颜色值。色标位置是一个0(开始的颜色)到1(结束的颜色)之间的数字。
示例:
- var drawing = document.getElementById("drawing");
-
- //确定浏览器支持<canvas>元素
- if(drawing.getContext){
-
- var context = drawing.getContext("2d"); //取得2D上下文对象
-
- var gradient = context.createLinearGradient(30, 30, 70, 70);
-
- gradient.addColorStop(0, "white");
- gradient.addColorStop(1, "black");
-
- //绘制红色矩形
- context.fillStyle = "#ff0000";
- context.fillRect(10, 10, 50, 50);
-
- //绘制渐变矩形
- context.fillStyle = gradient;
- context.fillRect(30, 30, 50, 50);
-
- }
要创建径向渐变(或放射性渐变),可以使用createRadialGradient()方法。
这个方法接收6个参数,对应着两个圆的圆心和半径。前三个参数指定的是起点圆的圆心和半径,后三个参数指定的是终点圆的圆心和半径。
示例:
- var drawing = document.getElementById("drawing");
-
- //确定浏览器支持<canvas>元素
- if(drawing.getContext){
-
- var context = drawing.getContext("2d"); //取得2D上下文对象
-
- var gradient = context.createRadialGradient(55, 55, 10, 55, 55, 30);
-
- gradient.addColorStop(0, "white");
- gradient.addColorStop(1, "black");
-
- //绘制红色矩形
- context.fillStyle = "#ff0000";
- context.fillRect(10, 10, 50, 50);
-
- //绘制渐变矩形
- context.fillStyle = gradient;
- context.fillRect(30, 30, 50, 50);
-
- }
globalCompositionOperation属性表示后绘制的图形怎样与先绘制的图形结合。
这个属性的值是字符串,可能的值如下:
①source-over(默认值)
- var drawing = document.getElementById("drawing");
-
- //确定浏览器支持<canvas>元素
- if(drawing.getContext){
-
- var context = drawing.getContext("2d"); //取得2D上下文对象
-
- context.globalCompositeOperation = "source-over";
-
- //绘制红色矩形
- context.fillStyle = "#F00";
- context.fillRect(10, 10, 50, 50);
-
- //绘制蓝色矩形
- context.fillStyle = "rgba(0, 0, 255, 1)";
- context.fillRect(30, 30, 50, 50);
- }
②source-in
- var drawing = document.getElementById("drawing");
-
- //确定浏览器支持<canvas>元素
- if(drawing.getContext){
-
- var context = drawing.getContext("2d"); //取得2D上下文对象
-
- //绘制红色矩形
- context.fillStyle = "#F00";
- context.fillRect(10, 10, 50, 50);
-
- context.globalCompositeOperation = "source-in";
-
- //绘制蓝色矩形
- context.fillStyle = "rgba(0, 0, 255, 1)";
- context.fillRect(30, 30, 50, 50);
- }
③source-out
- var drawing = document.getElementById("drawing");
-
- //确定浏览器支持<canvas>元素
- if(drawing.getContext){
-
- var context = drawing.getContext("2d"); //取得2D上下文对象
-
- //绘制红色矩形
- context.fillStyle = "#F00";
- context.fillRect(10, 10, 50, 50);
-
- context.globalCompositeOperation = "source-out";
-
- //绘制蓝色矩形
- context.fillStyle = "rgba(0, 0, 255, 1)";
- context.fillRect(30, 30, 50, 50);
- }
④source-atop
- var drawing = document.getElementById("drawing");
-
- //确定浏览器支持<canvas>元素
- if(drawing.getContext){
-
- var context = drawing.getContext("2d"); //取得2D上下文对象
-
- //绘制红色矩形
- context.fillStyle = "#F00";
- context.fillRect(10, 10, 50, 50);
-
- context.globalCompositeOperation = "source-atop";
-
- //绘制蓝色矩形
- context.fillStyle = "rgba(0, 0, 255, 1)";
- context.fillRect(30, 30, 50, 50);
- }
⑤destination-over
- var drawing = document.getElementById("drawing");
-
- //确定浏览器支持<canvas>元素
- if(drawing.getContext){
-
- var context = drawing.getContext("2d"); //取得2D上下文对象
-
- //绘制红色矩形
- context.fillStyle = "#F00";
- context.fillRect(10, 10, 50, 50);
-
- context.globalCompositeOperation = "destination-over";
-
- //绘制蓝色矩形
- context.fillStyle = "rgba(0, 0, 255, 1)";
- context.fillRect(30, 30, 50, 50);
- }
⑥destination-in
- var drawing = document.getElementById("drawing");
-
- //确定浏览器支持<canvas>元素
- if(drawing.getContext){
-
- var context = drawing.getContext("2d"); //取得2D上下文对象
-
- //绘制红色矩形
- context.fillStyle = "#F00";
- context.fillRect(10, 10, 50, 50);
-
- context.globalCompositeOperation = "destination-in";
-
- //绘制蓝色矩形
- context.fillStyle = "rgba(0, 0, 255, 1)";
- context.fillRect(30, 30, 50, 50);
- }
⑦destination-out
- var drawing = document.getElementById("drawing");
-
- //确定浏览器支持<canvas>元素
- if(drawing.getContext){
-
- var context = drawing.getContext("2d"); //取得2D上下文对象
-
- //绘制红色矩形
- context.fillStyle = "#F00";
- context.fillRect(10, 10, 50, 50);
-
- context.globalCompositeOperation = "destination-out";
-
- //绘制蓝色矩形
- context.fillStyle = "rgba(0, 0, 255, 1)";
- context.fillRect(30, 30, 50, 50);
- }
⑧destination-atop
- var drawing = document.getElementById("drawing");
-
- //确定浏览器支持<canvas>元素
- if(drawing.getContext){
-
- var context = drawing.getContext("2d"); //取得2D上下文对象
-
- //绘制红色矩形
- context.fillStyle = "#F00";
- context.fillRect(10, 10, 50, 50);
-
- context.globalCompositeOperation = "destination-atop";
-
- //绘制蓝色矩形
- context.fillStyle = "rgba(0, 0, 255, 1)";
- context.fillRect(30, 30, 50, 50);
- }
⑨lighter
- var drawing = document.getElementById("drawing");
-
- //确定浏览器支持<canvas>元素
- if(drawing.getContext){
-
- var context = drawing.getContext("2d"); //取得2D上下文对象
-
- //绘制红色矩形
- context.fillStyle = "#F00";
- context.fillRect(10, 10, 50, 50);
-
- context.globalCompositeOperation = "lighter";
-
- //绘制蓝色矩形
- context.fillStyle = "rgba(0, 0, 255, 1)";
- context.fillRect(30, 30, 50, 50);
- }
⑩copy
- var drawing = document.getElementById("drawing");
-
- //确定浏览器支持<canvas>元素
- if(drawing.getContext){
-
- var context = drawing.getContext("2d"); //取得2D上下文对象
-
- //绘制红色矩形
- context.fillStyle = "#F00";
- context.fillRect(10, 10, 50, 50);
-
- context.globalCompositeOperation = "copy";
-
- //绘制蓝色矩形
- context.fillStyle = "rgba(0, 0, 255, 1)";
- context.fillRect(30, 30, 50, 50);
- }
⑾xor
- var drawing = document.getElementById("drawing");
-
- //确定浏览器支持<canvas>元素
- if(drawing.getContext){
-
- var context = drawing.getContext("2d"); //取得2D上下文对象
-
- //绘制红色矩形
- context.fillStyle = "#F00";
- context.fillRect(10, 10, 50, 50);
-
- context.globalCompositeOperation = "xor";
-
- //绘制蓝色矩形
- context.fillStyle = "rgba(0, 0, 255, 1)";
- context.fillRect(30, 30, 50, 50);
- }
①清空canvas
除非要画的内容会完全充满canvas(例如背景图),否则需要清空所有。
最简单的做法就是用clearRect()方法。
②保存canvas状态
如果要改变一些会改变canvas状态的设置(样式,变形之类的),又要在每画一帧之时都是原始状态的话,需要先保存一下。
③绘制动画图形
这一步才是重绘动画帧
④恢复canvas状态
如果已经保存了canvas的状态,可以先恢复它,然后重绘下一帧。
在canvas上绘制内容是用canvas提供的或者自定义的方法,而通常,我们仅仅在脚本执行结束后才能看见结果,比如说,在for循环里面做完成动画是不太可能的,因为for循环一直高速执行,动画都来不及绘制。
因此,为了实现动画,我们需要一些可以定时执行重绘的方法。
首先,可以用window.setInterval(),window.setTimeout(),和window.requestAnimationFrame()来设定定期执行一个指定函数:
如果并不需要与用户互动,可以使用setInterval()方法,它就可以定期执行指定代码。
如果需要做一个游戏,我们可以使用键盘或者鼠标事件配合上setTimeout()方法来实现。
通过设置事件监听,可以捕捉用户的交互,并执行相应的动作。
下面的例子,采用window.requestAnimationFrame()实现动画效果。
这个方法提供了更加平缓并更加有效率的方式来执行动画,当系统准备好了重绘条件的时候,才调用绘制动画帧。
一般每秒钟回调函数执行60次,也有可能会被降低。
一个小型的太阳系模拟动画:
- var sun = new Image();
- var moon = new Image();
- var earth = new Image();
- function init(){
- sun.src = 'https://mdn.mozillademos.org/files/1456/Canvas_sun.png';
- moon.src = 'https://mdn.mozillademos.org/files/1443/Canvas_moon.png';
- earth.src = 'https://mdn.mozillademos.org/files/1429/Canvas_earth.png';
- window.requestAnimationFrame(draw);
- }
-
- function draw(){
- var ctx = document.getElementById("drawing").getContext('2d');
-
- //后绘制的图形位于先绘制的图形下方,只有之前透明像素下的部分才可见
- ctx.globalCompositeOperation = 'destination-over';
- ctx.clearRect(0, 0, 300, 300); //clear canvas
-
- ctx.fillStyle = 'rgba(0, 0, 0, 0.4)';
- ctx.strokeStyle = 'rgba(0, 153, 255, 0.4)';
- ctx.save();
- //移动坐标原点
- ctx.translate(150, 150);
-
- // Earth
- var time = new Date();
- ctx.rotate( ((2 * Math.PI) / 60) * time.getSeconds() + ((2 * Math.PI) / 60000) * time.getMilliseconds() );
- ctx.translate(105, 0);
- ctx.fillRect(0, -12, 50, 24); //Shadow
- ctx.drawImage(earth, -12, -12);
-
- // Moon
- ctx.save();
- ctx.rotate( ((2 * Math.PI) / 60) * time.getSeconds() + ((2 * Math.PI) / 60000) * time.getMilliseconds() );
- ctx.translate(0, 28.5);
- ctx.drawImage(moon, -3.5, -3.5);
- ctx.restore();
-
- ctx.restore();
-
- ctx.beginPath();
- ctx.arc(150, 150, 105, 0, Math.PI * 2, false); // Earth orbit
- ctx.stroke();
-
- ctx.drawImage(sun, 0, 0, 300, 300);
-
- window.requestAnimationFrame(draw);
-
- }
-
- init();
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。