Skip to content

鼓励作者:欢迎 star 或打赏犒劳

Canvas 绘制带圆角的矩形图

实现步骤:

  1. 绘制一个圆角矩形 (打开冰箱)
  2. 对圆角矩形进行剪切(把 🐘 放进去)
  3. 将图片绘制到矩形内(关上冰箱)

绘制圆角矩形

arcTo 方案

arcTo 可以根据控制点和半径绘制圆弧路径

js
// 绘制圆角矩形(使用 arcTo)
function drawRoundedRect(ctx, x, y, width, height, radius) {
  // 重置当前路径
  ctx.beginPath()

  // 移动到左上角
  ctx.moveTo(x + radius, y)
  // 绘制右上角
  ctx.arcTo(x + width, y, x + width, y + radius, radius)
  // 绘制右下角
  ctx.arcTo(x + width, y + height, x + width - radius, y + height, radius)
  // 绘制左下角
  ctx.arcTo(x, height, x, height - radius, radius)
  // 绘制左上角
  ctx.arcTo(x, y, x + radius, y, radius)

  // 填充当前路径
  ctx.fill()
}

quadraticCurveTo 二次贝塞尔曲线方案

quadraticCurveTo 用于创建二次贝塞尔曲线

js
// 绘制圆角矩形(使用二次贝塞尔曲线 quadraticCurveTo)
function drawRoundedRect(ctx, x, y, width, height, radius) {
  // 重置当前路径
  ctx.beginPath()

  // 移动到右上角
  ctx.moveTo(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.fill()
}

不得不说贝塞尔曲线真烦人,圆角矩形还是 arcTo

绘制图片

clip 方案

clip 可以从原始画布剪切任意形状和尺寸的区域。

html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Canvas 绘制带圆角的矩形图 — clip</title>
  </head>
  <body>
    <div>
      <img
        id="img"
        src="https://mms1.baidu.com/it/u=181635795,1817021705&fm=253&app=138&f=JPEG&fmt=auto&q=75?w=500&h=284"
        alt=""
      />
    </div>
    <canvas id="canvas" width="500" height="284"></canvas>
    <script>
      // 绘制圆角矩形(使用 arcTo)
      function drawRoundedRect(ctx, x, y, width, height, radius) {
        // 保存当前环境的状态
        ctx.save()
        // 重置当前路径
        ctx.beginPath()

        // 移动到左上角
        ctx.moveTo(x + radius, y)
        // 绘制右上角
        ctx.arcTo(x + width, y, x + width, y + radius, radius)
        // 绘制右下角
        ctx.arcTo(x + width, y + height, x + width - radius, y + height, radius)
        // 绘制左下角
        ctx.arcTo(x, height, x, height - radius, radius)
        // 绘制左上角
        ctx.arcTo(x, y, x + radius, y, radius)

        // 填充当前路径
        ctx.fill()
      }

      const img = document.getElementById('img')
      const canvas = document.getElementById('canvas')
      const ctx = canvas.getContext('2d')
      window.onload = function () {
        const x = 0
        const y = 0
        const width = canvas.width
        const height = canvas.height

        let radius = 50

        // 处理圆角边界值
        radius = Math.min(radius, Math.min(width, height) / 2)

        // 绘制圆角矩形
        drawRoundedRect(ctx, x, y, width, height, radius)

        // 对矩形进行剪切
        ctx.clip()
        // 绘制图片
        ctx.drawImage(img, x, y, width, height)
      }
    </script>
  </body>
</html>

CodeSandbox: Canvas 绘制带圆角的矩形图 — clip

globalCompositeOperation 方案

globalCompositeOperation 可以设置要在绘制新形状时应用的合成操作的类型

html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Canvas 绘制带圆角的矩形图 — globalCompositeOperation</title>
  </head>
  <body>
    <div>
      <img
        id="img"
        src="https://mms1.baidu.com/it/u=181635795,1817021705&fm=253&app=138&f=JPEG&fmt=auto&q=75?w=500&h=284"
        alt=""
      />
    </div>
    <canvas id="canvas" width="500" height="284"></canvas>
    <script>
      // 绘制圆角矩形(使用 arcTo)
      function drawRoundedRect(ctx, x, y, width, height, radius) {
        // 保存当前环境的状态
        ctx.save()
        // 重置当前路径
        ctx.beginPath()

        // 移动到左上角
        ctx.moveTo(x + radius, y)
        // 绘制右上角
        ctx.arcTo(x + width, y, x + width, y + radius, radius)
        // 绘制右下角
        ctx.arcTo(x + width, y + height, x + width - radius, y + height, radius)
        // 绘制左下角
        ctx.arcTo(x, height, x, height - radius, radius)
        // 绘制左上角
        ctx.arcTo(x, y, x + radius, y, radius)

        // 填充当前路径
        ctx.fill()
      }

      const img = document.getElementById('img')
      const canvas = document.getElementById('canvas')
      const ctx = canvas.getContext('2d')
      window.onload = function () {
        const x = 0
        const y = 0
        const width = canvas.width
        const height = canvas.height

        let radius = 600

        // 处理圆角边界值
        radius = Math.min(radius, Math.min(width, height) / 2)

        // 绘制圆角矩形
        drawRoundedRect(ctx, x, y, width, height, radius)
        // 只在新图形和目标画布重叠的地方绘制图形
        ctx.globalCompositeOperation = 'source-in'
        // 绘制图片
        ctx.drawImage(img, x, y, width, height)
      }
    </script>
  </body>
</html>

CodeSandbox: Canvas 绘制带圆角的矩形图 — globalCompositeOperation

这是李总教我的方案,再次膜拜一下大佬

相关资料

如有转载或 CV 的请标注本站原文地址