jQuery的SVG,为什么我不能添加类?

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

JQuery不能将一个类添加到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"); 

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

  • element.classList.add('newclass')在现代浏览器中工作
  • JQuery 3修复了潜在的问题

DOM API中有element.classList ,可以同时用于HTML和SVG元素。 不需要jQuery SVG插件甚至jQuery。

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

jQuery 3没有这个问题

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

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

这个问题的一个解决scheme是升级到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="jquery-3.0.0.min.js"></script> <svg> <circle cx="50" cy="50" r="25" /> </svg> 

如果你有dynamic类或者不知道哪些类可以被应用,那么我认为这种方法是最好的方法:

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

基于上面的答案,我创build了以下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.svg.js你必须加载这个文件: js/jquery.svgdom.jsjs/jquery.svgdom.js

资料来源: http : //keith-wood.name/svg.html#dom

工作示例: http : //jsfiddle.net/74RbC/99/

只需将缺less的原型构造函数添加到所有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'); 

所有功劳归功于Todd Moto 。

jQuery 2.2支持SVG类的操作

jQuery 2.2和1.12发布的post包含以下引用:

虽然jQuery是一个HTML库,但我们同意支持SVG元素的类可能是有用的。 用户现在可以在SVG上调用.addClass() ,.removeClass(),.toggleClass().hasClass()方法。 jQuery现在改变了class属性而不是className属性 。 这也使得类方法可以在一般的XML文档中使用。 请记住,许多其他的东西不适用于SVG,我们仍然build议使用专用于SVG的库,如果您需要超出类操作的任何东西。

使用jQuery 2.2.0的例子

它testing:

  • .addClass()
  • .removeClass()
  • .hasClass()

如果你点击那个小方块,它会改变它的颜色,因为class属性被添加/删除。

 $("#x").click(function() { if ( $(this).hasClass("clicked") ) { $(this).removeClass("clicked"); } else { $(this).addClass("clicked"); } }); 
 .clicked { fill: red !important; } 
 <html> <head> <script src="jquery-2.2.0.js"></script> </head> <body> <svg width="80" height="80"> <rect id="x" width="80" height="80" style="fill:rgb(0,0,255)" /> </svg> </body> </html> 

jQuery不支持SVG元素的类。 您可以直接获取元素$(el).get(0)并使用classListadd / remove 。 还有一个诀窍在于,最顶层的SVG元素实际上是一个普通的DOM对象,可以像jQuery中的其他元素一样使用。 在我的项目中,我创build了这个来照顾我需要的东西,但Mozilla开发人员networking上提供的文档有一个垫片,可以用来替代。

 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作为你的select器引擎。 我的项目有图表,所以它也在我的应用程序范围内。 D3正确地修改了vanilla DOM元素和SVG元素的类属性。 虽然为这种情况下添加D3可能会矫枉过正。

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

这是我相当不雅但工作的代码,处理以下问题(没有任何依赖):

  • IE中的<svg>元素不存在classList
  • className不能代表IE中<svg>元素的class属性
  • 旧的IE浏览器破坏了getAttribute()setAttribute()实现

它尽可能使用classList

码:

 var classNameContainsClass = function(fullClassName, className) { return !!fullClassName && new RegExp("(?:^|\\s)" + className + "(?:\\s|$)").test(fullClassName); }; var hasClass = function(el, className) { if (el.nodeType !== 1) { return false; } if (typeof el.classList == "object") { return (el.nodeType == 1) && el.classList.contains(className); } else { var classNameSupported = (typeof el.className == "string"); var elClass = classNameSupported ? el.className : el.getAttribute("class"); return classNameContainsClass(elClass, className); } }; var addClass = function(el, className) { if (el.nodeType !== 1) { return; } if (typeof el.classList == "object") { el.classList.add(className); } else { var classNameSupported = (typeof el.className == "string"); var elClass = classNameSupported ? el.className : el.getAttribute("class"); if (elClass) { if (!classNameContainsClass(elClass, className)) { elClass += " " + className; } } else { elClass = className; } if (classNameSupported) { el.className = elClass; } else { el.setAttribute("class", elClass); } } }; var removeClass = (function() { function replacer(matched, whiteSpaceBefore, whiteSpaceAfter) { return (whiteSpaceBefore && whiteSpaceAfter) ? " " : ""; } return function(el, className) { if (el.nodeType !== 1) { return; } if (typeof el.classList == "object") { el.classList.remove(className); } else { var classNameSupported = (typeof el.className == "string"); var elClass = classNameSupported ? el.className : el.getAttribute("class"); elClass = elClass.replace(new RegExp("(^|\\s)" + className + "(\\s|$)"), replacer); if (classNameSupported) { el.className = elClass; } else { el.setAttribute("class", elClass); } } }; //added semicolon here })(); 

用法示例:

 var el = document.getElementById("someId"); if (hasClass(el, "someClass")) { removeClass(el, "someClass"); } addClass(el, "someOtherClass"); 

我使用Snap.svg添加类和SVG。

 var jimmy = Snap(" .jimmy ") jimmy.addClass("exampleClass"); 

http://snapsvg.io/docs/#Element.addClass

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

 $('.svg-container').addClass('svg-red'); 
 .svg-red svg circle{ fill: #ED3F32; } 
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <div class="svg-container"> <svg height="40" width="40"> <circle cx="20" cy="20" r="20"/> </svg> </div> 

受到上述答案的鼓舞,特别是Sagar Gala,我创build了这个API 。 你可以使用它,如果你不想或不能升级你的jQuery版本。

我写在我的项目中,它的工作原理…可能;)

 $.fn.addSvgClass = function(className) { var attr this.each(function() { attr = $(this).attr('class') if(attr.indexOf(className) < 0) { $(this).attr('class', attr+' '+className+ ' ') } }) }; $.fn.removeSvgClass = function(className) { var attr this.each(function() { attr = $(this).attr('class') attr = attr.replace(className , ' ') $(this).attr('class' , attr) }) }; 

例子

 $('path').addSvgClass('fillWithOrange') $('path').removeSvgClass('fillWithOrange') 

或者当JQ在某个地方有一只猴子的时候,就使用老派的DOM方法。

 var myElement = $('#my_element')[0]; var myElClass = myElement.getAttribute('class').split(/\s+/g); //splits class into an array based on 1+ white space characters myElClass.push('new_class'); myElement.setAttribute('class', myElClass.join(' ')); //$(myElement) to return to JQ wrapper-land 

了解DOM人员。 即使在2016年的框架,paloza也相当有帮助。 另外,如果你听到有人比较DOM到程序集,就把它踢给我。