Snap.svg не может найти динамически (и успешно) добавленный элемент SVG с помощью jQuery

Snap.svg не работает в этом случае:

$('body').append($('<svg>').attr('id', 'test')) ;
console.log($('#test').length) ; // 1

var svg = Snap('#test') ;
svg.circle(100, 100, 50) ;
// Uncaught TypeError: Object [object Object] has no method 'circle'

... но работает, когда элемент уже находится в HTML:

<body>
    <svg id="test"></svg>
</body>

Элемент SVG успешно работает в HTML, но не может быть найден с помощью Snap.svg. Я делаю это неправильно с первым примером или это ошибка?

Ответ 1

Похоже, вы нашли обходной путь, но я думал, что вы или кто-нибудь, кто читает этот вопрос, может захотеть объяснений.

Чтобы создать элементы SVG, вы должны использовать document.createElementNS(), потому что элементы svg являются частью другого пространства имен, чем элементы html. Например:

var elementHTML = document.createElement("svg"); //does not work
var elementSVG = document.createElementNS("http://www.w3.org/2000/svg", "svg"); //works!

и внутренне, jquery использует document.createElement(), когда вы даете ему только имя тега. Когда у вас есть элемент, вы можете обернуть его как объект jquery и использовать его как обычно.

$(elementSVG).attr("width", 100); //etc.

Использование $("<svg data-blah='asdf'>") или подобных работ, потому что все, что находится за пределами простого тега, помещается в элемент через .innerHTML, а затем извлекается. Таким образом, тот же движок используется так, как если бы он находился в разметке HTML страницы. И теперь спецификация HTML5 имеет особые случаи для того, что делать, когда сталкивается элемент <svg> в разметке.

Некоторые вещи, которые нужно учитывать при работе с svg в jquery:

  • атрибуты не чувствительны к регистру, но некоторые атрибуты svg есть! Например, выполнение $element.attr("attributeName", "stroke") не будет работать.
  • .animate() имеет некоторые проблемы, но вы можете использовать пользовательскую функцию шага, чтобы обойти ее.

Подробнее об этом здесь