0

I'm trying to get a bar chart running based on this example.

 <body>
    </body>
    <script>
        var width = 960, height = 500;
        var margin = {top: 20, right: 20, bottom: 30, left: 40};

        //data
        var data = [ {"x":"A","y":0.15}, {"x":"B","y":0.10}, {"x":"C","y":0.35} ];

        //x and y Scales
        var xScale = d3.scale.ordinal()
            .rangeRoundBands([0, width], .1);

        var yScale = d3.scale.linear()
            .range([height, 0]);

        //x and y Axes
        var xAxis = d3.svg.axis()
            .scale(xScale)
            .orient("bottom");

        var yAxis = d3.svg.axis()
            .scale(yScale)
            .orient("left")
            .ticks(10, "%");

        //create svg container
        var svg = d3.select("body")
            .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 + ")");        

        //create bars
        d3.selectAll(".bar")
            .data(data)
            .enter()
            .append("rect")
            .attr("class", "bar")
            .attr("x", function(d) { return xScale(d.letter); })
            .attr("width", xScale.rangeBand())
            .attr("y", function(d) { return yScale(d.frequency); })
            .attr("height", function(d) { return height - yScale(d.frequency); });

        //drawing the x axis on svg
        svg.append("g")
            .attr("class", "x axis")
            .attr("transform", "translate(0," + height + ")")
            .call(xAxis);

        //drawing the y axis on svg
        svg.append("g")
            .attr("class", "y axis")
            .call(yAxis)
            .append("text")
            .attr("transform", "rotate(-90)")
            .attr("y", 6)
            .attr("dy", ".71em")
            .style("text-anchor", "end")
            .text("Frequency");
    </script>

All I see is the Y axis and nothing else. What am I missing?

1 Answer 1

2

There are three problems with your code. First, you need to set the domains of your scales. In the example, the code to do that is

x.domain(data.map(function(d) { return d.letter; }));
y.domain([0, d3.max(data, function(d) { return d.frequency; })]);

which you need to adapt to your variable names and data:

xScale.domain(data.map(function(d) { return d.x; }));
yScale.domain([0, d3.max(data, function(d) { return d.y; })]);

Second, you need to use svg when selecting the .bar elements so that the new bars are appended to the SVG:

svg.selectAll(".bar")
   .data(data)
   .enter()
   // etc

Finally, you forgot to change the data elements when copying and pasting. Your code still refers to .letter and .frequency when it should be .x and .y:

.attr("x", function(d) { return xScale(d.x); })
.attr("width", xScale.rangeBand())
.attr("y", function(d) { return yScale(d.y); })
.attr("height", function(d) { return height - yScale(d.y); });

Complete demo here.

4
  • thanks. I forked your demo here where I tried to add a transition. But it doesn't seem to work.
    – John Eipe
    Commented Apr 22, 2014 at 7:54
  • Rectangles have no cx or cy attributes. You need to update the attributes you're setting initially (and also the axes): jsfiddle.net/7Pm6f/2 Commented Apr 22, 2014 at 8:17
  • thanks. I thought transition() needs to come between data() and enter() so that the transition effect happens but your code works to my surprise. :)
    – John Eipe
    Commented Apr 22, 2014 at 8:43
  • The enter selection merges into the update selection once you've added the elements -- this is what I'm using there. Commented Apr 22, 2014 at 8:55

Not the answer you're looking for? Browse other questions tagged or ask your own question.