将单个 SVG 元素呈现为 canvas 或图像

Render a single SVG element to canvas or image

如何将单个 SVG 元素(而不是整个 SVG 文档或其中的一部分)呈现为图像或 canvas?

我有一个包含很多节点的 SVG 文档。如果我渲染整个 SVG 或其中的一部分,生成的图像将包含我不感兴趣的其他图形。我对一个特定的 SVG 元素感兴趣,并且想渲染所有它而不用其他任何东西。

示例:

<!DOCTYPE html>
<html>
<body>

  <svg height="150" width="150">
    <circle cx="50" cy="50" r="25" stroke="green" stroke-width="3" fill="gray" />
    <circle id="IWantToRenderThis" cx="75" cy="75" r="25" stroke="red" stroke-width="3" fill="white" />
    <circle cx="100" cy="100" r="25" stroke="blue" stroke-width="3" fill="black" />
  </svg>

  <script>
    const target = document.getElementById("IWantToRenderThis");
    // how can I render *target* into a texture?
  </script>

</body>
</html>

如何单独渲染 target?我想获得一张没有其他两个圆圈痕迹的图像,一个透明的背景,并且尺寸合适target

您可以删除所有元素,但要呈现的元素除外。 要使 SVG 适合剩余元素,您需要计算新的位置和大小。对于您的示例,代码可能如下所示:

<!DOCTYPE html>
<html>
<body>

  <svg height="150" width="150" id="svg">
    <circle cx="50" cy="50" r="25" stroke="green" stroke-width="3" fill="gray" />
    <circle id="IWantToRenderThis" cx="75" cy="75" r="25" stroke="red" stroke-width="3" fill="white" />
    <circle cx="100" cy="100" r="25" stroke="blue" stroke-width="3" fill="black" />
  </svg>

  <script>
    const svg = document.getElementById("svg");
    const target = document.getElementById("IWantToRenderThis");
    const children = svg.children;
    
    // Remove all child elements but the target
    for(let index = 0; index < children.length; index++) {
      const child = children[index];
            if(child.id !== 'IWantToRenderThis') {
        child.remove()
      }
    }
    
    // Recalculate element position and svg size
    const targetSize = parseInt(target.getAttribute('r'))    
    const targetStroke = parseInt(target.getAttribute('stroke-width'))
    target.setAttribute('cx', targetSize + (targetStroke/2))
    target.setAttribute('cy', targetSize + (targetStroke/2))
    
    svg.setAttribute('width', targetSize*2 + targetStroke)
    svg.setAttribute('height', targetSize*2 + targetStroke)
  </script>

</body>
</html>

请注意,您必须包括元素的笔划宽度才能正确计算其新位置和 SVG 的新大小。

这里只是使用 outerHTML 将目标元素复制到表示新 SVG 的新数据 URL 中,加载到图像对象中,在 canvas 中绘制并导出为PNG 图片。

let img = document.getElementById('img');
let target = document.getElementById("IWantToRenderThis");
let svg = target.closest('svg');
let width = svg.attributes['width'].value;
let height = svg.attributes['height'].value;
let image = new Image();
let canvas = document.getElementById('canvas');
canvas.height = height;
canvas.width = width;
let ctx = canvas.getContext('2d');

image.addEventListener('load', e => {
  ctx.drawImage(e.target, 0, 0, e.target.width, e.target.height);
  img.src = canvas.toDataURL("image/png");
});
image.src = `data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg"
             width="${width}" height="${height}">${target.outerHTML}</svg>`;
<p>Original SVG:</p>
<svg id="svg" height="150" width="150">
  <circle cx="50" cy="50" r="25" stroke="green" stroke-width="3" fill="gray" />
  <circle id="IWantToRenderThis" cx="75" cy="75" r="25" stroke="red" stroke-width="3" fill="white" />
  <circle cx="100" cy="100" r="25" stroke="blue" stroke-width="3" fill="black" />
</svg>
<p>SVG rendered in canvas:</p>
<canvas id="canvas"></canvas>
<p>PNG image based on canvas:</p>
<img id="img" />