canvas API——0710

一、什么是canvas?

HTML5 <canvas> 元素用于图形的绘制,通过脚本 (通常是JavaScript)来完成。
<canvas> 标签只是图形容器,必须使用脚本来绘制图形。

二、创建一个canvas画布

一个画布在网页中是一个矩形框,通过 <canvas> 元素来绘制。可以在HTML页面中使用多个 <canvas> 元素。

标签通常需要指定一个id属性 (脚本中经常引用),width 和 height 属性定义的画布的大小。
注意: width 和 height 使用的是元素的属性来设置,在style属性中设置的宽高是元素样式的宽高,不是canvas画布的宽高。

注意: 默认情况下 <canvas> 元素没有边框和内容。可以使用 style 属性来添加边框。

<canvas id="canvas" width="900" height="600"></canvas>

三、使用 JavaScript 来绘制图像——canvas绘图API的使用

使用canvas绘图API绘制图像之前,首先需要获取 canvas元素,设置canvas元素的宽高属性创建 context 对象

<canvas id="canvas"></canvas>
<script>
    //获取canvas元素
    var canvas = document.getElementById("canvas");
    //设置画布的宽高
    canvas.width = 900;
    canvas.height = 600;
    //将canvas转化为2d模型
    var context = canvas.getContext("2d");
</script>

接下来使用canvas绘图API进行绘制

下边举例说明常用的API属性和方法,更多内容参考:canvas API 中文网 或者 canvas API—MDN

1、填充和描边

context.fillStyle 填充样式。默认值是#000000纯黑色。
context.fill() 填充。
context.strokeStyle 描边样式。默认值是#000000纯黑色。
context.stroke() 描边。

2、绘制矩形

context.clearRect(x, y, width, height) 清除指定矩形区域内部所有的像素信息为初始色(通常为透明)。
context.fillRect(x, y, width, height) 矩形填充,可以填充颜色,渐变,图案等。
context.strokeRect(x, y, width, height) 矩形描边。

以上三个方法的参数相同,分别为:矩形的起始点横坐标、纵坐标、矩形的宽度、高度。

	//清除一个矩形区域的内容
	context.clearRect(0, 0, 900, 600);
	    
	//用红色填充一个矩形
    context.fillStyle = "red";
    context.fillRect(10, 10, 100, 100);
    context.fill();

	//用红色描边一个矩形
	context.strokeStyle = "green";
    context.strokeRect(230, 10, 100, 100);
    context.stroke();  

3、绘制文本

context.fillText(text, x, y [, maxWidth]) 文字填充,可以填充纯色,渐变或者图案。
context.strokeText(text, x, y [, maxWidth]) 文字描边。

以上两个方法的参数相同,分别为:
文本信息、
文本的起始点横坐标、
文本的起始点纵坐标、
文本占据的最大宽度(可选,当文本占据宽度超过此最大宽度的时候,通过压缩每个文本宽度进行适合,而非换行)。

	//黄色填充文本
    context.fillStyle = "yellow";
    context.font = "bold 60px 幼圆";
    context.fillText("Hello Word!", 350, 100, 300);

	//蓝色描边文本
    context.strokeStyle = "blue";
    context.font = "bold 50px 等线";
    context.strokeText("你好!", 700, 100, 200);

上例中的context.font 用来设置字体样式,其规则和 CSS 的 font 类似,参数分别为fontweight、fontsize、fontfamily。

除此之外还有其他设置字体样式的属性,如 textAlign、textBaseline、direction。

4、常用的线条样式设置

context.lineWidth 线条宽度,主使用场景是描边,默认宽度是1.0,支持小数。
context.lineCap 线条端点的样式。支持如下属性值:butt(默认值,断头,无端帽),round(圆形端帽),square(方形端帽)。

5、绘制路径

context.beginPath() 开始一个新路径。
context.closePath() 闭合一个路径。
context.moveTo(x,y) 路径绘制起始点。参数为落点的横坐标、纵坐标。
context.lineTo(x,y) 绘制直线到指定坐标点。参数为落点的横坐标、纵坐标。
context.arc(x, y, radius, startAngle, endAngle [, anticlockwise]) 绘制圆弧(包括圆)。参数为圆心横坐标、圆心纵坐标、半径、圆弧开始的角度(单位是弧度)、圆弧结束的角度(单位是弧度)、弧度的开始到结束的绘制是按照顺时针来算,还是按时逆时针来算(true为逆时针,默认为false)。
context.arcTo(x1, y1, x2, y2, radius) 绘制圆弧,和之前的点以直线相连。参数为第一个控制点的横坐标、纵坐标、第二个控制点的横坐标、纵坐标、圆弧的半径。
context.ellipse(x, y, radiusX, radiusY, rotation, startAngle, endAngle, anticlockwise) 绘制椭圆路径。参数分别为:椭圆弧的圆心横坐标,纵坐标、长轴半径大小、短轴半径大小、椭圆弧的旋转角度(单位是弧度)、圆弧开始的角度(角度从横轴开始算,单位是弧度)、圆弧结束的角度(单位是弧度)、弧度的开始到结束的绘制是按照顺时针来算,还是按时逆时针来算(true为逆时针,默认为false)。
context.clip() 创建剪裁路径。使用的时候,先绘制裁剪路径,再执行clip() 方法,之后再绘制的内容就在这个裁剪路径中呈现。

    context.strokeStyle = "green";
    context.fillStyle = "yellow";
    //绘制圆弧
    context.beginPath();
    context.arc(110, 200, 50, 0, Math.PI * 2, false);
    context.stroke();
    context.fill();
    context.closePath();

    //绘制线条
    context.beginPath();
    context.moveTo(200, 200);
    context.arcTo(260, 150, 350, 260, 60);
    context.arcTo(350, 260, 400, 200, 60);
    context.lineTo(400, 200);
    context.stroke();
    context.closePath();

    //绘制椭圆
    context.beginPath();
    context.ellipse(600, 200, 100, 50, Math.PI / 4, 0, Math.PI * 2, false);
    context.stroke();
    context.closePath();

下例中使用一个固定的路径裁剪图片:

    //路径裁剪
    var image1 = new Image();
    image1.onload = function () {
        context.clearRect(0, 0, 900, 600);
        context.beginPath();
        context.moveTo(200, 50);

        context.lineTo(200, 100);
        context.arcTo(100, 150, 200, 200, 50);
        context.lineTo(200, 200);
        context.lineTo(200, 250);

        context.lineTo(250, 250);
        context.arcTo(300, 400, 350, 250, 50);
        context.lineTo(350, 250);
        context.lineTo(400, 250);

        context.lineTo(400, 200);
        context.arcTo(500, 150, 400, 100, 50);
        context.lineTo(400, 100);
        context.lineTo(400, 50);

        context.lineTo(350, 50);
        context.arcTo(300, -50, 250, 50, 50);
        context.lineTo(250, 50);
        context.lineTo(200, 50);
        context.clip();
        context.closePath();
        context.drawImage(this, 0, 0, 533, 300);
    };
    image1.src = "http://img5.imgtn.bdimg.com/it/u=3908114527,2766768530&fm=26&gp=0.jpg";

裁剪后的效果如下:
图片裁剪

6、绘制图片

共有以下三种写法:

context.drawImage(image, dx, dy);
context.drawImage(image, dx, dy, dWidth, dHeight);
context.drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight);

各个参数含义和作用如下:
image
绘制在Canvas上的元素,可以是各类Canvas图片资源,如<img>图片,SVG图像,Canvas元素本身等。
dx
在Canvas画布上规划一片区域用来放置图片,dx就是这片区域的左上角横坐标。
dy
在Canvas画布上规划一片区域用来放置图片,dy就是这片区域的左上角纵坐标。
dWidth
在Canvas画布上规划一片区域用来放置图片,dWidth就是这片区域的宽度。
dHeight
在Canvas画布上规划一片区域用来放置图片,dHeight就是这片区域的高度。
sx
表示图片元素绘制在Canvas画布上起始横坐标。
sy
表示图片元素绘制在Canvas画布上起始纵坐标。
sWidth
表示图片元素从坐标点开始算,多大的宽度内容绘制Canvas画布上。
sHeight
表示图片元素从坐标点开始算,多大的高度内容绘制Canvas画布上。

其中sx、sy、sWidth、sHeight 可以看做是图片的裁剪。

    //绘制图片
    var image = new Image();
    image.onload = function () {
        context.drawImage(this, 0, 0, 533, 300, 50, 50, 533, 300);
    };
    image.src = "http://img5.imgtn.bdimg.com/it/u=3908114527,2766768530&fm=26&gp=0.jpg";

8、渐变相关

context.createLinearGradient(x0, y0, x1, y1); 创建线性渐变。参数为渐变起始点横坐标、纵坐标、渐变结束点横坐标、纵坐标。
context.createRadialGradient(x0, y0, r0, x1, y1, r1); 创建径向渐变。参数为:起始圆的横坐标、纵坐标、起始圆的半径、结束圆的横坐标、纵坐标、结束圆的半径。

线性渐变中,需要注意的是,参数中的坐标是相对于全局的,而不是相对于填充元素计算的;并且,如果渐变坐标在Canvas外部,也只会显示画布内的渐变效果。

以上两个方法一般和addColorStop(offset, color) 方法连用。
addColorStop(offset, color) 方法用来给渐变添加新的渐变点,参数为:渐变点相对于整个渐变范围的偏移(范围是0-1),渐变点的颜色值(只要能被正确解析为CSS颜色的值都是合法的)。

    //线性渐变
    var gradient = context.createLinearGradient(0, 150, 900, 150);
    gradient.addColorStop(0.2, "red");
    gradient.addColorStop(0.4, "orange");
    gradient.addColorStop(0.6, "yellow");
    gradient.addColorStop(0.8, "green");
    gradient.addColorStop(1, "cyan");
    context.fillStyle = gradient;
    context.fillRect(0, 0, 900, 200);

    //径向渐变——圆形渐变
    //起始圆半径为0
    var grad = context.createRadialGradient(200, 400, 0, 200, 400, 100);
    grad.addColorStop(.2, "white");
    grad.addColorStop(.5, "yellow");
    grad.addColorStop(1, "orange");
    context.fillStyle = grad;
    context.beginPath();
    context.arc(200, 400, 100, 0, Math.PI * 2, false);
    context.fill();
    context.stroke();
    context.closePath();

    //渐变色字
    var g = context.createLinearGradient(400, 500, 900, 500);
    g.addColorStop(0.2, "red");
    g.addColorStop(0.4, "orange");
    g.addColorStop(0.6, "yellow");
    g.addColorStop(0.8, "green");
    g.addColorStop(1, "cyan");
    context.fillStyle = g;
    context.font = "700 60px 幼圆";
    context.fillText("Hello World!", 400, 400, 500);

9、图案相关

context.createPattern(image, repetition) 创建图案。图案内容可以是图片,可以是<canvas>元素,也可以是渐变。参数为:用来平铺的CanvasImageSource图像、平铺方式(repeat,repeat-x,repeat-y,no-repeat)

    var image = new Image();
    image.onload = function () {
        var pattern = context.createPattern(this, "repeat");
        context.fillStyle = pattern;
        context.font = "700 60px 幼圆";
        context.fillText("Hello World!", 400, 550, 500);
    };
    image.src = "http://img3.imgtn.bdimg.com/it/u=3681705955,4153554780&fm=26&gp=0.jpg";

10、阴影相关

context.shadowColor 指定阴影的颜色。默认值是透明黑,也就是看不到颜色,因此,如果我们想要使用阴影效果,shadowColor是必须要指定的。
context.shadowBlur 指定阴影的模糊程度。默认值是0,表示不模糊。
context.shadowOffsetX 阴影的水平偏移,默认值是0。
context.shadowOffsetY 阴影的垂直偏移,默认值是0。

	//阴影
    context.shadowColor = "#c0c0c0";
    context.shadowBlur = 3;
    context.shadowOffsetX = 8;
    context.shadowOffsetY = 8;
    context.lineWidth=10;
    context.strokeStyle="blue";
    context.strokeRect(300,300,200,200);

11、透明度

context.globalAlpha 设置画布的全局透明度,范围是0到1,0表示完全透明,1表示完全不透明,范围以外的值会被忽略。

12、变换

(1)旋转:

context.rotate(angle);canvas画布添加旋转矩阵,顺时针方向,单位是弧度。

默认旋转中心点是Canvas的左上角(0, 0)坐标点,如果希望改变旋转中心点,例如以Canvas画布的中心旋转,需要先使用translate()位移旋转中心点。
注意: 此旋转和CSS3的旋转变换不一样,旋转的是坐标系,而非元素。因此,实际开发的时候,旋转完毕,需要设置 context.setTransform(1, 0, 0, 1, 0, 0); 将坐标系再还原。

比如:

// 文字旋转45度
context.rotate(45 * Math.PI / 180);
// 字体填充
context.font = '20px STHeiti, SimHei';
context.fillText('旋转,跳跃,我闭着眼', 60, -40, 188);
// 重置当前的变换矩阵为初始态
context.setTransform(1, 0, 0, 1, 0, 0);

旋转
(2)缩放

context.scale(x, y); 用来缩放Canvas画布的坐标系,只是影响坐标系,之后的绘制会受此方法影响,但之前已经绘制好的效果不会有任何变化。

默认缩放中心点是Canvas的左上角(0, 0)坐标点,如果希望改变缩放中心点,需要先使用translate()方法进行位移。

此缩放支持负数,也支持小数。如果参数 x,y 的值是-1,分别表示水平翻转和垂直翻转。

(3)位移

context.translate(x, y); 对canvas坐标系进行整体位移,实际开发中经常用来改变其它变换方法的中心点。 参数分别为坐标系水平和垂直位移的距离。

(4)当前矩阵变换基础上再次矩阵变换

context.transform(a, b, c, d, e, f); 对当前坐标系进行进一步变换,以实现缩放、旋转、拉伸、位移效果。

各个参数的含义分别为:水平缩放、水平斜切、垂直斜切、垂直缩放、水平位移、垂直位移。

设置 context.transform(1, 0, 0, 1, 0, 0); 即:维持当前的变换矩阵不变。

注意:
此方法和setTransform()方法的区别在于,后者一旦执行会完全重置已有的变换,transform()方法则是累加。

(5)直接重置为当前设置的矩阵变换

context.setTransform(a, b, c, d, e, f); 通过矩阵变换重置当前的坐标系。

各参数的含义和 transform() 方法相同。

设置 context.setTransform(1, 0, 0, 1, 0, 0); 即:重置当前的变换矩阵为初始态。

13、图片与像素

context.createImageData(width, height);
context.createImageData(imagedata);
创建一个全新的空的ImageData对象。该对象中的所有像素信息都是透明黑。返回值是ImageData对象,包含width,height和data这3个只读属性。

以上参数的含义:
width ——Number
ImageData对象包含的width值。如果ImageData对象转换成图像,则此width也是最终图像呈现的宽度。
height ——Number
ImageData对象包含的height值。如果ImageData对象转换成图像,则此height也是最终图像呈现的高度。
imagedata ——Object
一个存在的ImageData对象,只会使用该ImageData对象中的width和height值,包含的像素信息会全部转换为透明黑。

context.getImageData(sx, sy, sWidth, sHeight); 返回一个ImageData对象,其中包含Canvas画布部分或完整的像素点信息。

以上参数分别为:需要返回的图像数据区域的起始横坐标、需要返回的图像数据区域的起始点纵坐标、需要返回的图像数据区域的宽度、需要返回的图像数据区域的高度。

注意:当我们需要对图像进行像素级处理的时候,getImageData() 方法是不可或缺的。
getImageData()方法可能会出现CORS跨域报错,具体方法参见 解决canvas图片getImageData,toDataURL跨域问题

context.putImageData(imagedata, dx, dy); 将给定ImageData对象的数据绘制到位图上。
此方法不受画布变换矩阵的影响。

参数分别为:包含图像像素信息的 ImageData 对象、目标Canvas中被图像数据替换的起点横坐标、纵坐标。

应用示例:
绘制一张图片到Canvas画布上,然后把中间300*300区域变成灰色。

<canvas id="canvas"></canvas>
<script>
    var canvas = document.querySelector("canvas");
    //设置画布的尺寸
    canvas.width = 1024;
    canvas.height = 768;
    var image = new Image();
    image.onload = function () {
        //先将canvas   转化为2d模型
        var context = canvas.getContext("2d");
        //图片绘制
        context.drawImage(this, 0, 0, 1024, 768);
        //获取中间300*300区域数据
        var imageData=context.getImageData(362,234,300,300);
        console.log(imageData);
        var length=imageData.data.length;
        for(var index=0;index<length;index+=4){
            var r=imageData.data[index];
            var g=imageData.data[index+1];
            var b=imageData.data[index+2];
            //计算灰度
            var gray=r*0.299+g * 0.587 + b * 0.114;
            imageData.data[index]=gray;
            imageData.data[index+1]=gray;
            imageData.data[index+2]=gray;
        }
        //更新新数据
        context.putImageData(imageData,362,234);
    };
    image.src = "./image/1.jpg";
</script>

14、canvas状态

canvas.save() 保存当前Canvas画布状态并放在栈的最上面。可以使用restore()方法依次取出。
canvas.restore() 依次从堆栈的上方弹出存储的canvas状态,如果没有任何存储的canvas状态,则执行此方法没有任何变化。

举例:
先存储默认的Canvas状态,再还原,可以看到填充颜色变成了默认的黑色了。代码如下:

// 保存初始Canvas状态
context.save();
// 设置红色填充
context.fillStyle = 'red';
// 矩形填充
context.fillRect(20, 20, 100, 60);  //红色
// 还原在绘制
context.restore();
// 矩形填充again
context.fillRect(180, 60, 100, 60);  //黑色
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值