我使用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.');
});

当前回答

只需将缺失的原型构造函数添加到所有SVG节点:

SVGElement.prototype.hasClass = function (className) {
  return new RegExp('(\\s|^)' + className + '(\\s|$)').test(this.getAttribute('class'));
};

SVGElement.prototype.addClass = function (className) { 
  if (!this.hasClass(className)) {
    this.setAttribute('class', this.getAttribute('class') + ' ' + className);
  }
};

SVGElement.prototype.removeClass = function (className) {
  var removedClass = this.getAttribute('class').replace(new RegExp('(\\s|^)' + className + '(\\s|$)', 'g'), '$2');
  if (this.hasClass(className)) {
    this.setAttribute('class', removedClass);
  }
};

然后你可以这样使用它,而不需要jQuery:

this.addClass('clicked');

this.removeClass('clicked');

所有功劳都归功于托德·莫托。

其他回答

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);

编辑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");

受到上述答案的启发,尤其是Sagar Gala,我创建了这个API。如果你不想或不能升级jquery版本,你可以使用它。

如果你有动态类或者不知道什么类可以被应用,那么我认为这个方法是最好的方法:

// addClass
$('path').attr('class', function(index, classNames) {
    return classNames + ' class-name';
});

// removeClass
$('path').attr('class', function(index, classNames) {
    return classNames.replace('class-name', '');
});

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核心的范围,更适合插件。