Sau đây là một phiên bản khác của giải pháp của Mike Bostock và được truyền cảm hứng từ nhận xét của @hughes cho câu trả lời của @ kashandr. Nó thực hiện một cuộc gọi lại duy nhất khi transitionkết thúc.
Cho một drophàm ...
function drop(n, args, callback) {
for (var i = 0; i < args.length - n; ++i) args[i] = args[i + n];
args.length = args.length - n;
callback.apply(this, args);
}
... chúng tôi có thể mở rộng d3như vậy:
d3.transition.prototype.end = function(callback, delayIfEmpty) {
var f = callback,
delay = delayIfEmpty,
transition = this;
drop(2, arguments, function() {
var args = arguments;
if (!transition.size() && (delay || delay === 0)) { // if empty
d3.timer(function() {
f.apply(transition, args);
return true;
}, typeof(delay) === "number" ? delay : 0);
} else { // else Mike Bostock's routine
var n = 0;
transition.each(function() { ++n; })
.each("end", function() {
if (!--n) f.apply(transition, args);
});
}
});
return transition;
}
Là một JSFiddle .
Sử dụng transition.end(callback[, delayIfEmpty[, arguments...]]):
transition.end(function() {
console.log("all done");
});
... hoặc với độ trễ tùy chọn nếu transitiontrống:
transition.end(function() {
console.log("all done");
}, 1000);
... hoặc với các callbackđối số tùy chọn :
transition.end(function(x) {
console.log("all done " + x);
}, 1000, "with callback arguments");
d3.transition.endsẽ áp dụng giá trị được truyền callbackngay cả với giá trị trống transition nếu số mili giây được chỉ định hoặc nếu đối số thứ hai là đúng. Điều này cũng sẽ chuyển tiếp bất kỳ đối số bổ sung nào đến callback(và chỉ những đối số đó). Quan trọng hơn, điều này sẽ không theo mặc định áp dụng callbacknếu transitionlà trống rỗng, mà có lẽ là một giả định an toàn trong trường hợp này.