From c7baf96b6f512a162256da222d7cd46b0b5d3973 Mon Sep 17 00:00:00 2001 From: LCJ-MinYa <1049468118@qq.com> Date: Mon, 2 Feb 2026 17:44:44 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20canvas=20=E7=A4=BA=E4=BE=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/views/demo/canvasExample.vue | 94 ++++++++++++++++++++++---------- 1 file changed, 65 insertions(+), 29 deletions(-) diff --git a/src/views/demo/canvasExample.vue b/src/views/demo/canvasExample.vue index d4117ae..65d2aab 100644 --- a/src/views/demo/canvasExample.vue +++ b/src/views/demo/canvasExample.vue @@ -41,45 +41,81 @@ const startDraw = function () { function drawHexagon(radius = 50, custom) { const cornerRadius = 20; // 圆角半径(可调,控制弧度大小) - ctx.beginPath(); - - // 从顶部开始,逆时针绘制 - for (let i = 0; i < 6; i++) { - const startAngle = (Math.PI / 3) * i + Math.PI / 2; // 当前边的起始角度(从顶部开始) - - const x1 = centerX + radius * Math.cos(startAngle); - const y1 = centerY + radius * Math.sin(startAngle); - - const prevAngle = (Math.PI / 3) * (i - 1) + Math.PI / 2; - const prevX = centerX + radius * Math.cos(prevAngle); - const prevY = centerY + radius * Math.sin(prevAngle); - - // 画圆弧:从 prevX,prevY 到 x1,y1,以 cornerX,cornerY 为中心 - ctx.arcTo(prevX, prevY, x1, y1, cornerRadius); - } - - // 最后一段圆弧:连接最后一个点到第一个点 - const lastAngle = (Math.PI / 3) * 5 + Math.PI / 2; - const firstAngle = (Math.PI / 3) * 0 + Math.PI / 2; - const lastX = centerX + radius * Math.cos(lastAngle); - const lastY = centerY + radius * Math.sin(lastAngle); - const firstX = centerX + radius * Math.cos(firstAngle); - const firstY = centerY + radius * Math.sin(firstAngle); - ctx.arcTo(lastX, lastY, firstX, firstY, cornerRadius - cornerRadius / 2); - // 设置样式 ctx.fillStyle = 'rgba(255, 248, 244, 1)'; ctx.strokeStyle = 'rgba(253, 201, 171, 1)'; ctx.lineWidth = 3; - // === 条件判断:custom 为 true 时绘制虚线边框,不填充 === + ctx.beginPath(); + if (custom) { - // 虚线:10px 实线 + 5px 空白 + // === custom 为 true 时 (最外层) === + // 绘制虚线边框,且在每个角留出空隙给文字 + const gap = 40; // 避让距离,根据文字大小调整 + + for (let i = 0; i < 6; i++) { + // 当前顶点 (起点) + const angle1 = (Math.PI / 3) * i + Math.PI / 2; + const x1 = centerX + radius * Math.cos(angle1); + const y1 = centerY + radius * Math.sin(angle1); + + // 下一个顶点 (终点) + const angle2 = (Math.PI / 3) * (i + 1) + Math.PI / 2; + const x2 = centerX + radius * Math.cos(angle2); + const y2 = centerY + radius * Math.sin(angle2); + + // 计算向量 + const dx = x2 - x1; + const dy = y2 - y1; + const dist = Math.sqrt(dx * dx + dy * dy); + + // 只有当边长大于 2*gap 时才绘制,防止交叉 + if (dist > 2 * gap) { + const ux = dx / dist; + const uy = dy / dist; + + // 计算避让后的起点和终点 + const sx = x1 + ux * gap; + const sy = y1 + uy * gap; + const ex = x2 - ux * gap; + const ey = y2 - uy * gap; + + ctx.moveTo(sx, sy); + ctx.lineTo(ex, ey); + } + } + + // 绘制虚线 ctx.setLineDash([5, 8]); ctx.lineDashOffset = 0; ctx.stroke(); - ctx.setLineDash([]); + ctx.setLineDash([]); // 还原 } else { + // === 普通情况 (内部实心六边形) === + // 从顶部开始,逆时针绘制 + for (let i = 0; i < 6; i++) { + const startAngle = (Math.PI / 3) * i + Math.PI / 2; // 当前边的起始角度(从顶部开始) + + const x1 = centerX + radius * Math.cos(startAngle); + const y1 = centerY + radius * Math.sin(startAngle); + + const prevAngle = (Math.PI / 3) * (i - 1) + Math.PI / 2; + const prevX = centerX + radius * Math.cos(prevAngle); + const prevY = centerY + radius * Math.sin(prevAngle); + + // 画圆弧:从 prevX,prevY 到 x1,y1,以 cornerX,cornerY 为中心 + ctx.arcTo(prevX, prevY, x1, y1, cornerRadius); + } + + // 最后一段圆弧:连接最后一个点到第一个点 + const lastAngle = (Math.PI / 3) * 5 + Math.PI / 2; + const firstAngle = (Math.PI / 3) * 0 + Math.PI / 2; + const lastX = centerX + radius * Math.cos(lastAngle); + const lastY = centerY + radius * Math.sin(lastAngle); + const firstX = centerX + radius * Math.cos(firstAngle); + const firstY = centerY + radius * Math.sin(firstAngle); + ctx.arcTo(lastX, lastY, firstX, firstY, cornerRadius - cornerRadius / 2); + ctx.fill(); ctx.stroke(); }