{
const svg = d3.create('svg')
.attr('width', width)
.attr('height', width)
const wheel = svg.append('g')
.attr('transform', `translate(${width/2}, ${width/2})`)
wheel.classed('wheel')
data.rings.forEach((ring, i) => {
wheel.selectAll(`path .month-arcs`)
.data(data.years[0].monthAngles)
.enter().append('path')
.classed(`month-arcs`, true)
.attr('fill', (d,i) => colorScale(i%3, ring.color))
.attr('d', d => arcMaker({
startAngle: d.startAngle,
endAngle: d.endAngle,
innerRadius: ring.innerRadius,
outerRadius: ring.outerRadius
}))
if (!ring.simplified) {
wheel.selectAll(`path .week-lines`)
.data(data.years[0].weekAngles)
.enter().append('path')
.classed(`week-lines`, true)
.attr('stroke', 'white')
.attr('stroke-width', 1)
.attr('d', d => lineRadial([[d.startAngle, ring.innerRadius], [d.startAngle, ring.outerRadius]]))
}
})
data.rings.forEach((ring, i) => {
wheel.selectAll('path .periods')
.data(ring.periods)
.enter()
.append('path')
.classed('periods', true)
.attr('fill', ntnuSupportColors[ring.color])
.attr('stroke', ntnuSupportColorsDark[ring.color])
.attr('stroke-width', 2)
.attr('d', d => periodMaker({
startAngle: angleForDate(d.fromDate, data),
endAngle: angleForDate(d.toDate, data),
innerRadius: ring.innerRadius + 25, // Hand coded for design testing only
outerRadius: ring.outerRadius + 10
}))
.style('opacity', 0.7)
const tempInsetVariable = 25 // Shameful;y bad coding practice
wheel.selectAll('circle .events')
.data(ring.events)
.enter()
.append('circle')
.classed('events', true)
.attr('fill', ntnuSupportColors[ring.color])
.attr('stroke', ntnuSupportColorsDark[ring.color])
.attr('stroke-width', 2)
.attr('cx', d => d3.pointRadial(angleForDate(d.date, data), ring.outerRadius - tempInsetVariable)[0])
.attr('cy', d => d3.pointRadial(angleForDate(d.date, data), ring.outerRadius - tempInsetVariable)[1])
.attr('r', 20)
.style('opacity', 1)
wheel.selectAll('text .icon')
.data(ring.events)
.enter()
.append('text')
.classed('icon', true)
.attr('x', d => d3.pointRadial(angleForDate(d.date, data), ring.outerRadius - tempInsetVariable)[0])
.attr('y', d => d3.pointRadial(angleForDate(d.date, data), ring.outerRadius - tempInsetVariable)[1])
.attr('dy', 6)
.attr('text-anchor', 'middle')
.text(d => d.icon)
})
///////////////////////////////////////////////
// timeSlicer
///////////////////////////////////////////////
if (data.timeSlicer.show) {
const rotation = angleForDate(timeSlicerDate, data, 'start') * 360 / Tau
const timeSlicer = svg.append('g')
.attr('transform', `translate(${width/2}, ${width/2}) rotate(${rotation})`)
timeSlicer.classed('time-slicer')
timeSlicer.append('path')
.classed('time-slicer', true)
.attr('stroke', '#333')
.attr('stroke-width', 1.5)
.attr('d', lineRadial([[0, margin.linesInner], [0, width/2 - margin.linesOuter]]))
timeSlicer.append('circle')
.classed('time-slicer', true)
.attr('fill', '#333')
.attr('cx', 0)
.attr('cy', -margin.linesInner)
.attr('r', 3)
timeSlicer.append('circle')
.classed('time-slicer', true)
.attr('fill', '#333')
.attr('cx', 0)
.attr('cy', - width/2 + margin.linesOuter)
.attr('r', 3)
const arrowheadPos = {
x: 25,
y: -width/2 + margin.linesOuter + 12
}
// TODO: Add drop shadow to the left. Using drop shadow and clipping area?
timeSlicer.append('line')
.attr('stroke', '#333')
.attr('stroke-width', 1.5)
.attr('x1', 0)
.attr('y1', arrowheadPos.y)
.attr('x2', arrowheadPos.x)
.attr('y2', arrowheadPos.y)
const arrowhead = timeSlicer.append('g')
.attr('transform', `translate(${arrowheadPos.x}, ${arrowheadPos.y})`)
arrowhead.append('line')
.attr('stroke', '#333')
.attr('stroke-width', 2.5)
.attr('x1', 0)
.attr('y1', 0)
.attr('x2', -10)
.attr('y2', -7)
arrowhead.append('line')
.attr('stroke', '#333')
.attr('stroke-width', 2.5)
.attr('x1', 0)
.attr('y1', 0)
.attr('x2', -10)
.attr('y2', 7)
}
return svg.node()
}