const visualList = (() => { const xScale = d3.scaleLinear(); const yScale = d3.scaleBand(); return (svg, props) => { const data = props.data; const xValue = props.xValue; const yValue = props.yValue; const textValue = props.textValue; const margin = props.margin; const barPadding = props.barPadding; const verticalSpacing = props.verticalSpacing; const transitionDuration = props.transitionDuration; const transition = d3.transition() .duration(transitionDuration); data.sort((a, b) => d3.descending(xValue(a), xValue(b))); const width = +svg.attr('width'); const innerWidth = width - margin.left - margin.right; const innerHeight = verticalSpacing * data.length; svg .transition(transition) .attr('height', innerHeight + margin.top + margin.bottom); xScale .domain([0, d3.max(data, xValue)]) .range([0, innerWidth]); yScale .paddingInner(barPadding) .paddingOuter(barPadding / 2) .domain(data.map(yValue)) .range([0, innerHeight]); let g = svg.selectAll('g').data([null]); g = g.enter().append('g') .merge(g) .attr('transform', `translate(${margin.left},${margin.top})`); const groups = g.selectAll('g') .data(data, yValue); const groupsExit = groups.exit(); groupsExit .transition(transition) .remove(); const groupsEnter = groups .enter().append('g') .attr('transform', d => `translate(0,${yScale(yValue(d))})`); groups .merge(groupsEnter) .transition(transition) .attr('transform', d => `translate(0,${yScale(yValue(d))})`); const rects = groupsEnter .append('rect') .attr('fill', 'steelblue') .attr('width', 0) .merge(groups.select('rect')) .attr('height', yScale.bandwidth()) .transition(transition) .attr('width', d => xScale(xValue(d))); groupsExit.select('rect') .transition(transition) .attr('width', 0); const textBackground = groupsEnter .append('text') .attr('class', 'background') .style('font-size', '32pt') .style('font-family', 'Sans-Serif') .attr('x', 5) .attr('dy', '0.32em') .attr('fill', 'none') .attr('stroke', 'white') .attr('stroke-width', 5) .attr('stroke-linejoin', 'round') .merge(groups.select('.background')) .attr('y', yScale.bandwidth() / 2) .text(textValue); const textForeground = groupsEnter .append('text') .attr('class', 'foreground') .style('font-size', '32pt') .style('font-family', 'Sans-Serif') .attr('x', 5) .attr('dy', '0.32em') .merge(groups.select('.foreground')) .attr('y', yScale.bandwidth() / 2) .text(textValue); }; })();