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.js
: js/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)
并使用classList
并add / 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");
一种解决方法是将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到程序集,就把它踢给我。