{
const svg = d3.select(DOM.svg(width, height))
const margin = {left: 60, top: height * 0.25, right: 60, bottom: 60}
const xScale = d3.scaleLinear().domain([0, d3.max(data, d => d.sum)])
.range([margin.left, width - margin.right])
const yScale = d3.scaleBand().domain(_.map(data, 'label'))
.range([margin.top, height - margin.bottom])
.padding(0.2)
const patterns = _.reduce(_.keys(colors), (obj, color) => {
obj[color] = textures
.lines()
.size(4)
.strokeWidth(1)
.stroke(colors[color])
svg.call(obj[color])
return obj
}, {})
const xAxis = d3.axisTop().scale(xScale)
.ticks(4).tickSize(-height + margin.top + margin.bottom).tickSizeOuter(0)
svg.append('g').attr('id', 'axis')
.attr('transform', `translate(0, ${margin.top})`).call(xAxis)
svg.append('g').attr('id', 'bars')
.selectAll('rect')
.data(data).join('rect')
.attr('transform', d => `translate(${margin.left}, ${yScale(d.label)})`)
.attr('width', d => xScale(d.sum) - margin.left)
.attr('height', yScale.bandwidth())
.attr('fill', colors.bar)
svg.append('g').attr('id', 'textures')
.selectAll('rect')
.data(data).join('rect')
.attr('transform', d => `translate(${margin.left}, ${yScale(d.label)})`)
.attr('width', d => xScale(d.sum) - margin.left)
.attr('height', yScale.bandwidth())
.attr('fill', patterns.pattern.url())
svg.append('g').attr('id', 'labels')
.selectAll('text')
.data(data).join('text')
.attr('transform', d =>
`translate(${xScale(d.sum) + 5}, ${yScale(d.label) + yScale.bandwidth() / 2})`)
.text(d => d.label)
svg.append('g').attr('id', 'sums')
.selectAll('text')
.data(data).join('text')
.attr('transform', d =>
`translate(${xScale(d.sum) + 5}, ${yScale(d.label) + yScale.bandwidth() / 2 + 16})`)
.text(d => d3.format(',')(d.sum))
return scrollSVG(svg.node())
}