JavaScript-контекст в SVG-файле - PullRequest
3 голосов
/ 25 апреля 2019

Я планирую включить некоторую интерактивность непосредственно в файлы SVG (вместо файлов HTML, ссылающихся на указанные файлы SVG).

Вот мой тестовый файл SVG:

<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="210" height="297" viewbox="0 0 210 297" xmlns="http://www.w3.org/2000/svg">

  <script type="text/javascript"><![CDATA[
      function test() {alert("Test");}
      ]]>
  </script>

  <rect x="10" y="20" width="100" height="200" style="fill:red" onclick="test()"></rect>
  
</svg>

Я не совсем уверен, в каком контексте выполняется этот JavaScript.Стандарт svg не зависит от html.

Например, если бы я использовал document, всегда ли он ссылался бы на себя (вместо html-документа, если на него ссылается svg)?Возможно, использование window.alert() не совсем нормально, так как оно гарантированно существует только в контексте веб-браузера?Есть ли вообще какой-то набор требований, ожидаемых от приложения для просмотра svg, который определяет, какие глобальные объекты открыты для его JavaScript, когда файл открывается «голым»?Или, возможно, контекст не гарантируется, и разработчик svg file viewer должен решить, что, если какие-либо глобальные объекты открывать для встроенного JavaScript.

Ответы [ 2 ]

3 голосов
/ 25 апреля 2019

Если вы ссылаетесь на файл svg с помощью тега <img>, JavaScript будет полностью игнорироваться.

Если вместо этого вы используете тег <object>, как показано ниже, JavaScript будет работать, но document ссылается только на ваш SVG-файл и не может получить доступ к переменной document из файла HTML, который содержит тег <object>.Вы можете увидеть это, используя console.log(document) в вашем SVG-файле.

<object data="circle.svg" type="image/svg+xml">

Если вы хотите, чтобы JavaScript имел возможность доступа к вашему HTML document, вам нужно напрямую встроить содержимое вашего SVG-кода.в вашем HTML-коде вместо того, чтобы помещать его в отдельный файл.

Рабочий код, приведенный ниже, показывает все три приведенных выше примера.

<!-- This won't log anything, JavaScript disabled -->
<img src="https://tchaffee.github.io/so-svg/square.svg"/>

<!-- "document" here will reference the XML SVG document -->
<object data="https://tchaffee.github.io/so-svg/square.svg" type="image/svg+xml"></object>


<!-- "document" here will reference the HTML document -->
<svg width="210" height="297" viewBox="0 0 210 297"
     xmlns="http://www.w3.org/2000/svg">
  <script type="text/javascript"><![CDATA[
    function test(evt) {
      console.log('Internal HTML document:');
      console.log(document);
    }
  ]]></script>
  <rect x="10" y="20" width="100" height="200" style="fill:blue" onclick="test()"></rect>
</svg>

На случай разрыва связи, вот код https://tchaffee.github.io/so-svg/square.svg

<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="210" height="297" viewbox="0 0 210 297" xmlns="http://www.w3.org/2000/svg">
  <script type="text/javascript"><![CDATA[
    function test(evt) {
      console.log('External SVG document:');
      console.log(document);
    }
  ]]></script>
  <rect x="10" y="20" width="100" height="200" style="fill:red" onclick="test()"></rect>
</svg>
2 голосов
/ 25 апреля 2019

Для файлов SVG, включенных в HTML, контекст такой же, как для элементов HTML DOM - но когда вы используете ссылку на SVG в качестве отдельного документа, у вас есть доступ только к контексту этого документа.Чтобы получить доступ к элементу и событию, используйте onclick="test(this,event)" (во вложенном или отдельном файле).

function short() {
  document.querySelector('rect').setAttribute('height',100);
}
button {display: block}
<button id="msg" onclick="short()">Click on box and/or on this button</button>

<svg width="210" height="297" viewbox="0 0 210 297" xmlns="http://www.w3.org/2000/svg">
  <script type="text/javascript"><![CDATA[
    function test(rect,event) {
      let w= +rect.getAttribute("width")
      rect.setAttribute("width", w+10)
      msg.innerText+=' #'
      console.log({rect,event,document,window})
    }
  ]]></script>
  <rect x="10" y="20" width="100" height="200" style="fill:red" onclick="test(this,event)"></rect>
</svg>

В приведенном выше фрагменте - встроенный jv svg имеет доступ вне svg (изменить содержимое <div id="msg">) - а также другие html-сценарии (вне svg)иметь доступ к SVG.Если svg включен как <img src="test.svg">, то svg embeded js никогда не будет выполнен.Если svg включен как <object data="circle.svg" type="image/svg+xml">, JS будет выполняться как отдельный документ, поэтому он не будет иметь доступа к <div id="msg">, а также внешние html-скрипты имеют доступ только к объекту, но не имеют доступа к элементам svg.

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