mcpField
M
moai-tool-svg

moai-tool-svg

github.com/modu-ai设计与 UI1.2k100 次安装今天更新
代码仓库

关于 moai-tool-svg

moai-tool-svg 是用于创建和优化 SVG 图形的技能,面向制作图标、插画和可视化内容的开发者与设计师。内容涵盖 SVG 结构、样式、动画、无障碍设计及 SVGO 优化。

主要功能

  1. 01SVG 形状、路径与文档结构
  2. 02渐变、滤镜、裁剪与蒙版
  3. 03可复用符号与精灵图
  4. 04CSS 和 SMIL 动画模式
  5. 05SVGO 优化与配置
  6. 06无障碍支持与响应式缩放

适用场景

  1. 01制作 SVG 图标和插画
  2. 02在 React 组件中嵌入 SVG 图形
  3. 03优化导出的 SVG 文件
  4. 04添加无障碍标签并处理装饰性图像

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/modu-ai/moai-adk --skill moai-tool-svg

安装后在 Claude Code 中输入/moai-tool-svg确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

RETIRED.md
modules/
INDEX.md
svg-animation.md
svg-basics.md
svg-optimization.md
svg-styling.md
references/
examples.md
reference.md

详细介绍

SVG 创建与优化专家

全面的 SVG 开发,涵盖矢量图形创建、SVGO 优化、图标系统、数据可视化和动画。此技能提供适用于各种 SVG 工作流的模式,从基本形状到复杂动画图形。


快速参考(30 秒)

基本 SVG 模板
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" width="100" height="100">
  <title>Accessible Title</title>
  <desc>Description for screen readers</desc>
  
</svg>
常见形状速查表

矩形:<rect x="10" y="10" width="80" height="60" rx="5" />

圆形:<circle cx="50" cy="50" r="40" />

椭圆:<ellipse cx="50" cy="50" rx="40" ry="25" />

直线:<line x1="10" y1="10" x2="90" y2="90" stroke="black" />

折线:<polyline points="10,10 50,50 90,10" fill="none" stroke="black" />

多边形:<polygon points="50,10 90,90 10,90" />

路径命令速查

移动命令:

  • M x y:移动到绝对位置
  • m dx dy:相对移动
  • L x y:绘制到绝对位置的直线
  • l dx dy:相对绘制直线
  • H x:绘制绝对水平线
  • h dx:相对绘制水平线
  • V y:绘制绝对垂直线
  • v dy:相对绘制垂直线
  • Z:闭合路径

曲线命令:

  • C x1 y1 x2 y2 x y:三次贝塞尔曲线(两个控制点)
  • S x2 y2 x y:平滑三次曲线(反射前一个控制点)
  • Q x1 y1 x y:二次贝塞尔曲线(一个控制点)
  • T x y:平滑二次曲线(反射前一个控制点)
  • A rx ry rotation large-arc sweep x y:弧线
SVGO 命令行命令

全局安装:npm install -g svgo

优化单个文件:svgo input.svg -o output.svg

优化目录:svgo -f ./src/icons -o ./dist/icons

显示优化统计信息:svgo input.svg --pretty --indent=2

使用配置文件:svgo input.svg --config svgo.config.mjs

填充和描边速查

填充属性:fill、fill-opacity、fill-rule(nonzero、evenodd)

描边属性:stroke、stroke-width、stroke-opacity、stroke-linecap(butt、round、square)、stroke-linejoin(miter、round、bevel)、stroke-dasharray、stroke-dashoffset


实现指南(5 分钟)

SVG 文档结构

独立文件中的 SVG 元素需要 xmlns 属性。viewBox 将坐标系定义为“minX minY width height”。width 和 height 设置渲染尺寸。

<svg xmlns="http://www.w3.org/2000/svg"
     viewBox="0 0 200 200"
     width="200" height="200"
     preserveAspectRatio="xMidYMid meet">

  
  <defs>
    <linearGradient id="grad1">
      <stop offset="0%" stop-color="#ff0000" />
      <stop offset="100%" stop-color="#0000ff" />
    </linearGradient>
  </defs>

  
  <g id="main-group" transform="translate(10, 10)">
    <rect width="100" height="100" fill="url(#grad1)" />
  </g>
</svg>
创建可重用符号

符号用于定义可通过 use 元素实例化的可重用图形。符号支持用于缩放的自有 viewBox。

<svg xmlns="http://www.w3.org/2000/svg">
  <defs>
    <symbol id="icon-star" viewBox="0 0 24 24">
      <path d="M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z"/>
    </symbol>
  </defs>

  
  <use href="#icon-star" x="0" y="0" width="24" height="24" />
  <use href="#icon-star" x="30" y="0" width="24" height="24" fill="gold" />
  <use href="#icon-star" x="60" y="0" width="48" height="48" />
</svg>
路径创建模式

组合移动、直线和曲线的简单图标路径:

<path d="M10 20 L20 10 L30 20 L20 30 Z" />

使用弧线绘制圆角矩形:

<path d="M15 5 H85 A10 10 0 0 1 95 15 V85 A10 10 0 0 1 85 95 H15 A10 10 0 0 1 5 85 V15 A10 10 0 0 1 15 5 Z" />

使用三次贝塞尔曲线绘制心形:

<path d="M50 88 C20 65 5 45 5 30 A15 15 0 0 1 35 30 Q50 45 50 45 Q50 45 65 30 A15 15 0 0 1 95 30 C95 45 80 65 50 88 Z" />
渐变实现

从左到右的线性渐变:

<defs>
  <linearGradient id="horizontal-grad" x1="0%" y1="0%" x2="100%" y2="0%">
    <stop offset="0%" stop-color="#3498db" />
    <stop offset="50%" stop-color="#9b59b6" />
    <stop offset="100%" stop-color="#e74c3c" />
  </linearGradient>
</defs>
<rect fill="url(#horizontal-grad)" width="200" height="100" />

带焦点的径向渐变:

<defs>
  <radialGradient id="sphere-grad" cx="50%" cy="50%" r="50%" fx="30%" fy="30%">
    <stop offset="0%" stop-color="#ffffff" />
    <stop offset="100%" stop-color="#3498db" />
  </radialGradient>
</defs>
<circle fill="url(#sphere-grad)" cx="50" cy="50" r="40" />
SVGO 配置

在项目根目录创建 svgo.config.mjs:

export default {
  multipass: true,
  plugins: [
    'preset-default',
    'prefixIds',
    {
      name: 'sortAttrs',
      params: {
        xmlnsOrder: 'alphabetical'
      }
    },
    {
      name: 'removeAttrs',
      params: {
        attrs: ['data-name', 'class']
      }
    }
  ]
};

保留特定元素的配置:

export default {
  multipass: true,
  plugins: [
    {
      name: 'preset-default',
      params: {
        overrides: {
          removeViewBox: false,
          cleanupIds: {
            preserve: ['icon-', 'logo-']
          }
        }
      }
    }
  ]
};
在 React 中嵌入 SVG

内联 SVG 组件:

const Icon = ({ size = 24, color = 'currentColor' }) => (
  <svg width={size} height={size} viewBox="0 0 24 24" fill="none">
    <path d="M12 2L2 7l10 5 10-5-10-5z" stroke={color} strokeWidth="2" />
  </svg>
);

使用 use 元素的 SVG 雪碧图:

const SpriteIcon = ({ name, size = 24 }) => (
  <svg width={size} height={size}>
    <use href={`/sprites.svg#${name}`} />
  </svg>
);
文本元素

基本文本定位:

<text x="50" y="50" text-anchor="middle" dominant-baseline="middle"
      font-family="Arial" font-size="16" fill="#333">
  Centered Text
</text>

沿路径排列文本:

<defs>
  <path id="text-curve" d="M10 80 Q95 10 180 80" fill="none" />
</defs>
<text font-size="14">
  <textPath href="#text-curve">Text following a curved path</textPath>
</text>

高级实现(10 分钟以上)

复杂滤镜效果

带模糊的投影:

<defs>
  <filter id="drop-shadow" x="-20%" y="-20%" width="140%" height="140%">
    <feGaussianBlur in="SourceAlpha" stdDeviation="3" result="blur" />
    <feOffset in="blur" dx="3" dy="3" result="offsetBlur" />
    <feMerge>
      <feMergeNode in="offsetBlur" />
      <feMergeNode in="SourceGraphic" />
    </feMerge>
  </filter>
</defs>

发光效果:

<filter id="glow">
  <feGaussianBlur stdDeviation="4" result="coloredBlur" />
  <feMerge>
    <feMergeNode in="coloredBlur" />
    <feMergeNode in="SourceGraphic" />
  </feMerge>
</filter>
裁剪与蒙版

用于裁剪的裁剪路径:

<defs>
  <clipPath id="circle-clip">
    <circle cx="50" cy="50" r="40" />
  </clipPath>
</defs>
<image href="photo.jpg" width="100" height="100" clip-path="url(#circle-clip)" />

用于淡出效果的渐变蒙版:

<defs>
  <linearGradient id="fade-grad">
    <stop offset="0%" stop-color="white" />
    <stop offset="100%" stop-color="black" />
  </linearGradient>
  <mask id="fade-mask">
    <rect width="100" height="100" fill="url(#fade-grad)" />
  </mask>
</defs>
<rect width="100" height="100" fill="blue" mask="url(#fade-mask)" />
CSS 动画集成

SVG 元素的关键帧动画:

@keyframes pulse {
  0%, 100% { transform: scale(1); opacity: 1; }
  50% { transform: scale(1.1); opacity: 0.8; }
}

.animated-circle {
  animation: pulse 2s ease-in-out infinite;
  transform-origin: center;
}

描边绘制动画:

.draw-path {
  stroke-dasharray: 1000;
  stroke-dashoffset: 1000;
  animation: draw 2s ease forwards;
}

@keyframes draw {
  to { stroke-dashoffset: 0; }
}
无障碍最佳实践

对于有意义的图形,始终包含 title 和 desc:

<svg role="img" aria-labelledby="title desc">
  <title id="title">Company Logo</title>
  <desc id="desc">A blue mountain with snow-capped peak</desc>
  
</svg>

对于装饰性 SVG,应对屏幕阅读器隐藏:

<svg aria-hidden="true" focusable="false">
  
</svg>
性能优化

将路径数据精度从 6 位小数降低到 2 位:

之前:M10.123456 20.654321 L30.987654 40.123456

之后:M10.12 20.65 L30.99 40.12

适当情况下,将形状转换为路径以减小文件体积。对重复元素使用符号。应用 SVGZ 压缩,可将体积缩小 20-50%。

有关各主题的详细模式,请参阅 modules 目录。


模块索引

  • modules/svg-basics.md:文档结构、坐标系、形状、路径、文本
  • modules/svg-styling.md:填充、描边、渐变、图案、滤镜、裁剪、蒙版
  • modules/svg-optimization.md:SVGO 配置、压缩、精灵图、性能
  • modules/svg-animation.md:CSS 动画、SMIL、JavaScript、交互模式

配合使用效果良好

  • moai-domain-frontend:React/Vue SVG 组件集成
  • moai-docs-generation:为文档生成 SVG 图表
  • moai-domain-uiux:图标系统与设计系统集成

常见借口

借口事实
“这个图标用 PNG 就行,SVG 没必要”PNG 在不同分辨率下会模糊,而且需要准备多个尺寸。SVG 可以完美缩放,对于简单图形来说文件更小。
“我之后再优化 SVG”设计工具导出的未优化 SVG 包含编辑器元数据、隐藏图层和精度过高的小数,文件体积会因此膨胀 50-80%。
“内联 SVG 总是比 img 标签好”内联 SVG 会增加 HTML 负载,并阻止浏览器缓存。对于不需要动态样式的静态图标,请使用 img 标签。
“装饰性图标不需要考虑无障碍”装饰性图标需要设置 aria-hidden=true,才能被屏幕阅读器正确忽略。否则屏幕阅读器会读出无意义的内容。
“SVGO 默认设置适用于所有 SVG”SVGO 默认设置会移除 viewBox 和 title 元素。要保留无障碍支持和响应式特性,必须进行自定义配置。

警示信号

  • SVG 文件包含编辑器元数据(Illustrator、Sketch、Figma 导出杂项)
  • SVG 缺少 viewBox 属性(会导致响应式缩放失效)
  • 交互式 SVG 缺少 role 和 aria-label 属性
  • 装饰性 SVG 缺少 aria-hidden="true"
  • SVG 文件比视觉效果相同的 PNG 文件更大

验证

  • 使用 SVGO 或同类工具优化 SVG(展示优化前后的文件大小)
  • 所有 SVG 都存在 viewBox 属性(不能只有固定的 width/height)
  • 装饰性 SVG 设置了 aria-hidden="true"
  • 交互式 SVG 设置了 role="img" 和 aria-label
  • 在目标分辨率下,SVG 文件小于对应的 PNG 文件
  • 已提交的 SVG 文件不含编辑器元数据(检查是否含有 Illustrator/Sketch/Figma 标签)

评论

支持 Markdown