如何在Canvas已有内容上绘制SVG?保留背景
解决Canvas蓝色圆形背景上居中嵌入SVG的问题
当前代码的问题在于:Canvg渲染SVG时默认会清空画布,覆盖了预先绘制的蓝色圆形;同时SVG没有根据画布尺寸做缩放和居中处理,导致只显示SVG。以下是修复方案:
修改Worker内的代码
核心调整点:
- 禁用Canvg的自动清空画布行为
- 对SVG进行缩放适配,确保它能居中显示在蓝色圆形内部
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') // 1. 绘制蓝色圆形背景 ctx.beginPath() ctx.arc(width/2, height/2, Math.min(width, height)/2, 0, 2 * Math.PI) ctx.fillStyle = 'blue' ctx.fill() // 2. 配置Canvg,禁止清空画布,使用自定义尺寸实现居中缩放 const v = await Canvg.from(ctx, svg, { ...preset, ignoreClear: true, // 关键:保留已绘制的背景 ignoreDimensions: true, // 不使用SVG自身尺寸,改用画布适配规则 scaleWidth: width * 0.8, // SVG缩放到画布的80%,避免超出圆形边界 scaleHeight: height * 0.8, offsetX: (width - width*0.8)/2, // 水平居中偏移 offsetY: (height - height*0.8)/2 // 垂直居中偏移 }) await v.render() const blob = await canvas.convertToBlob() const pngUrl = URL.createObjectURL(blob) self.postMessage({ pngUrl }) }
主代码无需修改
const svg = `<svg xmlns="http://www.w3.org/2000/svg" fill="#ff0000" 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; };
效果说明
修改后,Canvas会先绘制蓝色圆形作为背景,再将SVG缩放到圆形内部的80%大小,并居中显示,最终呈现蓝色圆形包裹红色SVG的效果。
内容的提问来源于stack exchange,提问作者Eric G
相关产品推荐
相关产品推荐

