SVG
可伸缩矢量图形(SVG)是一种基于XML的二维矢量图形格式,也可以在HTML中使用。

查看更多相关内容
JavaScript 如何操作和操作 SVGJavaScript 与 SVG 的结合可以实现强大的动态交互功能。以下是 JavaScript 操作 SVG 的主要方法:
**1. 选择 SVG 元素**
使用标准 DOM 方法选择 SVG 元素。
```javascript
// 通过 ID 选择
const circle = document.getElementById('myCircle');
// 通过类名选择
const circles = document.querySelectorAll('.circle');
// 通过标签名选择
const allRects = document.querySelectorAll('rect');
// 通过属性选择
const filledElements = document.querySelectorAll('[fill="red"]');
```
**2. 创建 SVG 元素**
使用 `createElementNS` 创建 SVG 元素(注意命名空间)。
```javascript
const svgNS = 'http://www.w3.org/2000/svg';
// 创建 SVG 元素
const circle = document.createElementNS(svgNS, 'circle');
circle.setAttribute('cx', '100');
circle.setAttribute('cy', '100');
circle.setAttribute('r', '50');
circle.setAttribute('fill', 'blue');
// 添加到 SVG
const svg = document.querySelector('svg');
svg.appendChild(circle);
```
**3. 修改 SVG 属性**
使用 `setAttribute` 和 `getAttribute` 方法。
```javascript
const circle = document.querySelector('circle');
// 修改属性
circle.setAttribute('fill', 'red');
circle.setAttribute('r', '60');
circle.setAttribute('stroke', 'black');
circle.setAttribute('stroke-width', '3');
// 获取属性
const fill = circle.getAttribute('fill');
const radius = circle.getAttribute('r');
```
**4. 修改 SVG 样式**
使用 `style` 属性或 `classList`。
```javascript
const circle = document.querySelector('circle');
// 直接设置样式
circle.style.fill = 'green';
circle.style.opacity = '0.5';
circle.style.transform = 'scale(1.2)';
// 使用 classList
circle.classList.add('highlight');
circle.classList.remove('normal');
circle.classList.toggle('active');
```
**5. 事件监听**
为 SVG 元素添加事件监听器。
```javascript
const circle = document.querySelector('circle');
// 鼠标事件
circle.addEventListener('click', function() {
console.log('Circle clicked!');
this.setAttribute('fill', 'red');
});
circle.addEventListener('mouseover', function() {
this.style.cursor = 'pointer';
});
circle.addEventListener('mouseout', function() {
this.style.cursor = 'default';
});
// 键盘事件(需要 tabindex)
circle.setAttribute('tabindex', '0');
circle.addEventListener('keydown', function(event) {
if (event.key === 'Enter' || event.key === ' ') {
event.preventDefault();
console.log('Circle activated!');
}
});
```
**6. 动画实现**
使用 JavaScript 实现 SVG 动画。
```javascript
const circle = document.querySelector('circle');
// 使用 requestAnimationFrame
let progress = 0;
function animate() {
progress += 0.01;
const x = 100 + Math.sin(progress * 2 * Math.PI) * 50;
circle.setAttribute('cx', x);
if (progress < 1) {
requestAnimationFrame(animate);
}
}
animate();
// 使用 CSS 过渡
circle.style.transition = 'all 0.5s ease';
circle.setAttribute('fill', 'red');
circle.setAttribute('r', '60');
```
**7. 获取鼠标位置**
获取鼠标在 SVG 中的相对位置。
```javascript
const svg = document.querySelector('svg');
svg.addEventListener('click', function(event) {
const point = svg.createSVGPoint();
point.x = event.clientX;
point.y = event.clientY;
const svgPoint = point.matrixTransform(svg.getScreenCTM().inverse());
console.log(`SVG coordinates: x=${svgPoint.x}, y=${svgPoint.y}`);
});
```
**8. 拖拽功能**
实现 SVG 元素的拖拽。
```javascript
let selectedElement = null;
let offset = { x: 0, y: 0 };
function getMousePosition(evt) {
const CTM = svg.getScreenCTM();
return {
x: (evt.clientX - CTM.e) / CTM.a,
y: (evt.clientY - CTM.f) / CTM.d
};
}
function startDrag(evt) {
selectedElement = evt.target;
offset = getMousePosition(evt);
offset.x -= parseFloat(selectedElement.getAttribute('cx'));
offset.y -= parseFloat(selectedElement.getAttribute('cy'));
}
function drag(evt) {
if (selectedElement) {
evt.preventDefault();
const coord = getMousePosition(evt);
selectedElement.setAttribute('cx', coord.x - offset.x);
selectedElement.setAttribute('cy', coord.y - offset.y);
}
}
function endDrag(evt) {
selectedElement = null;
}
const svg = document.querySelector('svg');
svg.addEventListener('mousedown', startDrag);
svg.addEventListener('mousemove', drag);
svg.addEventListener('mouseup', endDrag);
svg.addEventListener('mouseleave', endDrag);
```
**9. 动态创建复杂图形**
使用 JavaScript 动态创建复杂的 SVG 图形。
```javascript
function createStar(cx, cy, spikes, outerRadius, innerRadius) {
const svgNS = 'http://www.w3.org/2000/svg';
const polygon = document.createElementNS(svgNS, 'polygon');
let points = [];
for (let i = 0; i < spikes * 2; i++) {
const radius = i % 2 === 0 ? outerRadius : innerRadius;
const angle = (Math.PI / spikes) * i;
const x = cx + Math.cos(angle) * radius;
const y = cy + Math.sin(angle) * radius;
points.push(`${x},${y}`);
}
polygon.setAttribute('points', points.join(' '));
polygon.setAttribute('fill', 'gold');
polygon.setAttribute('stroke', 'orange');
polygon.setAttribute('stroke-width', '2');
return polygon;
}
const svg = document.querySelector('svg');
const star = createStar(100, 100, 5, 50, 25);
svg.appendChild(star);
```
**10. 数据可视化**
使用 SVG 和 JavaScript 创建数据可视化。
```javascript
const data = [10, 25, 40, 30, 50];
const svg = document.querySelector('svg');
const barWidth = 40;
const gap = 20;
data.forEach((value, index) => {
const rect = document.createElementNS('http://www.w3.org/2000/svg', 'rect');
const x = 20 + index * (barWidth + gap);
const y = 200 - value * 3;
rect.setAttribute('x', x);
rect.setAttribute('y', y);
rect.setAttribute('width', barWidth);
rect.setAttribute('height', value * 3);
rect.setAttribute('fill', `hsl(${index * 60}, 70%, 50%)`);
svg.appendChild(rect);
});
```
**最佳实践:**
- 使用 `createElementNS` 创建 SVG 元素
- 合理使用事件委托
- 优化动画性能,使用 requestAnimationFrame
- 注意命名空间
- 考虑使用 SVG 库(如 D3.js)处理复杂场景
- 测试跨浏览器兼容性
前端 · 2月21日 15:58
SVG 如何与 CSS 结合使用SVG 与 CSS 的结合使用可以创建丰富的视觉效果和交互体验。以下是 SVG 与 CSS 结合的多种方式:
**1. 基本样式应用**
CSS 可以直接应用于 SVG 元素,就像应用于 HTML 元素一样。
```svg
<svg width="200" height="200">
<style>
.circle {
fill: blue;
stroke: red;
stroke-width: 2;
}
.rectangle {
fill: green;
stroke: black;
stroke-width: 3;
}
</style>
<circle class="circle" cx="100" cy="100" r="50" />
<rect class="rectangle" x="20" y="20" width="80" height="60" />
</svg>
```
**2. CSS 伪类**
使用 CSS 伪类实现交互效果。
```svg
<svg width="200" height="200">
<style>
.interactive {
fill: blue;
transition: all 0.3s ease;
cursor: pointer;
}
.interactive:hover {
fill: red;
transform: scale(1.1);
}
.interactive:active {
fill: green;
}
.interactive:focus {
outline: 3px solid #005fcc;
outline-offset: 2px;
}
</style>
<circle class="interactive" cx="100" cy="100" r="50" tabindex="0" />
</svg>
```
**3. CSS 动画**
使用 CSS 的 `@keyframes` 实现动画效果。
```svg
<svg width="200" height="200">
<style>
.rotating {
transform-origin: center;
animation: rotate 2s linear infinite;
}
.pulsing {
animation: pulse 1s ease-in-out infinite;
}
@keyframes rotate {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
@keyframes pulse {
0%, 100% { transform: scale(1); }
50% { transform: scale(1.2); }
}
</style>
<rect class="rotating" x="75" y="75" width="50" height="50" fill="blue" />
<circle class="pulsing" cx="100" cy="100" r="30" fill="red" />
</svg>
```
**4. CSS 变量**
使用 CSS 变量实现动态样式。
```svg
<svg width="200" height="200">
<style>
:root {
--primary-color: #3498db;
--secondary-color: #e74c3c;
--stroke-width: 2px;
}
.dynamic {
fill: var(--primary-color);
stroke: var(--secondary-color);
stroke-width: var(--stroke-width);
}
.dynamic:hover {
--primary-color: #2ecc71;
}
</style>
<circle class="dynamic" cx="100" cy="100" r="50" />
</svg>
```
**5. 外部 CSS 文件**
将 SVG 样式放在外部 CSS 文件中。
```html
<!-- HTML 文件 -->
<link rel="stylesheet" href="styles.css" />
<svg width="200" height="200">
<circle class="styled-circle" cx="100" cy="100" r="50" />
</svg>
```
```css
/* styles.css */
.styled-circle {
fill: #3498db;
stroke: #2c3e50;
stroke-width: 3px;
transition: all 0.3s ease;
}
.styled-circle:hover {
fill: #e74c3c;
transform: scale(1.1);
}
```
**6. CSS 选择器**
使用各种 CSS 选择器精确控制 SVG 元素。
```svg
<svg width="200" height="200">
<style>
/* ID 选择器 */
#unique-circle {
fill: red;
}
/* 类选择器 */
.blue-circle {
fill: blue;
}
/* 属性选择器 */
circle[fill="green"] {
stroke: black;
stroke-width: 2;
}
/* 后代选择器 */
.group circle {
fill: purple;
}
/* 伪元素 */
.special::after {
content: '';
/* SVG 不支持伪元素,但可以用于 SVG 内的 HTML 元素 */
}
</style>
<circle id="unique-circle" cx="50" cy="50" r="20" />
<circle class="blue-circle" cx="100" cy="50" r="20" />
<circle fill="green" cx="150" cy="50" r="20" />
<g class="group">
<circle cx="50" cy="100" r="20" />
<circle cx="100" cy="100" r="20" />
</g>
</svg>
```
**7. 响应式 SVG**
结合 CSS 媒体查询实现响应式 SVG。
```svg
<svg width="100%" height="auto" viewBox="0 0 200 200">
<style>
@media (max-width: 768px) {
.responsive-element {
fill: blue;
}
}
@media (min-width: 769px) {
.responsive-element {
fill: red;
}
}
</style>
<circle class="responsive-element" cx="100" cy="100" r="50" />
</svg>
```
**8. CSS transform**
使用 CSS transform 实现变换效果。
```svg
<svg width="200" height="200">
<style>
.transformed {
transition: transform 0.3s ease;
}
.transformed:hover {
transform: translate(20px, 20px) rotate(45deg) scale(1.2);
}
</style>
<rect class="transformed" x="75" y="75" width="50" height="50" fill="blue" />
</svg>
```
**最佳实践:**
- 优先使用 CSS 实现动画和交互
- 将样式与结构分离
- 使用 CSS 变量提高可维护性
- 考虑性能,避免过度使用复杂动画
- 测试跨浏览器兼容性
- 使用 CSS 过渡实现平滑效果
服务端 · 2月21日 15:22
SVG 与其他图形格式有什么区别和优劣SVG 与其他图形格式的对比是选择合适技术的重要依据。以下是 SVG 与其他常见图形格式的详细对比:
**1. SVG vs PNG/JPG(位图格式)**
**SVG 优势:**
- 矢量图形,无限缩放不失真
- 文件大小通常更小
- 可编辑和动画
- 支持 CSS 和 JavaScript 交互
- 可访问性好,支持屏幕阅读器
- SEO 友好,内容可被搜索引擎索引
**PNG/JPG 优势:**
- 适合照片和复杂图像
- 浏览器兼容性更好
- 文件格式更简单
- 不需要额外的解析开销
**适用场景:**
- SVG:图标、logo、图表、插画、需要缩放的图形
- PNG/JPG:照片、复杂图像、不需要编辑的图形
**2. SVG vs GIF**
**SVG 优势:**
- 动画更流畅(CSS/JS 动画)
- 文件大小更小
- 支持交互
- 颜色深度更高
- 无版权问题
**GIF 优势:**
- 动画兼容性更好
- 支持透明背景
- 文件格式简单
- 社交媒体支持广泛
**适用场景:**
- SVG:现代网页动画、交互式动画
- GIF:简单的循环动画、社交媒体分享
**3. SVG vs Canvas**
**SVG 优势:**
- 矢量图形,无限缩放
- DOM 元素,支持事件和交互
- 可访问性好
- 易于调试和编辑
- SEO 友好
**Canvas 优势:**
- 渲染大量对象时性能更好
- 适合游戏和复杂动画
- 像素级控制
- 不受 DOM 限制
**适用场景:**
- SVG:图标、图表、简单动画、需要交互的场景
- Canvas:游戏、大数据可视化、复杂动画、高性能场景
**4. SVG vs WebP**
**SVG 优势:**
- 矢量图形,可无限缩放
- 可编辑和动画
- 支持交互
- 可访问性好
**WebP 优势:**
- 压缩率更高,文件更小
- 支持动画
- 浏览器支持越来越广泛
- 适合照片和复杂图像
**适用场景:**
- SVG:矢量图形、图标、图表
- WebP:照片、复杂图像、需要高压缩率的场景
**5. SVG vs 图标字体(Icon Fonts)**
**SVG 优势:**
- 可以使用多种颜色和渐变
- 支持动画和交互
- 更好的可访问性
- 可以精确控制样式
- 不需要额外的字体文件
**图标字体优势:**
- 实现简单,兼容性好
- 可以像文字一样设置样式
- 文件大小小
- 支持文本效果
**适用场景:**
- SVG:需要多色图标、动画图标、交互式图标
- 图标字体:单色图标、需要广泛兼容性的场景
**6. SVG vs PDF**
**SVG 优势:**
- 网页原生支持
- 可以嵌入 HTML
- 支持动画和交互
- 文件格式更轻量
**PDF 优势:**
- 打印质量更好
- 跨平台一致性
- 支持复杂的文档结构
- 更适合文档分发
**适用场景:**
- SVG:网页图形、交互式内容
- PDF:文档、打印、跨平台分发
**7. 性能对比**
**文件大小:**
- 简单图形:SVG < PNG < JPG
- 复杂图像:JPG < WebP < PNG < SVG
- 图标:SVG ≈ 图标字体 < PNG
**渲染性能:**
- 少量元素:SVG > Canvas
- 大量元素:Canvas > SVG
- 动画:CSS 动画 > SMIL > JS 动画
**8. 选择建议**
**选择 SVG 的情况:**
- 需要矢量缩放
- 需要交互和动画
- 需要可访问性
- 需要编辑和修改
- SEO 重要
**选择其他格式的情况:**
- 照片或复杂图像:PNG/JPG/WebP
- 高性能渲染大量对象:Canvas
- 简单单色图标:图标字体
- 文档分发:PDF
**最佳实践:**
- 根据需求选择合适的格式
- 可以组合使用多种格式
- 考虑浏览器兼容性
- 优化文件大小和性能
- 测试不同场景的效果
服务端 · 2月21日 15:22
如何优化 SVG 以提升性能SVG 优化对于提升网页性能和用户体验非常重要。以下是常见的 SVG 优化技巧:
**1. 移除不必要的代码**
- 删除编辑器添加的元数据(如 `<title>Created with...</title>`)
- 移除注释和空行
- 删除未使用的定义和样式
- 使用工具如 SVGO 进行自动优化
**2. 简化路径**
- 使用更短的路径命令(如用 `h` 代替 `H`)
- 合并相邻的相同命令
- 减少小数位数精度(如 `50.123456` 改为 `50.12`)
- 使用相对坐标代替绝对坐标
**3. 优化属性**
- 移除默认值属性(如 `fill="black"` 可以省略)
- 使用简写属性(如 `stroke` 代替 `stroke-color`)
- 合并相同的样式到 class 或 `<style>` 标签
**4. 压缩 SVG 文件**
- 使用 gzip 压缩(服务器配置)
- 使用 SVGO 等工具进行优化
- 移除 DOCTYPE 声明(不影响渲染)
**5. 使用 SVG Sprite**
- 将多个图标合并到一个 SVG 文件中
- 使用 `<symbol>` 和 `<use>` 元素复用图形
- 减少 HTTP 请求
**示例:**
```svg
<svg style="display: none;">
<symbol id="icon-home" viewBox="0 0 24 24">
<path d="M10 20v-6h4v6h5v-8h3L12 3 2 12h3v8z"/>
</symbol>
<symbol id="icon-user" viewBox="0 0 24 24">
<path d="M12 12c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm0 2c-2.67 0-8 1.34-8 4v2h16v-2c0-2.66-5.33-4-8-4z"/>
</symbol>
</svg>
<!-- 使用图标 -->
<svg><use href="#icon-home"/></svg>
<svg><use href="#icon-user"/></svg>
```
**6. 内联关键 SVG**
- 首屏渲染的关键 SVG 内联到 HTML
- 避免额外的 HTTP 请求
- 非关键 SVG 可以延迟加载
**7. 使用 viewBox 代替 width/height**
- 使用 `viewBox` 实现响应式缩放
- 通过 CSS 控制显示尺寸
- 提高灵活性
**8. 减少元素数量**
- 合并可以合并的路径
- 使用 `<g>` 分组而不是多个独立元素
- 避免不必要的嵌套
**9. 优化动画性能**
- 优先使用 CSS 动画(GPU 加速)
- 使用 `transform` 和 `opacity` 属性
- 避免动画 `width`、`height`、`left`、`top` 等属性
**10. 工具推荐**
- **SVGO**:强大的 SVG 优化工具
- **SVGOMG**:在线 SVG 优化工具
- **Iconfont**:图标字体和 SVG 管理
- **Figma/Sketch**:导出时优化 SVG
**优化示例:**
```bash
# 使用 SVGO 优化
npx svgo input.svg -o output.svg
# 批量优化
npx svgo -f ./icons -o ./optimized
```
**性能测试:**
- 使用 Lighthouse 测试页面性能
- 检查 SVG 文件大小和加载时间
- 监控渲染性能
服务端 · 2月21日 15:21
SVG 动画有哪些实现方式,它们之间有什么区别SVG 动画可以通过多种方式实现,每种方式都有其特点和适用场景:
**1. SMIL 动画(原生 SVG 动画)**
SMIL(Synchronized Multimedia Integration Language)是 SVG 原生支持的动画语法。
**常用元素:**
- `<animate>`:基本属性动画
- `<animateTransform>`:变换动画(旋转、缩放、平移、倾斜)
- `<animateMotion>`:沿路径运动
**示例:**
```svg
<svg width="200" height="200">
<circle cx="50" cy="50" r="20" fill="red">
<animate attributeName="cx" from="50" to="150" dur="2s" repeatCount="indefinite" />
<animate attributeName="fill" values="red;blue;red" dur="2s" repeatCount="indefinite" />
</circle>
</svg>
```
**优点:**
- 原生支持,无需 JavaScript
- 声明式语法,易于理解
- 性能良好
**缺点:**
- Chrome 已宣布弃用 SMIL
- 灵活性有限
- 调试困难
**2. CSS 动画**
使用 CSS 的 `@keyframes` 和 `transition` 属性。
**示例:**
```svg
<svg width="200" height="200">
<style>
.circle {
animation: move 2s infinite alternate;
transition: fill 0.3s;
}
.circle:hover {
fill: blue;
}
@keyframes move {
from { transform: translateX(0); }
to { transform: translateX(100px); }
}
</style>
<circle class="circle" cx="50" cy="50" r="20" fill="red" />
</svg>
```
**优点:**
- 广泛支持,标准技术
- 性能优秀(GPU 加速)
- 易于维护和调试
- 支持 hover 等交互状态
**缺点:**
- 无法直接操作 SVG 内部属性
- 复杂动画需要大量 CSS
**3. JavaScript 动画**
使用 JavaScript 操作 SVG DOM 或使用动画库。
**原生 JavaScript 示例:**
```javascript
const circle = document.querySelector('circle');
let position = 50;
function animate() {
position += 1;
circle.setAttribute('cx', position);
if (position < 150) {
requestAnimationFrame(animate);
}
}
animate();
```
**使用 GSAP 库示例:**
```javascript
gsap.to('circle', {
attr: { cx: 150 },
duration: 2,
repeat: -1,
yoyo: true
});
```
**优点:**
- 最大灵活性
- 可以实现复杂逻辑
- 丰富的动画库支持(GSAP、Anime.js 等)
- 可以与其他 JavaScript 交互
**缺点:**
- 需要编写更多代码
- 性能需要优化
- 依赖 JavaScript
**选择建议:**
- 简单动画:优先使用 CSS 动画
- 复杂交互:使用 JavaScript + 动画库
- 向后兼容:避免使用 SMIL
- 性能关键:优先 CSS 和 requestAnimationFrame
服务端 · 2月21日 15:21
SVG 和 Canvas 有什么区别,如何选择使用SVG 和 Canvas 都是用于在网页上绘制图形的技术,但它们在工作原理、性能和适用场景上有显著差异:
**1. 工作原理**
- **SVG**:基于 DOM 的矢量图形,每个图形元素都是独立的 DOM 节点
- **Canvas**:基于像素的位图,通过 JavaScript 在画布上绘制,最终生成位图
**2. 图形类型**
- **SVG**:矢量图形,无限缩放不失真
- **Canvas**:位图,缩放会失真
**3. DOM 交互**
- **SVG**:
- 每个元素都可以绑定事件(click, hover 等)
- 可以通过 CSS 样式化
- 支持标准的 DOM 操作
- 适合需要交互的场景
- **Canvas**:
- 整个画布是一个 DOM 元素
- 需要手动计算点击位置和碰撞检测
- 无法直接通过 CSS 样式化内部元素
- 适合纯展示场景
**4. 性能对比**
- **SVG**:
- 元素数量较少时性能良好
- 元素数量过多(数千个)时性能下降
- 适合图标、图表、简单动画
- **Canvas**:
- 元素数量多时性能优秀
- 渲染大量对象时性能稳定
- 适合游戏、数据可视化、复杂动画
**5. 可访问性**
- **SVG**:
- 支持屏幕阅读器
- 可以添加 title 和 desc 元素
- 搜索引擎可以索引内容
- SEO 友好
- **Canvas**:
- 可访问性较差
- 需要额外实现 ARIA 支持
- 搜索引擎难以索引内容
**6. 文件大小**
- **SVG**:
- 简单图形文件小
- 复杂图形文件可能较大
- 可以 gzip 压缩
- **Canvas**:
- 不涉及文件大小(动态生成)
- 导出为图片时文件大小取决于分辨率
**7. 适用场景**
**SVG 适合:**
- 图标和 logo
- 简单到中等复杂度的图表
- 需要交互的图形
- 需要缩放的图形
- 打印和高质量输出
- SEO 重要的内容
**Canvas 适合:**
- 游戏开发
- 大数据可视化
- 复杂动画
- 图像处理
- 实时渲染
- 高性能要求的场景
**8. 选择建议**
- 需要交互和可访问性:选择 SVG
- 需要高性能渲染大量对象:选择 Canvas
- 需要矢量缩放:选择 SVG
- 需要像素级控制:选择 Canvas
- 可以结合使用两者,发挥各自优势
服务端 · 2月21日 15:21
如何创建和管理 SVG 图标系统SVG 图标系统是现代 Web 开发中的重要组成部分。以下是创建和管理 SVG 图标系统的最佳实践:
**1. SVG Sprite 技术**
将多个图标合并到一个 SVG 文件中,减少 HTTP 请求。
```svg
<!-- icons.svg -->
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
<symbol id="icon-home" viewBox="0 0 24 24">
<path d="M10 20v-6h4v6h5v-8h3L12 3 2 12h3v8z" fill="currentColor"/>
</symbol>
<symbol id="icon-user" viewBox="0 0 24 24">
<path d="M12 12c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm0 2c-2.67 0-8 1.34-8 4v2h16v-2c0-2.66-5.33-4-8-4z" fill="currentColor"/>
</symbol>
<symbol id="icon-search" viewBox="0 0 24 24">
<path d="M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z" fill="currentColor"/>
</symbol>
</svg>
```
**2. 使用 SVG Sprite**
在 HTML 中引用图标。
```html
<!-- 引用图标文件 -->
<body>
<!-- 隐藏的 SVG sprite -->
<svg style="display: none;">
<use href="icons.svg#icon-home" />
<use href="icons.svg#icon-user" />
<use href="icons.svg#icon-search" />
</svg>
<!-- 使用图标 -->
<button>
<svg width="24" height="24">
<use href="#icon-home" />
</svg>
首页
</button>
<button>
<svg width="24" height="24">
<use href="#icon-user" />
</svg>
用户
</button>
</body>
```
**3. 内联 SVG 图标**
直接在 HTML 中内联 SVG 代码。
```html
<button>
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M3 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2 2m-2-2v10a1 1 0 01-1 1h-3m-6 0a1 1 0 001-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 001 1m-6 0h6" />
</svg>
首页
</button>
```
**4. CSS 图标类**
使用 CSS 类管理图标样式。
```css
.icon {
display: inline-block;
width: 1em;
height: 1em;
vertical-align: middle;
fill: currentColor;
}
.icon-sm {
width: 16px;
height: 16px;
}
.icon-md {
width: 24px;
height: 24px;
}
.icon-lg {
width: 32px;
height: 32px;
}
.icon-xl {
width: 48px;
height: 48px;
}
/* 图标颜色 */
.icon-primary {
color: #3498db;
}
.icon-success {
color: #2ecc71;
}
.icon-warning {
color: #f39c12;
}
.icon-danger {
color: #e74c3c;
}
```
**5. React 组件封装**
在 React 中封装 SVG 图标组件。
```jsx
// Icon.jsx
import React from 'react';
const Icon = ({ name, size = 24, color = 'currentColor', className = '' }) => {
const icons = {
home: (
<path d="M10 20v-6h4v6h5v-8h3L12 3 2 12h3v8z" />
),
user: (
<path d="M12 12c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm0 2c-2.67 0-8 1.34-8 4v2h16v-2c0-2.66-5.33-4-8-4z" />
),
search: (
<path d="M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z" />
)
};
return (
<svg
width={size}
height={size}
viewBox="0 0 24 24"
fill={color}
className={`icon ${className}`}
aria-hidden="true"
>
{icons[name]}
</svg>
);
};
export default Icon;
// 使用示例
<Icon name="home" size={24} color="#3498db" />
<Icon name="user" size={32} />
```
**6. Vue 组件封装**
在 Vue 中封装 SVG 图标组件。
```vue
<!-- Icon.vue -->
<template>
<svg
:width="size"
:height="size"
viewBox="0 0 24 24"
:fill="color"
class="icon"
aria-hidden="true"
>
<slot />
</svg>
</template>
<script>
export default {
name: 'Icon',
props: {
size: {
type: Number,
default: 24
},
color: {
type: String,
default: 'currentColor'
}
}
}
</script>
<!-- 使用示例 -->
<Icon :size="24" color="#3498db">
<path d="M10 20v-6h4v6h5v-8h3L12 3 2 12h3v8z" />
</Icon>
```
**7. 自动化工具**
使用工具自动生成图标系统。
**使用 SVGO 优化:**
```bash
npx svgo -f ./icons -o ./optimized
```
**使用 Iconify:**
```html
<script src="https://code.iconify.design/1/1.0.7/iconify.min.js"></script>
<span class="iconify" data-icon="mdi:home"></span>
```
**8. 最佳实践**
**性能优化:**
- 使用 SVG Sprite 减少 HTTP 请求
- 优化 SVG 文件大小(SVGO)
- 首屏图标内联,其他延迟加载
- 使用 gzip 压缩
**可访问性:**
- 添加 `aria-hidden="true"`(装饰性图标)
- 添加 `aria-label`(功能性图标)
- 使用 `role="img"`
- 支持键盘导航
**维护性:**
- 统一命名规范
- 使用组件封装
- 版本控制图标库
- 文档化图标使用
**响应式设计:**
- 使用 viewBox 实现响应式
- 通过 CSS 控制尺寸
- 支持不同屏幕密度
- 测试各种设备
服务端 · 2月21日 15:21
如何使用 SVG 创建图表SVG 图表是数据可视化的重要工具,可以创建各种类型的图表。以下是使用 SVG 创建图表的方法:
**1. 柱状图**
使用 `<rect>` 元素创建柱状图。
```svg
<svg width="400" height="300" viewBox="0 0 400 300">
<!-- 坐标轴 -->
<line x1="50" y1="250" x2="380" y2="250" stroke="black" stroke-width="2" />
<line x1="50" y1="50" x2="50" y2="250" stroke="black" stroke-width="2" />
<!-- 柱子 -->
<rect x="70" y="100" width="40" height="150" fill="#3498db" />
<rect x="130" y="80" width="40" height="170" fill="#e74c3c" />
<rect x="190" y="120" width="40" height="130" fill="#2ecc71" />
<rect x="250" y="60" width="40" height="190" fill="#f39c12" />
<rect x="310" y="90" width="40" height="160" fill="#9b59b6" />
<!-- 标签 -->
<text x="90" y="270" text-anchor="middle" font-size="12">Q1</text>
<text x="150" y="270" text-anchor="middle" font-size="12">Q2</text>
<text x="210" y="270" text-anchor="middle" font-size="12">Q3</text>
<text x="270" y="270" text-anchor="middle" font-size="12">Q4</text>
<text x="330" y="270" text-anchor="middle" font-size="12">Q5</text>
</svg>
```
**2. 折线图**
使用 `<polyline>` 或 `<path>` 元素创建折线图。
```svg
<svg width="400" height="300" viewBox="0 0 400 300">
<!-- 坐标轴 -->
<line x1="50" y1="250" x2="380" y2="250" stroke="black" stroke-width="2" />
<line x1="50" y1="50" x2="50" y2="250" stroke="black" stroke-width="2" />
<!-- 网格线 -->
<line x1="50" y1="200" x2="380" y2="200" stroke="gray" stroke-dasharray="5,5" />
<line x1="50" y1="150" x2="380" y2="150" stroke="gray" stroke-dasharray="5,5" />
<line x1="50" y1="100" x2="380" y2="100" stroke="gray" stroke-dasharray="5,5" />
<!-- 折线 -->
<polyline points="70,200 130,150 190,180 250,100 310,120"
fill="none" stroke="#3498db" stroke-width="3" />
<!-- 数据点 -->
<circle cx="70" cy="200" r="5" fill="#3498db" />
<circle cx="130" cy="150" r="5" fill="#3498db" />
<circle cx="190" cy="180" r="5" fill="#3498db" />
<circle cx="250" cy="100" r="5" fill="#3498db" />
<circle cx="310" cy="120" r="5" fill="#3498db" />
</svg>
```
**3. 饼图**
使用 `<path>` 元素创建饼图。
```svg
<svg width="300" height="300" viewBox="0 0 300 300">
<g transform="translate(150, 150)">
<!-- 扇形 1: 30% -->
<path d="M 0 0 L 0 -100 A 100 100 0 0 1 95.1 -30.9 Z"
fill="#3498db" />
<!-- 扇形 2: 25% -->
<path d="M 0 0 L 95.1 -30.9 A 100 100 0 0 1 58.8 80.9 Z"
fill="#e74c3c" />
<!-- 扇形 3: 20% -->
<path d="M 0 0 L 58.8 80.9 A 100 100 0 0 1 -58.8 80.9 Z"
fill="#2ecc71" />
<!-- 扇形 4: 15% -->
<path d="M 0 0 L -58.8 80.9 A 100 100 0 0 1 -95.1 -30.9 Z"
fill="#f39c12" />
<!-- 扇形 5: 10% -->
<path d="M 0 0 L -95.1 -30.9 A 100 100 0 0 1 0 -100 Z"
fill="#9b59b6" />
</g>
</svg>
```
**4. 散点图**
使用 `<circle>` 元素创建散点图。
```svg
<svg width="400" height="300" viewBox="0 0 400 300">
<!-- 坐标轴 -->
<line x1="50" y1="250" x2="380" y2="250" stroke="black" stroke-width="2" />
<line x1="50" y1="50" x2="50" y2="250" stroke="black" stroke-width="2" />
<!-- 数据点 -->
<circle cx="80" cy="200" r="5" fill="#3498db" />
<circle cx="120" cy="150" r="5" fill="#3498db" />
<circle cx="160" cy="180" r="5" fill="#3498db" />
<circle cx="200" cy="100" r="5" fill="#3498db" />
<circle cx="240" cy="120" r="5" fill="#3498db" />
<circle cx="280" cy="80" r="5" fill="#3498db" />
<circle cx="320" cy="140" r="5" fill="#3498db" />
<circle cx="360" cy="60" r="5" fill="#3498db" />
</svg>
```
**5. 面积图**
使用 `<path>` 元素创建面积图。
```svg
<svg width="400" height="300" viewBox="0 0 400 300">
<!-- 坐标轴 -->
<line x1="50" y1="250" x2="380" y2="250" stroke="black" stroke-width="2" />
<line x1="50" y1="50" x2="50" y2="250" stroke="black" stroke-width="2" />
<!-- 面积 -->
<path d="M 70 200 L 130 150 L 190 180 L 250 100 L 310 120 L 310 250 L 70 250 Z"
fill="#3498db" opacity="0.5" />
<!-- 折线 -->
<polyline points="70,200 130,150 190,180 250,100 310,120"
fill="none" stroke="#3498db" stroke-width="3" />
</svg>
```
**6. 动态图表**
使用 JavaScript 创建动态图表。
```javascript
function createBarChart(data, containerId) {
const svgNS = 'http://www.w3.org/2000/svg';
const container = document.getElementById(containerId);
const svg = document.createElementNS(svgNS, 'svg');
svg.setAttribute('width', '400');
svg.setAttribute('height', '300');
svg.setAttribute('viewBox', '0 0 400 300');
const maxValue = Math.max(...data);
const barWidth = 40;
const gap = 20;
const startX = 50;
const startY = 250;
data.forEach((value, index) => {
const height = (value / maxValue) * 200;
const x = startX + index * (barWidth + gap);
const y = startY - height;
const rect = document.createElementNS(svgNS, 'rect');
rect.setAttribute('x', x);
rect.setAttribute('y', y);
rect.setAttribute('width', barWidth);
rect.setAttribute('height', height);
rect.setAttribute('fill', `hsl(${index * 60}, 70%, 50%)`);
svg.appendChild(rect);
});
container.appendChild(svg);
}
// 使用示例
const data = [100, 150, 120, 180, 90];
createBarChart(data, 'chart-container');
```
**最佳实践:**
- 使用 viewBox 实现响应式图表
- 添加适当的标签和图例
- 使用颜色区分不同数据系列
- 考虑添加交互效果(hover、tooltip)
- 优化性能,避免过多元素
- 为图表添加可访问性支持
- 使用 CSS 动画增强视觉效果
服务端 · 2月21日 15:21
如何在响应式设计中使用 SVGSVG 在响应式设计中有独特的优势和应用方式,可以创建适应各种屏幕尺寸的图形:
**1. 使用 viewBox 实现响应式**
viewBox 是 SVG 响应式设计的核心,定义了内部坐标系。
```svg
<svg viewBox="0 0 100 100" width="100%" height="auto">
<circle cx="50" cy="50" r="40" fill="blue" />
</svg>
```
**关键点:**
- viewBox 定义内部坐标系
- width/height 使用百分比或 auto
- SVG 会根据容器自动缩放
**2. preserveAspectRatio 控制缩放行为**
控制 SVG 如何适应容器。
```svg
<!-- 保持比例,完整显示 -->
<svg viewBox="0 0 100 100" preserveAspectRatio="xMidYMid meet"
width="100%" height="100%">
<!-- 保持比例,填充容器 -->
<svg viewBox="0 0 100 100" preserveAspectRatio="xMidYMid slice"
width="100%" height="100%">
<!-- 拉伸填充 -->
<svg viewBox="0 0 100 100" preserveAspectRatio="none"
width="100%" height="100%">
```
**3. 响应式图标系统**
创建可缩放的图标系统。
```svg
<!-- 图标定义 -->
<svg style="display: none;">
<symbol id="icon-home" viewBox="0 0 24 24">
<path d="M10 20v-6h4v6h5v-8h3L12 3 2 12h3v8z"/>
</symbol>
<symbol id="icon-search" viewBox="0 0 24 24">
<path d="M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z"/>
</symbol>
</svg>
<!-- 使用图标,自动适应容器 -->
<svg class="icon" width="24" height="24">
<use href="#icon-home"/>
</svg>
<svg class="icon" width="48" height="48">
<use href="#icon-search"/>
</svg>
```
**CSS 样式:**
```css
.icon {
display: inline-block;
width: 1em;
height: 1em;
vertical-align: middle;
}
/* 不同尺寸的图标 */
.icon-sm {
width: 16px;
height: 16px;
}
.icon-md {
width: 24px;
height: 24px;
}
.icon-lg {
width: 48px;
height: 48px;
}
```
**4. 响应式图表**
创建适应屏幕的图表。
```svg
<svg viewBox="0 0 400 200" width="100%" height="auto" preserveAspectRatio="xMidYMid meet">
<!-- 柱状图 -->
<rect x="20" y="80" width="40" height="100" fill="blue" />
<rect x="80" y="50" width="40" height="130" fill="green" />
<rect x="140" y="30" width="40" height="150" fill="red" />
<rect x="200" y="60" width="40" height="120" fill="yellow" />
<!-- 坐标轴 -->
<line x1="10" y1="190" x2="390" y2="190" stroke="black" stroke-width="2"/>
<line x1="10" y1="10" x2="10" y2="190" stroke="black" stroke-width="2"/>
</svg>
```
**5. 媒体查询结合 SVG**
使用 CSS 媒体查询调整 SVG 显示。
```css
/* 小屏幕 */
@media (max-width: 768px) {
.responsive-svg {
width: 100%;
height: auto;
}
}
/* 大屏幕 */
@media (min-width: 769px) {
.responsive-svg {
width: 50%;
height: auto;
}
}
```
**6. 响应式背景 SVG**
使用 SVG 作为响应式背景。
```css
.hero-section {
background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><circle cx="50" cy="50" r="40" fill="%233498db"/></svg>');
background-size: cover;
background-position: center;
background-repeat: no-repeat;
}
```
**7. JavaScript 动态调整**
使用 JavaScript 根据容器动态调整 SVG。
```javascript
function resizeSVG() {
const container = document.querySelector('.svg-container');
const svg = container.querySelector('svg');
const containerWidth = container.offsetWidth;
const containerHeight = container.offsetHeight;
svg.setAttribute('width', containerWidth);
svg.setAttribute('height', containerHeight);
}
window.addEventListener('resize', resizeSVG);
resizeSVG(); // 初始化
```
**最佳实践:**
- 始终使用 viewBox
- 合理使用 preserveAspectRatio
- 考虑移动端性能
- 使用 CSS 控制尺寸
- 测试各种屏幕尺寸
- 优化 SVG 文件大小
服务端 · 2月21日 15:21
SVG 在移动端开发中有哪些注意事项和最佳实践SVG 在移动端的应用需要特别注意性能、兼容性和用户体验。以下是 SVG 在移动端开发的最佳实践:
**1. 响应式设计**
**使用 viewBox 实现响应式:**
```svg
<svg viewBox="0 0 100 100" width="100%" height="auto">
<circle cx="50" cy="50" r="40" fill="blue" />
</svg>
```
**使用媒体查询调整 SVG:**
```css
/* 小屏幕 */
@media (max-width: 768px) {
.mobile-svg {
width: 100%;
height: auto;
}
}
/* 大屏幕 */
@media (min-width: 769px) {
.mobile-svg {
width: 50%;
height: auto;
}
}
```
**2. 触摸事件支持**
**添加触摸事件:**
```javascript
const svg = document.querySelector('svg');
// 触摸开始
svg.addEventListener('touchstart', function(event) {
event.preventDefault();
const touch = event.touches[0];
const point = svg.createSVGPoint();
point.x = touch.clientX;
point.y = touch.clientY;
const svgPoint = point.matrixTransform(svg.getScreenCTM().inverse());
console.log('Touch start:', svgPoint);
});
// 触摸移动
svg.addEventListener('touchmove', function(event) {
event.preventDefault();
const touch = event.touches[0];
// 处理触摸移动
});
// 触摸结束
svg.addEventListener('touchend', function(event) {
event.preventDefault();
// 处理触摸结束
});
```
**3. 性能优化**
**减少元素数量:**
```svg
<!-- 优化前:多个独立元素 -->
<circle cx="10" cy="10" r="5" fill="blue" />
<circle cx="20" cy="10" r="5" fill="blue" />
<circle cx="30" cy="10" r="5" fill="blue" />
<!-- 优化后:使用 group -->
<g fill="blue">
<circle cx="10" cy="10" r="5" />
<circle cx="20" cy="10" r="5" />
<circle cx="30" cy="10" r="5" />
</g>
```
**使用 CSS 动画代替 SMIL:**
```css
/* CSS 动画(性能更好)*/
.mobile-animated {
animation: pulse 1s ease-in-out infinite;
}
@keyframes pulse {
0%, 100% { transform: scale(1); }
50% { transform: scale(1.1); }
}
```
**4. 移动端特定优化**
**优化触摸目标大小:**
```svg
<svg width="44" height="44" viewBox="0 0 24 24">
<path d="M10 20v-6h4v6h5v-8h3L12 3 2 12h3v8z"
fill="currentColor" />
</svg>
```
**使用合适的字体大小:**
```svg
<svg width="200" height="100" viewBox="0 0 200 100">
<text x="100" y="50" font-size="16" text-anchor="middle">
移动端文本
</text>
</svg>
```
**5. 电池优化**
**减少动画复杂度:**
```css
/* 简单的动画(省电)*/
.simple-anim {
animation: fade 0.3s ease;
}
@keyframes fade {
from { opacity: 0; }
to { opacity: 1; }
}
/* 避免复杂的动画(耗电)*/
.complex-anim {
/* 避免在移动端使用 */
}
```
**使用 prefers-reduced-motion:**
```css
@media (prefers-reduced-motion: reduce) {
* {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
}
}
```
**6. 网络优化**
**延迟加载非关键 SVG:**
```html
<!-- 关键 SVG 立即加载 -->
<svg class="critical" viewBox="0 0 24 24">
<path d="M10 20v-6h4v6h5v-8h3L12 3 2 12h3v8z" />
</svg>
<!-- 非关键 SVG 延迟加载 -->
<img src="non-critical.svg" loading="lazy" alt="Non-critical" />
```
**使用 SVG Sprite:**
```html
<!-- 合并多个图标 -->
<svg style="display: none;">
<symbol id="icon1" viewBox="0 0 24 24">...</symbol>
<symbol id="icon2" viewBox="0 0 24 24">...</symbol>
</svg>
<!-- 使用图标 -->
<svg><use href="#icon1" /></svg>
```
**7. 兼容性处理**
**检测 SVG 支持:**
```javascript
function supportsSVG() {
return !!document.createElementNS &&
!!document.createElementNS('http://www.w3.org/2000/svg', 'svg').createSVGRect;
}
if (!supportsSVG()) {
// 回退到 PNG
document.querySelector('.svg-icon').src = 'icon.png';
}
```
**提供回退方案:**
```html
<picture>
<source type="image/svg+xml" srcset="icon.svg" />
<img src="icon.png" alt="Icon" />
</picture>
```
**8. 可访问性**
**添加适当的 ARIA 属性:**
```svg
<svg role="img" aria-labelledby="svg-title svg-desc" tabindex="0">
<title id="svg-title">图标</title>
<desc id="svg-desc">点击打开菜单</desc>
<path d="M3 18h18v-2H3v2zm0-5h18v-2H3v2zm0-7v2h18V6H3z" />
</svg>
```
**支持屏幕阅读器:**
```javascript
const svg = document.querySelector('svg');
svg.setAttribute('role', 'img');
svg.setAttribute('aria-label', '搜索图标');
```
**9. 调试和测试**
**使用 Chrome DevTools 调试:**
- 检查渲染性能
- 监控内存使用
- 测试触摸事件
**在真实设备上测试:**
- iOS Safari
- Android Chrome
- 各种屏幕尺寸
- 不同网络条件
**最佳实践:**
- 始终使用 viewBox 实现响应式
- 优化触摸目标大小(至少 44x44px)
- 减少动画复杂度以节省电池
- 延迟加载非关键 SVG
- 提供适当的回退方案
- 添加可访问性支持
- 在真实设备上测试
- 监控性能指标
服务端 · 2月21日 15:20