chart = dataset => {
const height = 300
const svg = d3.create("svg")
.attr("viewBox", [0, 0, width, height])
const fmt = d3.format(".1f")
const yPos = i => (i + 1) * 35
const textPos = i => yPos(i) + 4
svg.append('g')
.attr('class', 'boxes')
.attr('transform', `translate(0, ${height * 0.30})`)
const twoLines = (selection, d) => {
selection.append('line')
.attr('y1', (d, i) => yPos(i))
.attr('y2', (d ,i) => yPos(i))
.transition()
.attr('x1', d => x(d[0]))
.attr('x2', d => x(d[1]) - 0.25)
.call(enter => enter.transition()
.attr("x1", d => x(d[0])))
selection.append('line')
.attr('y1', (d, i) => yPos(i))
.attr('y2', (d ,i) => yPos(i))
.transition()
.attr('x1', d => x(d[1]) + 0.25)
.attr('x2', d => x(d[2]))
.call(enter => enter.transition()
.attr("x2", d => x(d[2])))
selection.append('text').text(d => fmt(d[0]))
.attr('y', (d, i) => textPos(i))
.attr('x', d => x(d[0]) - 2)
.style('fill', 'black')
.style('text-anchor', 'end'),
selection.append('text').text(d => fmt(d[1]))
.attr('y', (d, i) => textPos(i)-17)
.attr('x', d => x(d[1]))
.style('fill', 'black')
.style('text-anchor', 'middle')
selection.append('text').text(d => fmt(d[2]))
.attr('y', (d, i) => textPos(i))
.attr('x', d => x(d[2]) + 2)
.style('fill', 'black')
.style('text-anchor', 'start')
return selection
}
const twoLinesUpdate = (selection, d) => {
selection
.attr('y1', (d, i) => yPos(i))
.attr('y2', (d ,i) => yPos(i))
.transition()
.attr('x1', d => x(d[0]))
.attr('x2', d => x(d[1]) - 0.25)
selection
.attr('y1', (d, i) => yPos(i))
.attr('y2', (d ,i) => yPos(i))
.transition()
.attr('x1', d => x(d[1]) + 0.25)
.attr('x2', d => x(d[2]))
return selection
}
svg.select('.boxes').selectAll('line').data(dataset).join(
enter => {
enter.call(twoLines,dataset)
},
update => {
update.call(twoLinesUpdate,dataset)
},
exit => {
exit.remove()
}
)
return svg.node()
}