canvas

矩形绘制

实心矩形

使用 fillRect 方法可以绘制实心矩形,下面是fillRect 方法的参数说明

参数说明
x矩形左上角的 x 坐标
y矩形左上角的 y 坐标
width矩形的宽度,以像素计
height矩形的高度,以像素计
const el = document.getElementById('canvas')
// 画布对象
const app = el.getContext('2d')
// 定义天聪颜色
app.fillStyle = '#16a085'
// 绘制矩形
app.fillRect(0, 0, 500, 500)
<canvas id="canvas" width="500" height="500">
    您的浏览器不支持 HTML5 canvas
</canvas>

空心矩形

使用 strokeRect 方法可以绘制空心矩形,下面是strokeRect 方法的参数说明

参数说明
x矩形左上角的 x 坐标
y矩形左上角的 y 坐标
width矩形的宽度,以像素计
height矩形的高度,以像素计
const el = document.getElementById('canvas')
// 画布对象
const ctx = el.getContext('2d')
// 定义填充颜色
ctx.strokeStyle = '#16a085'
// 线条宽度
ctx.lineWidth = 30
// 边角类型:bevel斜角 ,round圆角,miter尖角
ctx.lineJoin = 'round'
// 绘制矩形边框
ctx.strokeRect(50, 50, 300, 300)

圆形绘制

arc

下面是绘制圆方法 arc 的参数说明

参数说明
x圆的中心的 x 坐标。
y圆的中心的 y 坐标。
r圆的半径。
sAngle起始角,以弧度计。(弧的圆形的三点钟位置是 0 度)。
eAngle结束角,以弧度计。
counterclockwise可选。规定应该逆时针还是顺时针绘图。False = 顺时针,true = 逆时针。

绘制空心圆

const el = document.getElementById('canvas')
const ctx = el.getContext('2d')
ctx.beginPath()
ctx.strokeStyle = 'red'
ctx.lineWidth = 20
ctx.arc(100, 100, 60, 0, 2 * Math.PI)
ctx.stroke()

绘制实心圆

const el = document.getElementById('canvas')
const ctx = el.getContext('2d')
ctx.beginPath()
ctx.fillStyle = '#f1c40f'
ctx.arc(100, 100, 60, 0, 2 * Math.PI)
ctx.fill()

节点绘制

我们可以通过以下方法定义不同节点、线条样式来绘制图形

  • beginPath() 重置绘制路径
  • lineTo() 开始绘制线条
  • moveTo() 把路径移动到画布中的指定点,但不会创建线条(lineTo方法会绘制线条)
  • closePath() 闭合线条绘制,即当前点连接到线条开始绘制点
  • lineWidth 线条宽度
  • strokeStyle 线条的样式,可以是颜色 、渐变
  • stroke() 根据上面方法定义的节点绘制出线条

绘制多边形

const el = document.getElementById('canvas')
const ctx = el.getContext('2d')
ctx.fillStyle = '#8e44ad'
ctx.fillRect(0, 0, el.clientWidth, el.height)
// 开始画线
ctx.beginPath()
// 移动起始点
ctx.moveTo(200, 0)
// 下一个节点
ctx.lineTo(400, 200)
ctx.lineTo(0, 200)
// 闭合节点
ctx.closePath()
// 线宽
ctx.lineWidth = 10
// 线颜色
ctx.strokeStyle = '#f1c40f'
// 划线
ctx.stroke()

线性渐变

使用canvas的createLinearGradient() 方法可以创建线性的渐变对象,用于实现线性渐变效果。

createLinearGradient

下面是createLinearGradient线性渐变的参数

参数描述
x0渐变开始点的 x 坐标
y0渐变开始点的 y 坐标
x1渐变结束点的 x 坐标
y1渐变结束点的 y 坐标

渐变边框

const el = document.getElementById('canvas')
const ctx = el.getContext('2d')
// 定义渐变的开始与结束坐标
const gradient = ctx.createLinearGradient(0, 0, 500, 500)
// 定义渐变位置与颜色,参数一为位置是从 0~1 之间,参数二为激变颜色
gradient.addColorStop(0, '#1abc9c')
gradient.addColorStop(0.5, '#9b59b6')
gradient.addColorStop(1, '#f1c40f')
// 渐变填充
ctx.strokeStyle = gradient
// 设置线的宽度
ctx.lineWidth = 20
// 绘制线条矩形
ctx.strokeRect(100, 100, 300, 300)

渐变填充

const el = document.getElementById('canvas')
const ctx = el.getContext('2d')
// 定义渐变的开始与结束坐标
const gradient = ctx.createLinearGradient(0, 0, 500, 500)
// 定义渐变位置与颜色,参数一为位置是从 0~1 之间,参数二为激变颜色
gradient.addColorStop(0, '#1abc9c')
gradient.addColorStop(0.5, '#9b59b6')
gradient.addColorStop(1, '#f1c40f')
// 渐变填充
ctx.fillStyle = gradient
// 绘制线条矩形
ctx.fillRect(0, 0, 500, 500)

清空区域

const el = document.getElementById('canvas')
const ctx = el.getContext('2d')
// 渐变填充
ctx.fillStyle = 'red'
// 绘制线条矩形
ctx.fillRect(0, 0, 500, 500)
// 清除矩形区域
ctx.clearRect(50, 50, 100, 100)

填充文字

fillText

下面是 fillText 方法的参数

参数描述
text规定在画布上输出的文本。
x开始绘制文本的 x 坐标位置(相对于画布)。
y开始绘制文本的 y 坐标位置(相对于画布)。
maxWidth可选。允许的最大文本宽度,以像素计。

textBaseline

textBaseline用于定义文字基线

参数说明
alphabetic默认。文本基线是普通的字母基线。
top文本基线是 em 方框的顶端。。
hanging文本基线是悬挂基线。
middle文本基线是 em 方框的正中。
ideographic文本基线是表意基线。
bottom文本基线是 em 方框的底端。

textAlign

textAlign用于文本的对齐方式的属性

参数说明
left文本左对齐
right文本右对齐
center文本居中对齐
start文本对齐界线开始的地方 (左对齐指本地从左向右,右对齐指本地从右向左)
end文本对齐界线结束的地方 (左对齐指本地从左向右,右对齐指本地从右向左)

示例

const el = document.getElementById('canvas')
const ctx = el.getContext('2d')
// 渐变填充
ctx.fillStyle = 'red'
// 文字大小与字体设置
ctx.font = '30px yahei'
// 定义文字基线
ctx.textBaseline = 'top'
// 文字对齐
ctx.textAlign = 'left'
// 清除矩形区域
ctx.fillText('mkimq.com', 0, 0)

激变文字

const el = document.getElementById('canvas')
const ctx = el.getContext('2d')
// 定义渐变的开始与结束坐标
const gradient = ctx.createLinearGradient(0, 0, 500, 500)
// 定义渐变位置与颜色,参数一为位置是从 0~1 之间,参数二为激变颜色
gradient.addColorStop(0, '#1abc9c')
gradient.addColorStop(0.5, '#9b59b6')
gradient.addColorStop(1, '#f1c40f')
// 渐变填充
ctx.strokeStyle = gradient
// 文字大小与字体设置
ctx.font = '30px yahei'
// 定义文字基线
ctx.textBaseline = 'top'
// 文字对齐
ctx.textAlign = 'left'
// 清除矩形区域
ctx.strokeText('http://www.mkimq.com', 0, 0)

图片填充

参数说明

参数描述
image规定要使用的图片、画布或视频元素。
repeat默认。该模式在水平和垂直方向重复。
repeat-x该模式只在水平方向重复。
repeat-y该模式只在垂直方向重复。
no-repeat该模式只显示一次(不重复)。
const el = document.getElementById('canvas')
const ctx = el.getContext('2d')
// 创建图片
const img = new Image()
img.src = 'https://img2.baidu.com/it/u=1814268193,3619863984&fm=253&fmt=auto&app=138&f=JPEG?w=632&h=500'

img.onload = () => {
	// 第二个参数:"repeat|repeat-x|repeat-y|no-repeat"
	const pat = ctx.createPattern(img, 'repeat')
	ctx.fillStyle = pat
	ctx.fillRect(0, 0, 500, 500)
}

图片缩放

const el = document.getElementById('canvas')
const ctx = el.getContext('2d')
// 创建图片
const img = new Image()
img.src = 'https://img2.baidu.com/it/u=1814268193,3619863984&fm=253&fmt=auto&app=138&f=JPEG?w=632&h=500'

img.onload = () => {
	el.width = img.naturalWidth * scale(img, el)
	el.height = img.naturalHeight * scale(img, el)
	ctx.drawImage(img, 0, 0, el.width, el.height)
}

// 取最小缩放
function scale(img, el) {
	return Math.min(el.width/ img.naturalWidth, el.height / img.naturalHeight)
}

绘制像素

const el = document.getElementById('canvas')
const ctx = el.getContext('2d')
ctx.fillStyle = 'red'
ctx.fillRect(0, 0, el.width, el.height)

// 像画布绘制点
for (let i = 0; i < 1000; i++) {
	// 随机坐标
	const x = Math.floor(Math.random() * el.width)
	const y = Math.floor(Math.random() * el.height)
	// 绘制5*5白块
	ctx.rect(x, y, 5, 5)
	ctx.fillStyle = '#fff'
	ctx.fill()
}

绘制不规则

const el = document.getElementById('canvas')
const ctx = el.getContext('2d')
ctx.fillStyle = '#000'
ctx.fillRect(0, 0, el.width, el.height)

// 像画布绘制点
for (let i = 0; i < 20; i++) {
	ctx.beginPath()
	ctx.arc(Math.random() * el.width, Math.random() * el.height, 5 + Math.floor(Math.random() * 100), 0, 2 * Math.PI)
	ctx.fillStyle = ['yellow', 'red', '#16a085', '#2ecc71', '#f1c40f', '#9b59b6'].sort(() => {
        return Math.floor(Math.random() * 3) ? 1 : -1
    })[0]
	ctx.fill()
}

黑板实例

class Draw {
	constructor(width, height, el, app, btns) {
		this.el = el
		this.app = app
		this.btns = btns
		this.el.width = width
		this.el.height = height
		this.#setBackground()
		this.#event()
	}

	#event() {
		// bind会返回新函数,addEventListener与removeEventListener要使用相同函数
		const callback = this.#drawEventCallback.bind(this)

		this.el.addEventListener('mousedown', () => {
			// 重新画线
			this.app.beginPath()
			// 鼠标移动事件
			this.el.addEventListener('mousemove', callback)
		})

		// 鼠标抬起时移除事件
		this.el.addEventListener('mouseup', () => this.el.removeEventListener('mousemove', callback))

		return this
	}

	// 黑板写字的事件回调函数
	#drawEventCallback(event) {
		this.app.lineTo(event.offsetX, event.offsetY)
		this.app.strokeStyle = 'white'
		this.app.stroke()
	}

	short() {
		const bt = document.createElement('button')
		bt.innerText = '截图'
		this.btns.insertAdjacentElement('beforeend', bt)
		const img = new Image()
		this.el.insertAdjacentElement('afterend', img)

		bt.addEventListener('click', () => {
			// 使用canval标签的toDataURL方法,获取图片数据内容
			img.src = this.el.toDataURL('image/jpeg')
			img.style.cssText = 'width:300px;position:absolute;bottom:50px;right:0;border:solid 10px white;left:50%;transform:translateX(-50%);'
		})
		return this
	}

	clear() {
		const bt = document.createElement('button')
		bt.innerText = '清屏'
		this.btns.insertAdjacentElement('beforeend', bt)
		bt.addEventListener('click', () => {
			this.app.fillStyle = '#000'
			this.app.fillRect(0, 0, this.el.width, this.el.height)
		})
	}

	#setBackground() {
		this.app.fillStyle = '#000'
		this.app.fillRect(0, 0, this.el.width, this.el.height)
	}
}

const el = document.getElementById('canvas')
const app = el.getContext('2d')
const btns = el.insertAdjacentElement('afterend', document.createElement('div'))

const blackboard = new Draw(800, 300, el, app, btns)
blackboard.short()
blackboard.clear()
贡献者: mankueng