基于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
相关产品推荐
相关产品推荐

