Canvas
Canvas概念
canvas
是h5提供的一个标签,帮我们创建一块画布。可以绘制任意图形,包括图片、动画等内容。当前主流浏览器均支持。
基本用法
<canvas id="canvas" width="500" height="500"></canvas>
注意:设置canvas
画布大小时不能通过style样式调整,会造成画布内容模糊
绘制上下文
Canvas创建了一个画布,并提供了一个上下文对象getContext()
获得渲染上下文和绘画功能
const canvas = document.getElementById('canvas')
const ctx = canvas.getContext('2d')
画布坐标系
Canvas坐标系采用笛卡尔坐标系,默认0,0
坐标为右上角。遵循我们屏幕、报纸的阅读习惯,从上往下,从左往右
了解了坐标系后让我们开始绘制基本图形吧
绘制图形
通过上下文对象,我们可以绘制多种图形,例如直线、矩形、圆形等
直线
绘制直线的基本api
moveTo(x, y)
画笔移动到指定位置
lineTo(x, y)
从画笔指定位置绘制到x和y坐标
stroke()
绘制
ctx.moveTo(50, 50) // 将画笔移动到50,50
ctx.lineTo(150, 150) // 画直线
ctx.stroke() // 绘制
矩形
strokeRect(x,y,width,height)
绘制矩形边框
fillRect(x,y,width,height)
绘制填充矩形
clearRect(x, y, width, height)
清除指定矩形区域
// 矩形的边框 strokeRect(x,y,width,height)
ctx.strokeStyle = 'red' // 设置边框颜色
ctx.strokeRect(50, 50, 200, 100)
// 填充矩形 fillRect(x,y,width,height)
ctx.fillStyle = 'blue' // 设置填充颜色
ctx.fillRect(100, 100, 200, 100)
// clearRect(x, y, width, height) 清除指定矩形区域
ctx.clearRect(120, 100, 100, 70)
红色区域为矩形边框,蓝色部分为填充矩形,中间白色缺少部分则是清除的矩形区域
圆弧和圆
arc(x, y, radius, startAngle, endAngle, anticlockwise)
x和y为圆心的坐标,radius为半径,startAngle为圆弧或圆的开始位置,endAngle为圆弧或圆的结束位置,anticlockwise是绘制的方向(不写默认为false,从顺时针方向)。
ctx.arc(60, 60, 50, 0, Math.PI, false)
ctx.stroke()
注意:startAngle
和endAngle
均为弧度,而不是角度。弧度转角度公式:弧度=(Math.PI/180)*角度 Math.PI*2
则是一个圆
ctx.arc(60, 60, 50, 0, Math.PI, false)
ctx.stroke()
ctx.arc(200, 60, 50, 0, Math.PI * 2, false)
ctx.stroke()
可以看到两个圆弧之间连接到了一起,这是因为每次绘制的时候没有开启关闭绘制路径
beginPath
开启新的路径绘制
closePath
关闭路径
ctx.beginPath() // 开启路径
ctx.arc(60, 60, 50, 0, Math.PI, false)
ctx.stroke()
ctx.closePath()
ctx.beginPath() // 开启路径
ctx.arc(200, 60, 50, 0, Math.PI * 2, false)
ctx.stroke()
ctx.closePath()
ctx.closePath()
并非必须,只需要每次重新绘制时开启新的路径即可
fill
可以为圆弧填充,填充时可以使用strokeStyle
和fillStyle
来调整边框颜色和填充颜色
ctx.beginPath() // 开启路径
ctx.arc(60, 60, 50, 0, Math.PI, false)
ctx.stroke()
ctx.beginPath() // 开启路径
ctx.arc(200, 60, 50, 0, Math.PI * 2, false)
ctx.stroke()
ctx.beginPath() // 开启路径
ctx.arc(60, 200, 50, 0, Math.PI * 2 / 4, false)
ctx.fill(); // 填充
ctx.stroke()
ctx.beginPath() // 开启路径
ctx.arc(200, 200, 50, 0, Math.PI * 2 / 6, false)
ctx.fill(); // 填充
ctx.stroke()
ctx.beginPath() // 开启路径
ctx.arc(400, 200, 50, 0, Math.PI * 2, false)
ctx.fill(); // 填充
ctx.stroke()
椭圆
ellipse(x, y, radiusX, radiusY, rotation, startAngle, endAngle, anticlockwise)
- x、y:椭圆的圆心位置
- radiusX、radiusY:x轴和y轴的半径
- rotation:椭圆的旋转角度,以弧度表示
- startAngle:开始绘制点
- endAngle:结束绘制点
- anticlockwise:绘制的方向(默认顺时针),可选参数。
ctx.beginPath();
ctx.ellipse(100, 100, 50, 100, 0, 0, 2 * Math.PI);
ctx.stroke()
ctx.beginPath();
ctx.ellipse(300, 100, 50, 100, Math.PI / 2, 0, 2 * Math.PI);
ctx.stroke()
ctx.beginPath();
ctx.ellipse(200, 350, 100, 100, Math.PI / 4, 0, 2 * Math.PI);
ctx.stroke()
当radiusX
和radiusY
相等是绘制出来的就是圆形,同样可以使用strokeStyle
和fillStyle
来调整边框颜色和填充颜色
贝塞尔曲线
二次贝塞尔曲线
二次贝塞尔曲线由三个点组成,分别是起点、终点、控制点
quadraticCurveTo(controlX, controlY, x, y)
- controlX、controlY:控制点坐标
- x、y:结束点坐标
- 起点坐标为画笔坐标,如
moveTo()
ctx.moveTo(50, 50);
ctx.quadraticCurveTo(200, 200, 350, 50);
ctx.stroke();// 绘制
三次贝塞尔曲线
三次贝塞尔曲线相较于二次贝塞尔曲线多了一个控制点
bezierCurveTo(control1X,control1Y, control2X,control2Y, x, y)
- control1X、control1Y:第一个控制点坐标
- control2X、control2Y:第二个控制点坐标
- x、y:结束点坐标
- 起点坐标为画笔坐标,如
moveTo()
ctx.moveTo(50, 200)
ctx.bezierCurveTo(150, 50, 250, 350, 350, 200)
ctx.stroke() // 绘制
样式
线条样式
lineWidth
设置绘制线条粗细,默认值1
// 绘制样式
// lineWidth 线宽
ctx.moveTo(50, 50)
ctx.lineTo(150, 50)
ctx.stroke()
ctx.beginPath();
ctx.moveTo(50, 100)
ctx.lineTo(200, 100)
ctx.lineWidth = 10
ctx.stroke()
ctx.beginPath();
ctx.moveTo(50, 150)
ctx.lineTo(250, 150)
ctx.lineWidth = 20
ctx.stroke()
lineCap
设置线段端点显示的样子,默认是 butt
。可选值为:butt
、round
、 square
。
// lineCap 线帽
ctx.moveTo(50, 50)
ctx.lineTo(200, 50)
ctx.lineWidth = 10
ctx.lineCap = 'butt'
ctx.stroke()
ctx.beginPath();
ctx.moveTo(50, 100)
ctx.lineTo(200, 100)
ctx.lineWidth = 10
ctx.lineCap = 'round'
ctx.stroke()
ctx.beginPath();
ctx.moveTo(50, 150)
ctx.lineTo(200, 150)
ctx.lineWidth = 10
ctx.lineCap = 'square'
ctx.stroke()
lineJoin
设置线段之间连接处的样式,默认是 miter
。可选值为:round
、bevel
、 miter
。
// lineJoin 线连接
ctx.moveTo(50, 50)
ctx.lineTo(100, 100)
ctx.lineTo(150, 50)
ctx.lineTo(200, 100)
ctx.lineTo(250, 50)
ctx.lineWidth = 10
ctx.lineJoin = 'miter'
ctx.stroke()
ctx.beginPath();
ctx.moveTo(50, 150)
ctx.lineTo(100, 200)
ctx.lineTo(150, 150)
ctx.lineTo(200, 200)
ctx.lineTo(250, 150)
ctx.lineWidth = 10
ctx.lineJoin = 'round'
ctx.stroke()
ctx.beginPath();
ctx.moveTo(50, 250)
ctx.lineTo(100, 300)
ctx.lineTo(150, 250)
ctx.lineTo(200, 300)
ctx.lineTo(250, 250)
ctx.lineWidth = 10
ctx.lineJoin = 'bevel '
ctx.stroke()
透明度
在之前绘制矩形时我们用到过fillRect
来填充矩形,颜色支持rgba
ctx.fillStyle = "rgba(255,0,0,0.2)" // 设置填充颜色
ctx.fillRect(100, 100, 200, 100)
ctx.fillStyle = "rgba(255,0,0,0.7)" // 设置填充颜色
ctx.fillRect(100, 300, 200, 100)
渐变
线性渐变
createLinearGradient(x1, y1, x2, y2)
,参数分别为 起点的坐标和终点的坐标。
在渐变的设置中还需要一个方法来添加渐变的颜色,语法为:gradient.addColorStop(offset, color)
,其中color就是颜色,offset 则是颜色的偏移值,只为0到1之间的数。
let gradient = ctx.createLinearGradient(10, 200, 400, 200)
gradient.addColorStop(0, '#00ff00')
gradient.addColorStop(1, '#ff0000')
ctx.fillStyle = gradient
ctx.fillRect(10, 10, 400, 400)
addColorStop
可以添加渐变颜色
let gradient = ctx.createLinearGradient(10, 200, 400, 200)
gradient.addColorStop(0, 'rgb(255, 0, 0)')
gradient.addColorStop(0.5, 'rgb(0, 255, 0)')
gradient.addColorStop(1, 'rgb(0, 0, 255)')
ctx.fillStyle = gradient
ctx.fillRect(10, 10, 400, 400)
createLinearGradient
创建渐变时可以设置颜色渐变方向,比如我们想让颜色从左上角到右下角渐变
let gradient = ctx.createLinearGradient(10, 10, 400, 400)
径向渐变
createRadialGradient(x0, y0, r0, x1, y1, r1)
,参数分别为开始圆的坐标和半径以及结束圆的坐标和半径。
let gradient = ctx.createRadialGradient(250, 250, 50, 250, 250, 200)
gradient.addColorStop(0, 'rgb(255, 0, 0)')
gradient.addColorStop(0.5, 'rgb(0, 255, 0)')
gradient.addColorStop(1, 'rgb(0, 0, 255)')
ctx.fillStyle = gradient
ctx.arc(250, 250, 200, 0, Math.PI * 2, false)
ctx.fill() // 填充
图案填充
createPattern(image, type)
,参数分别为:Image 参数可以是一个 Image 对象,也可以是一个 canvas 对象,Type 为图案绘制的类型,可用的类型分别有:repeat
、repeat-x
、repeat-y
和、no-repeat
let img = new Image()
img.src = 'https://img0.baidu.com/it/u=147381800,3591524360&fm=253&fmt=auto&app=138&f=JPEG?w=371&h=194'
img.onload = function () {
let pattern = ctx.createPattern(img, 'no-repeat')
ctx.fillStyle = pattern
ctx.fillRect(0, 0, 500, 500)
}
可以看到,我们绘制的矩形大小为500x500,当我们设置no-repeat时不会铺满。让我们改成repeat试试,repeat为x轴和y轴均平铺,可以自己尝试一下repeat-x和repeat-y。
let pattern = ctx.createPattern(img, 'repeat')
绘制文本
strokeText 文字描边
ctx.strokeText(text, x, y, maxWidth) 参数:text:文本内容、x,y :坐标、maxWidth:最大宽度
ctx.font = "50px serif"; // 设置字体大小和文字样式
ctx.strokeText("Canvas", 50, 50);
fillText 填充字体
ctx.fillText("Canvas", 50, 50);
文本样式
font
修改文本字体大小及文字样式,默认值:10px sans-serif
textAlign
文本对齐方式,参数为:left
、right
、center
、start
、end
,默认值:start
direction
文本方向,参数为:ltr(文本方向从左向右)
、rtl(文本方向从右向左)
、inherit(根据情况继承 Canvas元素或者 Document )
,默认值是: inherit
ctx.font = "30px serif"; // 设置文案大小和字体
ctx.direction = "ltr"; // 文本方向从左向右
ctx.textAlign = "left"; // 左对齐
ctx.strokeText("Hi Canvas !", 250, 100);
ctx.direction = "ltr"; // 文本方向从左向右
ctx.textAlign = "center"; // 右对齐
ctx.strokeText("Hi Canvas !", 250, 150);
ctx.direction = "ltr"; // 文本方向从左向右
ctx.textAlign = "right"; // 右对齐
ctx.strokeText("Hi Canvas !", 250, 200);
ctx.direction = "rtl"; // 文本方向从左向右
ctx.textAlign = "left"; // 左对齐
ctx.strokeText("Hi Canvas !", 250, 250);
ctx.direction = "rtl"; // 文本方向从左向右
ctx.textAlign = "center"; // 右对齐
ctx.strokeText("Hi Canvas !", 250, 300);
ctx.direction = "rtl"; // 文本方向从左向右
ctx.textAlign = "right"; // 右对齐
ctx.strokeText("Hi Canvas !", 250, 350);
后续内容待补充…
文章内容借鉴:原文连接