繁体   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