提取属性以便在 D3 转换中重用
Factoring out attributes for reuse in D3 transition
在下面的最小示例中,SVG 元素转换到不同的状态,然后恢复到原始状态。我怎样才能分解出原始属性,这样它们就不必重复了? selection.each()
和 transition.each()
给了我意想不到的混乱结果。
var circle = d3.select('svg').append('circle')
.attr('cx', 50) // this part should be factored out
.attr('cy', 130)
.attr('r', 25)
.attr('fill', 'blue');
circle.transition().duration(1000).delay(500)
.attr('cx', 200)
.attr('cy', 50)
.attr('r', 50)
.attr('fill', 'red')
.transition().duration(1000).delay(500)
.attr('cx', 50) // repeated
.attr('cy', 130)
.attr('r', 25)
.attr('fill', 'blue');
<!DOCTYPE html>
<script src="https://d3js.org/d3.v4.min.js"></script>
<svg width='300' height='170'>
</svg>
一个解决方案可能是利用 D3 data binding 的强大功能。您可以定义包含两者的配置对象,稍后要恢复的原始值以及元素应转换到的值。通过将此信息绑定到 D3 创建的 DOM 元素,您可以在以后的调用中访问它们。这些配置对象可能如下所示:
var circle = [{ // D3 binds data contained in arrays
orig: { // The original values
"cx": 50,
// ...
},
trans: { // The values to transition to
"cx": 200,
// ...
}
}];
投入 d3-selection-multi module you can directly use the above defined configuration objects by handing them to the selection.attrs()
方法:
函数的 return 值必须是具有字符串值的对象,然后用于设置当前元素的属性。
// Array of configuration objects
var circle = [{
orig: {
"cx": 50,
"cy": 130,
"r": 25,
"fill": "red"
},
trans: {
"cx": 200,
"cy": 50,
"r": 50,
"fill": "blue"
}
}];
// Create new elements by binding data and using data joins
var circle = d3.select('svg').selectAll('circle')
.data(circle) // Bind configuration objects to elements
.enter().append('circle')
.attrs(function(d) { return d.orig; }); // Use the original values
circle.transition().duration(1000).delay(500)
.attrs(function(d) { return d.trans; }) // Transition to new values
.transition().duration(1000).delay(500)
.attrs(function(d) { return d.orig; }); // And transition back to original values
<!DOCTYPE html>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="https://d3js.org/d3-selection-multi.v1.min.js"></script>
<svg width='300' height='170'>
</svg>
我需要的是 call()
而不是 each()
。我知道这是可能的!
function revert(selection) {
selection
.attr('cx', 50)
.attr('cy', 130)
.attr('r', 25)
.attr('fill','blue');
}
var circle = d3.select('svg').append('circle')
.call(revert);
circle.transition().duration(1000).delay(500)
.attr('cx', 200)
.attr('cy', 50)
.attr('r', 50)
.attr('fill','red')
.transition().duration(1000).delay(500)
.call(revert);
<!DOCTYPE html>
<script src="https://d3js.org/d3.v4.min.js"></script>
<svg width='300' height='170'>
</svg>
在下面的最小示例中,SVG 元素转换到不同的状态,然后恢复到原始状态。我怎样才能分解出原始属性,这样它们就不必重复了? selection.each()
和 transition.each()
给了我意想不到的混乱结果。
var circle = d3.select('svg').append('circle')
.attr('cx', 50) // this part should be factored out
.attr('cy', 130)
.attr('r', 25)
.attr('fill', 'blue');
circle.transition().duration(1000).delay(500)
.attr('cx', 200)
.attr('cy', 50)
.attr('r', 50)
.attr('fill', 'red')
.transition().duration(1000).delay(500)
.attr('cx', 50) // repeated
.attr('cy', 130)
.attr('r', 25)
.attr('fill', 'blue');
<!DOCTYPE html>
<script src="https://d3js.org/d3.v4.min.js"></script>
<svg width='300' height='170'>
</svg>
一个解决方案可能是利用 D3 data binding 的强大功能。您可以定义包含两者的配置对象,稍后要恢复的原始值以及元素应转换到的值。通过将此信息绑定到 D3 创建的 DOM 元素,您可以在以后的调用中访问它们。这些配置对象可能如下所示:
var circle = [{ // D3 binds data contained in arrays
orig: { // The original values
"cx": 50,
// ...
},
trans: { // The values to transition to
"cx": 200,
// ...
}
}];
投入 d3-selection-multi module you can directly use the above defined configuration objects by handing them to the selection.attrs()
方法:
函数的 return 值必须是具有字符串值的对象,然后用于设置当前元素的属性。
// Array of configuration objects
var circle = [{
orig: {
"cx": 50,
"cy": 130,
"r": 25,
"fill": "red"
},
trans: {
"cx": 200,
"cy": 50,
"r": 50,
"fill": "blue"
}
}];
// Create new elements by binding data and using data joins
var circle = d3.select('svg').selectAll('circle')
.data(circle) // Bind configuration objects to elements
.enter().append('circle')
.attrs(function(d) { return d.orig; }); // Use the original values
circle.transition().duration(1000).delay(500)
.attrs(function(d) { return d.trans; }) // Transition to new values
.transition().duration(1000).delay(500)
.attrs(function(d) { return d.orig; }); // And transition back to original values
<!DOCTYPE html>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="https://d3js.org/d3-selection-multi.v1.min.js"></script>
<svg width='300' height='170'>
</svg>
我需要的是 call()
而不是 each()
。我知道这是可能的!
function revert(selection) {
selection
.attr('cx', 50)
.attr('cy', 130)
.attr('r', 25)
.attr('fill','blue');
}
var circle = d3.select('svg').append('circle')
.call(revert);
circle.transition().duration(1000).delay(500)
.attr('cx', 200)
.attr('cy', 50)
.attr('r', 50)
.attr('fill','red')
.transition().duration(1000).delay(500)
.call(revert);
<!DOCTYPE html>
<script src="https://d3js.org/d3.v4.min.js"></script>
<svg width='300' height='170'>
</svg>