Made this as an answer to this: https://stackoverflow.com/a/53380041/7473025
Last active
November 21, 2018 14:10
-
-
Save LemoNode/903d4cffe5ec49bb0ee24cc75600ef0b to your computer and use it in GitHub Desktop.
Horizontal bar chart
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <!DOCTYPE html> | |
| <html> | |
| <head> | |
| <title></title> | |
| <style type="text/css"> | |
| body { | |
| margin: auto; | |
| width: 650px; | |
| font: 12px arial; | |
| } | |
| </style> | |
| <script src="https://d3js.org/d3.v5.min.js"></script> | |
| </head> | |
| <body> | |
| <svg id="chart" width="600" height="380"></svg><br> | |
| Choose year: | |
| <select id="year"></select> | |
| <script type="text/javascript"> | |
| var init = [ | |
| {"year": "2017", "name": "Apples", "value": 20}, | |
| {"year": "2017", "name": "Bananas","value": 12}, | |
| {"year": "2017", "name": "Grapes", "value": 19}, | |
| {"year": "2017", "name": "Lemons", "value": 5}, | |
| {"year": "2017", "name": "Limes", "value": 16}, | |
| {"year": "2017", "name": "Oranges", "value": 26}, | |
| {"year": "2017", "name": "Pears","value": 30}, | |
| {"year": "2018", "name": "Apples", "value": 10}, | |
| {"year": "2018", "name": "Bananas","value": 42}, | |
| {"year": "2018", "name": "Grapes", "value": 69}, | |
| {"year": "2018", "name": "Lemons", "value": 15}, | |
| {"year": "2018", "name": "Limes", "value": 26}, | |
| {"year": "2018", "name": "Oranges", "value": 36}, | |
| {"year": "2018", "name": "Pears","value": 20} | |
| ]; | |
| chart(init) | |
| function chart(result) { | |
| var format = d3.format(",.0f") | |
| var years = [...new Set(result.map(d => d.year))] | |
| var fruit = [...new Set(result.map(d => d.name))] | |
| var options = d3.select("#year").selectAll("option") | |
| .data(years) | |
| .enter().append("option") | |
| .text(d => d) | |
| var svg = d3.select("#chart"), | |
| margin = {top: 25, bottom: 10, left: 50, right: 45}, | |
| width = +svg.attr("width") - margin.left - margin.right, | |
| height = +svg.attr("height") - margin.top - margin.bottom; | |
| var x = d3.scaleLinear() | |
| .range([margin.left, width - margin.right]) | |
| var y = d3.scaleBand() | |
| .range([margin.top, height - margin.bottom]) | |
| .padding(0.1) | |
| .paddingOuter(0.5) | |
| .paddingInner(0.5) | |
| var xAxis = svg.append("g") | |
| .attr("class", "x-axis") | |
| .attr("transform", `translate(0,${margin.top})`) | |
| var yAxis = svg.append("g") | |
| .attr("class", "y-axis") | |
| .attr("transform", `translate(${margin.left},0)`) | |
| update(d3.select("#year").property("value"), 750, 250) | |
| function update(input, speed, delay) { | |
| var data = result.filter(f => f.year == input) | |
| var sum = d3.sum(data, d => d.value) | |
| x.domain([0, d3.max(data, d => d.value)]).nice() | |
| svg.selectAll(".x-axis").transition().duration(speed) | |
| .call(d3.axisTop(x).tickSizeOuter(0)); | |
| data.sort((a, b) => b.value - a.value) | |
| y.domain(data.map(d => d.name)) | |
| svg.selectAll(".y-axis").transition().duration(speed) | |
| .call(d3.axisLeft(y)); | |
| yAxis.selectAll("text").remove() | |
| yAxis.selectAll("line").remove() | |
| var bar = svg.selectAll(".bar") | |
| .data(data, d => d.name) | |
| bar.exit().remove(); | |
| bar.enter().insert("g", ".y-axis").append("rect") | |
| .attr("class", "bar") | |
| .attr("fill", "#ccc") | |
| .attr("x", x(0)) | |
| .attr("y", d => y(d.name)) | |
| .attr("height", y.bandwidth()) | |
| .merge(bar) | |
| .transition().duration(speed) | |
| .delay((_, i) => delay * i) | |
| .attr("y", d => y(d.name)) | |
| .attr("width", d => x(d.value) - x(0)); | |
| var value = svg.selectAll(".value") | |
| .data(data, d => d.name) | |
| value.exit().remove(); | |
| value.enter().append("text") | |
| .attr("class", "value") | |
| .attr("opacity", 0) | |
| .attr("dy", 4) | |
| .attr("y", d => y(d.name) + y.bandwidth() / 2) | |
| .merge(value) | |
| .transition().duration(speed) | |
| .delay((_, i) => delay * i) | |
| .attr("opacity", 1) | |
| .attr("y", d => y(d.name) + y.bandwidth() / 2) | |
| .attr("x", d => x(d.value) + 5) | |
| .text(d => format((d.value / sum) * 100) + " %") | |
| var name = svg.selectAll(".name") | |
| .data(data, d => d.name) | |
| name.exit().remove(); | |
| name.enter().append("text") | |
| .attr("class", "name") | |
| .attr("opacity", 0) | |
| .attr("dy", -5) | |
| .attr("y", d => y(d.name)) | |
| .merge(name) | |
| .transition().duration(speed) | |
| .delay((_, i) => delay * i) | |
| .attr("opacity", 1) | |
| .attr("y", d => y(d.name)) | |
| .attr("x", d => x(0) + 5) | |
| .text(d => d.name) | |
| } | |
| var select = d3.select("#year") | |
| .style("border-radius", "5px") | |
| .on("change", function() { | |
| update(this.value, 750, 0) | |
| }) | |
| } | |
| </script> | |
| </body> | |
| </html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment