Объединить два SVG-элемента в один, используя Javascript? - PullRequest
3 голосов
/ 21 марта 2019

Допустим, у меня есть следующий HTML-контекст, к которому у меня нет доступа к его созданию:

<div id="outer">
  <div id="chart-div">
    <svg id="chart"></svg>
  </div>
  <div id="legend-div">
    <svg id="legend"></svg>
  </div>
</div>

Я пытаюсь экспортировать этот SVG-файл в изображение с помощью библиотеки canvg,проблема здесь в том, что они разделены, и поэтому я получаю два холста, и библиотека canvg принимает строку определения SVG в качестве входных данных.

Как я могу изменить приведенные выше элементы html, чтобы они были только одним SVG?Использование Javascript, так как это расширение для браузера.

Я попытался просто переключить теги DIVs на SVG, но он просто сломал все, и SVG стал пустым

Ответы [ 2 ]

2 голосов
/ 22 марта 2019

Это мое решение вашей проблемы: я делаю внешний div display:none, я создаю еще один элемент svg (вы можете сделать это динамически) в конце #new svg. Я использую #chart и #legend. Надеюсь, это поможет.

svg{border:1px solid;}
#outer {display:none}
#outer div{position:absolute; width:500px;}
<div id="outer">
  <div id="chart-div">
    <svg id="chart" viewBox="0 0 300 150">
      <circle stroke="gold" fill="none" cx="100" cy="75" stroke-width="40" stroke-dasharray="124.85" stroke-dashoffset="20" r="20"  />
    </svg>
  </div>
  <div id="legend-div">
    <svg id="legend"  viewBox="0 0 300 150">
      <rect fill="skyBlue" x="200" y="100" width="80" height ="30" />
    </svg>
  </div>
</div>


<svg id="new" viewBox="0 0 300 150" width="500"> 
  <use xlink:href="#chart" />
  <use xlink:href="#legend" />
</svg>
1 голос
/ 22 марта 2019

Это Javascript решение для объединения двух доступных svg в документе посредством манипуляций DOM.

var svgNS = "http://www.w3.org/2000/svg";  
var outer = document.getElementById('outer');

// get chart content
var chart = document.getElementById('chart-div');
var chartSvg = chart.getElementsByTagName('svg')[0];
var chartContent = Array.from(chartSvg.childNodes);

// get legend content
var legend = document.getElementById('legend-div');
var legendSvg = legend.getElementsByTagName('svg')[0];
var legendContent = Array.from(legendSvg.childNodes);

// create a merged-div where we are going to merge the svgs
var merged = document.createElement('div');
merged.setAttribute('id', 'merged-div');
outer.appendChild(merged);

// createElementNS for svg
var mergedSvg = document.createElementNS(svgNS, 'svg');
mergedSvg.setAttribute('id', 'merged');
// keep the viewBox of the chart
mergedSvg.setAttribute('viewBox', chartSvg.getAttribute('viewBox'));
merged.appendChild(mergedSvg);

// adding the content of both svgs
for (let i = 0; i < chartContent.length; i++) {
  mergedSvg.appendChild(chartContent[i]);
}
for (let i = 0; i < legendContent.length; i++) {
  mergedSvg.appendChild(legendContent[i]);
}

// the unmerged svgs can be removed
chart.remove();
legend.remove();
<div id="outer">
  <div id="chart-div">
    <svg id="chart" viewBox="0 0 300 150">
      <circle stroke="gold" fill="none" cx="100" cy="75" stroke-width="40" stroke-dasharray="124.85" stroke-dashoffset="20" r="20"  />
    </svg>
  </div>
  <div id="legend-div">
    <svg id="legend"  viewBox="0 0 300 150">
      <rect fill="skyBlue" x="200" y="100" width="80" height ="30" />
    </svg>
  </div>
</div>

Результирующая разметка:


    <div id="outer">
        <div id="merged-div">
            <svg id="merged" viewBox="0 0 300 150">
                <circle stroke="gold" fill="none" cx="100" cy="75" stroke-width="40" stroke-dasharray="124.85" stroke-dashoffset="20" r="20"></circle>
                <rect fill="skyBlue" x="200" y="100" width="80" height="30"></rect>
            </svg>
        </div>
    </div>
...