1

$(document).ready(function () {
    const   margin = {top: 50, right: 50, bottom: 50, left: 50},
            width = 600 - margin.left - margin.right,
            height = 600 - margin.top - margin.bottom;
const svg = d3.select('.interact-map').append('svg')
    .attr('width', width + margin.left + margin.right)
    .attr('height', height + margin.top + margin.bottom)
    .append('g')
    .attr('transform', "translate(" + margin.left + "," + margin.top + ")");

var data = [
    {"filename": "https://upload.wikimedia.org/wikipedia/commons/d/de/SQUARE_SHAPE.svg"},
    {"filename": "https://upload.wikimedia.org/wikipedia/commons/a/a0/Circle_-_black_simple.svg"}
];

var widthOffset = 100,
    heightGapStep = 25,
    widthGapStep = 150;

(function draw() {

    const floors = svg.selectAll(".interact-floors").data(data);

    const addFloors = floors
        .enter()
            .append('g')
            .attr('class', 'interact-floors')
            .attr("transform", function (d, i) {
                return 'translate(' + (widthOffset + i * widthGapStep) + ',' + (data.length * heightGapStep - heightGapStep * i)  + ")"
            })
            .html(function (d) {
                    console.log(d.filename);
                    d3.xml("/img/interact-map/" + d.filename).then(function (content) {
                        return content.documentElement
                    });
                });
})();

});

<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="interact-map"></div>

Есть такой d3 код, он нужен что-бы импортнуть внешние SVG внутрь холста. Но столкнулся с проблемой, что полученный контент из content.documentElement я не могу вернуть в html элемента, как правильно это сделать?

Happy_Cougar
  • 1,384

1 Answers1

1

Я устал искать в интернете где бы найти svg с корректными cors заголовками, по-этому слегка видоизменил Ваш пример, имитировав запрос на сервер при помощи setTimeout (если svg будут загружаться с Вашего же сайта проблем с cors не будет)

Суть от этого не меняется и для кода с запросом нужно было бы написать следующее:


вместо:

.html(function (d) {
    d3.xml("/img/interact-map/" + d.filename).then(function (content) {
        return content.documentElement
    });
 });

Можно сделать как-то так:

.each(function (d) {
    let element = d3.select(this);
    d3.xml("/img/interact-map/" + d.filename).then(function (content) {
        element.html(content.documentElement)
    });
 });

Вот рабочий пример, с видоизменениями, про которые я писал в начале ответа:

const margin = {top: 50, right: 50, bottom: 50, left: 50},
        width = 600 - margin.left - margin.right,
        height = 600 - margin.top - margin.bottom;

const svg = d3.select('.interact-map').append('svg') .attr('width', width + margin.left + margin.right) .attr('height', height + margin.top + margin.bottom) .append('g') .attr('transform', "translate(" + margin.left + "," + margin.top + ")");

var data = [ {svg: &lt;svg height="100" width="100"&gt; &lt;circle cx="50" cy="50" r="40" stroke="black" stroke-width="3" fill="red" /&gt;&lt;/svg&gt;}, {svg: &lt;svg height="100" width="100"&gt; &lt;circle cx="50" cy="50" r="40" stroke="black" stroke-width="3" fill="green" /&gt;&lt;/svg&gt;} ];

var widthOffset = 100, heightGapStep = 25, widthGapStep = 150;

(function draw() {

const floors = svg.selectAll(".interact-floors").data(data);

const addFloors = floors
    .enter()
        .append('g')
        .attr('class', 'interact-floors')
        .attr("transform", function (d, i) {
            let x = widthOffset + i * widthGapStep;
            let y = data.length * heightGapStep - heightGapStep * i
            return 'translate(' + x + ',' + y  + ")"
        })
        .each(function (d) {
            let self = this;
            setTimeout(function (content) {
                d3.select(self).html(d.svg)
            })
        });

})();

<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>

<div class="interact-map"></div>