博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
HTML5之Canvas
阅读量:4544 次
发布时间:2019-06-08

本文共 8045 字,大约阅读时间需要 26 分钟。

感性认识

canvas元素是HTML5中新增的一个重要元素,专门用来绘制图形,它就像页面的一个画布,利用canvas绘图的步骤很简单:

  1. 页面放置canvas;
  2. 获取canvas的context;
  3. 通过context的api用JavaScript来进行绘画;
  4. 绘制路径(矩形不需要),设置样式,使用stroke或fill来填充;

首先我们了解canvas的坐标是这样的

先来看下示例

绘制的图形如下:

绘制简单图形

  1. 绘制矩形
    fillRect(x, y, width, height) //绘制实心矩形,被填充strokeRect(x, y, width, height)//绘制空心矩形,只是边框
    它的四个参数分别为矩形左上角顶点的x坐标、y坐标,以及矩形的宽和高。
  2. 绘制圆形
    矩形不用绘制路径,直接fill或stroke,而其他的图形需要先绘制路径,然后在fill或stroke。
    context.arc(x,y,r,sAngle,eAngle,counterclockwise);
    • x:圆的中心的 x 坐标。
    • y:圆的中心的 y 坐标。
    • r:圆的半径。
    • sAngle:起始角,以弧度计。(弧的圆形的三点钟位置是 0 度)。
    • eAngle:结束角,以弧度计。
    • counterclockwise:可选。规定应该逆时针还是顺时针绘图。False = 顺时针,true = 逆时针。
    如需通过 arc() 来创建圆,请把起始角设置为 0,结束角设置为 2*Math.PI
  3. 绘制直线
    ctx.moveTo(200,30); //设置路径的起点ctx.lineTo(280,60); //设置路径的终点ctx.stroke(); //给路径着色
    如果上面示例,我们并没有使用beginPath,因为这是第一次绘图,所以不用,但如上例中绘制圆形,如果不用beginPath,你绘制出的图如
    这是因为没有使用beginPath来重置路径,而且这还牵涉到另一个API:closePath,它的作用是把起点终点链接起来,如绘制三角形,如果你注释掉closePath,将不会绘制成三角形只是折线而已。
    这里需要强调的是使用fill时会自动把起点和终点链接起来,就类似隐含先执行了closePath一样。这一点可以这样验证,把示例中的绘制圆形注释掉beginPath,而且只绘半圆,代码如下
    绘制的图形如下
    是不是感觉奇怪,如果把绘制圆形使用closePath,再把fill改成stroke,你就会发现路径是这样的
    所以beginPath和closePath需要要搞懂,会用慎用!

绘制渐变

  1. 线性渐变
    示例:
    var canvas=document.getElementById("mycanvas");//获取contextvar ctx=canvas.getContext("2d");//设置样式ctx.lineWidth=20;var g=ctx.createLinearGradient(0,0,0,100);g.addColorStop(0,'green');g.addColorStop(0.5,'blue');g.addColorStop(1,'red');ctx.strokeStyle=g;ctx.moveTo(0,0);ctx.lineTo(0,100);ctx.stroke();
    绘图如
    绘制线性渐变需要使用createLinearGradient和addColorStop方法
    context.createLinearGradient(x0,y0,x1,y1);
    • x0:渐变开始点的 x 坐标
    • y0:渐变开始点的 y 坐标
    • x1:渐变结束点的 x 坐标
    • y1:渐变结束点的 y 坐标
    gradient.addColorStop(stop,color);
    • stop:介于 0.0 与 1.0 之间的值,表示渐变中开始与结束之间的位置。
    • color:在结束位置显示的 CSS 颜色值
  2. 径向渐变
    示例
    使用的径向渐变方法
    context.createRadialGradient(x0,y0,r0,x1,y1,r1);
    • x0:渐变的开始圆的 x 坐标
    • y0:渐变的开始圆的 y 坐标
    • r0:开始圆的半径
    • x1:渐变的结束圆的 x 坐标
    • y1:渐变的结束圆的 y 坐标
    • r1:结束圆的半径

绘制变形图

  1. 坐标变换
    可以通过变化canvas坐标来达到变换图形的效果,坐标有三种变换方式:
    • 平移:重新映射画布上的 (0,0) 位置
      context.translate(x,y);
      x和y分别表示把坐标原点向x和y方向移动多少个单位,默认的单位是像素;
    • 缩放:缩放当前绘图至更大或更小
      context.scale(x,y);
      x和y分别表示把x和y方向放大或缩小的倍数;
    • 旋转:旋转当前绘图
      context.rotate(angle);
      angle表示旋转角度,以弧度计。如需将角度转换为弧度,请使用 degrees*Math.PI/180 公式进行计算。
    示例
    绘制的图形
  2. 坐标变换和路径结合的使用
    路径一旦绘制好后是不会随着坐标变换而变换的,如
    var canvas=document.getElementById("mycanvas");//获取contextvar ctx=canvas.getContext("2d");//坐标变换前的路径ctx.moveTo(0,0);ctx.lineTo(100,20);ctx.lineTo(20,80);//变换坐标ctx.rotate(20*Math.PI/180);//为路径填色ctx.strokeStyle="green";ctx.stroke();//坐标变换后绘制的图像,路径与上一路径相同ctx.strokeStyle="red";ctx.beginPath();ctx.moveTo(0,0);ctx.lineTo(100,20);ctx.lineTo(20,80);ctx.stroke();
    绘制的图像
    可见坐标变换对路径是没影响的,一般这种情况我们会把绘图操作封装成一个函数,方便坐标变换后操作。
    var canvas=document.getElementById("mycanvas");//获取contextvar ctx=canvas.getContext("2d");doPic(ctx,"green");ctx.rotate(20*Math.PI/180);doPic(ctx,"red");ctx.rotate(20*Math.PI/180);doPic(ctx,"blue");function doPic(ctx,color){		ctx.beginPath();	ctx.moveTo(0,0);	ctx.lineTo(100,20);	ctx.lineTo(20,80);	ctx.strokeStyle=color;	ctx.stroke();	}
  3. 矩阵变换
    如果上述都不能满足需求,HTML5还提供一种更复杂的变化:矩阵变换,这块牵涉到矩阵的数学知识,稍后单一节示例。

图像组合

通常当绘制的图像重叠时将以绘制的先后顺序来处理重叠的部分,但HTML5提供了globalCompositeOperation 选项来设置如何处理重叠。

绘制的图像

globalCompositeOperation 属性设置或返回如何将一个源(新的)图像绘制到目标(已有)的图像上。

  • 源图像 = 您打算放置到画布上的绘图。
  • 目标图像 = 您已经放置在画布上的绘图。

属性值和描述

  • source-over:默认。在目标图像上显示源图像。
  • source-atop:在目标图像顶部显示源图像。源图像位于目标图像之外的部分是不可见的。
  • source-in:在目标图像中显示源图像。只有目标图像内的源图像部分会显示,目标图像是透明的。
  • source-out:在目标图像之外显示源图像。只会显示目标图像之外源图像部分,目标图像是透明的。
  • destination-over:在源图像上方显示目标图像。
  • destination-atop:在源图像顶部显示目标图像。源图像之外的目标图像部分不会被显示。
  • destination-in:在源图像中显示目标图像。只有源图像内的目标图像部分会被显示,源图像是透明的。
  • destination-out:在源图像外显示目标图像。只有源图像外的目标图像部分会被显示,源图像是透明的。
  • lighter:显示源图像 + 目标图像。
  • copy:显示源图像。忽略目标图像。
  • source-over:使用异或操作对源图像与目标图像进行组合。

绘制阴影

HTML5给添加阴影也非常简单,主要涉及到下面几个属性:

  • shadowColor:设置或返回用于阴影的颜色,如果取消只需设置为rgba(0,0,0,0);
  • shadowBlur:设置或返回用于阴影的模糊级别,一般设置在0-10之间;
  • shadowOffsetX:设置或返回阴影距形状的水平距离;
  • shadowOffsetY:设置或返回阴影距形状的垂直距离;
ctx.fillStyle="blue";ctx.shadowColor="#ccc";ctx.shadowBlur=5;ctx.shadowOffsetX=10;ctx.shadowOffsetY=10;ctx.fillRect(10,10,60,60);ctx.fillRect(80,80,60,60);

使用图片

    1. 绘制图片
      插入图片的方法只有一个,但是有三个重载方法,具体如下:
      context.drawImage (image, dx, dy)context.drawImage (image, dx, dy, dw, dh)context.drawImage (image, sx, sy, sw, sh, dx, dy, dw, dh)
      image是一个Image对象,用来装载图像文件,而其他参数参考下图:
      示例
      不支持canvas.
      但这样有时可能并不能绘制出图片,因为当image的src设置好后,但由于网络或图片过大导致不能及时加载,所以一般我们会在image的onload事件中操作
      不支持canvas.
      绘制的图片如:
      图像平铺 HTML5提供了一个非常方便的方法
createPattern(image, repetitionStyle)
    1. 创建并返回一个 CanvasPattern 对象,该对象表示一个贴图图像所定义的模式。要使用一个模式来勾勒线条或填充区域,可以把一个 CanvasPattern 对象用作 strokeStyle 属性或 fillStyle 属性的值。repetitionStyle 说明图像如何贴图。可能的值如下所示:
  • "repeat" - 在各个方向上都对图像贴图。默认值。
  • "repeat-x" - 只在 X 方向上贴图。
  • "repeat-y" - 只在 Y 方向上贴图。
  • "no-repeat" - 不贴图,只使用它一次。
示例
img.οnlοad=function(){	var ptt=ctx.createPattern(img,'repeat');	ctx.fillStyle=ptt;	ctx.fillRect(0,0,300,200);}

  1. 裁剪
    clip() 方法从原始画布中剪切出任意形状和尺寸。
    一旦再勾画出路径后调用clip方法,则所有只有的绘图都会被限制在这个路径区域,从而达到裁剪的效果,可以结合save和restore方法。
    img.οnlοad=function(){		ctx.beginPath();	ctx.arc(60,60,50,0,Math.PI*2,true);		ctx.clip();	ctx.drawImage(img,0,0);}
  2. 像素
    html5还有一个令人赞叹的技术就是可以处理像素,这设计到两个API:
    var imgData=context.getImageData(x,y,width,height);
    • x - 开始复制的左上角位置的 x 坐标。
    • y - 开始复制的左上角位置的 y 坐标。
    • width - 将要复制的矩形区域的宽度。
    • height - 将要复制的矩形区域的高度。
    getImageData() 方法返回 ImageData 对象,该对象拷贝了画布指定矩形的像素数据。对于 ImageData 对象中的每个像素,都存在着四方面的信息,即rgba 值:
    • r - 红色 (0-255)
    • g - 绿色 (0-255)
    • b - 蓝色 (0-255)
    • a - alpha 通道 (0-255; 0 是透明的,255 是完全可见的)
    color/alpha 以数组形式存在储于 ImageData对象的 data 属性中,形式如[r1,g1,b1,a1,r2,g2,b2,a2,....]。
    context.putImageData(imgData,x,y,dirtyX,dirtyY,dirtyWidth,dirtyHeight);
    • imgData - 规定要放回画布的 ImageData 对象。
    • x - ImageData 对象左上角的 x 坐标,以像素计。
    • y - ImageData 对象左上角的 y 坐标,以像素计。
    • dirtyX - 可选。水平值(x),以像素计,在画布上放置图像的位置。
    • dirtyY - 可选。水平值(y),以像素计,在画布上放置图像的位置。
    • dirtyWidth - 可选。在画布上绘制图像所使用的宽度。
    • dirtyHeight - 可选。在画布上绘制图像所使用的高度。
    putImageData() 方法将图像数据(从指定的 ImageData 对象)放回画布上。
    示例:我们把图片上的一部分颜色取反,并把透明度降到60%:
    img.οnlοad=function(){		ctx.drawImage(img,0,0);	var imgData=ctx.getImageData(10,10,80,80);	for(var i=0;i
    PS:在chrome等浏览器中这个API函数设计到跨域的问题,因此不能通过本地浏览(即file:///),需要通过webserver(即http://)才能看到效果,否则报类似下面的异常:
    但firefox是好用的。

绘制文字

在canvas中也可以绘制文字,这涉及到两个API:

context.fillText(text,x,y,maxWidth);context.strokeText(text,x,y,maxWidth);
  • text - 规定在画布上输出的文本。
  • x - 开始绘制文本的 x 坐标位置(相对于画布)。
  • y - 开始绘制文本的 y 坐标位置(相对于画布)。
  • maxWidth - 可选。允许的最大文本宽度,以像素计。

在绘制之前可以先设置文字的相关属性:

  • font属性:设置文字的字体,语法与 CSS font 属性相同,可以按顺序设置font-style、font-variant、font-weight、font-size/line-height、font-family;
  • textAlign属性:设置文字的水平对齐方式,可选值start、end、left、right、center,默认是start;
  • textBaseline属性:设置文字的垂直对齐方式,可选值top、hanging、middle、alphabetic、ideographic、bottom,默认是alphabetic;

有时为了方便定位,需要获取文字的宽度,html5提供了一个API:

context.measureText(text)

返回的TextMetrics对象的width属性表示使用当前指定的字体后文字的总长度。

ctx.font="italic 30px sans-serif";ctx.textBaseline="top";ctx.fillStyle="red";var txt='爱我中华';ctx.fillText(txt,0,0);var tml = ctx.measureText(txt);ctx.strokeStyle="green";ctx.strokeText(txt,tml.width+20,0);

善后工作

  1. 保存及恢复状态
    在绘制过程中,可能临时要改变一下属性设置,当临时绘制结束又想回到之前的状态,这就涉及到恢复,涉及到两个API:
    save() //把当前环境的状态压入栈restore() //状态出栈
    示例
    ctx.fillText(txt,0,0);ctx.save();//状态入栈ctx.fillStyle="green";ctx.textBaseline="bottom";ctx.fillText(txt,0,80);ctx.restore();//状态出栈ctx.fillText(txt,0,120);
  2. 保存文件
    在canvas绘制后可以使用toDataURL方法把它保存成浏览器能识别的data URL数据
    ctx.font="italic 30px sans-serif";ctx.textBaseline="top";ctx.fillStyle="red";var txt='爱我中华';ctx.fillText(txt,0,0);document.getElementById("img").src=mycanvas.toDataURL("image/jpeg");
    data URL是目前大多数浏览器能够识别的一种base64编码的URL,主要用于小型的、可以在网页中直接嵌入的数据,格式类似“data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAASwAAADICAYAAA....”
  3. 简单动画
    可以在canvas重复绘制、擦除、绘制的动作来实现动画,这其中涉及到一个擦除的API
    context.clearRect(x,y,width,height);
    setInterval函数
    setInterval(code,millisec[,"lang"])
    setInterval() 方法可按照指定的周期(以毫秒计)来调用函数或计算表达式。setInterval() 方法会不停地调用函数,直到 clearInterval() 被调用或窗口被关闭。由 setInterval() 返回的 ID 值可用作 clearInterval() 方法的参数。
    例如我们来绘制一个运动的小圆:
    var i=0;var intervalId=setInterval(doarc,1000);function doarc(){	ctx.clearRect(0,0,mycanvas.width,mycanvas.height);	ctx.beginPath();	ctx.arc(i,i,20,20,Math.PI*2,true);	ctx.fillStyle="blue";	ctx.fill();	i+=30;	if(i>200){clearInterval(intervalId);}}

转载于:https://www.cnblogs.com/zhaiqianfeng/p/4621670.html

你可能感兴趣的文章
Elasticsearch学习之深入聚合分析二---案例实战
查看>>
angularjs中的事件传播$emit,$broadcast,$on
查看>>
LOG4J
查看>>
Centos7 进入单用户模式,修复系统
查看>>
DataGridView列头checkbox 分类: .NET ...
查看>>
hutacm 1465错排
查看>>
.NET开源项目
查看>>
Ceph中Bufferlist的设计与使用
查看>>
左右浮动 三列布局
查看>>
mysql replication 复制的一些问题
查看>>
华为综合面被刷,写点经验,以备后用
查看>>
F-basic资源
查看>>
django的orm框架(进阶篇)
查看>>
js实现跨平台滑动加载
查看>>
win 10 slmgr.vbs -xpr 无法运行,被豆麦笔记打开解决方法
查看>>
CYQ学习主要摘要
查看>>
04 shell编程之循环语句
查看>>
mysql性能优化-慢查询分析、优化索引和配置
查看>>
Dubbo和Spring Cloud微服务架构对比
查看>>
发现对各类项目有用的不同JavaScript的Web UI
查看>>