合成与裁剪

1 阅读5分钟

Canvas 合成与裁剪 超详细讲解

Canvas 的**合成(Compositing)裁剪(Clip)**是实现高级视觉效果的核心技术,我会把 全局合成、透明度合成、路径裁剪 拆解得通俗易懂,附带可直接运行的代码和效果图逻辑。

先明确核心概念:

  • 透明度合成:单个图形/图片自身的透明效果
  • 路径裁剪(clip):用一个路径当“模具”,只在模具内绘制内容
  • 全局合成(globalCompositeOperation):控制新图形已有图形的叠加规则

一、基础前置:Canvas 渲染层级

Canvas 是画布,后绘制的图形默认会覆盖先绘制的图形,这是默认合成规则:source-over

所有合成/裁剪/透明度,都是在修改这个“覆盖规则”。


二、透明度合成(opacity)

1. 两种透明度设置方式

Canvas 支持全局透明度局部透明度

方式API作用范围
全局透明度ctx.globalAlpha = 0~1所有后续绘制的图形
局部透明度rgba/rbga 颜色值仅当前图形

2. 代码示例

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

// 1. 局部透明度:仅红色矩形生效
ctx.fillStyle = 'rgba(255, 0, 0, 0.5)'; // 透明度 0.5
ctx.fillRect(50, 50, 100, 100);

// 2. 全局透明度:后续所有图形都生效
ctx.globalAlpha = 0.3;
ctx.fillStyle = 'blue';
ctx.fillRect(100, 100, 100, 100); // 蓝色矩形透明度 0.3

// 重置全局透明度(必须!)
ctx.globalAlpha = 1;

3. 核心要点

  • globalAlpha全局生效的,用完必须重置为 1
  • 局部透明度(rgba)优先级更高,互不干扰
  • 透明度叠加:两个半透明图形重叠,重叠区域会更透明

三、路径裁剪 clip() —— 画布“模具”

1. 核心原理

clip() 会把当前路径变成一个裁剪区域(蒙版/模具),后续所有绘制只会显示在这个区域内,超出部分全部隐藏。

就像用剪纸模具,只能在模具里涂色。

2. 关键规则

  • 必须先定义路径,再调用 clip()
  • clip()单向不可逆的,想要恢复必须用 save() + restore()
  • 可以嵌套裁剪(模具里再做小模具)

3. 基础使用(圆形裁剪图片)

const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
const img = new Image();
img.src = '图片地址';

img.onload = function() {
  ctx.save(); // 保存画布状态(关键!)
  
  // 1. 绘制裁剪路径:圆形
  ctx.arc(150, 150, 100, 0, Math.PI * 2);
  ctx.clip(); // 把路径变成裁剪模具
  
  // 2. 在模具内绘制图片(只会显示圆形区域)
  ctx.drawImage(img, 50, 50, 200, 200);
  
  ctx.restore(); // 恢复画布状态,关闭裁剪
};

4. 高级:不规则路径裁剪

任何路径(多边形、曲线、文字)都能当裁剪模具:

// 五角星路径裁剪
ctx.save();
ctx.beginPath();
ctx.moveTo(150,50);
ctx.lineTo(180,150);
ctx.lineTo(280,150);
ctx.lineTo(200,200);
ctx.lineTo(230,300);
ctx.lineTo(150,250);
ctx.lineTo(70,300);
ctx.lineTo(100,200);
ctx.lineTo(20,150);
ctx.lineTo(120,150);
ctx.closePath();
ctx.clip();

// 绘制内容,只显示五角星内
ctx.fillStyle = 'red';
ctx.fillRect(0,0,300,300);
ctx.restore();

四、全局合成 globalCompositeOperation

这是 Canvas 最强大的功能,控制新图形和已有图形的叠加方式

合成.png

1. 核心概念

  • 源图像(source)即将绘制的新图形
  • 目标图像(destination):画布上已经存在的图形

ctx.globalCompositeOperation = "模式"

2. 常用合成模式详解

以下是几种最常用、最能体现其威力的模式:

模式描述典型应用
source-over默认值。新图形绘制在旧图形的上方。常规的绘图操作。
destination-over新图形绘制在旧图形的下方为已有图形添加背景或衬底。
source-in新图形只在与旧图形重叠的区域显示,其余部分变透明。遮罩/贴图。例如,将一张图片限制在一个圆形或文字形状内显示。
destination-in只保留旧图形中与新图形重叠的部分,其余清空。蒙版提取。例如,用文字的形状“抠”出底下图片的局部。
source-out新图形只在不与旧图形重叠的区域显示。制作镂空效果。
destination-out擦除旧图形中与新图形重叠的部分。橡皮擦效果。常用于涂鸦板或擦除动画。
lighter重叠区域的颜色值相加。创建发光或加亮效果。
xor重叠区域变为透明。制作特殊的异或效果。

3. 代码演示(source-in 蒙版)

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

// 1. 目标图像(已有图形):蓝色矩形
ctx.fillStyle = 'blue';
ctx.fillRect(50, 50, 150, 150);

// 2. 设置合成模式:只保留重叠区域,显示新图形
ctx.globalCompositeOperation = 'source-in';

// 3. 源图像(新图形):红色圆形
ctx.fillStyle = 'red';
ctx.arc(150, 150, 100, 0, Math.PI * 2);
ctx.fill();

// 重置合成模式(必须!)
ctx.globalCompositeOperation = 'source-over';

4. 橡皮擦效果(destination-out)

// 先铺满画布
ctx.fillStyle = 'black';
ctx.fillRect(0,0,400,400);

// 设置合成模式:擦除重叠区域
ctx.globalCompositeOperation = 'destination-out';

// 绘制圆形,重叠的黑色会被擦掉
ctx.arc(200,200,80,0,Math.PI*2);
ctx.fill();

五、关键避坑指南

  1. 状态管理clip()globalAlpha/globalCompositeOperation 修改后必须重置,最佳实践:
    ctx.save();    // 保存
    // 合成/裁剪代码
    ctx.restore(); // 恢复
    
  2. 执行顺序
    • 裁剪:先路径 → 再 clip → 再绘制
    • 合成:先画目标图形 → 设置模式 → 再画源图形
  3. clip 不可逆:不用 save/restore 无法取消裁剪,会一直生效
  4. 合成模式互斥:同一时间只能生效一种模式

总结

  1. 透明度globalAlpha(全局)/rgba(局部),控制半透明效果
  2. 路径裁剪 clip:用路径做模具,只在模具内绘制,必须配合 save/restore
  3. 全局合成globalCompositeOperation 控制新旧图形叠加方式,核心是 source-in(蒙版)和 destination-out(橡皮擦)
  4. 三者可以组合使用,实现图片圆角、蒙版、擦除、镂空等所有高级视觉效果