Фрагменты SVG по ошибке анализируются как HTMLUnknownElement - PullRequest
3 голосов
/ 20 мая 2011

У меня проблемы с составлением встроенного SVG с использованием Javascript.
Проблема может быть уменьшена до следующего кода ( живой пример здесь ):

Где-то внутри тела:

<svg id="drawing" xmlns="http://www.w3.org/2000/svg" version="1.1">
</svg>

Внутри onReady:

$("#drawing").append($("<rect style='fill: blue' width='100' height='100' />"));

Я ожидал увидеть синий прямоугольник сейчас. Тем не менее, Chrome и Firefox ничего не показывают.

Используя Firebug, я обнаружил, что Firefox интерпретирует «прямоугольник» как HTMLUnknownElement (а не как SVGElement).
Если я выберу «Редактировать SVG» в элементе SVG (используя Firebug) и вставлю куда-нибудь пробел, SVG, кажется, будет перепарсирован и появится прямоугольник.

Как я могу сказать парсеру правильно проанализировать этот фрагмент?

Ответы [ 4 ]

1 голос
/ 21 мая 2011

В этом примере показано, как встроить SVG в XHTML, включая программное создание новых элементов SVG: http://phrogz.net/svg/svg_in_xhtml5.xhtml

В этом примере показано, как использовать XHR для извлечения SVG в виде XML, найти его фрагмент,и два способа преобразовать его в локальный документ перед добавлением узла в существующий документ SVG: http://phrogz.net/svg/fetch_fragment.svg

В общем:

  1. Не используйте jQuery с SVG напрямую.
  2. Динамически созданные элементы SVG должны создаваться с использованием createElementNS, предоставляя URI пространства имен SVG 'http://www.w3.org/2000/svg'.(Обратите внимание, однако, что атрибуты SVG не должны создаваться с пространством имен.)
  3. Вы должны быть уверены, что ваш XHTML будет использоваться как XML (content-type: application / xhtml + xml), а не как текст/html.

Вот функция общего назначения, которую я иногда использую для удобного создания элементов SVG.Он работает как с документами SVG, так и с SVG-in-XHTML, позволяет напрямую создавать текстовое содержимое и поддерживает атрибуты пространства имен (например, xlink:href).

// Example usage:
//   var parentNode = findElementInTheSVGDocument();
//   var r = createOn( parentNode, 'rect', {
//     x:12, width:10, height:10, 'fill-opacity':0.3
//   });
function createOn(root,name,attrs,text){
  var doc = root.ownerDocument;
  var svg = root;
  while (svg.tagName!='svg') svg=svg.parentNode;
  var svgNS = svg.getAttribute('xmlns');
  var el = doc.createElementNS(svgNS,name);
  for (var attr in attrs){
    if (attrs.hasOwnProperty(attr)){
      var parts = attr.split(':');
      if (parts[1]) el.setAttributeNS(svg.getAttribute('xmlns:'+parts[0]),parts[1],attrs[attr]);
      else el.setAttributeNS(null,attr,attrs[attr]);
    }
  }
  if (text) el.appendChild(document.createTextNode(text));
  return root.appendChild(el);
} 
1 голос
/ 20 мая 2011

Боюсь, это не так просто:

  1. jsfiddle не место для тестирования svg, оно отправляет неправильный тип содержимого
  2. ссылки на внешние js-файлы могут 'не может быть создан html-путь (всегда имейте в виду, svg не нужно ничего делать с html)
  3. jquery использует некоторые dummy-div для создания элементов при использовании append (), но svg не делаетt-div-элементы
  4. также обратите внимание: привязка к событию загрузки svg-документа с jQuery, похоже, не работает

Здесь пример кода, работает дляя в FF при доставке как image / svg + xml


<svg id="drawing" 
     xmlns="http://www.w3.org/2000/svg" 
     xmlns:xlink="http://www.w3.org/1999/xlink"
     version="1.1"  
     onload="fx()">
  <script type="text/ecmascript" xlink:href="http://code.jquery.com/jquery-latest.js" />
  <script type="text/ecmascript">
  function fx()
  {
   $(document.createElementNS('http://www.w3.org/2000/svg', 'rect'))
     .css('fill','blue')
     .attr({'width':100,'height':100})
     .appendTo('#drawing');
   }
  </script>  
</svg>

Но, как и Marcin, я бы предложил использовать плагин.

Для добавления из родительского документа вы можете использовать объект, содержащий свойства элемента, базовый пример:


<html>
<head>
<script src="http://code.jquery.com/jquery-latest.js"></script>
<script  type="text/javascript">
/*<![CDATA[*/

function fx(obj,params)
{
  var svgDoc=obj.contentDocument;
  if(typeof params.name!='string')return;
  var props=$.extend({'attrs':{},'style':{},'selector':null},params);
      props.target=(!props.selector)?svgDoc.documentElement:$(svgDoc).find(props.selector)

    $(svgDoc.createElementNS('http://www.w3.org/2000/svg', props.name))
     .css(props.style)
     .attr(props.attrs)
     .appendTo(props.target);
}

/*]]>*/
</script>
</head>
<body>
  <object onload="fx(this,{'name':'rect','attrs':{'width':100,'height':100},'style':{'fill':'blue'},'selector':'#drawing'})" 
          data="my.svg" 
          type="image/svg+xml" 
          width="200" 
          height="200">
    <param name="src" value="my.svg">
  </object>
</body> 
</html>

Структура объекта:

  • имя: tagName (строка)
  • attrs: атрибуты (объект)
  • стиль: стиль (объект)
  • селектор: селектор (строка, если опущен, будет выбран корневой элемент)
0 голосов
/ 22 января 2016

См .: Преобразование SVG в base64

Я всегда проверяю, фрагмент SVG находится внутри элемента SVG или просто принудительно обновлять SVG.

0 голосов
/ 19 декабря 2011

Полагаю, вы хотели бы проанализировать фрагмент SVG без необходимости превращать его в JSON и так далее. Вот некоторый CoffeeScript, который делает это. Я протестировал код на SVG, встроенный в HTML, но я думаю, что он должен работать при любых обстоятельствах.

https://github.com/pwnall/ddr/blob/master/javascripts/graphics/pwnvg.coffee#L169

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

Теоретически, есть более простой (и более быстрый) подход, но сейчас он не работает. http://crbug.com/107982

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