Gerrit
Gerrit

Reputation: 2677

Visualize multidimensional Array in SVG

I have an array of objects which I bind to a g-element. For each g-element I generate a rect-element. It works so far but now I want to have a dynamic number of "parts" in each g-element which should generate a new rect and text element inside the existing rect.

Here you will find my example or on fiddle.net/tnnomejg/

var config = {
    width: 600
};

var data = [
    {
        height: 150,
        y: 0,
        parts: [
            {
                title: "Hello",
                x: 50,
                y: 60,
            },
            {
                title: "World",
                x: 350,
                y: 60,
            }
        ],        
    },
    {
        height: 150,
        y: 155,
        parts: [
            {
                title: "Demo",
                x: 280,
                y: 215,
            }
        ],        
    },
];

var svg = d3.select("body").append("svg").attr("width", config.width).attr("height", 500);

var g = svg.selectAll("g")
                .data(data)
                .enter()
                .append("g");

    g.append("rect")
        .attr("x", 1)
        .attr("y", function(d) { return d.y; })
        .attr("width", config.width)
        .attr("height", function(d) { return d.height; });

Thx.

Upvotes: 0

Views: 520

Answers (2)

altocumulus
altocumulus

Reputation: 21578

You could use a subselection binding your parts' data to the corresponding elements using an accessor function like this:

var parts = g.selectAll("g.part")
                .data(function(d) { return d.parts; })
                .enter()
                .append("g")
                    .attr("class", "part");

Having this subselection at your hands you may insert/append content accessing the corresponding data bound to each group/part.

var config = {
    width: 600
};

var data = [
    {
        height: 150,
        y: 0,
        parts: [
            {
                title: "Hello",
                x: 50,
                y: 60
            },
            {
                title: "World",
                x: 350,
                y: 60
            }
        ]        
    },
    {
        height: 150,
        y: 155,
        parts: [
            {
                title: "Demo",
                x: 280,
                y: 215
            }
        ]        
    }
];

var svg = d3.select("body").append("svg").attr("width", config.width).attr("height", 500);

var g = svg.selectAll("g")
                .data(data)
                .enter()
                .append("g");

    g.append("rect")
        .attr("x", 1)
        .attr("y", function(d) { return d.y; })
        .attr("width", config.width)
        .attr("height", function(d) { return d.height; });
    
var parts = g.selectAll("g.part")
                .data(function(d) { return d.parts; })
                .enter()
                .append("g")
                    .attr("class", "part");

    parts.append("rect")
        .attr({
        "class": "part",
        "x": function(d) { return d.x; },
        "y": function(d) { return d.y; },
        "width": 200,
        "height":80
        });
    
    parts.append("text")
        .attr({
        "class": "part",
        "x": function(d) { return d.x; },
        "y": function(d) { return d.y; }
        })
        .text(function(d) { return d.title; });    
g.part rect {
    fill:white;
}

g.part text {
    fill: red;
    stroke: none;
    font-size:20px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>

Upvotes: 3

Gilsha
Gilsha

Reputation: 14591

Use d3 selector each method.

g.each(function(d, i) {
    var rect = d3.select(this);
    d.parts.forEach(function(p) {
        rect.append("rect")
            .style("fill", "aliceblue")
            .attr("x", p.x)
            .attr("y", p.y)
            .attr("width", config.width / 3)
            .attr("height", d.height / 2);
        rect.append("text")
            .style("stroke", "brown")
            .attr("x", p.x)
            .attr("y", p.y)
            .text(p.title);
    });
});

var config = {
    width: 600
};

var data = [{
    height: 150,
    y: 0,
    parts: [{
        title: "Hello",
        x: 50,
        y: 60,
    }, {
        title: "World",
        x: 350,
        y: 60,
    }],
}, {
    height: 150,
    y: 155,
    parts: [{
        title: "Demo",
        x: 280,
        y: 215,
    }],
}, ];

var svg = d3.select("body").append("svg").attr("width", config.width).attr("height", 500);

var g = svg.selectAll("g")
    .data(data)
    .enter()
    .append("g");

g.append("rect")
    .attr("x", 1)
    .attr("y", function(d) {
        return d.y;
    })
    .attr("width", config.width)
    .attr("height", function(d) {
        return d.height;
    });

g.each(function(d, i) {
    var rect = d3.select(this);
    d.parts.forEach(function(p) {
        rect.append("rect")
            .style("fill", "aliceblue")
            .attr("x", p.x)
            .attr("y", p.y)
            .attr("width", config.width / 3)
            .attr("height", d.height / 2);
        rect.append("text")
            .style("stroke", "brown")
            .attr("x", p.x)
            .attr("y", p.y)
            .text(p.title);
    });
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>

Upvotes: 0

Related Questions