JQuery 3 не имеет этой проблемы
Одно из изменений, перечисленных в ревизиях jQuery 3.0 :
добавить манипуляции с классом SVG ( # 2199 , 20aaed3 )
Одним из решений этой проблемы было бы обновление до jQuery 3. Он прекрасно работает:
var flip = true;
setInterval(function() {
// Could use toggleClass, but demonstrating addClass.
if (flip) {
$('svg circle').addClass('green');
}
else {
$('svg circle').removeClass('green');
}
flip = !flip;
}, 1000);
svg circle {
fill: red;
stroke: black;
stroke-width: 5;
}
svg circle.green {
fill: green;
}
<script src="https://code.jquery.com/jquery-3.0.0.min.js"></script>
<svg>
<circle cx="50" cy="50" r="25" />
</svg>
Эта проблема:
Причина, по которой функции манипуляции с классом jQuery не работают с элементами SVG, заключается в том, что версии jQuery до 3.0 используют className
свойство для этих функций.
cur = elem.nodeType === 1 && ( elem.className ?
( " " + elem.className + " " ).replace( rclass, " " ) :
" "
);
Это ведет себя, как и ожидалось, для элементов HTML, но для элементов SVG className
немного отличается. Для элемента SVG className
это не строка, а экземпляр SVGAnimatedString
.
Рассмотрим следующий код:
var test_div = document.getElementById('test-div');
var test_svg = document.getElementById('test-svg');
console.log(test_div.className);
console.log(test_svg.className);
#test-div {
width: 200px;
height: 50px;
background: blue;
}
<div class="test div" id="test-div"></div>
<svg width="200" height="50" viewBox="0 0 200 50">
<rect width="200" height="50" fill="green" class="test svg" id="test-svg" />
</svg>
Если вы запустите этот код, вы увидите что-то вроде следующего в консоли разработчика.
test div
SVGAnimatedString { baseVal="test svg", animVal="test svg"}
Если бы мы приводили этот SVGAnimatedString
объект к строке, как это делает jQuery, мы бы это сделали [object SVGAnimatedString]
, где jQuery терпит неудачу.
Как плагин jQuery SVG справляется с этим:
Плагин jQuery SVG работает вокруг этого, исправляя соответствующие функции для добавления поддержки SVG.
function getClassNames(elem) {
return (!$.svg.isSVGElem(elem) ? elem.className :
(elem.className ? elem.className.baseVal : elem.getAttribute('class'))) || '';
}
Эта функция обнаружит, является ли элемент элементом SVG, и, если это так, будет использовать baseVal
свойство SVGAnimatedString
объекта, если оно доступно, прежде чем обратиться к class
атрибуту.
Историческая позиция jQuery по этому вопросу:
В настоящее время jQuery перечисляет эту проблему на своей странице « Не исправить» . Вот соответствующие части.
Ошибки SVG / VML или пространств имен
jQuery - это, прежде всего, библиотека для HTML DOM, поэтому большинство проблем, связанных с документами SVG / VML или элементами пространства имен, находятся вне области видимости. Мы стараемся решать проблемы, которые «просачиваются» в документы HTML, такие как события, возникающие в SVG.
Очевидно, jQuery считал полную поддержку SVG вне области действия ядра jQuery и лучше подходил для плагинов.