1
votes

Using d3.js, I'm trying to create a series of SVG groups (i.e. <g> elements), with a <g> element for each number in an array of data. Each <g> element should itself contain a <rect> and a <text>. The following code looks to me like it should do that, but when I inspect the <svg> element (in both Chrome and Firefox), it contains <rect> elements and <text> elements directly inside the <svg> element, with no <g> elements in sight.

The HTML page initially contains just an empty <svg> element. dataset is just a simple array of numbers.

var svg = d3.select("svg");

svg.selectAll("g")
    .data(dataset)
    .enter()
    .call( function(g) {
        g.append("rect")
            .attr("x", (d, i) => xScale(i))
            .attr("y", d => h - yScale(d))
            .attr("width", xScale.rangeBand())
            .attr("height", d => yScale(d))
            .attr("fill", d => "rgb(0,0," + (d*10) + ")")
            .on('click', d => console.log(d))
            .on('mouseover', function() {
                d3.select(this)
                    .attr('fill', 'orange');
                })
            .on('mouseout', function(d) {
                d3.select(this)
                    .transition()
                    .duration(250)
                    .attr("fill", d => "rgb(0,0," + (d*10) + ")")
                });
        })
    .call( function(g) {
        g.append('text')
            .text(d => d)
            .attr('class','label')
            .attr("x", (d, i) => xScale(i) + xScale.rangeBand() / 2)
            .attr("y", d =>  h - yScale(d) + 14);
        });
1

1 Answers

1
votes

I found my problem. I thought that selectAll('g').data(dataset).enter() would result in the <g> elements that don't match up with data in dataset being created for me. But they're not, and it's necessary to add .append('g') after the call to .enter() to actually create the missing <g> elements. After that, the function called by .call(...) will be passed the new <g> element.