1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 | 1× 1× 1× 1× 1× 1× 1× 1× 1× 1× 1× 1× 1× 1× 1× 1× 1× 1× 1× | /* eslint-env browser */ const d3 = Object.assign({}, require('d3-selection'), require('d3-scale'), require('d3-axis'), require('d3-ease')); /** * Builds a Bar Chart. * @constructor * @param {String} mode (init / refresh) * @exports barChart */ const barChart = function chart() { const svgContainer = d3.select(`#${this.chartData.selector}`); let cs = { palette: { fill: '#005792', stroke: '#d1f4fa', }, bar: { hPadding: 8, vPadding: 5, }, x: { axisHeight: 10, ticks: 5, }, y: { domain: [], range: [], axisWidth: null, }, }; /** * @method getWidth * @param {Object} d (svg element) * @description Returns width of the bar */ const getWidth = d => cs.x.scale(d.metric); /** * @method getHeight * @description Returns height of the bar */ const getHeight = () => ( this.height - cs.x.axisHeight - this.header - cs.bar.vPadding) / this.ds.length - 1; /** * @method getYCoord * @param {Object} d (svg element) * @param {Object} i (svg element) * @description Returns y axis co-ordinate of the bar */ const getYCoord = (d, i) => i * ( this.height - cs.x.axisHeight - this.header) / this.ds.length + 1 + this.header; /** * @method mouseOver * @param {Object} d (svg element) * @description Adds a tooltip on mouse over */ const mouseOver = (d) => { this.addTooltip(d, window.event); }; /** * @method mouseOut * @param {Object} d (svg element) * @description Removes tooltip on mouse out */ const mouseOut = (d) => { this.removeTooltip(d); }; /** * @method enter * @param {Object} rects (svg element) * @description Runs when a new element is added to the dataset */ const enter = (rects) => { rects.enter() .append('rect') .attr('fill', cs.palette.fill) .attr('stroke', cs.palette.stroke) .attr('class', this.selector) .attr('width', getWidth) .attr('height', getHeight) .attr('y', getYCoord) .attr('x', cs.y.axisWidth + cs.bar.hPadding) .on('mouseover', mouseOver) .on('mouseout', mouseOut); return rects; }; /** * @method transition * @param {Object} rects (svg element) * @description Runs when a value of an element in dataset is changed */ const transition = (rects) => { rects.transition() .attr('width', getWidth) .attr('height', getHeight) .attr('y', getYCoord) .attr('x', cs.y.axisWidth + cs.bar.hPadding); return rects; }; /** * @method exit * @param {Object} rect (svg element) * @description Runs when an element is removed from the dataset */ const exit = (rects) => { rects.exit().remove(); return rects; }; /** * @method buildScales * @description builds the scales for the x and y axes */ const buildScales = () => { cs.x.scale = d3.scaleLinear() .domain([0, this.max]) .range([0, this.width - cs.bar.hPadding - cs.y.axisWidth]); this.ds.forEach(t => cs.y.domain.push(t.dim)); this.ds.forEach((t, i) => cs.y.range.push((( this.chartData.height - cs.x.axisHeight - this.header + cs.bar.vPadding) * i) / this.ds.length)); cs.y.scale = d3.scaleOrdinal().domain(cs.y.domain).range(cs.y.range); }; /** * @method drawAxis * @description draws the x and y axes on the svg */ const drawAxis = () => { cs.x.axis = d3.axisBottom().ticks(cs.x.ticks, 's').scale(cs.x.scale); cs.y.axis = d3.axisLeft().scale(cs.y.scale); cs.x.yOffset = this.height - cs.x.axisHeight; cs.x.xOffset = cs.bar.hPadding + cs.y.axisWidth; cs.y.yOffset = cs.bar.vPadding + this.header - 1; cs.y.xOffset = cs.y.axisWidth; if (this.ds[0].dim) svgContainer.append('g').attr('class', 'axis').attr('transform', `translate(${cs.y.xOffset}, ${cs.y.yOffset})`).call(cs.y.axis); svgContainer.append('g').attr('class', 'axis').attr('transform', `translate(${cs.x.xOffset}, ${cs.x.yOffset})`).call(cs.x.axis); }; const getMaxDimLength = (accumulator, currentValue) => { return (currentValue.dim.length > accumulator) ? currentValue.dim.length : accumulator; } const rects = svgContainer.selectAll('rect').data(this.ds); cs = this.setOverrides(cs, this.chartData.overrides); cs.y.axisWidth = cs.y.axisWidth || (this.ds.reduce(getMaxDimLength, 0)) * 10; buildScales(cs); drawAxis(cs); enter(rects); transition(rects); exit(rects); }; export default barChart; |