block by nivas8292 66a3d472acdc1557d2fc

Column Bar Chart with Sort Animation

Full Screen

index.html

<html>
    <head>
        <title>D3 Bar Chart</title>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <link rel="stylesheet" href="main.css">
        <script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js"></script>
    </head>
    <body>
        <script>
            var N = 10;
            var w = 800;
            var h = 450;
            var margin = {
                top: 20,
                bottom: 100,
                left: 80,
                right: 20
            };
            var width = w - margin.left - margin.right;
            var height = h - margin.top - margin.bottom;
            var dataset = [
                {key: "Glazed", value: 132},
                {key: "Jelly", value: 71},
                {key: "Holes", value: 337},
                {key: "Sprinkles", value: 93},
                {key: "Crumb", value: 78},
                {key: "Chocolate", value: 43},
                {key: "Coconut", value: 20},
                {key: "Cream", value: 16},
                {key: "Cruller", value: 30},
                {key: "Éclair", value: 8},
                {key: "Fritter", value: 17},
                {key: "Bearclaw", value: 21}
            ];

            var yScale = d3.scale.linear()
                    .domain([0, d3.max(dataset, function (d) {
                            return d.value
                        })])
                    .range([height, 0]);

            var xScale = d3.scale.ordinal()
                    .domain(dataset.map(function (d) {
                        return d.key
                    }))
                    .rangeBands([0, width]);

            var linearColorScale = d3.scale.linear()
                    .domain([0, dataset.length])
                    .range(["#572500", "#F68026"]);

            var ordinalColorScale = d3.scale.category20();

            var xAxis = d3.svg.axis()
                    .scale(xScale)
                    .orient("bottom");

            var yAxis = d3.svg.axis()
                    .scale(yScale)
                    .orient("left");

            var yGridLines = d3.svg.axis()
                    .scale(yScale)
                    .tickSize(-width, 0, 0)
                    .tickFormat("")
                    .orient("left");

            var chartGroup = d3.select("body")
                    .append("svg")
                    .attr("id", "chart")
                    .attr("height", h)
                    .attr("width", w)
                    .append("g")
                    .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

            var controls = d3.select("body")
                    .append("div")
                    .attr("id", "control");

            var sort_btn = controls.append("button")
                    .attr("state", 0)
                    .html("Sort data: Ascending");

            function drawAxis(params) {
                if (params.initialize === true) {
                    //Draw Gridlines
                    this.append("g")
                            .call(params.gridline)
                            .classed('gridline', true);

                    //Draw X Axis
                    this.append("g")
                            .classed("x axis", true)
                            .attr("transform", "translate(" + 0 + " , " + height + ")")
                            .call(params.axis.x)
                            .selectAll("text")
                            .classed("x-axis-label", true)
                            .style("text-anchor", "end")
                            .attr("dx", -8)
                            .attr("dy", 8)
                            .attr("transform", "translate(0, 0) rotate(-45)");

                    //Draw Y Axis
                    this.append("g")
                            .classed("y axis", true)
                            .attr("transform", "translate(" + 0 + "," + 0 + ")")
                            .call(params.axis.y);

                    //Draw Y Label
                    this.select(".y.axis")
                            .append("text")
                            .attr("x", 0)
                            .attr("y", 0)
                            .style("text-anchor", "middle")
                            .attr("transform", "translate(-50," + height / 2 + ") rotate(-90)")
                            .text("Units Sold");

                    //Draw X Label
                    this.select(".x.axis")
                            .append("text")
                            .attr("x", 0)
                            .attr("y", 0)
                            .style("text-anchor", "middle")
                            .attr("transform", "translate(" + width / 2 + ", 80)")
                            .text("Donut Type");

                } else if (params.initialize === false) {
                    this.selectAll("g.x.axis")
                            .transition()
                            .duration(500)
                            .call(params.axis.x);
                    this.selectAll(".x-axis-label")
                            .style("text-anchor", "end")
                            .attr("dx", -8)
                            .attr("dy", 8)
                            .attr("transform", "translate(0, 0) rotate(-45)");

                    this.selectAll("g.y.axis")
                            .transition()
                            .duration(500)
                            .call(params.axis.y);
                }

            }
            function plot(params) {
                yScale.domain([0, d3.max(params.data, function (d) {
                        return d.value
                    })]);
                xScale.domain(params.data.map(function (d) {
                    return d.key
                }));

                drawAxis.call(this, params);

                //Enter Phase
                this.selectAll(".bar")
                        .data(params.data)
                        .enter()
                        .append("rect")
                        .classed("bar", true)
                        .on("mouseover", function (d, i) {
                            d3.select(this).style("fill", "yellow")
                        })
                        .on("mouseout", function (d, i) {
                            d3.select(this).style("fill", ordinalColorScale(d.key));
                        });


                this.selectAll(".bar-label")
                        .data(dataset)
                        .enter()
                        .append("text")
                        .classed("bar-label", true);

                //Update Phase
                this.selectAll(".bar")
                        .transition()
                        .duration(500)
                        .ease("bounce")
                        .delay(function (d, i) {
                            return i * 50
                        })
                        .attr("x", function (d, i) {
                            return xScale(d.key)
                        })
                        .attr("y", function (d, i) {
                            return yScale(d.value)
                        })
                        .attr("width", function (d, i) {
                            return xScale.rangeBand()
                        })
                        .attr("height", function (d, i) {
                            return height - yScale(d.value)
                        })
                        //.style("fill", function(d, i) {return linearColorScale(i)});	
                        .style("fill", function (d, i) {
                            return ordinalColorScale(d.key)
                        });

                this.selectAll(".bar-label")
                        .transition()
                        .duration(500)
                        .ease("bounce")
                        .delay(function (d, i) {
                            return i * 50
                        })
                        .attr("x", function (d, i) {
                            return xScale(d.key) + xScale.rangeBand() / 2
                        })
                        .attr("y", function (d, i) {
                            return yScale(d.value)
                        })
                        .attr("dy", 15)
                        .text(function (d, i) {
                            return d.value
                        })
                        .style("fill", "black")
                        .style("text-anchor", "middle");

                //Exit Phase
                this.selectAll(".bar")
                        .data(params.data)
                        .exit()
                        .remove();

                this.selectAll(".bar-label")
                        .data(params.data)
                        .exit()
                        .remove();

            }

            plot.call(chartGroup, {
                data: dataset,
                axis: {
                    x: xAxis,
                    y: yAxis
                },
                gridline: yGridLines,
                initialize: true
            });

            sort_btn.on("click", function () {
                var self = d3.select(this);
                var state = +self.attr("state");
                var ascending = function (a, b) {
                    return a.value - b.value
                }
                var descending = function (a, b) {
                    return b.value - a.value
                }
                var txt = "Sort data: ";
                if (state === 0) {
                    dataset.sort(ascending);
                    state = 1;
                    txt += "Descending";
                } else if (state === 1) {
                    dataset.sort(descending);
                    state = 0;
                    txt += "Ascending";
                }
                self.attr("state", state);
                self.html(txt);
                plot.call(chartGroup, {
                    data: dataset,
                    axis: {
                        x: xAxis,
                        y: yAxis
                    },
                    gridline: yGridLines,
                    initialize: false
                });
            });
        </script>
    </body>
</html>

main.css

body, html {
    margin:0;
    padding:0;
    font-family:"Arial", sans-serif;
    font-size:0.95em;
    text-align:center;
}

#chart {
    background-color:#F5F2EB;
    border: 1px solid #CCC;
}

.bar {
    fill:purple;
    shape-rendering:crispEdges;
}

.bar-label {
    text-anchor:end;
    fill:white;
}

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

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

.trendline {
    fill: none;
    stroke: #ccc;
    stroke-width: 2;
    /*stroke-dasharray:10;*/
}

.area {
    fill: #ccc;
    stroke: #ccc;
    opacity: 0.25;
}

.donut {
    opacity:0.1;
}
.axis-label {
    text-anchor: middle;
}
.chart-header {
    text-transform: capitalize;
    font-size: 110%;
}
.temperature {
    stroke:#95cddf;
    stroke-width:2px;
}

.rain {
    fill:none;
    stroke:#cc627a;
    stroke-width:0.5;
}

#cursor {
    stroke: black;
}