SVG 工具
概述
本文档介绍了一组用于处理 SVG(可缩放矢量图形)的实用工具函数。这些函数主要用于 SVG 转换、样式操作等场景,可以帮助开发者在前端应用中灵活处理 SVG 图像。
函数详解
1. SVG 转 PNG - convertSvgToPng
将 SVG 元素转换为 PNG 格式的 base64 数据 URL。
函数签名
typescript
async function convertSvgToPng(svg: HTMLElement, scale: number = 2): Promise<string>参数
svg: SVG 元素,可以是 SVGSVGElement 或包含 SVG 的 HTML 元素scale: 可选参数,输出图像的缩放比例,默认值为 2
返回值
返回一个 Promise,解析为 PNG 格式的 base64 数据 URL 字符串。
工作原理
- 检查并获取 SVG 内容
- 创建 Canvas 元素并获取 2D 上下文
- 将 SVG 字符串转换为 base64 格式的 data URL
- 创建 Image 对象并加载 SVG 数据
- 设置 Canvas 大小,考虑缩放比例和设备像素比
- 设置白色背景并将 SVG 绘制到 Canvas
- 将 Canvas 内容转换为 PNG 格式的 data URL
使用示例
javascript
import { convertSvgToPng } from '@pt/utils/modules/svg';
// 示例 1: 转换页面中的 SVG 元素
const svgElement = document.querySelector('svg');
try {
const pngDataUrl = await convertSvgToPng(svgElement);
// 创建下载链接
const link = document.createElement('a');
link.href = pngDataUrl;
link.download = 'image.png';
link.click();
} catch (error) {
console.error('SVG 转换失败:', error);
}
// 示例 2: 使用自定义缩放比例
const svgContainer = document.getElementById('chart-container');
const highResPng = await convertSvgToPng(svgContainer, 4); // 4倍缩放2. 移除 SVG 样式 - removeSvgStyle
从 SVG 字符串中移除 SVG 标签上的 style 属性。
函数签名
typescript
function removeSvgStyle(svgString: string): string参数
svgString: 包含 SVG 标记的字符串
返回值
返回移除 style 属性后的 SVG 字符串。
工作原理
使用正则表达式找到 SVG 标签中的 style 属性并将其移除。
使用示例
javascript
import { removeSvgStyle } from '@pt/utils/modules/svg';
// 原始 SVG 字符串
const originalSvg = '<svg width="100" height="100" style="background-color: blue;">';
// 移除样式
const cleanedSvg = removeSvgStyle(originalSvg);
console.log(cleanedSvg); // 输出: '<svg width="100" height="100">'3. 替换 SVG 样式 - replaceSvgStyles
替换 SVG 字符串中的所有 style 属性值。
函数签名
typescript
function replaceSvgStyles(svgContent: string, newStyle: string): string参数
svgContent: 包含 SVG 标记的字符串newStyle: 新的样式字符串,将替换现有的 style 属性值
返回值
返回替换样式后的 SVG 字符串。
工作原理
使用正则表达式找到所有 style 属性并替换其值为指定的新样式。
使用示例
javascript
import { replaceSvgStyles } from '@pt/utils/modules/svg';
// 原始 SVG 字符串
const originalSvg = '<svg width="100" height="100" style="background-color: blue;"><rect style="fill: red;"></rect></svg>';
// 替换所有样式
const newSvg = replaceSvgStyles(originalSvg, "background-color: white; border: 1px solid gray;");
console.log(newSvg);
// 输出: '<svg width="100" height="100" style="background-color: white; border: 1px solid gray;"><rect style="background-color: white; border: 1px solid gray;"></rect></svg>'实际应用场景
场景一:导出 SVG 图表为图片
javascript
import { convertSvgToPng } from '@pt/utils/modules/svg';
// 假设您使用了 D3.js 或 Chart.js 创建了一个 SVG 图表
const chartSvg = document.getElementById('chart');
// 添加导出按钮
const exportButton = document.getElementById('export-button');
exportButton.addEventListener('click', async () => {
try {
// 转换为高分辨率 PNG
const pngUrl = await convertSvgToPng(chartSvg, 3);
// 创建下载链接
const link = document.createElement('a');
link.href = pngUrl;
link.download = 'chart-export.png';
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
} catch (error) {
console.error('导出失败:', error);
alert('图表导出失败,请重试!');
}
});场景二:动态主题切换
javascript
import { replaceSvgStyles } from '@pt/utils/modules/svg';
// 主题样式映射
const themeStyles = {
light: 'background-color: white; color: black;',
dark: 'background-color: #333; color: white;',
blue: 'background-color: #e6f7ff; color: #0066cc;'
};
// 主题切换函数
function changeTheme(themeName) {
// 获取所有 SVG 元素
const svgElements = document.querySelectorAll('svg');
svgElements.forEach(svg => {
// 获取原始 SVG 内容
const svgString = svg.outerHTML;
// 替换样式
const newSvgString = replaceSvgStyles(svgString, themeStyles[themeName]);
// 更新 SVG 内容
svg.outerHTML = newSvgString;
});
}
// 使用示例
document.getElementById('theme-selector').addEventListener('change', (e) => {
changeTheme(e.target.value);
});场景三:创建干净的 SVG 以便应用自定义样式
javascript
import { removeSvgStyle } from '@pt/utils/modules/svg';
// 从外部来源获取 SVG
async function fetchAndCleanSvg(url) {
try {
const response = await fetch(url);
const svgText = await response.text();
// 移除原始样式
const cleanSvg = removeSvgStyle(svgText);
// 将干净的 SVG 插入到页面
document.getElementById('svg-container').innerHTML = cleanSvg;
// 现在可以通过 CSS 应用自定义样式
} catch (error) {
console.error('获取或处理 SVG 失败:', error);
}
}
// 使用示例
fetchAndCleanSvg('/assets/icons/chart.svg');注意事项
浏览器兼容性:
- 这些函数使用了现代 DOM API 和 Canvas API,支持大多数现代浏览器
- 在 IE11 等旧浏览器中可能需要使用 polyfill
SVG 复杂性:
- 复杂的 SVG(包含滤镜、动画等)在转换为 PNG 时可能会出现渲染差异
- 外部引用的资源(如外部 CSS 或图像)可能不会正确转换
安全考虑:
- 处理用户提供的 SVG 时应注意 XSS 安全风险
- SVG 可以包含 JavaScript 代码,应避免直接加载不可信的 SVG
性能:
- 大尺寸或复杂的 SVG 转换为 PNG 可能会占用较多内存和处理时间
- 使用合理的缩放比例,避免生成过大的图像
依赖项:
convertSvgToPng函数依赖js-base64库进行 base64 编码
兼容性特别处理
convertSvgToPng 函数中包含了几个特别的兼容性处理:
- 修复自闭合标签:将
<br>替换为<br/> - 修复 img 标签:确保所有 img 标签都是正确的自闭合格式
- 添加 XML 声明:确保 SVG 内容有正确的 XML 声明
- 考虑设备像素比:适应高 DPI 显示器
这些处理使得该函数在各种环境下都能可靠工作。