Deepak Sharma
Deepak Sharma

Reputation: 458

Line Bar Chart in D3 js

I have been trying to implement a Line-Bar Combo Chart but I'm not much successfull. Here's my code

function renderNormalizedStackBarChart(inputData,dom_element_to_append_to, path_to_data) {
            var margin = {top: 20, right: 231, bottom: 140, left: 40}, 
            width = $(dom_element_to_append_to).width() - margin.left - margin.right,
            height = 500 - margin.top - margin.bottom;

            var xscale = d3.scale.ordinal()
            .rangeRoundBands([0, width], .1);

            var yScaleLeft = d3.scale.linear()
            .rangeRound([height, 0]);

            var yScaleRight = d3.scale.linear()
            .rangeRound([height, 0]);

            var colors = d3.scale.ordinal()
            .range(["#63c172", "#ee9952", "#46d6c4", "#fee851", "#98bc9a"]);

            var xaxis = d3.svg.axis()
            .scale(xscale)
            .orient("bottom");

            var yAxisLeft = d3.svg.axis()
            .scale(yScaleLeft)
            .orient("left")
            .tickFormat(d3.format(".0%")); 

            var yAxisRight = d3.svg.axis()
            .scale(yScaleRight)
            .orient("right")
            .tickFormat(d3.format(".0%"));

            var x = d3.time.scale()
            .range([0, width - 25]);


            /*category.selectAll("rect")
            .data(function(d) { return d.responses; })
            .enter().append("rect")
            .attr("width", xscale.rangeBand())
            .attr("y", function(d) { return yScaleLeft(d.yp1); })
            .attr("height", function(d) { return yScaleLeft(d.yp0) - yScaleLeft(d.yp1); })
            .style("fill", function(d) { return colors(d.response); });*/
            var temp  = 0;
            var line = d3.svg.line()
            .x(function(d, i) {
                console.log(temp);
                var temp2 = temp;
                temp += xscale.rangeBand();
                return temp2;
            })
            .y(function(d) {
                console.log(yScaleRight(d.value));
                return yScaleRight(d.value);
            })
            .interpolate("linear")
            ;

            var svg = d3.select(dom_element_to_append_to).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 + ")");


            d3.tsv(path_to_data, function(error, data) {
                //data = inputData;
               
                var categories = d3.keys(data[0]).filter(function(key) { return key !== "CategoryNames"; });
                var parsedata = categories.map(function(name) { return { "CategoryNames": name }; });
                data.forEach(function(d) {
                    parsedata.forEach(function(pd) {
                        pd[d["CategoryNames"]] = d[pd["CategoryNames"]];
                    });
                });

              
                colors.domain(d3.keys(parsedata[0]).filter(function(key) { return key !== "CategoryNames" && key !== "Base"; }));


                parsedata.forEach(function(pd) {
                    var y0 = 0;

                    pd.responses = colors.domain().map(function(response) {
                        var responseobj = {response: response, y0: y0, yp0: y0};
                        y0 += +pd[response];
                        responseobj.y1 = y0;
                        responseobj.yp1 = y0;
                        return responseobj;
                    });

                    pd.responses.forEach(function(d) { d.yp0 /= y0; d.yp1 /= y0; });

                    pd.totalresponses = pd.responses[pd.responses.length - 1].y1;
                });
                console.log(parsedata);
                xscale.domain(parsedata.map(function(d) { return d.CategoryNames; }));


                svg.append("g")
                .attr("class", "x axis")
                .attr("transform", "translate(0," + height + ")")
                .call(xaxis)
                .selectAll("text")
                .attr("y", 5)
                .attr("x", 7)
                .attr("dy", ".35em")
                .attr("transform", "rotate(65)")
                .style("text-anchor", "start");


                svg.append("g")
                .attr("class", "y axisLeft")
                .call(yAxisLeft);

                svg.append("g")
                .attr("class", "y axisRight")
                .attr("transform", function() { return "translate(" + width + "," + 0 + ")"; })
                .call(yAxisRight);

                var category = svg.selectAll(".category")
                .data(parsedata)
                .enter().append("g")
                .attr("class", "category")
                .attr("transform", function(d) { return "translate(" + xscale(d.CategoryNames) + ",0)"; });


                category.selectAll("rect")
                .data(function(d) { return d.responses; })
                .enter().append("rect")
                .attr("width", xscale.rangeBand())
                .attr("y", function(d) { return yScaleLeft(d.yp1); })
                .attr("height", function(d) { return yScaleLeft(d.yp0) - yScaleLeft(d.yp1); })
                .style("fill", function(d) { return colors(d.response); });
                
                var convertedData = [];
                parsedata.forEach(function(item) {
                    convertedData.push({response: item.CategoryNames, value: item.responses[0].yp1})
                });
                temp = xscale.rangeBand()/2;
                console.log(convertedData);
                svg.append("path")
                .data(convertedData)
                .attr("class", "line")
                
                .attr("d", line(convertedData));

                var legend = svg.selectAll(".legend")
                .data(colors.domain())
                .enter().append("g")
                .attr("class", "legend")
                .attr("transform", function(d, i) { return "translate(82," + ((height - 18) - (i * 20)) + ")"; });

                legend.append("rect")
                .attr("x", width - 18)
                .attr("width", 18)
                .attr("height", 18)
                .style("fill", colors);

                legend.append("text")
                .attr("x", width + 10)
                .attr("y", 9)
                .attr("dy", ".35em")
                .style("text-anchor", "start")
                .text(function(d) { return d; });


                d3.selectAll("input").on("change", handleFormClick);

                function handleFormClick() {
                    if (this.value === "bypercent") {
                        transitionPercent();
                    } else {
                        transitionCount();
                    }
                }


                function transitionPercent() {

                    yScaleLeft.domain([0, 1]);


                    var trans = svg.transition().duration(250);


                    var categories = trans.selectAll(".category");
                    categories.selectAll("rect")
                    .attr("y", function(d) { return yScaleLeft(d.yp1); })
                    .attr("height", function(d) { return yScaleLeft(d.yp0) - yScaleLeft(d.yp1); });


                    yAxisLeft.tickFormat(d3.format(".0%"));
                    svg.selectAll(".y.axisLeft").call(yAxisLeft);
                }


                function transitionCount() {

                    yScaleLeft.domain([0, d3.max(parsedata, function(d) { return d.totalresponses; })]);


                    var transone = svg.transition()
                    .duration(100);


                    var categoriesone = transone.selectAll(".category");
                    categoriesone.selectAll("rect")
                    .attr("y", function(d) { return this.getBBox().y + this.getBBox().height - (yScaleLeft(d.y0) - yScaleLeft(d.y1)) })
                    .attr("height", function(d) { return yScaleLeft(d.y0) - yScaleLeft(d.y1); });


                    var transtwo = transone.transition()
                    .delay(150)
                    .duration(200)
                    .ease("bounce");

                    var categoriestwo = transtwo.selectAll(".category");
                    categoriestwo.selectAll("rect")
                    .attr("y", function(d) { return yScaleLeft(d.y1); });


                    yAxisLeft.tickFormat(d3.format(".2s"));
                    svg.selectAll(".y.axisLeft").call(yAxisLeft);
                }
            });

d3.select(self.frameElement).style("height", (height + margin.top + margin.bottom) + "px");
}
var inputData = [];
renderNormalizedStackBarChart(inputData,"#normalizedChart", "data/normalizedChart.tsv");
 rect.bordered {
            stroke: #E6E6E6;
            stroke-width: 2px;
        }

        body {
            font-size: 9pt;
            font-family: Consolas, courier;
        }

        text.axis {
            fill: #000;
        }
        
        .axisLeft path,
        .axisLeft line {
            fill: none;
            stroke: #000;
            shape-rendering: crispEdges;
        }

        .axisRight path,
        .axisRight line {
            fill: none;
            stroke: #000;
            shape-rendering: crispEdges;
        }

        .bar {
            fill: steelblue;
        }
       
        .x.axis path {
            display: none;
        }
        
        .legend line {
            stroke: #000;
            shape-rendering: crispEdges;
        }
        path .line {
            stroke: #000;
            shape-rendering: crispEdges;
        }

        form {
            position: absolute;
            right: 10px;
            top: 10px;
        }
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.3.13/d3.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.7/angular.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.1/jquery.min.js"></script>
<div class="row">
        <form>
          <label><input type="radio" name="mode" value="bypercent" checked> Percent</label>
          <label><input type="radio" name="mode" value="bycount"> Number of Respondants</label>
        </form>
                
        <div id="normalizedChart"></div>
        </div>

but all I'm getting is the graph shown in the image below. How to make the path appear as line.Here in the code InputData variable is of no use as I'm reading data through a tsv file. enter image description here

Upvotes: 0

Views: 178

Answers (1)

Tim B
Tim B

Reputation: 1983

You have to add the style to your fill : none to your path

svg.append("path")
    .data(convertedData)
    .attr("class", "line")
    .attr("d", line(convertedData));
    .attr("stroke", "blue")
    .attr("stroke-width", 2)
    .attr("fill", "none");

Upvotes: 1

Related Questions