克隆时SVG变黑

时间:2013-10-29 12:58:53

标签: javascript jquery html svg clone

当我发现一个奇怪的行为时,我正在玩jQuery的clone()函数。

此代码重现了该问题。第一个div包含一个SVG。两个按钮允许将SVG的克隆进行/撤消到第二个div中。尝试两次会使圆圈变黑。

enter image description here enter image description here

HTML

<div id="orgdiv">
    <svg width="200" height="200" style="margin:0">
        <linearGradient  id="r" x1="0" y1="0" x2="1" y2="1">
            <stop offset="0%" stop-color="#00ffff"></stop>
            <stop  offset="100%" stop-color="#ffff00"></stop>
        </linearGradient>
        <circle cx="100" cy="100" r="80" style="fill:url(#r)" />
    </svg>
</div>

<input type="button" value="copy">
<input type="button" value="clear">

<div id="copydiv"></div>

JS

$('input[value="copy"]').click(function(){
    $("#copydiv").html($("#orgdiv").clone());
});

$('input[value="clear"]').click(function(){
    $("#copydiv").empty();
});

jsFiddle here

注意:

  • 使用jQuery或Javascript进行克隆会导致同样的错误。

3 个答案:

答案 0 :(得分:7)

我有预感,因为你正在克隆linearGradient,它具有id属性(当然,在整个文档中它应该是唯一的。)这可能会让SVG处理器感到困惑。 / p>

我的理论似乎通过改变克隆途中的ID来证实:

$('input[value="copy"]').click(function () {
    var clone = $("#orgdiv").clone();
    // Change the ID of the clone, so we don't have duplicate IDs
    clone.find("#r").attr('id', 'unique');
    $("#copydiv").html(clone);
});

...这似乎可以防止出现问题。 (在这种情况下,克隆仍然会获得渐变,即使其克隆渐变的ID已更改,因为它通过其ID找到原始渐变。)

JSFiddle:http://jsfiddle.net/2K4xv/2/

我猜测你的情况下发生的事情是处理器正在拾取你正在创建的第二个渐变滤镜元素,以便与第一个圆圈一起使用,然后失去对它的引用。它被你的empty()摧毁了,因此留下了圆圈而没有渐变。究竟为什么这只是第二次发生的原因可能取决于SVG渲染器与HTML5文档交互的实现细节。

this earlier question中有关于此问题的更多信息。

答案 1 :(得分:2)

克隆后,你有两个id为“r”的元素,一个在原文中,一个在克隆中。所有ID必须是唯一的,因此文档不再有效。

答案 2 :(得分:1)

@Matt Gibson提出了一个黑客攻击:打造新的ID,然后重复使用引用原始linearGradient的冗余linearGradient定义的html。

很高兴,你需要这样做;)

svg标签的部分优势在于它们是他们自己疯狂的小容器。所以你可以从uri外部引用东西。

&amp;所以,如果您从事克隆业务,那么您可以抽象出模板模型,而不是担心ID。 ad-infinitum重复使用它:

$(document).ready(function(){
  $('input[value="copy"]').click(function () {
      $("#copydiv").append($(":first", "#orgdiv").clone());
  });

  $('input[value="clear"]').click(function () {
      $("#copydiv").empty();
  });
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<!-- ------------------- platonic horse ------------------------- -->
<div style="visibility:hidden; position:absolute; width:0">
  <svg>
    <g id="my-funky-svg-defs">
	  <defs>
	    <radialGradient id="gradient" cx="25%" cy="25%" r="100%" fx="40%" fy="40%">
		  <stop offset=  "0%" stop-color="hsla(313,  80%, 80%, 1)"/>
		  <stop offset= "40%" stop-color="hsla(313, 100%, 65%, 1)"/>
		  <stop offset="110%" stop-color="hsla(313, 100%, 50%, 0.7)"/>
	    </radialGradient>
	  </defs>    
	  <title>smarteee</title>
	  <circle  class="face" cx="200" cy="200" r="195" fill="url(#gradient)" />
	  <ellipse class="eye eye-left" cx="140" cy="150" rx="10" ry="40" fill="#131313"/>
	  <ellipse class="eye eye-right" cx="260" cy="150" rx="10" ry="40" fill="#131313"/>
	  <path class="smile" d="M120,280 Q200,330 280,280" stroke-width="10" stroke="#131313" fill="none" stroke-linecap="round"/>
    </g>
  </svg>	
</div>

<!-- ---------------------- prototype ----------------------- ---- -->
proto
<input type="button" value="copy"/>
<hr/>
<div id="orgdiv">
    <svg width="20px" height="20px" viewBox="0 0 400 400" style="margin:20px;">
        <use xlink:href="#my-funky-svg-defs"></use>
    </svg>
</div>

<!-- ------------------------- clones ----------------------- ---- -->
clones
<input type="button" value="clear"/>
<hr/>
<div id="copydiv"></div>

here's a fork of your jsfiddle