chart = {
const globalScale = width / 5000
const svg = d3.create('svg')
.attr('viewBox', [0, 0, width, height])
const g = svg.append('g')
.attr('cursor', 'grab')
g.selectAll('rect')
.data(epochs)
.join('rect')
.attr('x', ({from}) => from)
.attr('y', height/4)
.attr('width', ({duration}) => duration)
.attr('height', height/2)
.attr('fill', (d, i) => d3.interpolateRainbow(i / 5))
.on('click', (event) => {
console.log('Clicked', event)
})
const groupEventLabels = svg.append('g')
.attr('class', 'event-labels')
.attr('cursor', 'grab')
const eventLabels = groupEventLabels.selectAll('event-labels')
.data(eventLabelsData)
.join('g')
.attr('transform', ({time}) => 'translate('+ time * globalScale +' '+height/2+')')
eventLabels.append('circle')
.attr('cx', 0)
.attr('cy', 20)
.attr('r', 1.5)
.attr('transform-origin', '50% 50%')
.attr('fill', 'black')
eventLabels.append('text')
.attr('x', 10)
.attr('y', 20)
.attr('text-anchor', 'start')
.attr('alignment-baseline', 'middle')
.text(d => d.text)
.attr('font-family', 'Verdana, sans-serif')
.attr("font-size", '14px')
.attr("fill", 'black')
eventLabels.append('rect')
.attr('x', -0.5)
.attr('y', 0)
.attr('width', 1)
.attr('height', height*0.8)
.attr('stroke', 'black')
.attr('stroke-width', 0)
.attr('fill', 'black')
const groupTimeLabels = svg.append('g')
.attr('class', 'time-labels')
.attr('cursor', 'grab')
const timeLabels = groupTimeLabels.selectAll('time-labels')
.data(timeLabelsData)
.join('g')
.attr('transform', ({time}) => 'translate('+ time * globalScale +' '+height/2+')')
timeLabels.append('circle')
.attr('cx', 0)
.attr('cy', height - 20)
.attr('r', 1.5)
.attr('transform-origin', '50% 50%')
.attr('fill', 'black')
timeLabels.append('text')
.attr('x', 10)
.attr('y', height - 20)
.attr('text-anchor', 'start')
.attr('alignment-baseline', 'middle')
.text(d => d.text)
.attr('font-family', 'Verdana, sans-serif')
.attr("font-size", '14px')
.attr("fill", 'black')
timeLabels.append('rect')
.attr('x', -0.5)
.attr('y', height*0.2)
.attr('width', 1)
.attr('height', height*0.8)
.attr('stroke', 'black')
.attr('stroke-width', 0)
.attr('fill', 'black')
const zoom = d3.zoom()
.extent(extent)
.scaleExtent(scaleExtent)
.translateExtent(translateExtent)
.on('zoom', () => {
const {k, x, y} = d3.event.transform
g.attr('transform', 'translate(' + x + ' 0) scale(' + (k) + ' 1)')
eventLabels.attr('transform', ({time}) => 'translate(' + (x + time * k) + ' '+ 10 +')')
timeLabels.attr('transform', ({time}) => 'translate(' + (x + time * k) + ' '+ 10 +')')
})
svg.call(zoom)
svg.call(zoom.scaleBy, globalScale)
return svg.node();
}