最简路径是用ctx.arc()画双圆、预设五角星顶点、逐字极坐标定位+独立旋转弧形文字,并清空画布确保透明PNG导出。

canvas 绘制圆形印章最简路径
直接用 canvas 画电子印章,核心不是“做印章”,而是“模拟盖章效果”:外圆 + 内字 + 五角星 + 倾斜弧形文字。浏览器不支持自动排版弧形字,得手动算坐标,所以别指望一行代码出效果。
关键步骤:
- 用
ctx.arc()画外圈(粗线)和内圈(细线),注意lineCap: 'round'让起止点更圆润 - 五角星用
ctx.moveTo()+ctx.lineTo()连 5 个顶点,中心点建议固定在 canvas 中心,避免偏移 - 文字分两层:顶部“中华人民共和国”这类横排字直接
ctx.fillText();环形字必须拆成单字,用极坐标公式x = cx + r * cos(θ)、y = cy + r * sin(θ)逐个定位 - 每个环形字要单独旋转(
ctx.save()→ctx.rotate()→fillText()→ctx.restore()),否则整体歪斜
arc 文字排布常见翻车点
网上很多示例把整个字符串当一个整体去 rotate,结果所有字朝向一致、挤在一边——这不是印章,是扇形贴纸。
正确做法是让每个字的基线切于圆弧,即每个字的旋转角度 = 该字所在位置的切线角(也就是极角 ± 90°)。例如从 12 点钟方向开始逆时针排 12 个字,第 i 个字的角度应为 startAngle + i * (Math.PI * 2 / charCount) - Math.PI / 2。
立即学习“前端免费学习笔记(深入)”;
容易漏的细节:
将调研报告、方案对比、数据分析、需求梳理、会议纪要、设计说明、代码评审、学习笔记等任务产物输出为可在浏览器直接打开的单文件 HTML,替代 Markdown 作为最终交付物。Markdown 在信息密度、视觉清晰度和可分享性上已跟不上 AI 产物的丰富度,HTML 能同时承载排版、表格、SVG 等。
- 字体大小要用
ctx.font = 'bold 14px SimSun'显式指定中文字体,否则 macOS 上可能 fallback 到无衬线体,失去印章感 - 中文字符宽度不等宽,但印章里要求视觉均匀,所以不能按字符串长度均分角度,得按字数均分(即每个字占相同弧度)
-
ctx.textAlign = 'center'和ctx.textBaseline = 'middle'必须设,否则文字上下左右全飘
导出 PNG 时透明背景失效?
调用 canvas.toDataURL('image/png') 默认带透明通道,但如果 canvas 创建时没清空或用了 fillRect() 填白底,导出就是白底图——电子印章必须透明背景才能叠在 PDF 或文档上。
确保透明的唯一可靠方式:
- 创建 canvas 后立刻执行
ctx.clearRect(0, 0, canvas.width, canvas.height) - 绝对不要写
ctx.fillStyle = '#fff'; ctx.fillRect(...) - 检查导出 base64 字符串开头是不是
data:image/png;base64,iVBORw0KGgo...(PNG 标识),而不是data:image/jpeg...(JPEG 不支持透明) - 如果后端要接收,记得前端传的是 base64,不是 blob;blob 需先用
new FileReader().readAsDataURL(blob)转换
IE11 或旧安卓 WebView 不渲染?
老环境不支持 ctx.ellipse()(画椭圆),但印章外圈用 arc() 完全够用;真正卡住的是 ctx.textBaseline = 'middle' 在 IE11 下部分失效,导致文字垂直错位。
兼容方案:
- 放弃
'middle',改用'alphabetic',然后手动调整 y 坐标:y ≈ centerY + fontSize * 0.35 - 避免使用
ctx.measureText().width算单字宽(IE 返回 0),环形字统一按固定角度间隔(如每字 28°)即可 - 五角星顶点坐标别用
Math.sin()/Math.cos()实时算,预计算好 5 个点存数组,减少浮点误差累积 - 如果项目仍需支持 Android 4.x,禁用
ctx.lineDashOffset类高级属性,它们会直接让整段绘图静默失败
印章不是越复杂越像,而是越克制越可用:去掉阴影、渐变、模糊,只留硬边线条和标准宋体字,反而更接近政务场景真实用印规范。


















