我正在尝试在图表上添加一些元素,并在传递给onrendered
配置的billboard.js
函数中进行操作。
在此功能中,我必须知道图表上是否有某些系列,这可以通过轻松检查其不透明度来完成。
现在,在下面的示例中,您可以看到,有时onrendered
中的代码触发时,不透明度转换不会完成。
如何确保在图表中显示/隐藏了所有系列之后,onrendered
中会发生什么?因此,所有转换结束之后。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<script src="https://d3js.org/d3.v4.min.js"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/billboard.js/dist/billboard.min.css" />
<script src="https://cdn.jsdelivr.net/npm/billboard.js/dist/billboard.pkgd.min.js"></script>
<title>JS Bin</title>
</head>
<body>
<div id="chart"></div>
<script>
console.log('should be d1=1,d2=1')
var c = bb.generate({
bindto: "#chart",
size: {
width: 500,
height: 250
},
transition: 0,
data: {
x: "x",
columns: [
["x", "2013-01-01", "2013-01-02", "2013-01-03", "2013-01-04", "2013-01-05", "2013-01-06"],
["data1", 30, 200, 100, 400, 150, 250],
["data2", 130, 340, 200, 500, 250, 350],
]
},
axis: {
x: {
type: "timeseries",
tick: {
format: "%Y-%m-%d"
}
}
},
onrendered: function() {
var data1op = d3.select(".bb-chart-line.bb-target.bb-target-data1").style("opacity");
var data2op = d3.select(".bb-chart-line.bb-target.bb-target-data2").style("opacity");
console.log(`data1 op: ${data1op} --- data2 op: ${data2op}`);
}
});
setTimeout(function(){console.log('should be d1=0,d2=1');c.hide('data1')},500);
setTimeout(function(){console.log('should be d1=0,d2=0');c.hide('data2')},1000);
setTimeout(function(){console.log('should be d1=1,d2=0');c.show('data1')},1500);
setTimeout(function(){console.log('should be d1=1,d2=1');c.show('data2')},2000);
setTimeout(function(){console.log('more waiting between hide/show')},3500);
setTimeout(function(){console.log('should be d1=0,d2=1');c.hide('data1')},5000);
setTimeout(function(){console.log('should be d1=0,d2=0');c.hide('data2')},6000);
setTimeout(function(){console.log('should be d1=1,d2=0');c.show('data1')},7000);
setTimeout(function(){console.log('should be d1=1,d2=1');c.show('data2')},8000);
</script>
</body>
</html>
答案 0 :(得分:0)
问题在于,完成所有onrendered
操作之后,将调用svg
。但是过渡仍然必须开始。您必须等到转换完成。
天真的方法是在调用transition
或c.hide
之后获得c.show
,但尚未附加。您必须等到第一个空闲处理完成并处理第一个过渡标记为止。您可以通过使用几毫秒的超时来做到这一点,然后使用所附的transition
并对其进行后续跟踪,并等待其开始以在过渡结束时调用要处理的函数。这是通过以下功能完成的。
function atEndOf(dataN, action) {
setTimeout(function() {
var transition = d3.active(d3.select(".bb-chart-line.bb-target.bb-target-"+dataN).node());
if (!transition) { return; } // no transition running
transition.transition().on("start", action);
}, 10);
}
要知道隐藏和显示过渡何时完成,您可以构建一个atEndOf
链
// wait till main animation is finished
setTimeout(function() {
c.hide('data1');
atEndOf('data1', function () {
console.log('should be d1=0,d2=1');
showOpacity();
c.hide('data2');
atEndOf('data2', function () {
console.log('should be d1=0,d2=0');
showOpacity();
});
});
}, 6000);
我不知道为什么,但是这个技巧在主启动绘制过渡中不起作用。我收到错误消息:“为时已晚:已经开始”
这使用以下功能
function showOpacity() {
var data1op = d3.select(".bb-chart-line.bb-target.bb-target-data1").style("opacity");
var data2op = d3.select(".bb-chart-line.bb-target.bb-target-data2").style("opacity");
console.log(`data1 op: ${data1op} --- data2 op: ${data2op}`);
}
由于show
和hide
过渡使用默认的1s持续时间,因此很难看出我们要等到过渡结束。要更改这些过渡的持续时间,我们需要装饰ChartInternal.endAll()
方法。在这里,我为所有转换设置了5000ms的持续时间。
var bb_endall = bb.chart.internal.fn.endall;
bb.chart.internal.fn.endall = function (transition, callback) {
transition.duration(5000);
bb_endall(transition, callback);
};
我尝试使用另一种装饰,该装饰使用atEndOf
技术来调用用户定义的函数,但无法使其正常工作。
一个完整的示例,其中所有过渡的持续时间都设置为5000ms
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<script src="https://d3js.org/d3.v4.min.js"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/billboard.js/dist/billboard.min.css" />
<script src="https://cdn.jsdelivr.net/npm/billboard.js/dist/billboard.pkgd.min.js"></script>
<title>JS Bin</title>
</head>
<body>
<div id="chart"></div>
<script>
var bb_endall = bb.chart.internal.fn.endall;
bb.chart.internal.fn.endall = function (transition, callback) {
transition.duration(5000);
bb_endall(transition, callback);
};
//console.log('should be d1=1,d2=1');
var c = bb.generate({
bindto: "#chart",
size: {
width: 500,
height: 250
},
// transition: 0,
transition: {duration: 5000},
data: {
x: "x",
columns: [
["x", "2013-01-01", "2013-01-02", "2013-01-03", "2013-01-04", "2013-01-05", "2013-01-06"],
["data1", 30, 200, 100, 400, 150, 250],
["data2", 130, 340, 200, 500, 250, 350],
]
},
axis: {
x: {
type: "timeseries",
tick: {
format: "%Y-%m-%d"
}
}
},
onrendered: function() {
// not usefull for end of transition
}
});
function showOpacity() {
var data1op = d3.select(".bb-chart-line.bb-target.bb-target-data1").style("opacity");
var data2op = d3.select(".bb-chart-line.bb-target.bb-target-data2").style("opacity");
console.log(`data1 op: ${data1op} --- data2 op: ${data2op}`);
}
function atEndOf(dataN, action) {
setTimeout(function() {
var transition = d3.active(d3.select(".bb-chart-line.bb-target.bb-target-"+dataN).node());
if (!transition) { return; } // no transition running
transition.transition().on("start", action);
}, 10);
}
// wait till main animation is finished
setTimeout(function() {
c.hide('data1');
atEndOf('data1', function () {
console.log('should be d1=0,d2=1');
showOpacity();
c.hide('data2');
atEndOf('data2', function () {
console.log('should be d1=0,d2=0');
showOpacity();
});
});
}, 6000);
// setTimeout(function(){console.log('should be d1=0,d2=1');c.hide('data1')},500);
// setTimeout(function(){console.log('should be d1=0,d2=0');c.hide('data2')},1000);
// setTimeout(function(){console.log('should be d1=1,d2=0');c.show('data1')},1500);
// setTimeout(function(){console.log('should be d1=1,d2=1');c.show('data2')},2000);
// setTimeout(function(){console.log('more waiting between hide/show')},3500);
// setTimeout(function(){console.log('should be d1=0,d2=1');c.hide('data1')},5000);
// setTimeout(function(){console.log('should be d1=0,d2=0');c.hide('data2')},6000);
// setTimeout(function(){console.log('should be d1=1,d2=0');c.show('data1')},7000);
// setTimeout(function(){console.log('should be d1=1,d2=1');c.show('data2')},8000);
</script>
</body>
</html>
在{strong> TabVisible 中,billboard.js
中有一些代码调用onrendered
。过渡完成后将推迟到此时间。到目前为止,我还不知道。