Canvas是什么
- Canvas 中文名叫 “画布”,是 HTML5 新增的一个标签。
- Canvas 允许开发者通过 JS在这个标签上绘制各种图案。
- Canvas 拥有多种绘制路径、矩形、圆形、字符以及图片的方法, 在某些情况下可以 “代替” 图片。
- Canvas 可用于动画、游戏、数据可视化、图片编辑器、实时视频处理等领域。
Canvas和SVG的区别
| Canvas | SVG |
|---|---|
| 用JS动态生成元素(一个HTML元素) | 用XML描述元素(类似HTML元素那样,可用多个元素来描述一个图形) |
| 位图(受屏幕分辨率影响) | 矢量图(不受屏幕分辨率影响) |
| 不支持事件 | 支持事件 |
| 数据发生变化需要重绘 | 不需要重绘 |
总结
- 如果你需要高质量的矢量图形、复杂的图形设计、SEO优化、图形的可编辑性和可访问性,那么SVG是更好的选择。
- 如果你需要高性能的图形渲染、大量的动态渲染、复杂的图像合成,或者图形不需要高清晰度或缩放,那么Canvas可能更适合你的需求。
起步
注意点
- 默认宽高 canvas默认宽度为300px,默认高度为150px。不设置宽高,取默认值
- 设置宽高,不需要带单位
- 不能通过css设置canvas的宽高,否则会被拉伸
- 线条的默认宽度是 1px ,默认颜色是黑色。但由于默认情况下 canvas 会将线条的中心点和像素的底部对齐,所以会导致显示效果是 2px 和非纯黑色问题。
基础图形
直线
<canvas id="c" width="300" height="200"></canvas>
<script>
const cvs = document.querySelector("#c")
const ctx = cvs.getContext("2d")
ctx.moveTo(100,100) // 坐标起点 移动到(100,100)(x轴坐标,y轴坐标)
ctx.lineTo(200,100) // 下一个坐标(x,y)
ctx.stroke() // 将所有坐标连在一起
</script>
设置样式
lineWidth线的粗细 (不要带单位 )strokeStyle线的颜色lineCap线帽:默认 butt;圆形:round;方形:square
<canvas id="c" width="300" height="200"></canvas>
<script>
const cvs = document.querySelector("#c")
const ctx = cvs.getContext("2d")
ctx.moveTo(50,100) // 坐标起点 移动到(100,100)(x轴坐标,y轴坐标)
ctx.lineTo(200,100) // 下一个坐标(x,y)
// 设置宽度
ctx.lineWidth = '20px'
// 设置颜色
ctx.strokeStyle = 'pink'
// 设置线帽
ctx.lineCap = 'round'
ctx.stroke() // 将所有坐标连在一起
</script>
新开路径
为什么要开辟新的路径:防止多条线段绘制时,样式污染
开辟路径的方法
- beginPath()
<canvas id="c" width="300" height="300" style="border: 1px solid #ccc;"></canvas>
<script>
const cnv = document.getElementById('c')
const ctx = cnv.getContext('2d')
ctx.moveTo(20, 100)
ctx.lineTo(200, 100)
ctx.lineWidth = 10
ctx.strokeStyle = 'pink'
ctx.stroke()
ctx.beginPath() // 重新开启一个路径
ctx.moveTo(20, 120.5)
ctx.lineTo(200, 120.5)
ctx.lineWidth = 4
ctx.strokeStyle = 'red'
ctx.stroke()
</script>
折线
和直线差不多,可以使用moveTo(),lineTo(),stroke()实现
<canvas id="c" width="300" height="300" style="border: 1px solid #ccc;"></canvas>
<script>
const cnv = document.getElementById('c')
const ctx = cnv.getContext('2d')
ctx.moveTo(50,200)
ctx.lineTo(100,50)
ctx.lineTo(200,200)
ctx.lineTo(250,50)
ctx.stroke()
</script>
矩形
使用strokeRect() 描边矩形
- strokeStyle:设置描边属性(颜色,渐变,图案)
- strokeRect(x,y,width,height):描边矩形(x,y是矩形的左上角起点,width和height是矩形的宽高)
- strokeStyle 必须写在前面,否则样式不生效
<canvas id="c" width="300" height="300" style="border: 1px solid #ccc;"></canvas>
<script>
const cnv = document.getElementById('c')
const ctx = cnv.getContext('2d')
// 设置线条颜色
ctx.strokeStyle = 'pink'
// 描边矩形 起点坐标(50,50) 宽度200 长度100
ctx.strokeRect(50,50,200,100)
</script>
使用fillRect() 填充矩形
需要注意fillStyle 需要用在fillRect前面,不然样式不生效
<canvas id="c" width="300" height="300" style="border: 1px solid #ccc;"></canvas>
<script>
const cnv = document.getElementById('c')
const ctx = cnv.getContext('2d')
// 设置填充颜色
ctx.fillStyle = 'pink'
// 描边矩形 起点坐标(50,50) 宽度200 长度100
ctx.fillRect(50,50,200,100)
</script>
同时使用strokeRect()和fillRect()
同时使用会产生描边和填充的效果
<canvas id="c" width="300" height="300" style="border: 1px solid #ccc;"></canvas>
<script>
const cnv = document.getElementById('c')
const ctx = cnv.getContext('2d')
// 设置填充颜色
ctx.fillStyle = 'yellow'
// 描边矩形 起点坐标(50,50) 宽度200 长度100
ctx.fillRect(50,50,200,100)
// 设置线条颜色
ctx.strokeStyle = 'pink'
// 描边矩形 起点坐标(50,50) 宽度200 长度100
ctx.strokeRect(50,50,200,100)
</script>
使用rect() 生成矩形
与strokeRect()和fillRect()不同,使用rect()绘制矩形时,需要调用stroke()和fill()辅助渲染,否则绘制不出来
<canvas id="c" width="300" height="300" style="border: 1px solid #ccc;"></canvas>
<script>
const cnv = document.getElementById('c')
const ctx = cnv.getContext('2d')
// 设置填充颜色
ctx.fillStyle = 'yellow'
// 设置线条颜色
ctx.strokeStyle = 'pink'
ctx.rect(50,50,200,100)
ctx.stroke()
ctx.fill()
</script>
清空矩形 clearRect()
使用clearRect可以清空指定区域
clearRect(x,y,width,height)
通过如下代码可以实现清空画布
// const cnv = document.querySelector("#c")
clearRect(0,0,cnv.width,cnv.height) // cnv为canvas dom对象
多边形
canvas绘制多边形,需要使用moveTo(),lineTo()和closePath()
三角形
canvas没有直接提供类似与rect()的方法绘制三角形,需要确定3个点的坐标,使用stroke或者fill实现
<canvas id="c" width="300" height="300" style="border: 1px solid #ccc;"></canvas>
<script>
const cnv = document.getElementById('c')
const ctx = cnv.getContext('2d')
ctx.moveTo(50, 50)
ctx.lineTo(200, 50)
ctx.lineTo(200, 200)
// 手动闭合
ctx.closePath()
ctx.lineJoin = 'miter' // 线条连接的样式。miter: 默认; bevel: 斜面; round: 圆角
ctx.lineWidth = 20
ctx.stroke()
</script>
菱形
临边相等的平行四边形就是菱形
<canvas id="c" width="300" height="300" style="border: 1px solid #ccc;"></canvas>
<script>
const cnv = document.getElementById('c')
const ctx = cnv.getContext('2d')
ctx.moveTo(150, 50)
ctx.lineTo(250, 100)
ctx.lineTo(150, 150)
ctx.lineTo(50, 100)
// 手动闭合
ctx.closePath()
ctx.stroke()
</script>
圆形
使用arc() 可以绘制圆
语法:
arc(x,y,r,sAngle,eAngle, counterClockwise)
x和y:圆心坐标r:圆的半径sAngle: 开始角度eAngle: 结束角度counterClockwise: 绘制方向(true:逆时针,false:顺时针)默认false
<canvas id="canvas" width="300" height="300"></canvas>
<script>
const canvas = document.querySelector("#canvas")
const ctx = canvas.getContext("2d")
ctx.beginPath()
ctx.arc(150,150,80, 0, 360)
ctx.closePath()
ctx.stroke()
</script>
半圆
<canvas id="canvas" width="300" height="300"></canvas>
<script>
const canvas = document.querySelector("#canvas")
const ctx = canvas.getContext("2d")
ctx.beginPath()
ctx.arc(150,150,80, 0, 180 * Math.PI / 180)
ctx.closePath()
ctx.stroke()
</script>
使用arcTo()绘制圆弧
语法:
arcTo(cx, cy, x2,y2, radius)
arcTo() 方法利用 开始点、控制点和结束点形成的夹角,绘制一段与夹角的两边相切并且半径为 radius 的圆弧。
cx:两切线焦点的横坐标cy:两切线焦点的纵坐标x2:结束点的横坐标y2:结束点的横坐标radius:半径
文本
样式
语法:
ctx.font= 'font-style font-variant font-weight font-size/line-height font-family'
描边 strokeText && 填充 fillText
哈哈 哈哈
语法:
// 描边
strokeText(text, x, y, maxWidth)
// 填充
fillText(text, x, y, maxWidth)
text: 字符串 要绘制的内容x: 横坐标y: 纵坐标maxWidth: 可选参数,表示文本最大的渲染宽度,超出会被压缩
描边样式 strokeStyle() && 填充样式 fillStyle()
语法:
ctx.strokeStyle='red'
ctx.fillStyle = 'green'
获取文本长度
measureText().width 可以获取文本长度
<canvas id="c" width="300" height="300" style="border: 1px solid #ccc;"></canvas>
<script>
const cnv = document.getElementById('c')
const cxt = cnv.getContext('2d')
let text = 'hello Canvas'
cxt.font = 'bold 40px Arial'
cxt.fillText(text, 40, 80)
console.log(cxt.measureText(text).width) // 80
</script>
水平对齐方式 textAlign
使用 textAlign 属性可以设置文字的水平对齐方式,一共有5个值可选
start: 默认。在指定位置的横坐标开始。end: 在指定坐标的横坐标结束。left: 左对齐。right: 右对齐。center: 居中对齐。
垂直对齐方式 textBaseline
使用 textBaseline 属性可以设置文字的垂直对齐方式。
在使用 textBaseline 前,需要自行了解 css 的文本基线。
textBaseline 可选属性:
alphabetic: 默认。文本基线是普通的字母基线。top: 文本基线是 em 方框的顶端。bottom: 文本基线是 em 方框的底端。middle: 文本基线是 em 方框的正中。hanging: 文本基线是悬挂基线。
图片渲染
在 Canvas 中可以使用 drawImage() 方法绘制图片。
通常渲染图片有2种方式,一种是在js中实现,另一种是通过拿到dom中的图片拿到canvas中渲染
语法
drawImage(img,dx,dy)
// 设置图片宽高
drawImage(img,dx,dy,dw,dh)
// 截取图片
drawImage(image, sx, sy, sw, sh, dx, dy, dw, dh)
-
image: 要渲染的图片对象。 -
dx:图片左上角的横坐标位置。 -
dy:图片左上角的纵坐标位置。 -
dw用来定义图片的宽度 -
dh定义图片的高度。
截取图片 参数缺一不可
image: 图片对象sx: 开始截取的横坐标sy: 开始截取的纵坐标sw: 截取的宽度sh: 截取的高度dx: 图片左上角的横坐标位置dy: 图片左上角的纵坐标位置dw: 图片宽度dh: 图片高度
<canvas id="c" width="300" height="200"></canvas>
<img src='/xx/xx' />
<script>
const canvas = document.querySelector("#c")
const ctx = canvas.getContext("2d")
// 创建Image对象
const img = new Image()
// 引入图片 // js 版本
img.src = '/public/hero.png'
// 获取 dom // DOM版
// const img = document.querySelector("img").src
// 等待图片加载完成
img.onload = () => {
ctx.drawImage(img, 200, 300)
}
</script>
总结
上面主要是记录了关于canvas的绘制基础图形的一些笔记记录,关于进阶部分,等待后续学习之后,继续深入探索。