我使用jQuery SVG。我不能向对象添加或删除类。有人知道我的错误吗?

SVG:

<rect class="jimmy" id="p5" x="200" y="200" width="100" height="100" />

jQuery不会添加类:

$(".jimmy").click(function() {
    $(this).addClass("clicked");
});

我知道SVG和jQuery一起工作很好,因为我可以瞄准对象,并在点击时发出警报:

$(".jimmy").click(function() {
    alert('Handler for .click() called.');
});

当前回答

一个解决方法是将class添加到svg元素的容器中:

$ (' .svg-container ') .addClass(“svg-red”); . SVG -红色SVG圆圈{ 填充:# ED3F32; } < script src = " https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js " > < /脚本> < div class = " svg-container”> <svg height="40" width="40"> <circle cx="20" cy="20" r="20"/> < / svg > < / div >

其他回答

有元素。用于HTML和SVG元素的DOM API中的classList。不需要jQuery SVG插件,甚至jQuery。

$(".jimmy").click(function() {
    this.classList.add("clicked");
});

基于以上答案,我创建了以下API

/*
 * .addClassSVG(className)
 * Adds the specified class(es) to each of the set of matched SVG elements.
 */
$.fn.addClassSVG = function(className){
    $(this).attr('class', function(index, existingClassNames) {
        return ((existingClassNames !== undefined) ? (existingClassNames + ' ') : '') + className;
    });
    return this;
};

/*
 * .removeClassSVG(className)
 * Removes the specified class to each of the set of matched SVG elements.
 */
$.fn.removeClassSVG = function(className){
    $(this).attr('class', function(index, existingClassNames) {
        var re = new RegExp('\\b' + className + '\\b', 'g');
        return existingClassNames.replace(re, '');
    });
    return this;
};

jQuery 3没有这个问题

jQuery 3.0版本中列出的一个变化是:

添加SVG类操作(#2199,20aaed3)

这个问题的一个解决方案是升级到jQuery 3。它很有效:

Var翻转= true; setInterval(函数(){ //可以使用toggleClass,但要演示addClass。 If(翻转){ $ (svg圆).addClass(“绿色”); } 其他{ $ (svg圆).removeClass(“绿色”); } 翻转= ! }, 1000); SVG圆{ 填充:红色; 中风:黑色; 笔划宽度:5; } svg圆。绿色{ 填充:绿色; } < script src = " https://code.jquery.com/jquery-3.0.0.min.js " > < /脚本> svg < > <circle cx="50" cy="50" r="25" /> < / svg >


存在的问题:

jQuery类操作函数不能与SVG元素一起工作的原因是jQuery 3.0之前的版本对这些函数使用className属性。

摘自jQuery attributes/classes.js:

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 { 宽度:200 px; 高度:50 px; 背景:蓝色; } <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支持,从而解决了这个问题。

摘自jQuery SVG jQuery .svgdom.js

function getClassNames(elem) {
    return (!$.svg.isSVGElem(elem) ? elem.className :
        (elem.className ? elem.className.baseVal : elem.getAttribute('class'))) || '';
}

这个函数将检测一个元素是否是SVG元素,如果是,它将使用SVGAnimatedString对象的baseVal属性(如果可用),然后返回到class属性。

jQuery在这个问题上的历史立场:

jQuery目前在Won 't Fix页面上列出了这个问题。以下是相关部分。

SVG/VML或命名空间元素bug jQuery主要是HTML DOM的库,因此大多数与SVG/VML文档或名称空间元素相关的问题都不在讨论范围之内。我们确实尝试解决“渗透”到HTML文档的问题,比如从SVG冒出来的事件。

显然,jQuery认为完全支持SVG超出了jQuery核心的范围,更适合插件。

编辑2016:阅读下面两个答案。

JQuery 3修复了潜在的问题 Vanilla JS: element.classList.add('newclass')适用于现代浏览器


JQuery(小于3)不能向SVG添加类。

.attr()与SVG一起工作,所以如果你想依赖jQuery:

// Instead of .addClass("newclass")
$("#item").attr("class", "oldclass newclass");
// Instead of .removeClass("newclass")
$("#item").attr("class", "oldclass");

如果你不想依赖jQuery:

var element = document.getElementById("item");
// Instead of .addClass("newclass")
element.setAttribute("class", "oldclass newclass");
// Instead of .removeClass("newclass")
element.setAttribute("class", "oldclass");

jQuery不支持SVG元素的类。您可以直接获取元素$(el).get(0),并使用classList和添加/删除。这也有一个技巧,最上面的SVG元素实际上是一个普通的DOM对象,可以像jQuery中的其他元素一样使用。在我的项目中,我创建了这个来照顾我需要的东西,但Mozilla开发者网络上提供的文档有一个垫片,可以用作替代方案。

例子

function addRemoveClass(jqEl, className, addOrRemove) 
{
  var classAttr = jqEl.attr('class');
  if (!addOrRemove) {
    classAttr = classAttr.replace(new RegExp('\\s?' + className), '');
    jqEl.attr('class', classAttr);
  } else {
    classAttr = classAttr + (classAttr.length === 0 ? '' : ' ') + className;
    jqEl.attr('class', classAttr);
  }
}

一个更困难的选择是使用D3.js作为你的选择器引擎。我的项目有用它构建的图表,所以它也在我的应用范围内。D3正确地修改了普通DOM元素和SVG元素的类属性。不过在这种情况下添加D3可能会过量。

d3.select(el).classed('myclass', true);