HTML+JS-canvas图形标签

<canvas> 标签用于绘制图像(通过脚本,通常是 JavaScript)。<canvas> 元素本身并没有绘制能力(它仅仅是图形的容器/画布),可以通过多种方法使用 canvas 绘制路径,盒、圆、字符以及添加图像。


一个画布在网页中是一个矩形框,通过 <canvas> 元素来绘制。需要赋予id,width,height属性。

<canvas id="myCanvas" width="200" height="100"></canvas>

可以通过style赋予背景颜色,边框等属性


画布建成以后,剩下的绘制工作都通过脚本去绘制。绘制分为两个步骤:初始化画布对象 与 对应的绘制操作。

初始化画布对象有两步:

①获取画布元素:如

var c=document.getElementById("myCanvas"); 

②通过getContext() 方法可返回一个对象,该对象提供了用于在画布上绘图的方法和属性。如

var ctx=c.getContext("2d");

  之后的绘制只需要对ctx对象操作即可。

备注:

画布是矩形框,以矩形框的左上角为原点构建二维坐标系,向右为x轴正方向,向下为y轴正方向,如图所示


绘制矩形:

strokeRect(x,y,width,height)方法绘制空心矩形(x,y为起点坐标,width,height为矩形宽度长度)

fillRect(x,y,width,height) 绘制实心矩形。

strokeStyle属性设置空心矩形线条颜色,lineWidth属性设置空心矩形的线条宽度,lineCap属性设置线条端点形状,lineJoin属性设置线条交点的形状。

fillStyle属性设置实心矩形颜色。

ctx.strokeStyle = "#0000ff";
ctx.lineWidth = 5;
ctx.strokeRect(10, 10, 80, 80)

ctx.fillStyle="#FF0000";
ctx.fillRect(0,0,150,75);


绘制线条:

moveTo(x,y) 定义线条开始坐标

lineTo(x,y) 定义线条结束坐标

stroke()方法绘制路径。

ctx.moveTo(0,0);
ctx.lineTo(200,100);
ctx.stroke();

备注:

①连续的线条可以一次使用多个lineTo()方法。

②线条绘制出来的图形若为封闭图形,也可使用fill()绘制图形,且可以填充颜色(即可以用线条去画出三角形,五边形等自定义形状且填色)

ctx.moveTo(30, 30)
ctx.lineTo(40, 10)
ctx.lineTo(50, 30)
ctx.lineTo(70, 30)
ctx.lineTo(50, 50)
ctx.lineTo(30, 30)

ctx.fill()


绘制圆形:

arc(x,y,r,start,stop)定义圆形(x,y为圆心坐标,r为半径,start,stop为起始角度和结束角度,以弧度表示)

stroke()方法绘制空心圆

fill()方法绘制实心圆。

ctx.arc(95,50,40,0,2*Math.PI);
ctx.stroke();

ctx.arc(95, 50, 40, 0, 2 * Math.PI);
ctx.fillStyle = "#009900";
ctx.fill()


绘制文本:

font属性定义字体

strokeText(text,x,y)方法绘制空心的文本

fillText(text,x,y)方法绘制实心的文本

ctx.font="30px Arial";
ctx.strokeText("Hello World",10,50);

ctx.font="30px Arial";
ctx.fillText("Hello World",10,50);


放置图像:

drawImage(image,x,y,width,height)方法放置图像,其中image为图像对象(需要先获取),x与y为图像左上角坐标,width,height为图像的宽高。

var img = document.getElementById('myImg')
// 也可以使用js创建图像标签
// var img = new Image();
// img.src = 'http://www.runoob.com/images/pulpit.jpg';
ctx.drawImage(img, 10, 10, 180, 80)

补充:可以对源图片进行裁剪处理

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

第一个参数和其它的是相同的,都是一个图像或者另一个 canvas 的引用。

其他 8 个参数:

前 4 个是定义图像源的切片位置和大小,后 4 个则是定义切片的目标显示位置和大小。


更多:

 1.如果要对ctx对象进行多次绘制 需要通过beginPath()方法开始一个新的路径。而如果要将图形变成一个封闭图形,可使用closePath()方法使用直线封闭图形,如

ctx.moveTo(0, 0)
ctx.lineTo(200, 100)
ctx.stroke()

ctx.beginPath()

ctx.arc(95, 50, 40, 0, Math.PI)
ctx.closePath()

ctx.stroke()

2.渐变色设置:线条渐变 与 径向/圆渐变

①设置渐变方案

createLinearGradient(x,y,x1,y1)方法创建线条渐变(箭头,x,y为起点坐标,x1,y1为终点坐标,起点左侧的全部区域是开始渐变的颜色,重点右侧的全部区域是结束渐变的颜色,箭头上下的区域按照渐变方向进行统一调整)

createRadialGradient(x,y,r,x1,y1,r1)方法创建一个径向/圆渐变区域(圆形,x,y为起始圆圆心坐标,r为起始圆半径,x1,y1为终止圆圆心坐标,r1为终止圆半径)

备注:渐变方案的坐标原点是画布的原点,与绘制的矩形无关

var grd = ctx.createLinearGradient(20, 0, 180, 0);

②添加渐变颜色(两个及以上)

addColorStop( 位置, 颜色 )方法(位置用数字表示,可以是0-1,0为起点,1为终点)

grd.addColorStop(0, "red");
grd.addColorStop(0.5, "skyblue");
grd.addColorStop(1, "white");

③将渐变方案设置给需要的属性,如strokeStyle或fillStyle

ctx.fillStyle = grd;

④再进行绘制图形即可。

全部代码如下:

<canvas id="myCanvas" width="200" height="100" style="background-color: pink;"></canvas>
<script>
  var c = document.getElementById("myCanvas");
  var ctx = c.getContext("2d");

  var grd = ctx.createLinearGradient(0, 0, 180, 0);
  grd.addColorStop(0, "red");
  grd.addColorStop(0.5, "skyblue");
  grd.addColorStop(1, "white");

  ctx.fillStyle = grd;
  ctx.fillRect(10, 10, 180, 80);
</script>

3.样式的保存与恢复

save()方法可以保存当前画布对象的参数(可以调用多次,相当于入栈push):

  • 变形(移动,旋转和缩放)

  • strokeStylefillStyleglobalAlphalineWidthlineCaplineJoinmiterLimitshadowOffsetXshadowOffsetYshadowBlurshadowColorglobalCompositeOperation 的值

  • 当前的遮罩层

restore()方法可以将保存的方法恢复(可以调用多次,相当于出栈pop)

ctx.fillRect(0, 0, 150, 150);   // 使用默认设置绘制一个矩形
ctx.save();                  // 保存默认状态

ctx.fillStyle = 'red'       // 在原有配置基础上对颜色做改变
ctx.fillRect(15, 15, 120, 120); // 使用新的设置绘制一个矩形

ctx.save();                  // 保存当前状态
ctx.fillStyle = '#FFF'       // 再次改变颜色配置
ctx.fillRect(30, 30, 90, 90);   // 使用新的配置绘制一个矩形

ctx.restore();               // 重新加载之前的颜色状态
ctx.fillRect(45, 45, 60, 60);   // 使用上一次的配置绘制一个矩形

ctx.restore();               // 加载默认颜色配置
ctx.fillRect(60, 60, 30, 30);   // 使用加载的配置绘制一个矩形

4.变形(移动,旋转,缩放)

①移动translate

translate(x,y)方法用来移动canvas的原点到指定的位置(x为向右移动的距离,y为向下移动的距离)

ctx.strokeRect(0, 0, 100, 50);

ctx.translate(20, 20);
ctx.strokeRect(0, 0, 100, 50);

②旋转rotate

rotate(angle)方法旋转坐标轴(angle为旋转的角度,弧度制,顺时针方向)

ctx.strokeRect(0, 0, 100, 50);

ctx.rotate(45 / 180 * Math.PI)
ctx.strokeRect(0, 0, 100, 50);

③缩放scale

scale(x,y)方法对画布进行缩放(x,y控制x轴,y轴的缩放,必须是正值,且比1小表示缩小,比1大表示放大,等于1则无效果)

ctx.strokeRect(0, 0, 100, 50);

ctx.scale(1.5, 1.5)
ctx.strokeRect(0, 0, 100, 50);

5.多图形之间的显示规则

globalCompositeOperation属性可以改变默认的显示规则(默认:新图形若与老图形重叠,则新图形会覆盖在老图形之上)设置globalCompositeOperation属性之前的图形为老图形,设置之后的图形为新图形,可以填写的值有:

描述
destination-over新图像在老图像的下面
source-in新图像只显示与老图像重叠的部分,其他部分全部透明。(老图像透明)
source-out新图像只显示与老图像没有重叠的部分,其余部分全部透明。(老图像透明)
source-atop新图像只显示与老图像重叠的部分,其余部分全部透明。(老图像显示)
destination-in老图像只显示与新图像重叠的部分,其他部分全部透明。(新图像透明)
destination-out老图像只显示与新图像没有重叠的部分,其余部分全部透明。(新图像透明)
destination-atop老图像只显示与新图像重叠的部分,老图形在上。
xor重叠部分会变成透明
copy只有新图像会被保留,其余的全部变透明。
lighter新老图像都显示,但是重叠部分的颜色做加处理。
darken保留重叠部分最黑的像素。(每个颜色位进行比较,得到最小的)
lighten保证重叠部分最量的像素。(每个颜色位进行比较,得到最大的)
ctx.lineWidth = 10
ctx.moveTo(0, 0)
ctx.lineTo(100, 100)
ctx.stroke()

ctx.globalCompositeOperation = "xor";
ctx.beginPath()
ctx.strokeStyle = 'red'
ctx.moveTo(200, 0)
ctx.lineTo(0, 100)
ctx.stroke()

6.遮罩层(裁剪)

clip()方法实现遮罩层,只显示设置clip()之前的区域,区域外的部分会被隐藏。(类似于设置globalCompositeOperation属性的source-atop值,不同的是clip()只需要设置区域,不需要创建图形,而globalCompositeOperation属性需要一个老图形)

ctx.arc(0, 0, 100, 0, Math.PI * 2);
ctx.clip();
//只需要给出圆形范围,不需要fill()或stroke()方法去创建圆形

ctx.fillStyle = "blue";
ctx.fillRect(0, 0, 200, 100);

7.弧线

①圆弧:arc(x, y, r, startAngle, endAngle)方法实现,设置第四五个参数的范围即可

ctx.arc(50, 50, 40, 0, Math.PI / 2);
ctx.stroke();

②圆弧:arcTo(x1, y1, x2, y2, radius): : 根据给定的控制点和半径画一段圆弧,最后再以直线连接两个控制点(个人感觉不怎么实用?主要还是用贝塞尔曲线)。

ctx.moveTo(50, 50);
ctx.arcTo(200, 50, 200, 200,150);
ctx.stroke();

③二次贝塞尔曲线:quadraticCurveTo(cp1x,cp1y,x,y)方法创建二次贝塞尔曲线(cp1x,cp1y是控制点坐标,x,y是结束点坐标)

④三次贝塞尔曲线:bezierCurveTo(cp1x,cp1y,cp2x,cp2y,x,y)方法创建三次贝塞尔曲线(cp1x,cp1y是控制点1坐标,cp2x,cp2y是控制点2坐标,x,y是结束点坐标)

对贝塞尔曲线的个人理解:首先先确定起始点后终点坐标(起始点通过moveTo()方法给出,终点是贝塞尔方法的最后两个参数),然后通过一个或两个控制点去拉扯曲线,让曲线的轨迹符合你的需要,这时候就需要不断调整控制点的坐标了,以及控制点越多自然越精确。理论上讲所有曲线都可以通过贝塞尔曲线实现。

ctx.moveTo(40, 200);
ctx.bezierCurveTo(20, 100, 100, 120, 200, 200);
ctx.stroke();

9.动画

通过定时器实现,埋坑,后面再学。


备注:

1.通过画布对象c的toDataURL()方法,可以将画布中的内容导出,返回参数为图片地址


let c = document.getElementById('myCanvas')
let ctx = c.getContext('2d')

let imgUrl = c.toDataURL('image/png')

2.如果绘制的图形初始位置贴边的话,clearRect()貌似会出bug清除不干净

3.isPointInPath()方法可以判断某一个点是否在绘制区域内,返回布尔值:

isPointInPath(x,y)判断点是否在当前绘制的图形区域内(未被closePath关闭)

isPointInPath(路径对象,x,y)判断点是否在参数1的图形区域内(可以通过new一个Path2D对象存储路径)

let p = new Path2D()
p.arc(10, 10, 10, 0, 2 * Math.PI)  //此时路径就保存在p对象里
ctx.fill(p)  //绘制p对象即可
c.addEventListener('mousemove', (e) => {
   if (ctx.isPointInPath(p, 10, 10)) {
      console.log('在')// 坐标(10,10在p路径内,所以会执行这条语句)
   }
})

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值