阿里云主机折上折
  • 微信号
您当前的位置:网站首页 > Canvas绘图API(路径、矩形、文本等)

Canvas绘图API(路径、矩形、文本等)

作者:陈川 阅读数:37192人阅读 分类: HTML

Canvas是HTML5中一个强大的绘图工具,通过JavaScript API可以实现丰富的图形绘制功能。它支持路径、矩形、文本等多种绘图操作,适用于数据可视化、游戏开发、图像处理等场景。

路径绘制

路径是Canvas中最基础的绘图方式,通过一系列线段或曲线组合成任意形状。使用beginPath()开始一个新路径,moveTo()移动画笔到指定坐标,lineTo()绘制直线到新坐标,最后用stroke()fill()描边或填充路径。

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

// 绘制三角形
ctx.beginPath();
ctx.moveTo(50, 50);
ctx.lineTo(100, 50);
ctx.lineTo(75, 100);
ctx.closePath(); // 自动闭合路径
ctx.strokeStyle = 'blue';
ctx.stroke();

贝塞尔曲线可以创建平滑曲线,二次贝塞尔曲线使用quadraticCurveTo(),三次贝塞尔曲线使用bezierCurveTo()

// 二次贝塞尔曲线
ctx.beginPath();
ctx.moveTo(20, 20);
ctx.quadraticCurveTo(80, 100, 150, 20);
ctx.strokeStyle = 'red';
ctx.stroke();

// 三次贝塞尔曲线
ctx.beginPath();
ctx.moveTo(50, 150);
ctx.bezierCurveTo(100, 50, 150, 250, 200, 150);
ctx.strokeStyle = 'green';
ctx.stroke();

矩形绘制

Canvas提供了直接绘制矩形的API,比路径方式更简便。rect()方法定义矩形路径,fillRect()直接绘制填充矩形,strokeRect()绘制描边矩形,clearRect()清除矩形区域。

// 填充矩形
ctx.fillStyle = 'rgba(255, 0, 0, 0.5)';
ctx.fillRect(10, 10, 100, 80);

// 描边矩形
ctx.lineWidth = 3;
ctx.strokeStyle = '#00f';
ctx.strokeRect(150, 10, 100, 80);

// 清除区域
ctx.clearRect(180, 30, 40, 40);

圆角矩形需要结合路径和arcTo()方法实现:

function drawRoundedRect(x, y, width, height, radius) {
  ctx.beginPath();
  ctx.moveTo(x + radius, y);
  ctx.lineTo(x + width - radius, y);
  ctx.quadraticCurveTo(x + width, y, x + width, y + radius);
  ctx.lineTo(x + width, y + height - radius);
  ctx.quadraticCurveTo(x + width, y + height, x + width - radius, y + height);
  ctx.lineTo(x + radius, y + height);
  ctx.quadraticCurveTo(x, y + height, x, y + height - radius);
  ctx.lineTo(x, y + radius);
  ctx.quadraticCurveTo(x, y, x + radius, y);
  ctx.closePath();
  ctx.stroke();
}

文本绘制

Canvas支持两种文本绘制方法:fillText()填充文本和strokeText()描边文本。通过font属性设置字体样式,textAlign控制水平对齐,textBaseline控制垂直对齐。

ctx.font = 'bold 24px Arial';
ctx.fillStyle = 'purple';
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
ctx.fillText('Hello Canvas', canvas.width/2, 50);

ctx.font = 'italic 18px serif';
ctx.strokeStyle = 'black';
ctx.lineWidth = 1;
ctx.strokeText('描边文字效果', 100, 100);

测量文本宽度使用measureText()方法:

const text = '测量文本宽度';
const metrics = ctx.measureText(text);
console.log(`文本宽度:${metrics.width}px`);

样式与颜色

Canvas提供了丰富的样式设置选项。fillStylestrokeStyle接受颜色字符串、渐变对象或图案对象。线性渐变使用createLinearGradient(),径向渐变使用createRadialGradient()

// 线性渐变
const gradient = ctx.createLinearGradient(0, 0, 200, 0);
gradient.addColorStop(0, 'red');
gradient.addColorStop(0.5, 'yellow');
gradient.addColorStop(1, 'green');
ctx.fillStyle = gradient;
ctx.fillRect(10, 10, 200, 100);

// 径向渐变
const radialGrad = ctx.createRadialGradient(100, 100, 10, 100, 100, 50);
radialGrad.addColorStop(0, 'white');
radialGrad.addColorStop(1, 'blue');
ctx.fillStyle = radialGrad;
ctx.arc(100, 100, 50, 0, Math.PI*2);
ctx.fill();

图像操作

Canvas可以绘制图像并进行各种变换。drawImage()方法有三种形式:基本绘制、缩放绘制和切片绘制。

const img = new Image();
img.src = 'example.jpg';
img.onload = function() {
  // 基本绘制
  ctx.drawImage(img, 0, 0);
  
  // 缩放绘制
  ctx.drawImage(img, 0, 0, img.width/2, img.height/2);
  
  // 切片绘制
  ctx.drawImage(img, 
    10, 10, 100, 100,  // 源图像切片区域
    0, 0, 200, 200    // 目标绘制区域
  );
};

变换与合成

Canvas支持多种图形变换:translate()移动原点,rotate()旋转,scale()缩放,transform()矩阵变换。使用save()restore()可以保存和恢复绘图状态。

// 绘制旋转矩形
ctx.save();
ctx.translate(150, 150);
ctx.rotate(Math.PI/4);
ctx.fillStyle = 'orange';
ctx.fillRect(-50, -50, 100, 100);
ctx.restore();

// 图形合成
ctx.globalCompositeOperation = 'xor';
ctx.fillStyle = 'red';
ctx.fillRect(100, 100, 100, 100);
ctx.fillStyle = 'blue';
ctx.fillRect(150, 150, 100, 100);

动画实现

Canvas动画通过连续清除和重绘实现,通常使用requestAnimationFrame优化性能。

let x = 0;
function animate() {
  ctx.clearRect(0, 0, canvas.width, canvas.height);
  ctx.fillRect(x, 50, 50, 50);
  x += 2;
  if(x > canvas.width) x = 0;
  requestAnimationFrame(animate);
}
animate();

性能优化

对于复杂绘图,可以采用以下优化策略:

  • 使用offscreenCanvas进行离屏渲染
  • 避免在动画循环中频繁创建对象
  • 对静态内容分层绘制
  • 合理使用willReadFrequently提示
// 离屏Canvas示例
const offscreen = new OffscreenCanvas(300, 150);
const offCtx = offscreen.getContext('2d');
// 在离屏Canvas上绘制复杂图形
offCtx.fillRect(0, 0, 300, 150);
// 将结果绘制到主Canvas
ctx.drawImage(offscreen, 0, 0);

高级路径操作

Canvas还支持路径剪裁和命中检测。clip()方法可以创建剪裁区域,isPointInPath()检测点是否在路径内。

// 创建圆形剪裁区域
ctx.beginPath();
ctx.arc(100, 100, 50, 0, Math.PI*2);
ctx.clip();
// 后续绘制只会显示在剪裁区域内
ctx.fillRect(0, 0, 200, 200);

// 命中检测
canvas.addEventListener('click', (e) => {
  const rect = canvas.getBoundingClientRect();
  const x = e.clientX - rect.left;
  const y = e.clientY - rect.top;
  
  ctx.beginPath();
  ctx.arc(100, 100, 50, 0, Math.PI*2);
  if(ctx.isPointInPath(x, y)) {
    alert('点击了圆形!');
  }
});

本站部分内容来自互联网,一切版权均归源网站或源作者所有。

如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn

前端川

前端川,陈川的代码茶馆🍵,专治各种不服的Bug退散符💻,日常贩卖秃头警告级的开发心得🛠️,附赠一行代码笑十年的摸鱼宝典🐟,偶尔掉落咖啡杯里泡开的像素级浪漫☕。‌