我正在嘗試通過 HTML5 Canvas 將生成的 SVG 轉換為 PNG/JPG。到目前為止,除了一個例外,該方法適用于我向它拋出的所有內容。當源 SVG 中的元素具有clip-path屬性時,canvas.toDataURL()回傳空 url(即data;)。
這些是我用來執行轉換的相關函式。
// expects svg dataurl
// returns a dataurl
async function _svgToRasterImage(url, options) {
const image = await _svgToImageElement(url)
const context = document.createElement('canvas').getContext('2d', {
antialias: options.rasterAA
})
context.canvas.width = options.rasterW || image.width
context.canvas.height = options.rasterH || image.height
context.drawImage(image,
0, 0, image.width, image.height,
0, 0, context.canvas.width, context.canvas.height
)
return context.canvas.toDataURL(
options.rasterTarget,
options.rasterQuality
)
}
// expects svg dataurl
// returns an SVGImageElement
function _svgToImageElement(url) {
return new Promise(async (resolve) => {
const image = new Image()
image.addEventListener(
'load',
resolve(image),
{ once: true }
)
image.src = url
})
}
這是一個有問題的 SVG 示例(我已經縮寫了一些嵌入元素,例如href="data:image/png;base64,...")。
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:svgjs="http://svgjs.dev/svgjs" width="180" height="252">
<svg width="180" height="252" x="0" y="0">
<g>
<rect width="162" height="226.8" x="9" y="12.600000000000001" fill-opacity="0" rx="7.2" ry="7.2" stroke-width="7.2" stroke="#00ff00"/>
</g>
<g>
<ellipse rx="81" ry="113.4" cx="90" cy="126" fill-opacity="0" stroke-width="7.2" stroke="#0000ff"/>
</g>
<g clip-path="url("#SvgjsClipPath1009")">
<image width="256" height="256" xlink:href="data:image/png;base64,..." transform="matrix(0.6328125,0,0,0.6328125,9,45.00000000000001)"/>
</g>
</svg>
<defs>
<clipPath id="SvgjsClipPath1009">
<rect width="162" height="226.8" x="9" y="12.600000000000001"/>
</clipPath>
</defs>
</svg>
雖然我不確定,但我相信上面的 SVG 是有效的,因為它在 Chrome 和 Firefox 的 DOM 中都能正確呈現;但是,很可能我遺漏了瀏覽器忽略的明顯內容(或在這種情況下為我修復)!
uj5u.com熱心網友回復:
感謝@Kaiido的幫助!
您的影像加載器有一個錯誤,它在呼叫 resolve(img) 之前沒有等待影像加載,而是將此呼叫的結果設定為事件的處理程式,從而直接呼叫它。
解決方案是在事件偵聽器的回呼中使用箭頭函式,因為resolve(image)直接呼叫將立即執行,在影像實際加載之前決議承諾。
function _svgToImageElement(url) {
return new Promise(async (resolve) => {
const image = new Image()
image.addEventListener(
'load',
e => resolve(image), // <-- DO
// resolve(image), <-- DON'T
{ once: true }
)
image.src = url
})
}
令人驚訝的是,缺少 3 個字符會造成多大的痛苦。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/536438.html
