Canvas绘制圆形教程,使用arc方法绑制各种圆形和圆弧。Canvas中使用
arc方法绑制圆形和圆弧。圆形是最常用的基础图形之一。
ctx.arc(x, y, radius, startAngle, endAngle, counterclockwise)
| 参数 | 类型 | 说明 |
|---|---|---|
| x | number | 圆心x坐标 |
| y | number | 圆心y坐标 |
| radius | number | 半径 |
| startAngle | number | 起始角度(弧度) |
| endAngle | number | 结束角度(弧度) |
| counterclockwise | boolean | 是否逆时针(可选,默认false) |
const canvas = document.getElementById('canvas')
const ctx = canvas.getContext('2d')
// 填充圆
ctx.beginPath()
ctx.arc(100, 100, 50, 0, Math.PI * 2)
ctx.fillStyle = '#3498db'
ctx.fill()
// 描边圆
ctx.beginPath()
ctx.arc(250, 100, 50, 0, Math.PI * 2)
ctx.strokeStyle = '#e74c3c'
ctx.lineWidth = 3
ctx.stroke()
// 填充+描边
ctx.beginPath()
ctx.arc(400, 100, 50, 0, Math.PI * 2)
ctx.fillStyle = '#2ecc71'
ctx.fill()
ctx.strokeStyle = '#27ae60'
ctx.lineWidth = 2
ctx.stroke()
Canvas使用弧度而非角度:
// 角度转弧度
function toRadians(degrees) {
return degrees * Math.PI / 180
}
// 常用角度
const PI = Math.PI
const HALF_PI = Math.PI / 2 // 90度
const QUARTER_PI = Math.PI / 4 // 45度
const TWO_PI = Math.PI * 2 // 360度
// 上半圆
ctx.beginPath()
ctx.arc(100, 200, 40, 0, Math.PI)
ctx.fillStyle = '#9b59b6'
ctx.fill()
// 下半圆
ctx.beginPath()
ctx.arc(200, 200, 40, Math.PI, 0)
ctx.fillStyle = '#8e44ad'
ctx.fill()
// 左半圆
ctx.beginPath()
ctx.arc(300, 200, 40, HALF_PI, -HALF_PI)
ctx.fillStyle = '#1abc9c'
ctx.fill()
// 右半圆
ctx.beginPath()
ctx.arc(400, 200, 40, -HALF_PI, HALF_PI)
ctx.fillStyle = '#16a085'
ctx.fill()
ctx.beginPath()
ctx.arc(100, 350, 50, 0, Math.PI / 2)
ctx.lineTo(100, 350) // 连接到圆心
ctx.closePath()
ctx.fillStyle = '#e67e22'
ctx.fill()
// 60度圆弧
ctx.beginPath()
ctx.arc(250, 350, 50, 0, toRadians(60))
ctx.strokeStyle = '#e74c3c'
ctx.lineWidth = 3
ctx.stroke()
// 120度圆弧
ctx.beginPath()
ctx.arc(400, 350, 50, toRadians(-60), toRadians(60))
ctx.strokeStyle = '#3498db'
ctx.lineWidth = 3
ctx.stroke()
// 顺时针(默认)
ctx.beginPath()
ctx.arc(100, 500, 40, 0, Math.PI, false)
ctx.fillStyle = '#3498db'
ctx.fill()
// 逆时针
ctx.beginPath()
ctx.arc(200, 500, 40, 0, Math.PI, true)
ctx.fillStyle = '#e74c3c'
ctx.fill()
扇形需要连接圆心:
function drawSector(ctx, x, y, radius, startAngle, endAngle, fillColor) {
ctx.beginPath()
ctx.moveTo(x, y) // 移动到圆心
ctx.arc(x, y, radius, startAngle, endAngle)
ctx.closePath()
ctx.fillStyle = fillColor
ctx.fill()
}
// 绘制饼图
const data = [30, 25, 20, 15, 10]
const colors = ['#3498db', '#e74c3c', '#2ecc71', '#f1c40f', '#9b59b6']
let startAngle = 0
data.forEach((value, index) => {
const angle = (value / 100) * Math.PI * 2
drawSector(ctx, 300, 500, 80, startAngle, startAngle + angle, colors[index])
startAngle += angle
})
function drawRing(ctx, x, y, outerRadius, innerRadius, color) {
ctx.beginPath()
ctx.arc(x, y, outerRadius, 0, Math.PI * 2)
ctx.arc(x, y, innerRadius, 0, Math.PI * 2, true) // 逆时针,形成环形
ctx.fillStyle = color
ctx.fill()
}
drawRing(ctx, 500, 500, 60, 40, '#9b59b6')
function drawProgressRing(ctx, x, y, radius, progress, lineWidth, bgColor, progressColor) {
// 背景圆环
ctx.beginPath()
ctx.arc(x, y, radius, 0, Math.PI * 2)
ctx.strokeStyle = bgColor
ctx.lineWidth = lineWidth
ctx.stroke()
// 进度圆环
const endAngle = -Math.PI / 2 + progress * Math.PI * 2
ctx.beginPath()
ctx.arc(x, y, radius, -Math.PI / 2, endAngle)
ctx.strokeStyle = progressColor
ctx.lineCap = 'round'
ctx.stroke()
// 进度文字
ctx.fillStyle = '#333'
ctx.font = 'bold 20px Arial'
ctx.textAlign = 'center'
ctx.textBaseline = 'middle'
ctx.fillText(Math.round(progress * 100) + '%', x, y)
}
drawProgressRing(ctx, 150, 650, 50, 0.75, 10, '#ecf0f1', '#3498db')
function drawConcentricCircles(ctx, x, y, count, maxRadius) {
const step = maxRadius / count
for (let i = count; i > 0; i--) {
const radius = i * step
const alpha = i / count
ctx.beginPath()
ctx.arc(x, y, radius, 0, Math.PI * 2)
ctx.fillStyle = `rgba(52, 152, 219, ${alpha})`
ctx.fill()
}
}
drawConcentricCircles(ctx, 400, 650, 5, 80)
// 错误:没有beginPath,会连接到上一个路径
ctx.arc(100, 100, 30, 0, Math.PI * 2)
ctx.fill()
ctx.arc(200, 100, 30, 0, Math.PI * 2) // 会和上一个圆连接
ctx.fill()
// 正确:每次都beginPath
ctx.beginPath()
ctx.arc(100, 100, 30, 0, Math.PI * 2)
ctx.fill()
ctx.beginPath()
ctx.arc(200, 100, 30, 0, Math.PI * 2)
ctx.fill()
// Canvas中0度在3点钟方向
// 角度顺时针增加
// 从12点钟开始
ctx.arc(x, y, r, -Math.PI/2, Math.PI/2) // 右半圆
// 从9点钟开始
ctx.arc(x, y, r, Math.PI, 0) // 上半圆
ctx.arc(100, 100, 0, 0, Math.PI * 2) // 不绘制任何内容