barchart.js 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. class Barchart extends Chart {
  2. constructor(customId) {
  3. super(customId);
  4. //////////
  5. // AXES //
  6. //////////
  7. this.x = d3.scaleLinear()
  8. .range([this.margin.left, this.width - this.margin.right]);
  9. this.y = d3.scaleBand()
  10. .rangeRound([this.height - this.margin.bottom, this.margin.top])
  11. .padding(0.1);
  12. this.xAxis = d3.axisBottom(this.x).ticks(10);
  13. this.yAxis = d3.axisLeft(this.y).ticks(0);
  14. this.svg.append("g")
  15. .attr('id', "axis--x-" + this.customId)
  16. .attr("transform", "translate(0," + (this.height - this.margin.bottom) + ")")
  17. .call(this.xAxis);
  18. this.svg.append("g")
  19. .attr('id', "axis--y-" + this.customId)
  20. // offset to right so ticks are not covered
  21. .attr("transform", "translate(" + (this.margin.left) + ",0)")
  22. .call(this.yAxis)
  23. /////////////
  24. // SPECIAL //
  25. /////////////
  26. this.labels = ["picked", "selected", "all"];
  27. d3.selectAll(".checkbox-" + this.customId).on("change", () => {
  28. this.draw();
  29. });
  30. }
  31. updateAndDraw(chartData) {
  32. let data = []
  33. for (const idx in chartData[0]) {
  34. let arr = chartData[0][idx];
  35. data.push({"name":arr.name,
  36. [this.labels[0]]:arr.value[0],
  37. [this.labels[1]]:arr.value[1],
  38. [this.labels[2]]:arr.value[2]});
  39. }
  40. this.data = data;
  41. this.draw();
  42. }
  43. draw() {
  44. // calculate max domain x
  45. let maxDomainXList = [0];
  46. d3.selectAll(".checkbox-" + this.customId).each((d, i, nodes) => {
  47. let checkbox = d3.select(nodes[i]);
  48. if(checkbox.property("checked")) {
  49. let group = checkbox.property("value");
  50. let maxVal = d3.max(this.data, (d) => {return d[group]; });
  51. maxDomainXList.push(maxVal);
  52. }
  53. });
  54. this.x.domain([0, d3.max(maxDomainXList)]);
  55. this.y.domain(this.data.map((d) => {return d.name; }));
  56. // redraw bars
  57. for (const idx in this.labels) {
  58. // draw group in reverse order (slice makes new array so original is not modified)
  59. let group = this.labels.slice().reverse()[idx];
  60. // ex: checkbox-barchart-picked
  61. let unchecked = !d3.select("#checkbox-"+ this.customId + "-" + [group]).property("checked");
  62. let bars = this.svg.selectAll(".bar-" + [group])
  63. .data(this.data);
  64. // new data (optical illusion animation, bars are inverse)
  65. bars
  66. .enter().append("rect")
  67. .attr("class", "bar-" + [group])
  68. .attr("y", (d) => { return this.y(d.name); })
  69. .attr("height", (d) => { return this.y.bandwidth(); })
  70. .attr("x", (d) => {
  71. if (unchecked) { return 0; }
  72. return this.x(d[group]); })
  73. .attr("width", (d) => {
  74. if (unchecked) { return 0; }
  75. return this.width - (this.x(d[group])); });
  76. bars.exit().remove();
  77. // updated data:
  78. bars.transition()
  79. .duration(750)
  80. .attr("y", (d) => { return this.y(d.name); })
  81. .attr("height", (d) => { return this.y.bandwidth(); })
  82. .attr("x", (d) => {
  83. if (unchecked) { return 0; }
  84. return this.margin.left })
  85. .attr("width", (d) => {
  86. if (unchecked) { return 0; }
  87. return this.x(d[group]) - this.margin.left; });
  88. }
  89. // update axes
  90. this.svg.select("#axis--y-" + this.customId).transition().duration(750).call(this.yAxis)
  91. this.svg.select("#axis--x-" + this.customId).transition().duration(750).call(this.xAxis)
  92. }
  93. }