重要前提
安装AI Skills的关键前提是:必须科学上网,且开启TUN模式,这一点至关重要,直接决定安装能否顺利完成,在此郑重提醒三遍:科学上网,科学上网,科学上网。查看完整安装教程 →
moai-tool-svg by modu-ai/moai-adk
npx skills add https://github.com/modu-ai/moai-adk --skill moai-tool-svg全面的 SVG 开发,涵盖矢量图形创建、SVGO 优化、图标系统、数据可视化和动画。此技能为所有 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>
<!-- Content here -->
</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" />
广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
多边形: <polygon points="50,10 90,90 10,90" />
移动命令:
曲线命令:
全局安装: 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
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.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-']
}
}
}
}
]
};
内联 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>
带模糊的投影:
<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)" />
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>
<!-- graphic content -->
</svg>
对于装饰性 SVG,对屏幕阅读器隐藏:
<svg aria-hidden="true" focusable="false">
<!-- decorative content -->
</svg>
将路径数据精度从 6 位小数减少到 2 位:
优化前: M10.123456 20.654321 L30.987654 40.123456
优化后: M10.12 20.65 L30.99 40.12
在适当时将形状转换为路径以减小文件大小。对重复元素使用符号。应用 SVGZ 压缩可减少 20-50% 的大小。
关于每个主题的详细模式,请参阅模块目录。
每周安装数
89
代码仓库
GitHub 星标数
907
首次出现
Jan 27, 2026
安全审计
安装于
opencode84
gemini-cli83
codex83
github-copilot81
cursor77
kimi-cli76
Comprehensive SVG development covering vector graphics creation, SVGO optimization, icon systems, data visualizations, and animations. This skill provides patterns for all SVG workflows from basic shapes to complex animated graphics.
<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>
<!-- Content here -->
</svg>
Rectangle: <rect x="10" y="10" width="80" height="60" rx="5" />
Circle: <circle cx="50" cy="50" r="40" />
Ellipse: <ellipse cx="50" cy="50" rx="40" ry="25" />
Line: <line x1="10" y1="10" x2="90" y2="90" stroke="black" />
Polyline: <polyline points="10,10 50,50 90,10" fill="none" stroke="black" />
Polygon: <polygon points="50,10 90,90 10,90" />
Movement Commands:
Curve Commands:
Install globally: npm install -g svgo
Optimize single file: svgo input.svg -o output.svg
Optimize directory: svgo -f ./src/icons -o ./dist/icons
Show optimization stats: svgo input.svg --pretty --indent=2
Use config file: svgo input.svg --config svgo.config.mjs
Fill properties: fill, fill-opacity, fill-rule (nonzero, evenodd)
Stroke properties: stroke, stroke-width, stroke-opacity, stroke-linecap (butt, round, square), stroke-linejoin (miter, round, bevel), stroke-dasharray, stroke-dashoffset
The SVG element requires the xmlns attribute for standalone files. The viewBox defines the coordinate system as "minX minY width height". Width and height set the rendered size.
<svg xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 200 200"
width="200" height="200"
preserveAspectRatio="xMidYMid meet">
<!-- Reusable definitions -->
<defs>
<linearGradient id="grad1">
<stop offset="0%" stop-color="#ff0000" />
<stop offset="100%" stop-color="#0000ff" />
</linearGradient>
</defs>
<!-- Grouped content -->
<g id="main-group" transform="translate(10, 10)">
<rect width="100" height="100" fill="url(#grad1)" />
</g>
</svg>
Symbols define reusable graphics that can be instantiated with use elements. They support their own viewBox for scaling.
<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 the symbol multiple times -->
<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>
Simple icon path combining moves, lines, and curves:
<path d="M10 20 L20 10 L30 20 L20 30 Z" />
Rounded rectangle using arcs:
<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" />
Heart shape using cubic beziers:
<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" />
Linear gradient from left to right:
<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" />
Radial gradient with focal point:
<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" />
Create svgo.config.mjs in project root:
export default {
multipass: true,
plugins: [
'preset-default',
'prefixIds',
{
name: 'sortAttrs',
params: {
xmlnsOrder: 'alphabetical'
}
},
{
name: 'removeAttrs',
params: {
attrs: ['data-name', 'class']
}
}
]
};
Configuration preserving specific elements:
export default {
multipass: true,
plugins: [
{
name: 'preset-default',
params: {
overrides: {
removeViewBox: false,
cleanupIds: {
preserve: ['icon-', 'logo-']
}
}
}
}
]
};
Inline SVG component:
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>
);
SVG sprite with use element:
const SpriteIcon = ({ name, size = 24 }) => (
<svg width={size} height={size}>
<use href={`/sprites.svg#${name}`} />
</svg>
);
Basic text positioning:
<text x="50" y="50" text-anchor="middle" dominant-baseline="middle"
font-family="Arial" font-size="16" fill="#333">
Centered Text
</text>
Text on a path:
<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>
Drop shadow with blur:
<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>
Glow effect:
<filter id="glow">
<feGaussianBlur stdDeviation="4" result="coloredBlur" />
<feMerge>
<feMergeNode in="coloredBlur" />
<feMergeNode in="SourceGraphic" />
</feMerge>
</filter>
Clip path for cropping:
<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)" />
Gradient mask for fade effect:
<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)" />
Keyframe animation for SVG elements:
@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;
}
Stroke drawing animation:
.draw-path {
stroke-dasharray: 1000;
stroke-dashoffset: 1000;
animation: draw 2s ease forwards;
}
@keyframes draw {
to { stroke-dashoffset: 0; }
}
Always include title and desc for meaningful graphics:
<svg role="img" aria-labelledby="title desc">
<title id="title">Company Logo</title>
<desc id="desc">A blue mountain with snow-capped peak</desc>
<!-- graphic content -->
</svg>
For decorative SVGs, hide from screen readers:
<svg aria-hidden="true" focusable="false">
<!-- decorative content -->
</svg>
Reduce precision in path data from 6 decimals to 2:
Before: M10.123456 20.654321 L30.987654 40.123456
After: M10.12 20.65 L30.99 40.12
Convert shapes to paths for smaller file size when appropriate. Use symbols for repeated elements. Apply SVGZ compression for 20-50% size reduction.
For detailed patterns on each topic, see the modules directory.
Weekly Installs
89
Repository
GitHub Stars
907
First Seen
Jan 27, 2026
Security Audits
Gen Agent Trust HubPassSocketPassSnykPass
Installed on
opencode84
gemini-cli83
codex83
github-copilot81
cursor77
kimi-cli76
React 组合模式指南:Vercel 组件架构最佳实践,提升代码可维护性
122,000 周安装