首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >我做了一个SVG-to-PNG在线转换工具,无限免费,附代码

我做了一个SVG-to-PNG在线转换工具,无限免费,附代码

作者头像
Ai学习的老章
发布2026-01-13 19:56:33
发布2026-01-13 19:56:33
1360
举报

为什么做这个工具?

最近在做知识卡片时遇到了一个问题:我用 SVG 制作的精美卡片,里面用了 foreignObject 嵌入 HTML 内容来实现自动换行,效果非常好。

但当我想把这些 SVG 转成 PNG 分享到社交媒体时,傻眼了:

rsvg-convert 不支持 foreignObject!

试了各种命令行工具,要么文字丢失,要么布局错乱。

Chrome 的 headless 截图呢?尺寸又不精确,需要各种 hack。

于是我花了一天时间,做了这个工具。

在线体验

完全免费,无需登录,开源透明。

功能特点

  • 完美支持 foreignObject - 基于 Puppeteer 真实渲染
  • 📦 批量转换 - 最多 50 个文件同时处理,打包 ZIP 下载
  • 🔥 高清输出 - 支持 1x / 2x / 3x 倍率
  • 🎨 拖拽上传 - 现代化交互体验
  • 💯 完全免费 - 没有水印,没有限制

技术原理

核心思路很简单:

  1. 把 SVG 嵌入到一个精确尺寸的 HTML 页面中
  2. 用 Puppeteer 启动无头浏览器渲染
  3. 截图导出为 PNG

关键代码:

代码语言:javascript
复制
const puppeteer = require('puppeteer');

asyncfunction convertSvgToPng(svgContent, scale = 2) {
// 从 SVG 提取尺寸
const { width, height } = extractDimensions(svgContent);

const browser = await puppeteer.launch({
    headless: true,
    args: ['--no-sandbox', '--disable-setuid-sandbox']
  });

const page = await browser.newPage();

// 设置精确视口
await page.setViewport({
    width: width,
    height: height,
    deviceScaleFactor: scale  // 2x 高清
  });

// 创建 HTML 包装器
const html = `
<!DOCTYPE html>
<html>
<head>
  <style>
    * { margin: 0; padding: 0; }
    html, body {
      width: ${width}px;
      height: ${height}px;
      overflow: hidden;
      font-family: -apple-system, "PingFang SC", sans-serif;
    }
  </style>
</head>
<body>${svgContent}</body>
</html>`;

await page.setContent(html, { waitUntil: 'networkidle0' });
await page.evaluate(() =>document.fonts.ready);

const pngBuffer = await page.screenshot({
    type: 'png',
    clip: { x: 0, y: 0, width, height }
  });

await browser.close();
return pngBuffer;
}

开源地址

GitHub:github.com/tjxj/svg2png

欢迎 Star ⭐️ 和 PR!

本地运行

代码语言:javascript
复制
git clone https://github.com/tjxj/svg2png.git
cd svg2png
npm install
npm run dev
# 访问 http://localhost:3000

部署

推荐部署到 Railway 或 Render,它们原生支持 Puppeteer:

代码语言:javascript
复制
# Railway
railway up

# Render
# 连接 GitHub 仓库即可

彩蛋:macOS Quick Action

除了 Web 版,我还做了一个 macOS 右键菜单工具。

在 Finder 里右键点击 SVG 文件,选择「快速操作」→「SVG to PNG」,秒转!

Quick Action 演示

完整搭建教程

1. 创建项目目录
代码语言:javascript
复制
mkdir -p ~/svg-to-png-quickaction
cd ~/svg-to-png-quickaction
2. 创建 package.json
代码语言:javascript
复制
{
  "name": "svg-to-png-quickaction",
  "version": "1.0.0",
  "description": "macOS Quick Action - SVG to PNG 转换器",
  "main": "convert.js",
  "dependencies": {
    "puppeteer": "^24.0.0"
  }
}
3. 创建转换脚本 convert.js
代码语言:javascript
复制
#!/usr/bin/env node
/**
 * SVG to PNG 转换脚本
 * 用于 macOS Quick Action
 */

const puppeteer = require('puppeteer');
const fs = require('fs');
const path = require('path');

asyncfunction convertSvgToPng(svgPath) {
const svgContent = fs.readFileSync(svgPath, 'utf8');

// 从 SVG 提取尺寸
const viewBoxMatch = svgContent.match(/viewBox=["']([^"']+)["']/);
const widthMatch = svgContent.match(/width=["'](\d+)/);
const heightMatch = svgContent.match(/height=["'](\d+)/);

let width = 900, height = 1200;

if (viewBoxMatch) {
    const parts = viewBoxMatch[1].split(/\s+/).map(Number);
    width = parts[2] || width;
    height = parts[3] || height;
  } else {
    width = widthMatch ? parseInt(widthMatch[1]) : width;
    height = heightMatch ? parseInt(heightMatch[1]) : height;
  }

const browser = await puppeteer.launch({
    headless: true,
    args: ['--no-sandbox', '--disable-setuid-sandbox']
  });

const page = await browser.newPage();

await page.setViewport({
    width: width,
    height: height,
    deviceScaleFactor: 2
  });

const html = `
<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <style>
    * { margin: 0; padding: 0; box-sizing: border-box; }
    html, body {
      width: ${width}px;
      height: ${height}px;
      overflow: hidden;
      font-family: -apple-system, BlinkMacSystemFont, "PingFang SC", sans-serif;
    }
    svg { display: block; width: ${width}px; height: ${height}px; }
  </style>
</head>
<body>${svgContent}</body>
</html>`;

await page.setContent(html, { waitUntil: 'networkidle0' });
await page.evaluate(() =>document.fonts.ready);
awaitnewPromise(resolve => setTimeout(resolve, 300));

const pngPath = svgPath.replace(/\.svg$/i, '.png');

await page.screenshot({
    path: pngPath,
    type: 'png',
    clip: { x: 0, y: 0, width, height }
  });

await browser.close();
return pngPath;
}

asyncfunction main() {
const args = process.argv.slice(2);

if (args.length === 0) {
    console.error('用法:node convert.js <svg 文件路径>');
    process.exit(1);
  }

const svgFiles = args.filter(f => f.endsWith('.svg') && fs.existsSync(f));

console.log(`开始转换 ${svgFiles.length} 个文件...`);

for (const svgPath of svgFiles) {
    try {
      const pngPath = await convertSvgToPng(svgPath);
      console.log(`✅ ${path.basename(svgPath)} → ${path.basename(pngPath)}`);
    } catch (error) {
      console.error(`❌ ${path.basename(svgPath)}: ${error.message}`);
    }
  }

console.log('转换完成!');
}

main().catch(console.error);
4. 安装依赖
代码语言:javascript
复制
npm install
chmod +x convert.js
5. 创建 Quick Action
  1. 打开 Automator(Cmd + Space 搜索 "Automator")
  2. 选择「Quick Action」
  3. 配置顶部选项
    • 工作流程收到当前:文件或文件夹
    • 位于:Finder.app
  4. 添加「Run Shell Script」动作
    • Shell:/bin/bash
    • 传递输入:作为自变量
  5. 粘贴以下脚本
代码语言:javascript
复制
export PATH="/opt/homebrew/bin:/usr/local/bin:$PATH"
SCRIPT_DIR="$HOME/svg-to-png-quickaction"

for f in "$@"; do
    if [[ "$f" == *.svg ]]; then
        node "$SCRIPT_DIR/convert.js" "$f"
    fi
done

osascript -e 'display notification "SVG 转换完成!" with title "SVG to PNG"'
  1. 保存(Cmd + S),命名为 SVG to PNG

使用方法

  1. 在 Finder 中找到 SVG 文件
  2. 右键点击快速操作SVG to PNG
  3. PNG 文件会生成在同一目录下
  4. 屏幕右上角会弹出通知

支持批量转换

选中多个 SVG 文件,右键,同样的操作,一次全部转换!

最后

这个小工具解决了我的实际痛点,希望对你也有帮助。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2026-01-13,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 机器学习与统计学 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 为什么做这个工具?
  • 在线体验
    • 功能特点
  • 技术原理
  • 开源地址
    • 本地运行
    • 部署
  • 彩蛋:macOS Quick Action
    • 完整搭建教程
      • 1. 创建项目目录
      • 2. 创建 package.json
      • 3. 创建转换脚本 convert.js
      • 4. 安装依赖
      • 5. 创建 Quick Action
    • 使用方法
    • 支持批量转换
  • 最后
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档