Javascript 转换条形图中的数字标签
我正在学习d3.js,我有一个问题: d3中的以下代码基本上绘制了一个条形图,带有一个更新按钮,该按钮按降序和升序分别对数据进行排序。此外,条形图上还会显示数字标签 我想将数字标签从当前值转换为更新值。例如,如果第一个条的数字标签为20,排序后的新更新值为100,我希望此标签在特定转换时间内从20转换为100(20,21,…,100),反之亦然,如果原始标签为100,更新值为20,则转换为100,99,…,20 我知道我可以用条形图转换数值,但作为练习,我想知道如何从当前数值转换到新的更新值Javascript 转换条形图中的数字标签,javascript,d3.js,Javascript,D3.js,我正在学习d3.js,我有一个问题: d3中的以下代码基本上绘制了一个条形图,带有一个更新按钮,该按钮按降序和升序分别对数据进行排序。此外,条形图上还会显示数字标签 我想将数字标签从当前值转换为更新值。例如,如果第一个条的数字标签为20,排序后的新更新值为100,我希望此标签在特定转换时间内从20转换为100(20,21,…,100),反之亦然,如果原始标签为100,更新值为20,则转换为100,99,…,20 我知道我可以用条形图转换数值,但作为练习,我想知道如何从当前数值转换到新的更新值 c
const data = [
{key: 0, value: 50},
{key: 1, value: 20},
{key: 2, value: 100},
{key: 3, value: 30},
{key: 4, value: 40},
{key: 5, value: 70}
]
// const dataset = [50, 20, 100, 30, 40]
const svgWidth = 800;
const svgHeight = 400;
const xScale = d3.scaleBand()
.domain(d3.range(data.length))
.rangeRound([0, svgWidth])
.paddingInner(0.1);
const yScale = d3.scaleLinear()
.domain([0, d3.max(data, d => d.value)])
.range([0, svgHeight]);
const svg = d3.select('#chart')
.append('svg')
.attr('width', svgWidth)
.attr('height', svgHeight);
let bars = svg.selectAll('rect').data(data, d => d.key);
let labels = svg.selectAll('text').data(data);
bars.enter()
.append('rect')
.each(function(d){return this._old = d;})
.attr('width', xScale.bandwidth)
.attr('height', d => yScale(d.value))
.attr('fill', d => `rgb(${d.value}, ${d.value * 2}, ${d.value * 3})`)
.attr('x', (d, i) => xScale(i))
.attr('y', d => svgHeight - yScale(d.value))
.attr('stroke', 'black')
.attr('stroke-width', 3)
labels.enter()
.append('text')
.attr('x', (d, i) => xScale(i) + (xScale.bandwidth() / 2))
.attr('y', d => svgHeight - yScale(d.value) + 20)
.attr('font-size', 20)
.attr('text-anchor', 'middle')
.attr('fill', 'white')
.text(d => d.value);
let asc = false;
d3.select('button').on('click', () => {
if(!asc){
data.sort((a,b) => b.value - a.value );
}else{
data.sort((a,b) => a.value - b.value );
};
asc = !asc;
bars = svg.selectAll('rect').data(data, d => d.key);
labels = svg.selectAll('text').data(data);
bars
.transition()
.delay((d, i) => (i * 10))
.duration(3000)
.each(function(d){return this._old = d;})
.attr('x', (d, i) => xScale(i))
.attr('height', d => yScale(d.value))
.attr('y', d => svgHeight - yScale(d.value));
labels
.transition()
.delay((d, i) => (i * 10))
.duration(3000)
.tween("text", function(d) {
var that = this;
var i = d3.interpolate(0, d.value); // Number(d.percentage.slice(0, -1))
return function(t) {
d3.select(that).text(i(t).toFixed(0));
}
})
.attr('y', d => svgHeight - yScale(d.value) + 20);
})
我发现上面代码中包含的“tween”函数用于一个类似但不完全相同的问题。我不知道如何使插值从当前值开始,而不是从0开始。我知道我需要以某种方式存储旧值,并在tween中访问它,但不确定如何访问
关于tween函数的另一个问题:为什么我们在返回的函数中分配var that=this
并选择that
提前感谢您可以通过不同的方式获取每个文本的当前值 例如,使用vanilla JavaScript:
var current = +(this.textContent);
或者使用D3吸气剂:
var current = +(d3.select(this).text());
以下是更改后的代码:
const数据=[{
关键字:0,
价值:50
},
{
重点:1,,
价值:20
},
{
重点:二,,
数值:100
},
{
重点:三,,
价值:30
},
{
重点:四,,
价值:40
},
{
重点:五,,
价值:70
}
]
//常量数据集=[50,20,100,30,40]
常数svgWidth=800;
常数svgHeight=400;
常量xScale=d3.scaleBand()
.域(d3.范围(数据.长度))
.rangeRound([0,svgWidth])
.填充器(0.1);
常量yScale=d3.scaleLinear()
.domain([0,d3.max(数据,d=>d.value)])
.范围([0,svgHeight]);
const svg=d3.select('body')
.append('svg')
.attr('width',svgWidth)
.attr('高度',Svghight);
让bar=svg.selectAll('rect').data(data,d=>d.key);
让labels=svg.selectAll('text').data(数据);
输入()
.append('rect')
.每个功能(d){
将此返回。_old=d;
})
.attr('width',xScale.bandwidth)
.attr('height',d=>yScale(d.value))
.attr('fill',d=>`rgb(${d.value},${d.value*2},${d.value*3})`)
.attr('x',(d,i)=>xScale(i))
.attr('y',d=>svgHeight-yScale(d.value))
.attr('笔划','黑色')
.attr('stroke-width',3)
标签。输入()
.append('文本')
.attr('x',(d,i)=>xScale(i)+(xScale.bandwidth()/2))
.attr('y',d=>svgHeight-yScale(d.value)+20)
.attr('font-size',20)
.attr('text-anchor','middle')
.attr('填充','白色')
.text(d=>d.value);
设asc=false;
d3.选择('按钮')。在('点击',()=>{
如果(!asc){
data.sort((a,b)=>b.value-a.value);
}否则{
data.sort((a,b)=>a.value-b.value);
};
asc=!asc;
bar=svg.selectAll('rect').data(data,d=>d.key);
labels=svg.selectAll('text').data(数据);
酒吧
.transition()
.延迟((d,i)=>(i*10))
.持续时间(3000)
.每个功能(d){
将此返回。_old=d;
})
.attr('x',(d,i)=>xScale(i))
.attr('height',d=>yScale(d.value))
.attr('y',d=>svgHeight-yScale(d.value));
标签
.transition()
.延迟((d,i)=>(i*10))
.持续时间(3000)
.tween(“文本”,功能(d){
var current=+(d3.select(this.text());
var=这个;
var i=d3.interpolate(当前,d.value);//Number(d.percentage.slice(0,-1))
返回函数(t){
d3.选择(that).text(i(t).toFixed(0));
}
})
.attr('y',d=>svgHeight-yScale(d.值)+20);
})
点击
我刚刚意识到,不将数据绑定到键上的元素在视觉上更有意义。这样,条和标签的转换将同步进行。再次感谢。