Конвертировать рендеринг SVG-изображения во встроенный SVG без перезагрузки внешнего файла? - PullRequest
0 голосов
/ 14 марта 2019

Эти два вопроса, здесь и здесь , похожи, но не совпадают.

Предположим, что такой элемент связан с внешним SVG-изображением:

<div style="background-image: url("/images/tags/icon/star.svg");"></div>

Если изображение уже отображается как фоновое изображение, каковы варианты преобразования этого SVG-изображения во встроенный SVG (в другом месте документа)?

Является ли единственный способ перезагрузить внешний файл, как предложено в в этом ответе ?

Цель - по возможности пропустить загрузку файла SVG.

1 Ответ

1 голос
/ 14 марта 2019

Существуют и другие решения, но AJAX действительно прост, если вы планируете добавить SVG в ваш документ.
Но будьте осторожны, это может быть не очень хорошая идея.
Как вы, вероятно, знаете, SVG являются документами, и их узлы могут иметь атрибуты id. id атрибуты должны быть уникальными для каждого документа, поэтому, если вы добавите дважды один и тот же документ SVG, содержащий узлы с id, у вас будут дубликаты идентификаторов и, возможно, проблемы.

const svg = `<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200">
  <defs>
    <rect id="rect1" x="0" y="0" width="50" height="50" fill="red"/>
  </defs>
  <use xlink:href="#rect1" stroke="green"/>
</svg>`;

function appendSVGDoc(markup, parent) {
  const doc = (new DOMParser).parseFromString(markup, 'image/svg+xml');
  const docEl = document.adoptNode(doc.documentElement); parent.appendChild(docEl);
}
// append a first version
appendSVGDoc(svg, document.body);
onclick = e => {
  // let's do some modifs
  document.getElementById('rect1').setAttribute('fill', 'yellow');
  onclick = e => {
    // append an other one
    appendSVGDoc(svg, document.body);
    // guess what color is the rect here?
  };
};
<p>click to modify the svg element.</p>
<p>click again to add a new copy of the original svg</p>

Другой пример? Если ваш документ SVG содержит таблицу стилей, то правила этой таблицы стилей будут влиять на весь ваш документ:

const svg = `<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="500" height="200">
  <style>
    :root {
      font: 40px Serif;
    }
    rect {
      fill: green;
    }
  </style>
  <text y="50">I'm a big text in an svg image.</text>
  <rect x="25" y="75" width="50" height="50"/>
</svg>`;

function appendSVGDoc(markup, parent) {
  const doc = (new DOMParser).parseFromString(markup, 'image/svg+xml');
  const docEl = document.adoptNode(doc.documentElement); parent.appendChild(docEl);
}
onclick = e => {
  appendSVGDoc(svg, document.body);
};
<p>I am a simple html text content, and here is a simple svg &lt;rect> that should be red: <svg width="50" height="50"><rect x="0" y="0" height="50" width="50" fill="red"/></svg></p>

<p> click to append the external SVG </p>

Поэтому, чтобы избежать таких случаев, я могу только посоветовать вам реально загрузить ваши svg docs в

function appendSVGDoc(blob, parent) {
  return new Promise((res, rej) => {
    const url = URL.createObjectURL(blob);
    const iframe = document.createElement('iframe');
    iframe.classList.add('svg-viewer');
    iframe.onload = e => {
      const doc = iframe.contentDocument;
      const docEl = doc.documentElement;
      // iframe doesn't auto size like <object> would
      iframe.width = docEl.getAttribute('width') || '100%';
      iframe.height = docEl.getAttribute('height') || '100%';
      res(doc);
    };
    iframe.onerror = rej;
    iframe.src = url;
    parent.appendChild(iframe);
  });
}

fetch(url)
  .then(resp => resp.blob())
  .then(blob => appendSVGDoc(blob, document.body));
.then(svgdoc => {
    // here manipulate the svg document
  })
  .catch(console.error);

StackSnippets®, чрезмерно защищенный (с нулевым происхождением), который блокирует нам доступ к внутреннему контенту iframes, мне пришлось перевести этот последний пример в jsfiddle .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...