javascript SVG< image>标记未导出到画布

kqlmhetl  于 2023-05-05  发布在  Java
关注(0)|答案(2)|浏览(126)

我有一个问题,通过canvas元素将带有image标签的SVG导出为PNG。如果以前有人问过这个问题,我很抱歉,但我自己找不到相关的问题。
下面的svg和代码示例应该可以更好地解释它,下面是我的SVG(我也尝试在image标签的xlink:href属性中使用URL而不是本地文件,结果相同):

<svg
  xmlns="http://www.w3.org/2000/svg"
  style="
    left: 0px;
    top: 0px;
    width: 100%;
    height: 100%;
    display: block;
    min-width: 250px;
    min-height: 190px;
  "
  viewBox="-100 -100 300 300"
>
  <g>
    <g />
    <g>
      <g style="visibility: visible">
        <image
          x="199"
          y="139"
          width="50"
          height="50"
          xmlns:xlink="http://www.w3.org/1999/xlink"
          xlink:href="http://localhost:5173/test.png"
          preserveAspectRatio="none"
          opacity="1"
        />
      </g>
      <g style="">
        <g>
          <foreignObject
            style="overflow: visible; text-align: left"
            pointer-events="none"
            width="100%"
            height="100%"
          >
            <div
              xmlns="http://www.w3.org/1999/xhtml"
              style="
                display: flex;
                align-items: unsafe center;
                justify-content: unsafe center;
                width: 48px;
                height: 1px;
                padding-top: 164px;
                margin-left: 200px;
              "
            >
              <div style="box-sizing: border-box; font-size: 0; text-align: center">
                <div
                  style="
                    display: inline-block;
                    font-size: 14px;
                    font-family: Arial, Helvetica;
                    color: #252b3a;
                    line-height: 1.2;
                    pointer-events: all;
                    white-space: normal;
                    word-wrap: break-all;
                  "
                >
                  Image Test
                </div>
              </div>
            </div>
          </foreignObject>
        </g>
      </g>
    </g>
    <g />
    <g />
  </g>
</svg>

下面是我用来将svgString加载到图像中的代码,并通过HTMLCanvasElementtoDataURL方法将其转换为dataURL:

const img = new Image();
img.onload = () => {
  // Draw the Image object onto the canvas
  const canvas = document.createElement("canvas");
  canvas.width = img.width;
  canvas.height = img.height;

  const ctx = canvas.getContext("2d");
  ctx.drawImage(img, 0, 0);

  const dataURL = canvas.toDataURL(`image/png`);
  // This dataURL does not render my image, even though it is there in the SVG
};

// Setting img's width and height according to prior calculations
img.width = width;
img.height = height;
img.src = `data:image/svg+xml;base64,${window.btoa(svgString)}`;
gopyfrb3

gopyfrb31#

我使用了Robert Longson的答案,即加载图像数据并将其转换为Base64。我是这样做到的:

function imageToDataURL(imageUrl: string): Promise<string | ArrayBuffer> {
  return fetch(imageUrl)
    .then((response) => response.blob())
    .then((blob) => {
      return new Promise((resolve, reject) => {
        const reader = new FileReader();
        reader.onloadend = function () {
          resolve(reader.result);
        };
        reader.onerror = reject;
        reader.readAsDataURL(blob);
      });
    });
}

上面的函数返回一个promise,一旦图像成功加载,它将被解析为DataURL。然后我调用它来转换SVG元素中的image标签,如下所示:

// I'm calling this in an async function, hence await is available
const images = svg.querySelectorAll("image");
for (const i in images) {
  if (Object.prototype.hasOwnProperty.call(images, i)) {
    const img = images[i];
    const imgHref = img.getAttribute("xlink:href");
    const dataURL = (await this.imageToDataURL(imgHref)) as string;
    img.setAttribute("xlink:href", dataURL);
  }
}
qmelpv7a

qmelpv7a2#

这个带花括号的美元是什么?你没提过的第三方图书馆?

img.src = `data:image/svg+xml;base64,${window.btoa(svgString)}`;

我会用这个替换非标准的JS。

img.src = 'data:image/svg+xml;base64,'+btoa(unescape(encodeURIComponent(svgString))); // <-- it has to be encoded!

但无论如何,为什么我们甚至需要这条线?是否保存到磁盘?这就是dataURL的用途!
任何渲染都应该用...

ctx.drawImage(img, 0, 0);

这就是您所需要的全部内容,因此您可以删除dataURL行。
但无论如何,问题是你的视框...你可以通过添加一个“x”来暂时禁用viewbox,你会看到你的图像…

XviewBox="-100 -100 300 300"

当我禁用viewBox时,我可以用你的脚本看到 * 我的 * 图像!
祝你好运

相关问题