как обновить источник встроенного элемента SVG - PullRequest
3 голосов
/ 15 марта 2019

У меня есть изображение svg, сохраненное на s3.Я встраиваю его в веб-страницу с помощью тега 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 Ответ

2 голосов
/ 20 марта 2019

Я подробно рассмотрел ваш вопрос, и мне кажется, что трудно (возможно, невозможно) добиться большего успеха, чем то, что я придумал с кодом ниже.

Мое решение устанавливает ширину и высоту дляdiv, который равен ширине и высоте заменяемого объекта.Затем он заменяет объект и снова удаляет ширину и высоту.Это предотвращает свертывание и расширение текста при замене объектов.

Само изображение, к сожалению, все еще несколько мерцает.Я не смог решить эту проблему.Создание объекта в JavaScript без добавления его в документ не вызывает загрузку изображения.Добавление его к невидимому div и ожидание события загрузки, а затем перемещение его к целевому div работает, но все еще имеет мерцание, которое я пытался предотвратить.

В любом случае, вот код.Ох, а вот и ручка с тем же кодом.Нажмите «Заменить 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>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...