簡體   English   中英

用 Javascript 修改 Canvas SVG 圖片

[英]Modify Canvas SVG Image with Javascript

我有一張 svg 圖像,可以用來繪制到 canvas:

    image = new Image()
    image.src = "image.svg"

是否可以修改image ,例如,更改元素的顏色?

加載SVG

您可以使用提取 function 而不是將 SVG 直接加載到圖像元素中。這里的數據 URL 僅用於示例——它可以被 URL 替換。此時您可以將 SVG 存儲在變量中。

解析 SVG

要更改 SVG ,一種方法是使用XPath 這就是 function changeAttribute() 中發生的情況,它采用 SVG、XPath 表達式和包含有關更改內容的數據的 object。

將 SVG 加載到圖像元素中並在 canvas 中渲染

當我閱讀您的問題時,您已經明白了這一點。 在 function insertIntoCanvas() 中,使用FileReader將 SVG(XML 文檔)轉換為數據 URL。 之后創建圖像並在 canvas 上繪制。

 const canvas = document.getElementById('canvas'); const ctx = canvas.getContext('2d'); fetch('data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMTAgMTAiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CiAgPHBhdGggZD0iTSA1IDAgTCAwIDUgTCA1IDEwIEwgMTAgNSBaIiAvPgo8L3N2Zz4=').then(response => response.text()).then(text => { let xmlDoc = new DOMParser().parseFromString(text,'text/xml'); changeAttribute(xmlDoc, '//svg:path', {fill:'red'}); changeAttribute(xmlDoc, '//svg:svg', {width:100, height:100}); insertIntoCanvas(xmlDoc); }); function insertIntoCanvas(xmlDoc){ let file = new File([xmlDoc.rootElement.outerHTML], 'svg.svg', { type: "image/svg+xml" }); // and a reader let reader = new FileReader(); reader.addEventListener('load', e => { /* create a new image assign the result of the filereader to the image src */ let img = new Image(); // wait for it to got load img.addEventListener('load', e => { // update canvas with new image ctx.clearRect(0, 0, canvas.width, canvas.height); ctx.drawImage(e.target, 0, 0); }); img.src = e.target.result; }); // read the file as a data URL reader.readAsDataURL(file); } function changeAttribute(doc, xpath, obj) { let r = doc.evaluate(xpath, doc, nsResolver, XPathResult.ANY_TYPE, null); let nodes = []; let next = r.iterateNext(); while (next) { nodes.push(next); next = r.iterateNext(); } nodes.forEach(node => { Object.keys(obj).forEach(key => { node.setAttribute(key, obj[key]); }); }); } function nsResolver(prefix) { const ns = { 'xhtml': 'http://www.w3.org/1999/xhtml', 'svg': 'http://www.w3.org/2000/svg' }; return ns[prefix] || null; }
 canvas { border: thin solid black; }
 <canvas id="canvas" width="300" height="200"></canvas>

你必須:

  • 外部SVG 文件加載為文本
  • 將其注入到 shadowDOM 中(瀏覽器將進行解析)
  • 添加你的<style>元素
  • 提取 SVG outerHTML
  • 替換無效的 URI 字符"#
  • 創建一個<canvas>
  • 將 SVG 寫入canvas.img為 XML DataURI
  • 將你的<canvas>添加到 shadowDOM
    或替換為完成工作的replaceWith組件

所有現代瀏覽器都支持的原生 JavaScript Web 組件<svg-to-canvas>
它能為你做所有事情嗎,所以你只寫:

<svg-to-canvas src="//load-file.github.io/heart.svg">
  <style>
    svg  { background:green }
    path { fill:red }
  </style>
</svg-to-canvas>

JSFiddle: https://jsfiddle.net/WebComponents/cosfrqyv/

StackOverflow 片段:

 <style> svg-to-canvas { background: lightgreen } canvas { background:pink } </style> <svg-to-canvas src="//load-file.github.io/heart.svg"> <style> svg { background:green } path { fill:red } </style> </svg-to-canvas> <svg-to-canvas replaceWith src="//load-file.github.io/heart.svg"></svg-to-canvas> <script> customElements.define("svg-to-canvas", class extends HTMLElement { async connectedCallback(svg,canvas,img) { this.style.display = "inline-block"; this.attachShadow({mode:"open"}).innerHTML = await (await fetch(this.getAttribute("src"))).text(); svg = this.shadowRoot.querySelector("svg"); svg.append(...this.querySelectorAll("*")); // stop here for an SVG inside shadowDOM canvas = document.createElement('canvas'); img = Object.assign(new Image(), { onload: () => { canvas.width = img.width; canvas.height = img.height; canvas.getContext('2d').drawImage(img, 0, 0); }, src: "data:image/svg+xml;utf8," + svg.outerHTML.replace(/"/g, "'").replace(/#/g, "%23") }); if (this.hasAttribute("replaceWith")) this.replaceWith(canvas); else { svg.remove(); this.shadowRoot.append(canvas) } } }) </script>

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM