d3.js - D3.js 在具有不同持续时间的每个元素上重复转换
问题描述
我正在尝试沿圆形路径转换点。每个变换都有不同的持续时间。结束时,一旦具有最短速度持续时间的变换结束,所有点的过渡就会重新开始。如何独立地为每个点重新开始过渡?
const graphWidth = 500;
const graphHeight = 500;
const svg = d3.select("svg")
.attr("width", graphWidth)
.attr("height", graphHeight);
const testData = [{
"country": "Netherlands",
"speed": 4000
},
{
"country": "Belgium",
"speed": 2000
},
{
"country": "Austria",
"speed": 1000
},
{
"country": "Germany",
"speed": 5000
},
{
"country": "USA",
"speed": 4000
}
];
const dots = svg.selectAll('circle')
.data(testData)
.enter()
.append('circle')
.attr('transform', `translate(${graphWidth / 2}, ${graphHeight / 2})`)
.attr('cx', 223)
.attr('r', 5)
.attr('fill', 'yellow')
.attr('stroke', 'black');
function transition() {
svg.selectAll('circle').each(function(d) {
d3.select(this)
.transition()
.ease(d3.easeLinear)
.duration(d.speed)
.attrTween('transform', rotTween)
.on('end', transition);
})
}
transition();
function rotTween() {
var i = d3.interpolate(0, 360);
return function(t) {
return `translate(${graphWidth / 2}, ${graphHeight / 2}) rotate(${i(t)}, 0, 0)`;
};
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<svg></svg>
解决方案
最简单的方法是通过取出函数来改变你的transition
函数来处理一个圆的一个转换.each()
:
const graphWidth = 500;
const graphHeight = 500;
const svg = d3.select("svg")
.attr("width", graphWidth)
.attr("height", graphHeight);
const testData = [{
"country": "Netherlands",
"speed": 4000
},
{
"country": "Belgium",
"speed": 2000
},
{
"country": "Austria",
"speed": 1000
},
{
"country": "Germany",
"speed": 5000
},
{
"country": "USA",
"speed": 4000
}
];
const dots = svg.selectAll('circle')
.data(testData)
.enter()
.append('circle')
.attr('transform', `translate(${graphWidth / 2}, ${graphHeight / 2})`)
.attr('cx', 223)
.attr('r', 5)
.attr('fill', 'yellow')
.attr('stroke', 'black');
function transition(circle, d) {
d3.select(circle)
.transition()
.ease(d3.easeLinear)
.duration(d.speed)
.attrTween('transform', rotTween)
.on('end', function() {
transition(circle, d);
});
}
svg.selectAll('circle').each(function(d) {
transition(this, d);
});
function rotTween() {
var i = d3.interpolate(0, 360);
return function(t) {
return `translate(${graphWidth / 2}, ${graphHeight / 2}) rotate(${i(t)}, 0, 0)`;
};
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<svg></svg>
或者,您可以命名您传递给的其他匿名函数.each()
(在这种情况下我命名它repeat
),然后在.on("end"
子句中再次调用该函数
const graphWidth = 500;
const graphHeight = 500;
const svg = d3.select("svg")
.attr("width", graphWidth)
.attr("height", graphHeight);
const testData = [{
"country": "Netherlands",
"speed": 4000
},
{
"country": "Belgium",
"speed": 2000
},
{
"country": "Austria",
"speed": 1000
},
{
"country": "Germany",
"speed": 5000
},
{
"country": "USA",
"speed": 4000
}
];
const dots = svg.selectAll('circle')
.data(testData)
.enter()
.append('circle')
.attr('transform', `translate(${graphWidth / 2}, ${graphHeight / 2})`)
.attr('cx', 223)
.attr('r', 5)
.attr('fill', 'yellow')
.attr('stroke', 'black');
svg.selectAll('circle')
.each(function repeat(d) {
d3.select(this)
.transition()
.ease(d3.easeLinear)
.duration(function(d) { return d.speed; })
.attrTween('transform', rotTween)
.on("end", repeat);
});
function rotTween() {
var i = d3.interpolate(0, 360);
return function(t) {
return `translate(${graphWidth / 2}, ${graphHeight / 2}) rotate(${i(t)}, 0, 0)`;
};
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<svg></svg>
推荐阅读
- flutter - 在 Flutter 中挂载新状态
- sql-server - 基于不在主键中的列对 SQL Server 表进行分区?
- powershell - 防止脚本在启动时自动启动
- r - 在 R 中使用 t.test 的人群更大?如何告诉功能?
- .net - 数据集更新应用新记录的默认值而不是已设置的值
- django - 查询作为字典列表的 Django JSONFields
- python - Python Web Scraping - 如何抓取这种类型的网站?
- python - 如何在单击 tkinter 按钮之前暂停代码执行?
- sympy - 从 Sympy 到数组的多项式系数
- node.js - Node.js 应用程序——如何为生产部署构建和打包?