最可靠方案是用 SVG <circle> 配合 stroke-dasharray 与 stroke-dashoffset 截取半圆:设 r=80,周长≈502.65,半圆弧长251.33,stroke-dasharray="251.33 251.33",再 transform="rotate(-90 100 50)" 定位上半圆;动态更新仅需修改 strokeDashoffset 并加 CSS 过渡,指针和文字通过极坐标计算末端位置精准对齐。

用 SVG <circle> + stroke-dasharray 画半圆弧线最可靠
纯 HTML 无法直接绘制半圆仪表盘,必须借助 SVG。核心思路是:用一个 <circle> 元素画完整圆,再通过 stroke-dasharray 和 stroke-dashoffset 截取其中一半(180°),最后旋转定位到水平朝上或朝下。关键不是“画半圆”,而是“控制圆弧长度+起始角度”。
常见错误是直接用 <path d="M...A..."> 手写贝塞尔弧线——参数难调、响应式缩放易变形、IE/旧 Edge 支持差。SVG <circle> 方案兼容性好,CSS 可控,JS 更新也简单。
-
r设为固定值(如80),避免缩放失真;视口用viewBox="0 0 200 100"保证半圆居中且顶部留空 - 总周长 =
2 * Math.PI * r≈502.65;半圆弧长 =251.33;所以stroke-dasharray="251.33 251.33" - 起始点默认在 3 点钟方向,要让弧线从 9 点钟画到 3 点钟(即“上半圆”),需
transform="rotate(-90 100 50)"(绕中心逆时针转 90°)
动态更新值:改 stroke-dashoffset 比重绘更高效
仪表盘数值变化时,不要删掉 <circle> 再新建,直接用 JS 修改 stroke-dashoffset 即可实现“进度回退/前进”。原理是:dasharray 固定为 "251.33 251.33",偏移量越大,显示弧线越短。
比如满值 100% 对应 offset = 0(全显),0% 对应 offset = 251.33(全隐)。中间值线性映射:offset = 251.33 * (1 - value / 100)。
立即学习“前端免费学习笔记(深入)”;
将调研报告、方案对比、数据分析、需求梳理、会议纪要、设计说明、代码评审、学习笔记等任务产物输出为可在浏览器直接打开的单文件 HTML,替代 Markdown 作为最终交付物。Markdown 在信息密度、视觉清晰度和可分享性上已跟不上 AI 产物的丰富度,HTML 能同时承载排版、表格、SVG 等。
- 务必用
element.style.strokeDashoffset = offset + "px"(注意驼峰写法),不能写stroke-dashoffset字符串 - 加 CSS 过渡:给
<circle>加transition: stroke-dashoffset 0.4s ease-out,动画自然不突兀 - 若值突变(如从 10% 跳到 90%),过渡仍有效;但若频繁高频更新(>60fps),建议节流
文字标签和指针怎么对齐到弧线中点?
百分比数字和小三角指针需要贴在当前弧线末端,不能靠估算 left/top。正确做法是:用 SVG <text> + <path> 的 textPath,或用 JS 计算极坐标位置。
推荐后者——更可控、兼容性更好。已知圆心 (cx, cy)、半径 r、当前角度 θ = -90° + value * 1.8°(-90° 是起始角,1.8 = 180° / 100),则末端坐标:
const rad = (θ * Math.PI) / 180; const x = cx + r * Math.cos(rad); const y = cy + r * Math.sin(rad);
- 指针用
<line x1="{cx}" y1="{cy}" x2="{x}" y2="{y}",线宽设stroke-width="2"避免太细看不清 - 文字用
<text>包裹,dom.style.transform = `translate(${x}px, ${y}px)`定位,再加text-anchor="middle" dominant-baseline="middle"居中 - 别忘了给文字加背景遮罩(如小圆白底),否则压在弧线上会看不清
响应式缩放时,viewBox 和 preserveAspectRatio 必须配对用
如果容器宽度变,只靠 CSS width: 100% 会导致 SVG 拉伸变形,弧线变椭圆。根本解法是固定 viewBox,并设 preserveAspectRatio="xMidYMid meet"。
-
viewBox="0 0 200 100"定义逻辑坐标系(宽 200、高 100),所有 SVG 元素按此比例绘制 - 容器 CSS 设
width: 100%; height: 0; padding-bottom: 50%(因为宽高比 2:1),再用position: relative+ 内部position: absolute布局内容 - 千万别用
transform: scale()缩放整个 SVG——文字和描边会糊,且 pointer-events 失准
复杂点在于角度计算和坐标转换必须基于 viewBox 的逻辑单位,而不是像素。一旦混用,缩放后指针就飘。


















