chart = {
const height = 500
const svg = d3.select(DOM.svg(width, height))
const margin = {
top: 60,
right: 0,
bottom: 5,
left: 80
}
const barPadding = (height - (margin.bottom + margin.top)) / ((topCount + 1) * 5)
const title = svg.append('text')
.attrs({
class: 'title',
y: 24
})
.html('Суммарный рейтинг сообществ d3.ru')
const months = Object.keys(ratings).sort()
const next = (index) => {
return index >= months.length ? null : ratings[months[index]].top
}
let index = 0
let slice = next(index)
let x = d3.scaleLinear()
.domain([0, d3.max(ratings[months[index]].top, d => d.rating)])
.range([margin.left, width-margin.right - 65])
let y = d3.scaleLinear()
.domain([topCount + 1, 0])
.range([height - margin.bottom, margin.top])
let xAxis = d3.axisTop()
.scale(x)
.ticks(width > 500 ? 5 : 2)
.tickSize(-(height - margin.top - margin.bottom))
.tickFormat(d => d3.format(',')(d))
svg.append('g')
.attrs({
class: 'axis xAxis',
transform: `translate(0, ${margin.top})`
})
.call(xAxis)
.selectAll('.tick line')
.classed('origin', d => d == 0)
svg.selectAll('rect.bar')
.data(slice, d => d.domain)
.enter()
.append('rect')
.attrs({
class: 'bar',
x: x(0) + 1,
width: d => x(d.rating) - x(0) - 1,
y: d => y(d.rank) + 5,
height: y(1) - y(0) - barPadding
})
.styles({
fill: '#f7da72'
})
svg.selectAll('text.label')
.data(slice, d => d.domain)
.enter()
.append('text')
.attrs({
class: 'label',
x: d => x(d.rating) - 8,
y: d => y(d.rank) + 5 + ((y(1) - y(0)) / 2) + 1,
'text-anchor': 'end'
})
.html(d => d.domain)
svg.selectAll('text.valueLabel')
.data(slice, d => d.domain)
.enter()
.append('text')
.attrs({
class: 'valueLabel',
x: d => x(d.rating) + 5,
y: d => y(d.rank) + 5 + ((y(1) - y(0)) / 2) + 1,
})
.text(d => d3.format(',.0f')(d.rating))
let yearText = svg.append('text')
.attrs({
class: 'yearText',
x: width-margin.right,
y: height - 40
})
.styles({
'text-anchor': 'end'
})
.html(months[index].replace('-', '.'))
.call(halo, 10)
let ticker = d3.interval(e => {
slice = next(index++)
if(slice === null) ticker.stop()
x.domain([0, d3.max(slice, d => d.rating)])
svg.select('.xAxis')
.transition()
.duration(duration)
.ease(d3.easeLinear)
.call(xAxis)
let bars = svg.selectAll('.bar').data(slice, d => d.domain)
bars
.enter()
.append('rect')
.attrs({
class: d => `bar ${d.domain.replace(/\s/g,'_')}`,
x: x(0) + 1,
width: d => x(d.rating) - x(0) - 1,
y: d => y(topCount + 2) + 5,
height: y(1) - y(0) - barPadding
})
.styles({
fill: d => '#f7da72'
})
.transition()
.duration(duration)
.ease(d3.easeLinear)
.attrs({
y: d => y(d.rank) + 5
})
bars
.transition()
.duration(duration)
.ease(d3.easeLinear)
.attrs({
width: d => x(d.rating) - x(0) - 1,
y: d => y(d.rank) + 5
})
bars
.exit()
.transition()
.duration(100)
.ease(d3.easeLinear)
.attrs({
width: d => x(d.rating) - x(0) - 1,
y: d => y(topCount + 2) + 5
})
.remove()
let labels = svg.selectAll('.label').data(slice, d => d.domain)
labels
.enter()
.append('text')
.attrs({
class: 'label',
x: d => x(d.rating) - 8,
y: d => y(topCount + 2) + 5 + ((y(1) - y(0)) / 2),
'text-anchor': 'end'
})
.html(d => d.domain)
.transition()
.duration(duration)
.ease(d3.easeLinear)
.attrs({
y: d => y(d.rank) + 5 + ((y(1) - y(0)) / 2) + 1,
})
labels
.transition()
.duration(duration)
.ease(d3.easeLinear)
.attrs({
x: d => x(d.rating) - 8,
y: d => y(d.rank) + 5 + ((y(1) - y(0)) / 2) + 1
})
labels
.exit()
.transition()
.duration(100)
.ease(d3.easeLinear)
.attrs({
x: d => x(d.rating) - 8,
y: d => y(topCount + 2) + 5
})
.remove()
let valueLabels = svg.selectAll('.valueLabel').data(slice, d => d.domain)
valueLabels
.enter()
.append('text')
.attrs({
class: 'valueLabel',
x: d => x(d.rating) + 5,
y: d => y(topCount + 2) + 5,
})
.text(d => d3.format(',.0f')(d.rating))
.transition()
.duration(duration)
.ease(d3.easeLinear)
.attrs({
y: d => y(d.rank) + 5 + ((y(1) - y(0)) / 2) + 1
})
valueLabels
.transition()
.duration(duration)
.ease(d3.easeLinear)
.attrs({
x: d => x(d.rating) + 5,
y: d => y(d.rank) + 5 + ((y(1) - y(0)) / 2) + 1
})
.tween('text', function(d) {
const previous = ratings[months[Math.max(0, index - 2)]].all.find(x => x.domain === d.domain)
let previousRating = 0
if (previous) {
previousRating = previous.rating
}
debugger
let i = d3.interpolateRound(previousRating, d.rating)
return function(t) {
this.textContent = d3.format(',')(i(t));
}
})
valueLabels
.exit()
.transition()
.duration(100)
.ease(d3.easeLinear)
.attrs({
x: d => x(d.rating) + 5,
y: d => y(topCount + 2) + 5
})
.remove()
yearText.html(months[index].replace('-', '.'))
}, duration)
return svg.node()
}