diff --git a/src/views/demo/canvasExample.vue b/src/views/demo/canvasExample.vue index 65d2aab..26c212e 100644 --- a/src/views/demo/canvasExample.vue +++ b/src/views/demo/canvasExample.vue @@ -51,7 +51,7 @@ const startDraw = function () { if (custom) { // === custom 为 true 时 (最外层) === // 绘制虚线边框,且在每个角留出空隙给文字 - const gap = 40; // 避让距离,根据文字大小调整 + const gap = 55; // 避让距离,根据文字大小调整 for (let i = 0; i < 6; i++) { // 当前顶点 (起点) @@ -122,25 +122,62 @@ const startDraw = function () { } // 添加文本到六边形的角上 - function drawTextAtCorners(radius, textArray) { - // 文本内容数组,对应六边形的6个角 - const text = textArray || ['医疗险', '定期寿险', '储蓄养老', '家财宠险', '重疾险', '意外险']; - const textColors = ['#333', '#333', '#333', '#333', '#333', '#333']; // 文本颜色 - const textSizes = [20, 20, 20, 20, 20, 20]; // 文本大小 + function drawTextAtCorners(radius, dataArray) { + // 默认兜底数据 + const data = dataArray; + const titleSize = 20; // 标题文本大小 + const statusSize = 14; // 状态文本大小 + const rowGap = 10; // 标题与状态行的间距 for (let i = 0; i < 6; i++) { - const angle = (Math.PI / 3) * i + Math.PI / 2; // 当前角的角度(从顶部开始) + const item = data[i]; + const angle = (Math.PI / 3) * i + Math.PI / 2; // 当前角的角度 const x = centerX + radius * Math.cos(angle); const y = centerY + radius * Math.sin(angle); - // 设置文本样式 - ctx.font = `bold ${textSizes[i]}px Arial`; - ctx.fillStyle = textColors[i]; + // === 1. 绘制标题 === + ctx.font = `bold ${titleSize}px Arial`; + ctx.fillStyle = '#333'; ctx.textAlign = 'center'; ctx.textBaseline = 'middle'; + ctx.fillText(item.title, x, y); + + // === 2. 绘制状态行 (图标 + 文字) === + const isGuaranteed = item.status; + const statusText = isGuaranteed ? '已保障' : '未保障'; + const activeColor = '#67C23A'; // 高亮绿色 + const inactiveColor = '#909399'; // 置灰颜色 + const color = isGuaranteed ? activeColor : inactiveColor; + + // 计算位置 + // 标题中心是 y,下移距离 = 标题半高 + 间距 + 状态文字半高 + // 简单估算:y + 10 (标题下沿) + 10 (间距) + 7 (状态文字中心) ≈ y + 27 + const statusY = y + 27; + + // 测量宽度以实现整体居中 + ctx.font = `normal ${statusSize}px Arial`; + const textWidth = ctx.measureText(statusText).width; + const iconRadius = 4; + const iconGap = 4; // 图标与文字间距 + const totalWidth = iconRadius * 2 + iconGap + textWidth; + + // 计算起始 X 坐标 (使得 [图标+间距+文字] 整体居中) + // 整体左边缘 = 中心点x - 总宽的一半 + // 图标中心x = 整体左边缘 + 半径 + const iconCenterX = x - totalWidth / 2 + iconRadius; + + // A. 绘制图标 (实心圆) + ctx.beginPath(); + ctx.arc(iconCenterX, statusY, iconRadius, 0, Math.PI * 2); + ctx.fillStyle = color; + ctx.fill(); - // 绘制文本 - ctx.fillText(text[i], x, y); + // B. 绘制状态文字 + ctx.fillStyle = color; + ctx.textAlign = 'left'; // 改为左对齐,基于图标位置排列 + ctx.textBaseline = 'middle'; + const textX = iconCenterX + iconRadius + iconGap; + ctx.fillText(statusText, textX, statusY); } } @@ -151,7 +188,15 @@ const startDraw = function () { drawHexagon(50); // 在最外层六边形的角上添加文本 - drawTextAtCorners(200, ['医疗险', '定期寿险', '储蓄养老', '家财宠险', '重疾险', '意外险']); + const cornerData = [ + { title: '医疗险', status: false }, + { title: '定期寿险', status: true }, + { title: '储蓄养老', status: false }, + { title: '家财宠险', status: true }, + { title: '重疾险', status: false }, + { title: '意外险', status: false }, + ]; + drawTextAtCorners(200, cornerData); };