如何更新嵌入式svg元素的来源

时间:2019-03-15 03:36:05

标签: javascript html svg

我在s3上存储了一个svg图像。像这样,我使用object标签将其嵌入网页中。

 <object
    type="image/svg+xml"
    data="https://bucket.actual_url_to_amazon_s3_bucket"
    id="graph-svg"></object>

到目前为止,很不错,很简单。现在,有时用户会进行更改,而我想向他们显示不同的svg。我只想更新对象标签的来源,就像使用img标签一样。

虽然这在技术上是可行的,并且已加载新的svg,但我遇到了奇怪的渲染问题-svg的大小全部错误并且被截断了。我发现,如果我从DOM中删除对象标签,然后更新数据,然后将其重新添加到DOM中,则呈现效果很好。

html:

<div id="svgcont">
  <object
    type="image/svg+xml"
    data="https://bucket.actual_url_to_amazon_s3_bucket.svg"
    id="graph-svg"></object>
</div> 

js:

// make an api call to get the new svg url and then:
var ob = $("#graph-svg").remove();
ob.attr("data", newSVGurl); 
$("#svgcont").prepend(ob);

如果执行上述操作,我会根据需要显示svg。但只需直接调用

ob.attr("data", newSVGurl)

是否有一种方法可以直接告诉对象“刷新您的源数据”,或者在将其插入DOM时强制其重新渲染或执行任何操作,而无需实际删除它然后重新插入它? >

删除操作的问题是它看起来很怪异和跳动,并且使图像闪光和页面上的其他项目略有跳动。因此,我希望找到看起来更平滑,更不像毛刺的东西。

1 个答案:

答案 0 :(得分:2)

我已经仔细研究了您的问题,似乎很难(也许是不可能)做得比我下面的代码要好。

我的解决方案在包装div上设置了宽度和高度,该宽度和高度等于要替换的对象的宽度和高度。然后,它将替换对象并再次删除宽度和高度。这样可以防止替换对象时文本塌陷和扩展。

不幸的是,图像本身仍然有些闪烁。我无法解决该问题。在JavaScript中创建对象而不将其附加到文档不会触发图像加载。将其附加到一个不可见的div上,然后等待load事件,然后将其移至目标div即可,但是仍然存在我试图防止的闪烁。

无论如何,这是代码。哦,这是一个Pen,具有相同的代码。 点击“替换SVG!”

urls = [
  "https://dev.w3.org/SVG/tools/svgweb/samples/svg-files/debian.svg",
  "https://dev.w3.org/SVG/tools/svgweb/samples/svg-files/ubuntu.svg",
  "https://dev.w3.org/SVG/tools/svgweb/samples/svg-files/jquery.svg",
  "https://dev.w3.org/SVG/tools/svgweb/samples/svg-files/json.svg"
];
index = 0;

let doTheBusiness = () => {
  index = index + 1 > urls.length - 1 ? 0 : index + 1;
  let url = urls[index];
  let invisibleDiv = document.getElementById("my-invisible-div");
  let newObject = document.createElement("object");
  newObject.setAttribute("type", "image/svg+xml");
  newObject.setAttribute("data", urls[index]);
  let oldObject = document.querySelector("#my-wrapper object");
  let bBox = oldObject.getBoundingClientRect();
  let w = bBox.width;
  let h = bBox.height;
  let parent = oldObject.parentNode;
  parent.style.width = `${w}px`;
  parent.style.height = `${h}px`;
  // parent.removeChild(oldObject);
  parent.replaceChild(newObject, oldObject);
  newObject.onload = () => {
    parent.style.width = null;
    parent.style.height = null;
    newObject.onload = null;
  };
};
.container {
  width: 500px;
  margin-left: auto;
  margin-right: auto;
}

#my-invisible-div {
  position: absolute;
  right: -10000px;
  top: -10000px;
}

#my-wrapper {
  padding: 0px;
}

object {
  width: 100%;
}
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
</head>

<body>
  <div class="container">
    <button onclick="doTheBusiness()">Replace SVG!</button>
    <p>Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It
      has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop
      publishing software like Aldus PageMaker including versions of Lorem Ipsum.
    </p>
    <div id="my-wrapper">
      <object type="image/svg+xml" data="https://dev.w3.org/SVG/tools/svgweb/samples/svg-files/debian.svg"></object>
    </div>
    <p>
      It is a long established fact that a reader will be distracted by the readable content of a page when looking at its layout. The point of using Lorem Ipsum is that it has a more-or-less normal distribution of letters, as opposed to using 'Content here,
      content here', making it look like readable English. Many desktop publishing packages and web page editors now use Lorem Ipsum as their default model text, and a search for 'lorem ipsum' will uncover many web sites still in their infancy. Various
      versions have evolved over the years, sometimes by accident, sometimes on purpose (injected humour and the like).
    </p>
  </div>
  <div id="my-invisible-div">

  </div>
</body>

</html>