矩形是Canvas中最基础的图形,也是唯一可以直接绑制而不需要路径的形状。
Canvas提供了三个绑制矩形的方法:
| 方法 | 说明 |
|---|---|
| fillRect() | 绑制填充矩形 |
| strokeRect() | 绑制描边矩形 |
| clearRect() | 清除矩形区域 |
ctx.fillRect(x, y, width, height)
| 参数 | 说明 |
|---|---|
| x | 矩形左上角x坐标 |
| y | 矩形左上角y坐标 |
| width | 矩形宽度 |
| height | 矩形高度 |
const canvas = document.getElementById('canvas')
const ctx = canvas.getContext('2d')
// 基础填充矩形
ctx.fillStyle = '#3498db'
ctx.fillRect(50, 50, 200, 100)
// 不同颜色
ctx.fillStyle = '#e74c3c'
ctx.fillRect(50, 200, 200, 100)
// 半透明矩形
ctx.fillStyle = 'rgba(46, 204, 113, 0.5)'
ctx.fillRect(100, 100, 200, 150)
ctx.strokeRect(x, y, width, height)
// 基础描边矩形
ctx.strokeStyle = '#333'
ctx.lineWidth = 2
ctx.strokeRect(300, 50, 200, 100)
// 粗边框
ctx.strokeStyle = '#9b59b6'
ctx.lineWidth = 5
ctx.strokeRect(300, 200, 200, 100)
// 虚线边框
ctx.setLineDash([10, 5])
ctx.strokeStyle = '#1abc9c'
ctx.lineWidth = 2
ctx.strokeRect(300, 350, 200, 100)
ctx.setLineDash([]) // 重置虚线
// 先填充后描边
ctx.fillStyle = '#f1c40f'
ctx.fillRect(50, 400, 200, 100)
ctx.strokeStyle = '#f39c12'
ctx.lineWidth = 3
ctx.strokeRect(50, 400, 200, 100)
// 绑制一个矩形
ctx.fillStyle = '#3498db'
ctx.fillRect(50, 50, 300, 200)
// 清除中间区域
ctx.clearRect(100, 100, 200, 100)
Canvas没有内置的圆角矩形方法,需要手动实现。
function roundRect(ctx, x, y, width, height, radius) {
ctx.beginPath()
ctx.moveTo(x + radius, y)
ctx.arcTo(x + width, y, x + width, y + height, radius)
ctx.arcTo(x + width, y + height, x, y + height, radius)
ctx.arcTo(x, y + height, x, y, radius)
ctx.arcTo(x, y, x + width, y, radius)
ctx.closePath()
}
// 填充圆角矩形
ctx.fillStyle = '#2ecc71'
roundRect(ctx, 50, 50, 200, 100, 15)
ctx.fill()
// 描边圆角矩形
ctx.strokeStyle = '#27ae60'
ctx.lineWidth = 3
roundRect(ctx, 300, 50, 200, 100, 20)
ctx.stroke()
function roundRect(ctx, x, y, width, height, radii) {
// radii可以是数字或数组[topLeft, topRight, bottomRight, bottomLeft]
if (typeof radii === 'number') {
radii = [radii, radii, radii, radii]
}
const [tl, tr, br, bl] = radii
ctx.beginPath()
ctx.moveTo(x + tl, y)
ctx.lineTo(x + width - tr, y)
ctx.arcTo(x + width, y, x + width, y + tr, tr)
ctx.lineTo(x + width, y + height - br)
ctx.arcTo(x + width, y + height, x + width - br, y + height, br)
ctx.lineTo(x + bl, y + height)
ctx.arcTo(x, y + height, x, y + height - bl, bl)
ctx.lineTo(x, y + tl)
ctx.arcTo(x, y, x + tl, y, tl)
ctx.closePath()
}
// 不同圆角
ctx.fillStyle = '#9b59b6'
roundRect(ctx, 50, 200, 200, 100, [30, 10, 30, 10])
ctx.fill()
function drawButton(ctx, x, y, width, height, text, bgColor, textColor) {
// 按钮背景
ctx.fillStyle = bgColor
roundRect(ctx, x, y, width, height, 8)
ctx.fill()
// 按钮文字
ctx.fillStyle = textColor
ctx.font = '16px Arial'
ctx.textAlign = 'center'
ctx.textBaseline = 'middle'
ctx.fillText(text, x + width / 2, y + height / 2)
}
drawButton(ctx, 50, 350, 120, 40, '点击按钮', '#3498db', '#fff')
drawButton(ctx, 200, 350, 120, 40, '取消', '#95a5a6', '#fff')
drawButton(ctx, 350, 350, 120, 40, '确认', '#2ecc71', '#fff')
function drawCard(ctx, x, y, width, height, title, content) {
// 卡片阴影
ctx.shadowColor = 'rgba(0, 0, 0, 0.1)'
ctx.shadowBlur = 10
ctx.shadowOffsetX = 0
ctx.shadowOffsetY = 4
// 卡片背景
ctx.fillStyle = '#fff'
roundRect(ctx, x, y, width, height, 10)
ctx.fill()
// 重置阴影
ctx.shadowColor = 'transparent'
ctx.shadowBlur = 0
ctx.shadowOffsetX = 0
ctx.shadowOffsetY = 0
// 标题
ctx.fillStyle = '#333'
ctx.font = 'bold 18px Arial'
ctx.fillText(title, x + 20, y + 35)
// 内容
ctx.fillStyle = '#666'
ctx.font = '14px Arial'
ctx.fillText(content, x + 20, y + 65)
}
drawCard(ctx, 50, 450, 300, 120, '卡片标题', '这是卡片的内容描述')
// 超出部分会被裁剪,不会报错
ctx.fillRect(350, 250, 200, 200) // 部分在画布外
// 负值会反向绘制
ctx.fillRect(200, 200, -100, -50) // 从(200,200)向左上绘制
// fillRect不受lineWidth影响
ctx.lineWidth = 10
ctx.fillRect(50, 50, 100, 50) // 矩形大小不变
// strokeRect受lineWidth影响
ctx.strokeRect(200, 50, 100, 50) // 边框会向外扩展