使用canvg在Web Worker中绘制SVG时,如何不修改SVG或CSS更改颜色?
问题
我正在Web Worker中使用canvg将SVG绘制到OffscreenCanvas中。当前SVG默认以黑色绘制,请问是否可以在不修改SVG本身或使用CSS的情况下为其设置颜色(例如红色)?如果可以,具体该如何操作?
代码示例
主页面脚本
const svg = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--!Font Awesome Free 6.7.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2024 Fonticons, Inc.--><path d="M256 0c17.7 0 32 14.3 32 32l0 10.4c93.7 13.9 167.7 88 181.6 181.6l10.4 0c17.7 0 32 14.3 32 32s-14.3 32-32 32l-10.4 0c-13.9 93.7-88 167.7-181.6 181.6l0 10.4c0 17.7-14.3 32-32 32s-32-14.3-32-32l0-10.4C130.3 455.7 56.3 381.7 42.4 288L32 288c-17.7 0-32-14.3-32-32s14.3-32 32-32l10.4 0C56.3 130.3 130.3 56.3 224 42.4L224 32c0-17.7 14.3-32 32-32zM107.4 288c12.5 58.3 58.4 104.1 116.6 116.6l0-20.6c0-17.7 14.3-32 32-32s32 14.3 32 32l0 20.6c58.3-12.5 104.1-58.4 116.6-116.6L384 288c-17.7 0-32-14.3-32-32s14.3-32 32-32l20.6 0C392.1 165.7 346.3 119.9 288 107.4l0 20.6c0 17.7-14.3 32-32 32s-32-14.3-32-32l0-20.6C165.7 119.9 119.9 165.7 107.4 224l20.6 0c17.7 0 32 14.3 32 32s-14.3 32-32 32l-20.6 0zM256 224a32 32 0 1 1 0 64 32 32 0 1 1 0-64z"/></svg>`; var blob = new Blob( Array.prototype.map.call( document.querySelectorAll('script[type="text/js-worker"]'), function (oScript) { return oScript.textContent; } ), { type: "text/javascript" } ); const worker = new Worker(window.URL.createObjectURL(blob), { type: "module" }); const img = document.querySelector('img') worker.postMessage({ width: 20, height: 20, svg: svg }) worker.onmessage = (event) => { img.src = event.data.pngUrl }
Worker脚本
import { DOMParser } from 'https://cdn.skypack.dev/@xmldom/xmldom@^0.7.5' import { Canvg, presets } from 'https://cdn.skypack.dev/canvg@^4.0.0' const preset = presets.offscreen({ DOMParser }) self.onmessage = async (event) => { const { width, height, svg } = event.data const canvas = new OffscreenCanvas(width, height) const ctx = canvas.getContext('2d') const v = await Canvg.from(ctx, svg, preset) // Render only first frame, ignoring animations and mouse. await v.render() const blob = await canvas.convertToBlob() const pngUrl = URL.createObjectURL(blob) self.postMessage({ pngUrl }) }
HTML页面
<script type="text/js-worker"> <!-- 上述Worker脚本内容 --> </script> <img />
解决方案
可以实现,无需修改SVG本身或额外CSS,利用canvg的渲染回调或配置项即可动态覆盖颜色,以下是两种可行方法:
方法1:使用render回调强制覆盖元素样式
在调用v.render()时传入apply回调,针对所有路径元素设置填充色:
修改Worker中的渲染代码:
// 替换原有的await v.render() await v.render({ apply: (node, ctx) => { // 对所有path元素设置红色填充 if (node.tagName === 'path') { ctx.fillStyle = '#ff0000'; // 如果SVG包含描边,可同时设置描边色 // ctx.strokeStyle = '#ff0000'; } } });
方法2:通过canvg全局配置设置默认颜色
创建Canvg实例时,通过options设置全局默认填充样式:
修改Worker中的Canvg初始化代码:
const v = await Canvg.from(ctx, svg, { ...preset, defaultStyle: { fill: '#ff0000' // 可选:设置全局默认描边色 // stroke: '#ff0000' } });
说明
- 方法1优先级更高,即使SVG本身带有
fill属性,也会被强制覆盖; - 方法2会设置全局默认样式,仅对未指定颜色的SVG元素生效;
- 两种方法都不会修改原始SVG内容,仅在渲染阶段动态调整颜色。
内容的提问来源于stack exchange,提问作者Eric G
相关产品推荐
相关产品推荐

