在下面的示例中,我尝试为新项目设置外观。
如您所见,它们从图表底部动画到其位置。
但是,现有项目("第二个"在此示例中)跳转,而不是平稳过渡到新位置。
我认为这是因为新乐队突然出现,没有过渡。所以,我尝试添加转换:
const band = bandUpdate.enter()
.append('g')
.attr('class', 'band')
.merge(bandUpdate)
.transition(t)
.attr('transform', (_, i) => `translate(0, ${i * bandHeight})`);
但是,我得到了:
未捕获的TypeError:band.selectAll(...)。data不是函数
请你解释一下这个错误,并建议一种避免意外跳跃的方法吗?
加分:我如何为y轴标签设置动画?
const width = 300;
const height = 200;
const margin = { top: 30, right: 30, bottom: 30, left: 50 };
let data = {};
const main = d3.select('.chart')
.append('svg')
.attr('width', width + margin.left + margin.right)
.attr('height', height + margin.top + margin.bottom)
.append('g')
.attr('transform', `translate(${margin.left}, ${margin.top})`);
const xScale = d3.scaleLinear().domain([0, 16]).range([0, width]);
const xAxis = d3.axisBottom(xScale);
main.append('g')
.attr('transform', `translate(0, ${height})`)
.call(xAxis);
const yScale = d3.scaleBand().domain([]).range([0, height]);
const yAxis = d3.axisLeft(yScale);
const yAxisG = main.append('g').call(yAxis);
const bandG = main.append('g');
function update() {
const t = d3.transition().duration(500);
const ids = Object.keys(data);
yScale.domain(ids);
yAxisG.call(yAxis);
const bandHeight = yScale.bandwidth();
const bandUpdate = bandG.selectAll('.band').data(ids, id => id);
const band = bandUpdate.enter()
.append('g')
.attr('class', 'band')
.merge(bandUpdate)
// .transition(t) // Throws: Uncaught TypeError: band.selectAll(...).data is not a function
.attr('transform', (_, i) => `translate(0, ${i * bandHeight})`);
bandUpdate.exit().remove();
const itemUpdate = band.selectAll('.item')
.data(id => data[id], item => item.value);
const itemG = itemUpdate.enter().append('g').attr('class', 'item');
const rectHeight = 4;
itemG
.append('rect')
.attr('class', (_, i) => `item-${i}`)
.attr('x', d => xScale(d.value))
.attr('width', d => width - xScale(d.value))
.attr('height', rectHeight)
.attr('y', height)
.transition(t)
.attr('y', bandHeight / 2 - rectHeight / 2);
itemG
.append('circle')
.attr('class', (_, i) => `item-${i}`)
.attr('cx', d => xScale(d.value))
.attr('r', 6)
.attr('cy', height)
.transition(t)
.attr('cy', bandHeight / 2);
itemUpdate
.select('rect')
.attr('x', d => xScale(d.value))
.attr('width', d => width - xScale(d.value))
.transition(t)
.attr('y', bandHeight / 2 - rectHeight / 2);
itemUpdate
.select('circle')
.attr('cx', d => xScale(d.value))
.transition(t)
.attr('cy', bandHeight / 2);
itemUpdate.exit().remove();
}
update();
setTimeout(() => {
data['first'] = [
{
value: 7
},
{
value: 10
}
];
update();
}, 1000);
setTimeout(() => {
data['second'] = [
{
value: 1
}
];
update();
}, 2000);
setTimeout(() => {
data['third'] = [
{
value: 13
}
];
update();
}, 3000);

svg {
margin: 0 30px 30px 30px;
}
.item-0 {
fill: red;
}
.item-1 {
fill: green;
}

<div class="chart"></div>
<script src="https://unpkg.com/d3@4.4.1/build/d3.js"></script>
&#13;
答案 0 :(得分:1)
打破你的band
常数:
const band = bandUpdate.enter()
.append('g')
.attr('class', 'band')
.merge(bandUpdate);
band.transition(t)
.attr('transform', (_, i) => `translate(0, ${i * bandHeight})`);
以下是更新的CodePen:http://codepen.io/anon/pen/oBWJdp?editors=0010
说明:
根据文件,selection.transition([name]):
返回具有指定名称的给定选择的新转换。
因此,当您稍后在代码中执行此操作时:
const itemUpdate = band.selectAll('.item')
.data(id => data[id], item => item.value);
您正在选择新转换,并且会给您错误(您无法将数据绑定到转换)。
打破band
常量会使itemUpdate
选择基于band
选择,而不是在以下转换中。