SVG становится черным при клонировании

я играл с clone() функция из jQuery, когда я обнаружил странное поведение.

этот код воспроизводит проблему. Первый div содержит SVG. Две кнопки позволяют делать / отменять клон SVG во второй div. Если попробовать два раза, круг почернеет.

enter image description hereenter 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 вот!--5-->

Примечание:

  • клонирование с помощью jQuery или JavaScript приводит к той же ошибке.

3 ответов


у меня есть предчувствие, что это может быть потому, что вы клонируете linearGradient, у которого есть id атрибут (который, конечно же, должен быть уникальным во всем документе.) Это может запутать процессор SVG.

моя теория, кажется, подтверждается изменением идентификатора по пути через клон:

$('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);
});

...что, похоже, предотвращает проблему. (В этом случае клон все еще получает градиент, даже если идентификатор его клонированного градиента изменился, потому что он поиск исходного градиента по его идентификатору.)

JSFiddle здесь:http://jsfiddle.net/2K4xv/2/

Я предполагаю, что то, что происходит "под капотом" в вашем случае, заключается в том, что процессор подбирает второй градиентный фильтрующий элемент, который вы создаете для использования с первым кругом, а затем теряет ссылку на него, когда он уничтожается вашим empty(), таким образом, оставив вас с кругом, но без градиента. Именно поэтому это происходит только во второй раз through, вероятно, вплоть до деталей реализации взаимодействия SVG renderer с документом HTML5.

есть больше информации по этому вопросу в этот предыдущий вопрос.


Как только вы клонируете его, у вас есть два элемента с идентификатором "r", один в оригинале и один в Клоне. Все идентификаторы должны быть уникальными, поэтому документ больше не действителен.


@Matt Gibson представляет Хак: барабанить новые идентификаторы, а затем дублировать html с избыточным linearGradient определения ссылка на оригинал linearGradient.

к счастью, вам нужно это сделать;)

часть силы svg теги - это их собственные сумасшедшие маленькие контейнеры. таким образом, вы можете ссылаться на материал извне из uri.

&поэтому, если вы занимаетесь клонированием, то вместо того, чтобы беспокоиться об идентификаторах, вы можете абстрагироваться от шаблон модели и повторно использовать его 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>

и вот вилка вашего jsfiddle.