You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于Canvas实现自定义90度切角参数化图形的技术求助

实现Canvas参数化90度切角图形

要实现你需要的90度切角(切角深度由像素值控制),核心是修改Canvas的路径绘制逻辑——切角是通过直线段替代圆角的贝塞尔曲线,每个切角的本质是从角点向相邻两边各偏移指定深度后,连接这两个偏移点形成斜切边。

关键修改步骤

  • 调整数据结构:将原detail对象中的radius改为depth,对应切角深度(像素值)
  • 编写切角矩形绘制函数:替换原roundRect,通过直线段实现切角路径
  • 适配输入与交互逻辑:更新输入框对应关系,确保参数能正确传递到绘制函数

修改后的完整代码

<div class="solution__wrapper">
    <canvas id="detail" width="1000" height="600"></canvas>
</div>

<div id="app">
  <div class="control">
    <button id="rotateZ">Rotate</button>
    <span> Length: </span>
    <input id="heightInput" placeholder="Length:" type="text" />
    <span> Width: </span>
    <input id="widthInput" placeholder="Width:" type="text" />
    <span> 右上角切角深度: </span>
    <input id="rightAngleInput" placeholder="切角深度:" type="text" />
  </div>
</div>

<script>
  let detail = {
  length: 350,
  width: 250,
  lt: { depth: 0 },
  lb: { depth: 0 },
  rt: { depth: 50 },
  rb: { depth: 0 }
};

const app = document.getElementById("app");
const heightInput = document.getElementById("heightInput");
const widthInput = document.getElementById("widthInput");
const rightCutInput = document.getElementById("rightAngleInput");
const rotateZ = document.getElementById("rotateZ");

(() => {

const myDetail = document.getElementById("detail");
const context = myDetail.getContext("2d");

  // 绘制带90度切角的矩形
  const cutCornerRect = (x, y, w, h, cuts) => {
    const { lt, rt, rb, lb } = cuts;
    const rightX = x + w;
    const bottomY = y + h;

    context.beginPath();
    context.strokeStyle = "black";
    context.lineWidth = "2";

    // 左上角到右上角(含切角)
    context.moveTo(x + lt.depth, y);
    context.lineTo(rightX - rt.depth, y);
    if (rt.depth > 0) {
      context.lineTo(rightX, y + rt.depth);
    }
    // 右侧边到右下角(含切角)
    context.lineTo(rightX, bottomY - rb.depth);
    if (rb.depth > 0) {
      context.lineTo(rightX - rb.depth, bottomY);
    }
    // 底部边到左下角(含切角)
    context.lineTo(x + lb.depth, bottomY);
    if (lb.depth > 0) {
      context.lineTo(x, bottomY - lb.depth);
    }
    // 左侧边回到左上角(含切角)
    context.lineTo(x, y + lt.depth);
    if (lt.depth > 0) {
      context.lineTo(x + lt.depth, y);
    }

    context.closePath();
    context.stroke();
  }

  // 初始绘制
  cutCornerRect(400, 100, detail.width, detail.length, detail);

  let rotation = 0;
  let targetRotate = 90;

  rotateZ.addEventListener("click", () => {
    // 处理输入值,空输入时保留原数值
    let newLength = +heightInput.value || detail.length;
    let newWidth = +widthInput.value || detail.width;
    let newRtDepth = +rightCutInput.value || detail.rt.depth;

    detail.length = newLength;
    detail.width = newWidth;
    detail.rt.depth = newRtDepth;

    // 旋转画布容器
    rotation = (rotation + targetRotate) % 360;
    myDetail.style.transform = `rotate(${rotation}deg)`;

    // 清空画布并重绘
    context.clearRect(0, 0, myDetail.width, myDetail.height);
    cutCornerRect(400, 100, detail.width, detail.length, detail);
  });
})();
</script>

代码说明

  • 切角逻辑:以右上角为例,当切角深度为d时,从顶部边终点(rightX - d, y)绘制到(rightX, y + d),形成90度斜切角
  • 扩展性:支持单独设置四个角的切角深度,修改detail对象中lt/lb/rt/rb的depth值即可
  • 交互优化:添加了输入值的默认处理,避免空输入导致绘制异常

内容的提问来源于stack exchange,提问作者user19163646

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 04:50:11