Skip to content

canvas 裁剪

CanvasRenderingContext2D.clip() 是 Canvas 2D API 将当前创建的路径设置为当前剪切路径的方法。

语法

js
void ctx.clip();
void ctx.clip(fillRule);
void ctx.clip(path, fillRule);

参数

fillRule
  这个算法判断一个点是在路径内还是在路径外。 允许的值:
  nonzero
    非零环绕原则,默认的原则。
  evenodd
    奇偶环绕原则。

path
  需要剪切的 Path2D 路径。

代码:

vue
<script setup lang="ts">
import { onMounted } from 'vue';

onMounted(() => {
  const ctx = (document.getElementById('clip-demo') as HTMLCanvasElement).getContext('2d')
  ctx.fillRect(0, 0, 200, 200);
  // 移动坐标圆点至 canvas 中间
  ctx.translate(100, 100);

  // 开始画一条新线段 
  ctx.beginPath();
  ctx.arc(0, 0, 60, 0, Math.PI * 2, true);
  // 剪切
  ctx.clip();

  // 画背景
  const lingrad = ctx.createLinearGradient(0, -100, 0, 100);
  lingrad.addColorStop(0, '#fff');
  lingrad.addColorStop(1, '#143778');
  ctx.fillStyle = lingrad;
  ctx.fillRect(-100, -100, 200, 200);

  // 画五角星
  for (let j = 1; j < 100 ; j ++){
    ctx.save();
    ctx.fillStyle = '#fff';
    ctx.translate(100 - Math.floor(Math.random() * 200), 100 - Math.floor(Math.random() * 200));
    ctx.rotate(Number((Math.random() * 2).toFixed(2)) * Math.PI)
    drawStar(Math.floor(Math.random() * 6) + 3);
    ctx.restore();
  }

  // 以坐标原点为中心,让 4 条射线穿过原点。
  // 4 条射线把平面分成总共 10 份。
  // 在一条射线上标记两个点,这两个点分别会穿过星星的两个不同的顶点(一个向外凸的顶点,一个向内凹的顶点)。
  // 然后两两连接相邻的两条射线的标记点,最终就画好了五角星。
  function drawStar(r: number) {
    // 将当前 canvas 的所有状态放入栈中
    ctx.save();
    // 开始画新线段
    ctx.beginPath()
    ctx.lineWidth = 0.5
    ctx.moveTo(r, 0);
    for (let i = 0; i < 9; i ++){
      ctx.rotate(Math.PI / 5);
      if(i % 2 === 0) {
        ctx.lineTo((r / 0.525731) * 0.200811, 0);
      } else {
        ctx.lineTo(r, 0);
      }
    }
    ctx.closePath();
    ctx.fill();
    ctx.restore();
  }
})
</script>
<template>
  <div class="border-t-1 border-b-1 border-l-none border-r-none border-solid border-t-gray-700 border-b-gray-700 pa-4 my-4">
    <canvas id="clip-demo" width="200" height="200" class="border border-solid border-red">
    </canvas>
  </div>
</template>

Released under the MIT License.