动态添加SVG渐变

我有这个带路径的SVG容器。 我想编辑它,所以路径的填充将是一个模式。 这是我失败的尝试:

我添加了一个渐变:

$('svg defs').prepend(''); 

然后改变路径的填充:

 $(base + ' svg path').each(function() { this.setAttribute('fill','url(#MyGradient)') } 

这不起作用。 我错过了什么?

你的问题(你“缺少”)是jQuery在XHTML命名空间中创建新元素,而SVG元素必须在SVG命名空间中创建。 您不能在SVG元素的字符串中使用原始代码。

最简单的(无插件)方法是停止依赖jQuery这么多,只需使用简单的DOM方法来创建元素。 是的,它比仅仅使用jQuery为你神奇地构建你的元素更加冗长……但是在这种情况下jQuery不起作用。

演示: http : //jsfiddle.net/nra29/2/

 createGradient($('svg')[0],'MyGradient',[ {offset:'5%', 'stop-color':'#f60'}, {offset:'95%','stop-color':'#ff6'} ]); $('svg path').attr('fill','url(#MyGradient)'); // svg: the owning  element // id: an id="..." attribute for the gradient // stops: an array of objects with  attributes function createGradient(svg,id,stops){ var svgNS = svg.namespaceURI; var grad = document.createElementNS(svgNS,'linearGradient'); grad.setAttribute('id',id); for (var i=0;i 

使用图书馆

或者,您可以包含Keith Woods的“jQuery SVG”插件 ,该插件具有许多常用SVG操作的便捷方法,包括创建线性渐变的function 。

找到了解决方案。 它有点难看,但不需要使用额外的插件。

显然,首次创建SVG时必须在模板中包含一个模式(它可能只读取)。

因此,用自己替换SVG标记的包装器内容是有效的( base是包装器):

 $(base).html($(base).html()) 

我想你必须使用jQuery的SVG插件(在这里找到)。 使用“普通”jQuery库添加SVG元素时,命名空间可能会混淆。

请尝试以下方法:

 svg.linearGradient( $('svg defs'), 'MyGradient', [ ['5%', '#F60'], ['95%', '#FF6']] ); 

(但不完全确定。你可能需要用这个代码来摆弄一下。)

编辑

刚刚创建了这个小提琴来测试论文(正如@Phrogz所建议的那样)。 实际上,它返回http://www.w3.org/1999/xhtml作为插入的的命名空间,这是错误的命名空间,因此validation了我的上述推测。

我只想说,我已经找到了一个更优雅的解决方案,它允许你继续使用jQuery与SVG元素,但没有jQuery SVG库(不再更新,并且jQuery 1.8或更高版本有一些问题)。 只需使用这样的function:

 createSVGElement= function(element) { return $(document.createElementNS('http://www.w3.org/2000/svg', element)); } 

它在SVG命名空间上创建一个SVG元素并用jQuery封装它,一旦在正确的命名空间中创建了元素,你就可以在jQuery中自由使用它:

然后,您可以以这种方式使用该函数:

 var $myGradient= createSVGElement('linearGradient') .attr( { id:"MyGradient" }); //if you dont need `defs`, skip this next line var $myDefs = createSVGElement('defs'); createSVGElement('stop') .attr({ offset: "5%", "stop-color": "#F60" }) .appendTo($myGradient); createSVGElement('stop') .attr({ offset:"95%", "stop-color":"#FF6" }) .appendTo($myGradient); //Use this if you already have `defs` $('svg defs').prepend($myGradient); //Use this if you dont have `defs` $('svg').prepend($myDefs); $('svg defs').prepend($myGradient); 

它不像你想要的那样紧凑,因为你必须手工创建每个元素,但它比使用DOM方法操作所有元素要好得多。

小小的一点,jQuery .attr()函数假设所有属性都是小写的,而SVG元素则不是这种情况(例如标签中的viewBox属性)。 为了解决这个问题,当使用大写字母设置属性时,请使用以下内容:

 $("svg")[0].setAttribute("viewBox", "0 0 1000 1000");