Скриптинг <path>данных в SVG (чтение и изменение) - PullRequest
27 голосов
/ 08 ноября 2011

Может ли кто-нибудь действительно помочь мне, пожалуйста? Я искал способы запуска скриптов для моего SVG. Но все, что я получил, не совпадает! И это не содержит достаточно информации, почему он использовал этот набор кодов. Например, один использовал event.target, другой имел event.getTarget (), а другой имел event.target.firstchild.data. Кто-нибудь может мне помочь, пожалуйста?

<svg xmlns="http://www.w3.org/2000/svg" version="1.1">
  <path d="M150 0 L75 200 L225 200 Z" />
</svg>

это пример пути svg, верно? Что мне нужно, это получить эти координаты, возможно, положить его в переменную, и использовать его в качестве координат для другого SVG. Так как я могу это сделать? Другое дело, как я могу изменить эти координаты, введя числа в интерфейсе.

Так что я пытался искать ответы, но, как я уже сказал, я не нашел нужную мне информацию или, может быть, просто не понял, что она мне показала.

Ответы [ 2 ]

95 голосов
/ 14 ноября 2011

Похоже, у вас может быть четыре вопроса:

  1. Как встроить скрипт в файл SVG?
  2. Как запустить скрипт внутри файла SVG?
  3. Как мне получить доступ к данным для элемента <path> из скрипта?
  4. Как я могу манипулировать данными для элемента <path> из скрипта?

Давайте разберемся с ними однимза один раз:


Как встроить скрипт в файл SVG?

Как описано в спецификации SVG , вы можете поместить элемент <script> вВаш документ должен содержать код JavaScript.Согласно последним спецификациям SVG, вам не нужно указывать атрибут type для вашего скрипта.По умолчанию используется значение type="application/ecmascript".

  • Другие распространенные типы пантомимы включают "text/javascript", "text/ecmascript" (указано в SVG 1.1), "application/javascript" и "application/x-javascript".У меня нет подробной информации о поддержке всех этих браузеров или об отсутствии атрибута type.У меня всегда был хороший успех с text/javascript.

Как и в случае с HTML, вы можете либо поместить код скрипта непосредственно в документ, либо ссылаться на внешний файл.При выполнении последнего вы должны использовать атрибут href (не src) для URI с атрибутом в пространстве имен xlink.

<svg version="1.1" baseProfile="full" xmlns="http://www.w3.org/2000/svg"
     xmlns:xlink="http://www.w3.org/1999/xlink">
  <script xlink:href="/js/mycode.js" />
  <script><![CDATA[
    // Wrap the script in CDATA since SVG is XML and you want to be able to write
    // for (var i=0; i<10; ++i )
    // instead of having to write
    // for (var i=0; i&lt;10; ++i )
  ]]></script>
</svg>

Как запустить скриптвнутри файла SVG?

Как и в случае с HTML, код, включенный в ваш документ SVG, будет запущен, как только он встретится.Если вы поместите свой элемент <script> над остальной частью документа (как вы могли бы поместить <script> в <head> документа HTML), то ни один из ваших элементов документа не будет доступен, когда ваш код выполняется.

Самый простой способ избежать этого - поместить элементы <script> внизу документа:

<svg version="1.1" baseProfile="full" xmlns="http://www.w3.org/2000/svg"
     xmlns:xlink="http://www.w3.org/1999/xlink">
  <!-- all SVG content here, above the script -->
  <script><![CDATA[
    // Now I can access the full DOM of my document
  ]]></script>
</svg>

В качестве альтернативы, вы можете создать функцию обратного вызова в верхней части документа, котораявызывается только тогда, когда остальная часть документа готова:

<svg version="1.1" baseProfile="full" xmlns="http://www.w3.org/2000/svg">
  <title>SVG Coordinates for Embedded XHTML Elements</title>
  <script>document.documentElement.addEventListener('load',function(){
    // This code runs once the 'onload' event fires on the root SVG element
    console.log( document.getElementById('foo') );
  },false)</script>
  <path id="foo" d="M0 0" />
</svg>

Как получить доступ к данным для элемента <path> из скрипта?

Существует два способа получить доступ к большинствуинформация об элементах в SVG: вы можете получить доступ к атрибуту в виде строки через стандартный метод DOM Level 1 Core getAttribute(), или вы можете использовать объекты и методы SVG DOM .Давайте рассмотрим оба варианта:

Доступ к данным пути через getAttribute()

Использование getAttribute() возвращает ту же строку, что и при просмотре источника:

<path id="foo" d="M150 0 L75 200 L225 200 Z" />
<script><![CDATA[
  var path = document.getElementById('foo');
  var data = path.getAttribute('d');
  console.log(data);
  //-> "M150 0 L75 200 L225 200 Z"
]]></script>
  • Плюсы: очень просто звонить;вам не нужно ничего знать о SVG DOM
  • Con: поскольку вы получаете строку, вы должны проанализировать атрибут самостоятельно;для данных SVG <path> это может быть мучительно.

Доступ к данным пути с помощью методов SVG DOM

<path id="foo" d="M150 0 L75 200 L225 200 Z" />
<script><![CDATA[
  var path = document.getElementById('foo');

  // http://www.w3.org/TR/SVG/paths.html#__svg__SVGAnimatedPathData__normalizedPathSegList
  // See also path.pathSegList and path.animatedPathSegList and path.animatedNormalizedPathSegList
  var segments = path.normalizedPathSegList ;

  for (var i=0,len=segments.numberOfItems;i<len;++i){
    var pathSeg = segments.getItem(i);
    // http://www.w3.org/TR/SVG/paths.html#InterfaceSVGPathSeg
    switch(pathSeg.pathSegType){
      case SVGPathSeg.PATHSEG_MOVETO_ABS:
        // http://www.w3.org/TR/SVG/paths.html#InterfaceSVGPathSegMovetoAbs
        console.log("Move to",pathSeg.x,pathSeg.y);
      break;
      case SVGPathSeg.PATHSEG_LINETO_ABS:
        // http://www.w3.org/TR/SVG/paths.html#InterfaceSVGPathSegLinetoAbs
        console.log("Line to",pathSeg.x,pathSeg.y);
      break;
      case SVGPathSeg.PATHSEG_CLOSEPATH:
        // http://www.w3.org/TR/SVG/paths.html#InterfaceSVGPathSegClosePath
        console.log("Close Path");
      break;
    }
  }
]]></script>

Приведенный выше скрипт выдает следующий вывод:

Move to 150 0
Line to 75 200
Line to 225 200
Close Path
  • Плюсы: данные пути анализируются для вас;вы получаете точные цифры от самого API;использование normalizedPathSegList принимает относительные команды и делает их абсолютными для вас;если SMIL-анимация изменяет данные пути, использование неанимированного pathSegList может дать вам доступ к базовой неанимированной информации, недоступной через getAttribute().

  • Минусы: сладкие шимпанзеПламя, посмотри на этот код!И это даже не обрабатывает все возможные сегменты пути.

Поскольку читать спецификации W3C для SVG DOM может быть сложно, много лет назад я создал онлайн-инструмент для просмотракакие свойства и объекты существуют.Вы можете использовать его здесь: http://objjob.phrogz.net/svg/hierarchy


Как я могу манипулировать данными для элемента <path> из скрипта

Как и выше, вы можете создать новую строку ииспользуйте setAttribute(), чтобы вставить его в объект, или вы можете манипулировать SVG DOM.

Управление данными пути с помощью setAttribute()

<path id="foo" d="M150 0 L75 200 L225 200 Z" />
<script><![CDATA[
  var path = document.getElementById('foo');
  path.setAttribute('d','M150,0 L150,100 200,300 Z');
]]></script>

Управление данными пути с использованием SVG DOM

<path id="foo" d="M150,0 L75,200 l150,0 Z" />
<script><![CDATA[
  var path = document.getElementById('foo');
  var segments = path.pathSegList;
  segments.getItem(2).y = -10;
]]></script>

В общем, вам просто нужно изменить свойства различных экземпляров подкласса SVGPathSeg;изменения вносятся сразу в DOM.(В приведенном выше примере исходный треугольник перекошен, поскольку последняя точка слегка смещена вверх.)

Когда вам нужно создать новые сегменты пути, вам нужно использовать такие методы, как var newSegment = myPath.createSVGPathSegArcAbs(100,200,10,10,Math.PI/2,true,false) и затем используйте один из методов, чтобы вставить этот сегмент в список, например, segments.appendItem(newSegment).

5 голосов
/ 31 марта 2014

Элементы динамического пути в SVG с поддержкой Javascript и Css

var XMAX = 500;
    var YMAX = 500;
    var _xx=10;
    var _reg=100;
    var _l=10;
    // Create PATH element
    for(var x=1;x<20;x++)
    {
    var pathEl = document.createElementNS("http://www.w3.org/2000/svg", "path");
    pathEl.setAttribute('d','M'+_l+' 100 Q 100  300 '+_l+' 500' );
    pathEl.style.stroke = 'rgb('+(_reg)+',0,0)';
    pathEl.style.strokeWidth = '5';
    pathEl.style.fill = 'none';
        $(pathEl).mousemove(function(evt){$(this).css({"strokeWidth":"3","stroke":"#ff7200"}).hide(100).show(500).css({"stroke":"#51c000"})});

    document.querySelector('svg').appendChild(pathEl);
    _l+=50;
    }

Демонстрация в jsfiddle

...