删除具有过渡的项目可防止在该期间添加它们
Removing items with a transition prevents them from being added during that period
我有一些数据偶尔会被删除和添加。这种情况不经常发生,但可以快速连续发生。
我发现 dataGroups.exit().transition()....remove()
'overrides' 输入 dataGroups.enter(...).append(...).transition()
。
似乎当一个项目被移除时,然后再次 'enters',它无法停止移除过程,所以项目要么被移除,要么处于被移除状态(例如透明或尺寸 0) .
这是一个工作示例,缓慢单击按钮,它会按预期工作,但如果速度太快,您会在应该出现的时候丢失下面的栏。
我尝试添加 interupt()
来尝试中断退出动画,但它似乎不起作用。找不到对此的任何参考,但我很惊讶这不是有人以前见过并提出解决方案的问题:
const dataset1 = [
{ name: "item 1", value: 200 },
{ name: "item 2", value: 100 }
];
const dataset2 = [{ name: "item 1", value: 100 }];
let currentDataset = undefined;
function refresh() {
const newDataset = currentDataset === dataset1 ? dataset2 : dataset1;
currentDataset = newDataset;
// Join new data with old elements, if any.
const dataGroups = d3
.select(".vis")
.selectAll(".box")
.data(newDataset, (d) => d.name);
// Remove old elements as needed.
dataGroups
.exit()
.transition("remove")
.duration(400)
.attr("opacity", 0.2)
.remove();
// Create new elements as needed.
const newGroups = dataGroups
.enter()
.append("rect")
.attr("class", "box")
.attr("height", 10);
newGroups.transition("add").duration(400).attr("opacity", 1);
// Merge and update
newGroups
.merge(dataGroups)
.attr("width", (d) => d.value)
.attr("y", (d, i) => i * 12);
}
document.getElementById("button").onclick = () => {
refresh();
};
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<!DOCTYPE html>
<html>
<head>
<title>Parcel Sandbox</title>
<meta charset="UTF-8" />
</head>
<body>
<button id="button">Update data</button>
<svg class="vis" width="200" height="30"></svg>
<p>
Click the button slowly, and see it add and remove elements with a
transition
</p>
<p>
Click the button twice in quick succession, and see it doesn't correctly
represent the data
</p>
<p>It should look like:</p>
<pre>
|====
|==
</pre
>
<p>Or:</p>
<pre>
|==
|
</pre
>
<p>Never:</p>
<pre>
|====
|
</pre
>
<script src="src/index.js"></script>
</body>
</html>
https://codesandbox.io/s/focused-almeida-dp58f?file=/src/index.js
首先,应该注意到 D3 selection 是不可变的,因此在您输入 selection 时使用 merge
是没有效果的。另外,如果你想正确地看到过渡,你应该将输入 selection 的不透明度设置为 0
。
回到问题,这里的问题是,当您 select 所有具有 box
class 的元素时,退出柱被计算在内,因此您输入 select离子是空的。最简单的解决方案是使用 selection.interrupt()
。与你所说的相反 interrupt
确实 有效,但问题只是因为你命名了退出转换,所以你需要使用相同的名称:
dataGroups.interrupt("remove");
这是您的代码,其中包含该更改:
const dataset1 = [{
name: "item 1",
value: 200
},
{
name: "item 2",
value: 100
}
];
const dataset2 = [{
name: "item 1",
value: 100
}];
let currentDataset = undefined;
function refresh() {
const newDataset = currentDataset === dataset1 ? dataset2 : dataset1;
currentDataset = newDataset;
// Join new data with old elements, if any.
let dataGroups = d3
.select(".vis")
.selectAll(".box")
.data(newDataset, (d) => d.name);
dataGroups.interrupt("remove");
dataGroups.attr("opacity", 1);
// Remove old elements as needed.
dataGroups
.exit()
.transition("remove")
.duration(400)
.attr("opacity", 0.2)
.remove();
// Create new elements as needed.
const newGroups = dataGroups
.enter()
.append("rect")
.attr("class", "box")
.attr("height", 10)
.attr("opacity", 0)
newGroups.transition("add").duration(400).attr("opacity", 1);
// Merge and update
dataGroups = newGroups.merge(dataGroups);
dataGroups.attr("width", (d) => d.value)
.attr("y", (d, i) => i * 12);
}
document.getElementById("button").onclick = () => {
refresh();
};
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<!DOCTYPE html>
<html>
<head>
<title>Parcel Sandbox</title>
<meta charset="UTF-8" />
</head>
<body>
<button id="button">Update data</button>
<svg class="vis" width="200" height="30"></svg>
<p>
Click the button slowly, and see it add and remove elements with a transition
</p>
<p>
Click the button twice in quick succession, and see it doesn't correctly represent the data
</p>
<p>It should look like:</p>
<pre>
|====
|==
</pre
>
<p>Or:</p>
<pre>
|==
|
</pre
>
<p>Never:</p>
<pre>
|====
|
</pre
>
<script src="src/index.js"></script>
</body>
</html>
此外,我在中断过渡后放了一个 dataGroups.attr("opacity", 1);
,所以我们 return 将渐变条的不透明度设置为 1。
我有一些数据偶尔会被删除和添加。这种情况不经常发生,但可以快速连续发生。
我发现 dataGroups.exit().transition()....remove()
'overrides' 输入 dataGroups.enter(...).append(...).transition()
。
似乎当一个项目被移除时,然后再次 'enters',它无法停止移除过程,所以项目要么被移除,要么处于被移除状态(例如透明或尺寸 0) .
这是一个工作示例,缓慢单击按钮,它会按预期工作,但如果速度太快,您会在应该出现的时候丢失下面的栏。
我尝试添加 interupt()
来尝试中断退出动画,但它似乎不起作用。找不到对此的任何参考,但我很惊讶这不是有人以前见过并提出解决方案的问题:
const dataset1 = [
{ name: "item 1", value: 200 },
{ name: "item 2", value: 100 }
];
const dataset2 = [{ name: "item 1", value: 100 }];
let currentDataset = undefined;
function refresh() {
const newDataset = currentDataset === dataset1 ? dataset2 : dataset1;
currentDataset = newDataset;
// Join new data with old elements, if any.
const dataGroups = d3
.select(".vis")
.selectAll(".box")
.data(newDataset, (d) => d.name);
// Remove old elements as needed.
dataGroups
.exit()
.transition("remove")
.duration(400)
.attr("opacity", 0.2)
.remove();
// Create new elements as needed.
const newGroups = dataGroups
.enter()
.append("rect")
.attr("class", "box")
.attr("height", 10);
newGroups.transition("add").duration(400).attr("opacity", 1);
// Merge and update
newGroups
.merge(dataGroups)
.attr("width", (d) => d.value)
.attr("y", (d, i) => i * 12);
}
document.getElementById("button").onclick = () => {
refresh();
};
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<!DOCTYPE html>
<html>
<head>
<title>Parcel Sandbox</title>
<meta charset="UTF-8" />
</head>
<body>
<button id="button">Update data</button>
<svg class="vis" width="200" height="30"></svg>
<p>
Click the button slowly, and see it add and remove elements with a
transition
</p>
<p>
Click the button twice in quick succession, and see it doesn't correctly
represent the data
</p>
<p>It should look like:</p>
<pre>
|====
|==
</pre
>
<p>Or:</p>
<pre>
|==
|
</pre
>
<p>Never:</p>
<pre>
|====
|
</pre
>
<script src="src/index.js"></script>
</body>
</html>
https://codesandbox.io/s/focused-almeida-dp58f?file=/src/index.js
首先,应该注意到 D3 selection 是不可变的,因此在您输入 selection 时使用 merge
是没有效果的。另外,如果你想正确地看到过渡,你应该将输入 selection 的不透明度设置为 0
。
回到问题,这里的问题是,当您 select 所有具有 box
class 的元素时,退出柱被计算在内,因此您输入 select离子是空的。最简单的解决方案是使用 selection.interrupt()
。与你所说的相反 interrupt
确实 有效,但问题只是因为你命名了退出转换,所以你需要使用相同的名称:
dataGroups.interrupt("remove");
这是您的代码,其中包含该更改:
const dataset1 = [{
name: "item 1",
value: 200
},
{
name: "item 2",
value: 100
}
];
const dataset2 = [{
name: "item 1",
value: 100
}];
let currentDataset = undefined;
function refresh() {
const newDataset = currentDataset === dataset1 ? dataset2 : dataset1;
currentDataset = newDataset;
// Join new data with old elements, if any.
let dataGroups = d3
.select(".vis")
.selectAll(".box")
.data(newDataset, (d) => d.name);
dataGroups.interrupt("remove");
dataGroups.attr("opacity", 1);
// Remove old elements as needed.
dataGroups
.exit()
.transition("remove")
.duration(400)
.attr("opacity", 0.2)
.remove();
// Create new elements as needed.
const newGroups = dataGroups
.enter()
.append("rect")
.attr("class", "box")
.attr("height", 10)
.attr("opacity", 0)
newGroups.transition("add").duration(400).attr("opacity", 1);
// Merge and update
dataGroups = newGroups.merge(dataGroups);
dataGroups.attr("width", (d) => d.value)
.attr("y", (d, i) => i * 12);
}
document.getElementById("button").onclick = () => {
refresh();
};
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<!DOCTYPE html>
<html>
<head>
<title>Parcel Sandbox</title>
<meta charset="UTF-8" />
</head>
<body>
<button id="button">Update data</button>
<svg class="vis" width="200" height="30"></svg>
<p>
Click the button slowly, and see it add and remove elements with a transition
</p>
<p>
Click the button twice in quick succession, and see it doesn't correctly represent the data
</p>
<p>It should look like:</p>
<pre>
|====
|==
</pre
>
<p>Or:</p>
<pre>
|==
|
</pre
>
<p>Never:</p>
<pre>
|====
|
</pre
>
<script src="src/index.js"></script>
</body>
</html>
此外,我在中断过渡后放了一个 dataGroups.attr("opacity", 1);
,所以我们 return 将渐变条的不透明度设置为 1。