绘制基本形状

Canvas绘制基本形状教程,学习矩形、圆形、直线等基础图形的绑制方法。Canvas提供了多种绑制基本形状的方法。掌握这些方法是创建复杂图形的基础。

形状绘制概览

形状方法说明
矩形fillRect / strokeRect唯一可直接绘制的形状
圆形arc + fill / stroke需要路径
椭圆ellipse需要路径
直线moveTo + lineTo需要路径
多边形路径组合需要路径

矩形

矩形是Canvas中唯一可以直接绑制的形状,不需要路径。

填充矩形

ctx.fillStyle = '#3498db'
ctx.fillRect(x, y, width, height)

描边矩形

ctx.strokeStyle = '#e74c3c'
ctx.lineWidth = 2
ctx.strokeRect(x, y, width, height)

清除矩形区域

ctx.clearRect(x, y, width, height)

完整示例

const canvas = document.getElementById('canvas')
const ctx = canvas.getContext('2d')

// 填充矩形
ctx.fillStyle = '#3498db'
ctx.fillRect(50, 50, 150, 100)

// 描边矩形
ctx.strokeStyle = '#e74c3c'
ctx.lineWidth = 3
ctx.strokeRect(250, 50, 150, 100)

// 填充+描边
ctx.fillStyle = '#2ecc71'
ctx.fillRect(50, 200, 150, 100)
ctx.strokeStyle = '#27ae60'
ctx.lineWidth = 2
ctx.strokeRect(50, 200, 150, 100)

圆形

圆形需要通过路径绑制。

绘制步骤

ctx.beginPath()                    // 1. 开始路径
ctx.arc(x, y, radius, 0, Math.PI * 2)  // 2. 绘制圆弧
ctx.fill()                         // 3. 填充或描边

arc参数说明

ctx.arc(x, y, radius, startAngle, endAngle, counterclockwise)
参数说明
x, y圆心坐标
radius半径
startAngle起始角度(弧度)
endAngle结束角度(弧度)
counterclockwise是否逆时针(可选,默认false)

示例

// 填充圆
ctx.beginPath()
ctx.arc(100, 100, 50, 0, Math.PI * 2)
ctx.fillStyle = '#9b59b6'
ctx.fill()

// 描边圆
ctx.beginPath()
ctx.arc(250, 100, 50, 0, Math.PI * 2)
ctx.strokeStyle = '#8e44ad'
ctx.lineWidth = 3
ctx.stroke()

// 半圆
ctx.beginPath()
ctx.arc(400, 100, 50, 0, Math.PI)
ctx.fillStyle = '#1abc9c'
ctx.fill()

椭圆

使用ellipse方法绑制椭圆。

参数说明

ctx.ellipse(x, y, radiusX, radiusY, rotation, startAngle, endAngle)
参数说明
x, y圆心坐标
radiusX水平半径
radiusY垂直半径
rotation旋转角度(弧度)
startAngle起始角度
endAngle结束角度

示例

// 水平椭圆
ctx.beginPath()
ctx.ellipse(150, 200, 80, 40, 0, 0, Math.PI * 2)
ctx.fillStyle = '#e67e22'
ctx.fill()

// 垂直椭圆
ctx.beginPath()
ctx.ellipse(350, 200, 40, 80, 0, 0, Math.PI * 2)
ctx.fillStyle = '#d35400'
ctx.fill()

// 旋转45度的椭圆
ctx.beginPath()
ctx.ellipse(550, 200, 60, 30, Math.PI / 4, 0, Math.PI * 2)
ctx.strokeStyle = '#c0392b'
ctx.lineWidth = 2
ctx.stroke()

直线

使用moveTolineTo绑制直线。

方法说明

ctx.moveTo(x1, y1)    // 移动到起点
ctx.lineTo(x2, y2)    // 画线到终点
ctx.stroke()          // 描边

示例

// 单条直线
ctx.beginPath()
ctx.moveTo(50, 50)
ctx.lineTo(200, 150)
ctx.strokeStyle = '#333'
ctx.lineWidth = 2
ctx.stroke()

// 多条连续线
ctx.beginPath()
ctx.moveTo(250, 50)
ctx.lineTo(400, 50)
ctx.lineTo(400, 150)
ctx.lineTo(250, 150)
ctx.closePath()  // 闭合路径
ctx.stroke()

三角形

三角形通过三条直线组成。

function drawTriangle(ctx, x1, y1, x2, y2, x3, y3, fill = true) {
  ctx.beginPath()
  ctx.moveTo(x1, y1)
  ctx.lineTo(x2, y2)
  ctx.lineTo(x3, y3)
  ctx.closePath()
  
  if (fill) {
    ctx.fill()
  } else {
    ctx.stroke()
  }
}

// 使用
ctx.fillStyle = '#16a085'
drawTriangle(ctx, 100, 50, 50, 150, 150, 150)

ctx.strokeStyle = '#2980b9'
ctx.lineWidth = 2
drawTriangle(ctx, 250, 50, 200, 150, 300, 150, false)

多边形

多边形由多条线段组成。

绘制正多边形

function drawPolygon(ctx, x, y, radius, sides, rotation = 0) {
  ctx.beginPath()
  
  for (let i = 0; i < sides; i++) {
    const angle = (i * 2 * Math.PI / sides) + rotation
    const px = x + radius * Math.cos(angle)
    const py = y + radius * Math.sin(angle)
    
    if (i === 0) {
      ctx.moveTo(px, py)
    } else {
      ctx.lineTo(px, py)
    }
  }
  
  ctx.closePath()
}

// 五边形
ctx.fillStyle = '#8e44ad'
drawPolygon(ctx, 100, 300, 50, 5)
ctx.fill()

// 六边形
ctx.fillStyle = '#27ae60'
drawPolygon(ctx, 250, 300, 50, 6)
ctx.fill()

// 八边形
ctx.fillStyle = '#e74c3c'
drawPolygon(ctx, 400, 300, 50, 8)
ctx.fill()

圆角矩形

Canvas没有直接的圆角矩形方法,需要手动绑制。

function roundRect(ctx, x, y, width, height, radius) {
  ctx.beginPath()
  ctx.moveTo(x + radius, y)
  ctx.lineTo(x + width - radius, y)
  ctx.arcTo(x + width, y, x + width, y + radius, radius)
  ctx.lineTo(x + width, y + height - radius)
  ctx.arcTo(x + width, y + height, x + width - radius, y + height, radius)
  ctx.lineTo(x + radius, y + height)
  ctx.arcTo(x, y + height, x, y + height - radius, radius)
  ctx.lineTo(x, y + radius)
  ctx.arcTo(x, y, x + radius, y, radius)
  ctx.closePath()
}

// 使用
ctx.fillStyle = '#3498db'
roundRect(ctx, 50, 400, 200, 100, 20)
ctx.fill()

ctx.strokeStyle = '#2980b9'
ctx.lineWidth = 3
roundRect(ctx, 300, 400, 200, 100, 30)
ctx.stroke()

实际应用:绘制简单图表

const data = [120, 200, 150, 80, 180, 100]
const barWidth = 50
const gap = 20
const startX = 50
const baseY = 350

// 绑制柱状图
data.forEach((value, index) => {
  const x = startX + index * (barWidth + gap)
  const height = value
  const y = baseY - height
  
  // 渐变色
  const gradient = ctx.createLinearGradient(x, y, x, baseY)
  gradient.addColorStop(0, '#3498db')
  gradient.addColorStop(1, '#2980b9')
  
  ctx.fillStyle = gradient
  ctx.fillRect(x, y, barWidth, height)
  
  // 数值标签
  ctx.fillStyle = '#333'
  ctx.font = '14px Arial'
  ctx.textAlign = 'center'
  ctx.fillText(value, x + barWidth / 2, y - 10)
})

// 基线
ctx.beginPath()
ctx.moveTo(startX - 10, baseY)
ctx.lineTo(startX + data.length * (barWidth + gap), baseY)
ctx.strokeStyle = '#333'
ctx.lineWidth = 1
ctx.stroke()