提问人:JakobFuglsang 提问时间:11/8/2023 最后编辑:JakobFuglsang 更新时间:11/8/2023 访问量:25
d3 比赛图表 - 年份转换为日期的示例
d3 Race chart - example with year converted to date
问:
我正在使用 d3 js 框架,并试图构建一个竞赛图表来吸引销售。 我找到了一个似乎非常接近的例子。
唯一的区别是它使用年份而不是正常日期。
example data:
{
name: 'test'
value: 12,
year: 2017,
lastValue: 34,
rank: 5
}
My data:
{
initials: 'jaf'
value: 12,
act_date: 2023-03-11,
lastValue: 34,
rank: 5
}
这是当前的代码,如果使用测试数据,它在某种程度上有效,我如何将其转换为与我的数据集一起使用?
function gen_chart(elm, url) {
var svg = d3.select(elm).append("svg")
.attr("width", 960)
.attr("height", 600);
var tickDuration = 250;
var top_n = 12;
var height = 600;
var width = 960;
const margin = {
top: 80,
right: 0,
bottom: 5,
left: 0
};
let barPadding = (height-(margin.bottom+margin.top))/(top_n*5);
let title = svg.append('text')
.attr('class', 'title')
.attr('y', 24)
.html('Ekstern salg - Telenor');
let subTitle = svg.append("text")
.attr("class", "subTitle")
.attr("y", 55)
.html("Siden 2015");
let caption = svg.append('text')
.attr('class', 'caption')
.attr('x', width)
.attr('y', height-5)
.style('text-anchor', 'end')
.html('Kilde: Intern måling');
let year = 2000;
d3.json(url).then(function(data) {
//if (error) throw error;
console.log(data);
data.forEach(d => {
d.value = +d.value,
d.lastValue = +d.lastValue,
d.value = isNaN(d.value) ? 0 : d.value,
d.year = +d.year,
d.colour = d3.hsl(Math.random()*360,0.75,0.75)
});
console.log(data);
let yearSlice = data.filter(d => d.year == year && !isNaN(d.value))
.sort((a,b) => b.value - a.value)
.slice(0, top_n);
yearSlice.forEach((d,i) => d.rank = i);
let x = d3.scaleLinear()
.domain([0, d3.max(yearSlice, d => d.value)])
.range([margin.left, width-margin.right-65]);
let y = d3.scaleLinear()
.domain([top_n, 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')
.attr('class', 'axis xAxis')
.attr('transform', `translate(0, ${margin.top})`)
.call(xAxis)
.selectAll('.tick line')
.classed('origin', d => d == 0);
svg.selectAll('rect.bar')
.data(yearSlice, d => d.name)
.enter()
.append('rect')
.attr('class', 'bar')
.attr('x', x(0)+1)
.attr('width', d => x(d.value)-x(0)-1)
.attr('y', d => y(d.rank)+5)
.attr('height', y(1)-y(0)-barPadding)
.style('fill', d => d.colour);
svg.selectAll('text.label')
.data(yearSlice, d => d.name)
.enter()
.append('text')
.attr('class', 'label')
.attr('x', d => x(d.value)-8)
.attr('y', d => y(d.rank)+5+((y(1)-y(0))/2)+1)
.style('text-anchor', 'end')
.html(d => d.name);
svg.selectAll('text.valueLabel')
.data(yearSlice, d => d.name)
.enter()
.append('text')
.attr('class', 'valueLabel')
.attr('x', d => x(d.value)+5)
.attr('y', d => y(d.rank)+5+((y(1)-y(0))/2)+1)
.text(d => d3.format(',.0f')(d.lastValue));
let yearText = svg.append('text')
.attr('class', 'yearText')
.attr('x', width-margin.right)
.attr('y', height-25)
.style('text-anchor', 'end')
.html(~~year)
.call(halo, 10);
let ticker = d3.interval(e => {
yearSlice = data.filter(d => d.year == year && !isNaN(d.value))
.sort((a,b) => b.value - a.value)
.slice(0,top_n);
yearSlice.forEach((d,i) => d.rank = i);
x.domain([0, d3.max(yearSlice, d => d.value)]);
svg.select('.xAxis')
.transition()
.duration(tickDuration)
.ease(d3.easeLinear)
.call(xAxis);
let bars = svg.selectAll('.bar').data(yearSlice, d => d.name);
bars
.enter()
.append('rect')
.attr('class', d => `bar ${d.name.replace(/\s/g,'_')}`)
.attr('x', x(0)+1)
.attr( 'width', d => x(d.value)-x(0)-1)
.attr('y', d => y(top_n+1)+5)
.attr('height', y(1)-y(0)-barPadding)
.style('fill', d => d.colour)
.transition()
.duration(tickDuration)
.ease(d3.easeLinear)
.attr('y', d => y(d.rank)+5);
bars
.transition()
.duration(tickDuration)
.ease(d3.easeLinear)
.attr('width', d => x(d.value)-x(0)-1)
.attr('y', d => y(d.rank)+5);
bars
.exit()
.transition()
.duration(tickDuration)
.ease(d3.easeLinear)
.attr('width', d => x(d.value)-x(0)-1)
.attr('y', d => y(top_n+1)+5)
.remove();
let labels = svg.selectAll('.label')
.data(yearSlice, d => d.name);
labels
.enter()
.append('text')
.attr('class', 'label')
.attr('x', d => x(d.value)-8)
.attr('y', d => y(top_n+1)+5+((y(1)-y(0))/2))
.style('text-anchor', 'end')
.html(d => d.name)
.transition()
.duration(tickDuration)
.ease(d3.easeLinear)
.attr('y', d => y(d.rank)+5+((y(1)-y(0))/2)+1);
labels
.transition()
.duration(tickDuration)
.ease(d3.easeLinear)
.attr('x', d => x(d.value)-8)
.attr('y', d => y(d.rank)+5+((y(1)-y(0))/2)+1);
labels
.exit()
.transition()
.duration(tickDuration)
.ease(d3.easeLinear)
.attr('x', d => x(d.value)-8)
.attr('y', d => y(top_n+1)+5)
.remove();
let valueLabels = svg.selectAll('.valueLabel').data(yearSlice, d => d.name);
valueLabels
.enter()
.append('text')
.attr('class', 'valueLabel')
.attr('x', d => x(d.value)+5)
.attr('y', d => y(top_n+1)+5)
.text(d => d3.format(',.0f')(d.lastValue))
.transition()
.duration(tickDuration)
.ease(d3.easeLinear)
.attr('y', d => y(d.rank)+5+((y(1)-y(0))/2)+1);
valueLabels
.transition()
.duration(tickDuration)
.ease(d3.easeLinear)
.attr('x', d => x(d.value)+5)
.attr('y', d => y(d.rank)+5+((y(1)-y(0))/2)+1)
.tween("text", function(d) {
let i = d3.interpolateRound(d.lastValue, d.value);
return function(t) {
this.textContent = d3.format(',')(i(t));
};
});
valueLabels
.exit()
.transition()
.duration(tickDuration)
.ease(d3.easeLinear)
.attr('x', d => x(d.value)+5)
.attr('y', d => y(top_n+1)+5)
.remove();
yearText.html(~~year);
let current_year = new Date();
current_year = current_year.getFullYear();
if(year == current_year) ticker.stop();
year = d3.format('.1f')((+year) + 0.1);
},tickDuration);
});
const halo = function(text, strokeWidth) {
text.select(function() { return this.parentNode.insertBefore(this.cloneNode(true), this); })
.style('fill', '#ffffff')
.style('stroke','#ffffff')
.style('stroke-width', strokeWidth)
.style('stroke-linejoin', 'round')
.style('opacity', 1);
}
}
gen_chart("#v_stats", "test.json")```
答: 暂无答案
评论