canvas快速上手
canvas基本使用
在body中添加标签canvas,然后标签间的文字会在浏览器不支持canvas是显示(例如低版本IE)。
<canvas id="canvas" width="500" height="500">浏览器不支持HTML5中的canvas,请升级浏览器或下载Chrome</canvas>
直线
- 单条直线
<!DOCTYPE html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Canvas</title>
</head>
<body>
<style>
body {
background-color: black;
}
canvas {
width: 500px;
height: 500px;
margin: 0 auto;
display: block;
border: 4px solid #bfc;
}
</style>
<canvas id="canvas" width="500" height="500">浏览器不支持HTML5中的canvas,请升级浏览器或下载Chrome</canvas>
<script>
class Canvas {
constructor(canvas) {
this.canvas = document.getElementById(canvas)
this.context = this.canvas.getContext('2d')
}
initLine(move = [0, 0], line = [0, 0], width = 10, color = '#bfc') {
//开始绘制
this.context.beginPath()
//画笔开始位置
this.context.moveTo(move[0], move[1])
//画笔结束位置
this.context.lineTo(line[0], line[1])
//直线颜色
this.context.strokeStyle = color
//直线宽度
this.context.lineWidth = width
//绘制
this.context.stroke()
//结束
this.context.closePath()
}
}
let c = new Canvas('canvas')
c.initLine([0, 0], [400, 400])
c.initLine([400, 400], [200, 300])
</script>
</body>
</html>
- 连续直线
除了和上面一样多次绘制,也可以连续多次
lineTo
。
initLines(move = [0, 0], lineList = [], width = 10, color = '#bfc') {
this.context.beginPath()
this.context.moveTo(move[0], move[1])
lineList?.forEach(item => {
this.context.lineTo(item.line[0], item.line[1])
})
this.context.strokeStyle = color
this.context.lineWidth = width
this.context.stroke()
this.context.closePath()
}
let c = new Canvas('canvas')
c.initLines([0, 0], [
{
line: [500, 250],
},
{
line: [0, 500],
}
])
虚线
这里,没有考虑其他方位的虚线,原理相似。
initDottedLine(move = [0, 0], line = [0, 0], width = 4, color = '#bfc', gutter = 5) {
let gutterX = 0, gutterY = 0
let x = move[0], y = move[1], lineTo = move
if (line[0] !== 0 && line[1] !== 0){
let dx = line[0] - move[0]
let dy = line[1] - move[1]
gutterX = (gutter*dx)/Math.sqrt(dx**2+dy**2)
gutterY = (gutter*dy)/Math.sqrt(dx**2+dy**2)
}
while (x < line[0] || y < line[1]) {
this.initLine([x, y], lineTo, width, color)
if (x < line[0]) {
x += 2 * gutterX
lineTo[0] = x + gutterX
}
if (y < line[1]) {
y += 2 * gutterY
lineTo[1] = y + gutterY
}
}
}
let c = new Canvas('canvas')
c.initDottedLine([0, 0], [200, 400])
c.initDottedLine([100, 100], [100, 400])
矩形
rect
单纯的画出一个矩形框,需要fill()或者stroke()进行绘制,可填充
fillRect
画出一个可以填充的矩形,默认黑色
stroke画出一个不可填充的矩形
initFillRect(move = [0, 0, 0, 0], color) {
this.context.fillStyle = color
this.context.fillRect(...move)
}
- 画一个统计图
initBar(data = [], gutter = 40) {
let rate = Math.max(...data) / 400
this.initLines([50, 50], [{ line: [50, 450] }, { line: [450, 450] }], 4)
data.forEach((item, index) => {
let color = `rgb(${Math.random() * 256},${Math.random() * 256},${Math.random() * 256})`
this.initFillRect([50 + (index + 1) * gutter, 450 - (item / rate), 20, item / rate], color)
})
}
let c = new Canvas('canvas')
c.initBar([0, 0, 0, 0, 0, 0, 0, 0, 0,].map(item => Math.random() * 400))
圆形和弧
initArc(center, radius, deg, direction) {
this.context.arc(...center, radius, ...deg, direction)
this.context.fillStyle = 'red'
this.context.fill()
this.context.strokeStyle = '#bfc'
this.context.lineWidth = 4
this.context.stroke()
}
文字
initFillText(text, position = [0, 0], color = '#bfc') {
this.context.font = '30px Arial';
this.context.fillStyle = color
this.context.fillText(text, ...position);
}
initStrokeText(text, position = [0, 0], color = '#bfc') {
this.context.font = '30px Arial';
this.context.strokeText(text, ...position);
}
做一个验证码
1.包括四位字符
2.自定义背景色
3.包括多个干扰点和线
4.字符旋转
(function initCode(codeLength = 4, lineLength = 4, dotLength = 10) {
let c = new Canvas('canvas')
let str = "a,b,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B,C,E,F,G,H,J,K,L,M,N,P,Q,R,S,T,W,X,Y,Z,1,2,3,4,5,6,7,8,9,0";
let arr = str.split(',')
let code = []
for (let index = 0; index < codeLength; index++) {
let num = Math.floor(Math.random() * arr.length)
c.initFillText(arr[num], [20 + index * 25, 18], `rgba(${Math.floor(Math.random() * 255)},${Math.floor(Math.random() * 255)},${Math.floor(Math.random() * 255)},0.5)`)
code.push(arr[num])
}
for (let index = 0; index < lineLength; index++) {
c.initLine([Math.floor(Math.random() * 130), Math.floor(Math.random() * 33)], [Math.floor(Math.random() * 130), Math.floor(Math.random() * 33)], 1)
}
for (let index = 0; index < dotLength; index++) {
let x = Math.floor(Math.random() * 130)
let y = Math.floor(Math.random() * 33)
c.initLine([x, y], [x + 3, y + 4], 5, `rgb(${Math.floor(Math.random() * 255)},${Math.floor(Math.random() * 255)},${Math.floor(Math.random() * 255)})`)
}
})()