最近添加的项目没有动画
Most recently added item is not being animated
我正在尝试使用 d3.js 库来制作折线图的动画。最终,我将从 websocket 异步获取数据,但为了举例,我只是使用 setInterval
+ getRandomInt
组合。我需要将新数据附加到已知数据并相应地更新图表。重要的是我不想删除旧数据 - 所有历史都必须无限期地显示在图表上。
我设法为图表制作了动画,但我的问题是最近添加的项目(图表的右端)只是添加而没有任何动画。它看起来很奇怪,我想解决这个问题。
我可能应该注意到,我希望在数据到达浏览器后立即显示最新数据,因此隐藏最后一项不是一个选项。
<html>
<head>
<title>Simple Line Graph using SVG and d3.js</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.17/d3.min.js"></script>
</head>
<body>
<script>
const margins = [80, 80, 80, 80]; // margins
const width = 1000 - margins[1] - margins[3]; // width
const height = 400 - margins[0] - margins[2]; // height
const svg = d3
.select("body")
.append("svg")
.attr("width", width + margins[1] + margins[3])
.attr("height", height + margins[0] + margins[2])
.append("svg:g")
.attr("transform", "translate(" + margins[3] + "," + margins[0] + ")");
const data = [1, 5, 2, 13, 0];
const x = d3.scale
.linear()
.domain([0, data.length])
.range([0, width]);
const y = d3.scale
.linear()
.domain([d3.min(data), d3.max(data)])
.range([height, 0]);
const lineFunction = d3.svg
.line()
.x((_, i) => x(i))
.y(d => y(d))
.interpolate("cardinal");
svg
.append("path")
.attr("d", lineFunction(data))
.attr("stroke-width", 5)
.attr("stroke", "red")
.attr("fill", "none");
setInterval(() => {
data.push(getRandomInt(1, 10));
x.domain([0, data.length]);
y.domain([d3.min(data), d3.max(data)]);
svg
.transition()
.duration(750)
.select("path")
.attr("d", lineFunction(data));
}, 1000);
function getRandomInt(min, max) {
min = Math.ceil(min);
max = Math.floor(max);
return Math.floor(Math.random() * (max - min + 1)) + min;
}
</script>
</body>
</html>
解决这个问题的最简单方法可能是复制最后一个节点,然后将其转移到需要去的地方。但是,由于您依赖于索引,因此您还需要 x 的附加参数(否则您不能有两个点重叠)。
<html>
<head>
<title>Simple Line Graph using SVG and d3.js</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.17/d3.min.js"></script>
</head>
<body>
<script>
const margins = [80, 80, 80, 80]; // margins
const width = 1000 - margins[1] - margins[3]; // width
const height = 400 - margins[0] - margins[2]; // height
const svg = d3
.select("body")
.append("svg")
.attr("width", width + margins[1] + margins[3])
.attr("height", height + margins[0] + margins[2])
.append("svg:g")
.attr("transform", "translate(" + margins[3] + "," + margins[0] + ")");
const data = [{
y: 10,
x: 0
}];
const x = d3.scale
.linear()
.domain([0, data.length])
.range([0, width]);
const y = d3.scale
.linear()
.domain([d3.min(data), d3.max(data)])
.range([height, 0]);
const lineFunction = d3.svg
.line()
.x((d, i) => x(i + d.x))
.y(d => y(d.y))
.interpolate("cardinal");
svg
.append("path")
.attr("d", lineFunction(data))
.attr("stroke-width", 5)
.attr("stroke", "red")
.attr("fill", "none");
setInterval(() => {
data.push({
y: data[data.length - 1].y,
x: 0
});
var path = svg
.select("path");
path
.datum(data)
.attr("d", lineFunction);
data[data.length - 1] = {
y: getRandomInt(1,10),
x: 1
};
x.domain([0, data.length]);
y.domain([d3.min(data, function(d) { return d.y; }),
d3.max(data, function(d) { return d.y; })]);
path
.datum(data)
.transition()
.duration(750)
.attr("d", lineFunction);
}, 1000);
function getRandomInt(min, max) {
min = Math.ceil(min);
max = Math.floor(max);
return Math.floor(Math.random() * (max - min + 1)) + min;
}
</script>
</body>
</html>
好吧,这是一种 DYI 方法。不过,我可能会看看这样的插件:https://github.com/pbeshai/d3-interpolate-path .
我正在尝试使用 d3.js 库来制作折线图的动画。最终,我将从 websocket 异步获取数据,但为了举例,我只是使用 setInterval
+ getRandomInt
组合。我需要将新数据附加到已知数据并相应地更新图表。重要的是我不想删除旧数据 - 所有历史都必须无限期地显示在图表上。
我设法为图表制作了动画,但我的问题是最近添加的项目(图表的右端)只是添加而没有任何动画。它看起来很奇怪,我想解决这个问题。
我可能应该注意到,我希望在数据到达浏览器后立即显示最新数据,因此隐藏最后一项不是一个选项。
<html>
<head>
<title>Simple Line Graph using SVG and d3.js</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.17/d3.min.js"></script>
</head>
<body>
<script>
const margins = [80, 80, 80, 80]; // margins
const width = 1000 - margins[1] - margins[3]; // width
const height = 400 - margins[0] - margins[2]; // height
const svg = d3
.select("body")
.append("svg")
.attr("width", width + margins[1] + margins[3])
.attr("height", height + margins[0] + margins[2])
.append("svg:g")
.attr("transform", "translate(" + margins[3] + "," + margins[0] + ")");
const data = [1, 5, 2, 13, 0];
const x = d3.scale
.linear()
.domain([0, data.length])
.range([0, width]);
const y = d3.scale
.linear()
.domain([d3.min(data), d3.max(data)])
.range([height, 0]);
const lineFunction = d3.svg
.line()
.x((_, i) => x(i))
.y(d => y(d))
.interpolate("cardinal");
svg
.append("path")
.attr("d", lineFunction(data))
.attr("stroke-width", 5)
.attr("stroke", "red")
.attr("fill", "none");
setInterval(() => {
data.push(getRandomInt(1, 10));
x.domain([0, data.length]);
y.domain([d3.min(data), d3.max(data)]);
svg
.transition()
.duration(750)
.select("path")
.attr("d", lineFunction(data));
}, 1000);
function getRandomInt(min, max) {
min = Math.ceil(min);
max = Math.floor(max);
return Math.floor(Math.random() * (max - min + 1)) + min;
}
</script>
</body>
</html>
解决这个问题的最简单方法可能是复制最后一个节点,然后将其转移到需要去的地方。但是,由于您依赖于索引,因此您还需要 x 的附加参数(否则您不能有两个点重叠)。
<html>
<head>
<title>Simple Line Graph using SVG and d3.js</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.17/d3.min.js"></script>
</head>
<body>
<script>
const margins = [80, 80, 80, 80]; // margins
const width = 1000 - margins[1] - margins[3]; // width
const height = 400 - margins[0] - margins[2]; // height
const svg = d3
.select("body")
.append("svg")
.attr("width", width + margins[1] + margins[3])
.attr("height", height + margins[0] + margins[2])
.append("svg:g")
.attr("transform", "translate(" + margins[3] + "," + margins[0] + ")");
const data = [{
y: 10,
x: 0
}];
const x = d3.scale
.linear()
.domain([0, data.length])
.range([0, width]);
const y = d3.scale
.linear()
.domain([d3.min(data), d3.max(data)])
.range([height, 0]);
const lineFunction = d3.svg
.line()
.x((d, i) => x(i + d.x))
.y(d => y(d.y))
.interpolate("cardinal");
svg
.append("path")
.attr("d", lineFunction(data))
.attr("stroke-width", 5)
.attr("stroke", "red")
.attr("fill", "none");
setInterval(() => {
data.push({
y: data[data.length - 1].y,
x: 0
});
var path = svg
.select("path");
path
.datum(data)
.attr("d", lineFunction);
data[data.length - 1] = {
y: getRandomInt(1,10),
x: 1
};
x.domain([0, data.length]);
y.domain([d3.min(data, function(d) { return d.y; }),
d3.max(data, function(d) { return d.y; })]);
path
.datum(data)
.transition()
.duration(750)
.attr("d", lineFunction);
}, 1000);
function getRandomInt(min, max) {
min = Math.ceil(min);
max = Math.floor(max);
return Math.floor(Math.random() * (max - min + 1)) + min;
}
</script>
</body>
</html>
好吧,这是一种 DYI 方法。不过,我可能会看看这样的插件:https://github.com/pbeshai/d3-interpolate-path .