[英]Modify Canvas SVG Image with Javascript
我有一张 svg 图像,可以用来绘制到 canvas:
image = new Image()
image.src = "image.svg"
是否可以修改image
,例如,更改元素的颜色?
您可以使用提取 function 而不是将 SVG 直接加载到图像元素中。这里的数据 URL 仅用于示例——它可以被 URL 替换。此时您可以将 SVG 存储在变量中。
要更改 SVG ,一种方法是使用XPath 。 这就是 function changeAttribute() 中发生的情况,它采用 SVG、XPath 表达式和包含有关更改内容的数据的 object。
当我阅读您的问题时,您已经明白了这一点。 在 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>
你必须:
<style>
元素outerHTML
<canvas>
canvas.img
为 XML DataURI<canvas>
添加到 shadowDOMreplaceWith
组件所有现代浏览器都支持的原生 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>
<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.