D3.js를 사용하여 FadeOut 메서드 (jQuery와 유사)를 만들어야합니다 . 내가해야 할 일은를 사용하여 불투명도를 0으로 설정하는 것 transition()
입니다.
d3.select("#myid").transition().style("opacity", "0");
문제는 전환이 끝났음을 깨닫기 위해 콜백이 필요하다는 것입니다. 콜백을 어떻게 구현할 수 있습니까?
답변
전환의 “종료”이벤트를 수신하려고합니다.
// d3 v5
d3.select("#myid").transition().style("opacity","0").on("end", myCallback);
// old way
d3.select("#myid").transition().style("opacity","0").each("end", myCallback);
- 이 데모 는 “end”이벤트를 사용하여 많은 전환을 순서대로 연결합니다.
- D3와 함께 제공 되는 도넛 예제 에서도이를 사용하여 여러 전환을 연결합니다.
- 다음 은 전환의 시작과 끝에서 요소의 스타일을 변경하는 자체 데모 입니다.
에 대한 문서에서 transition.each([type],listener)
:
유형 이 지정된 경우 “시작”및 “종료”이벤트를 모두 지원하는 전환 이벤트에 대한 리스너를 추가합니다. 리스너는 전환의 지연과 지속 시간이 일정하더라도 전환의 각 개별 요소에 대해 호출됩니다. 시작 이벤트는 각 요소가 전환을 시작할 때 즉각적인 변경을 트리거하는 데 사용할 수 있습니다. 종료 이벤트는 현재 요소를 선택하고
this
새 전환을 파생 하여 다단계 전환을 시작하는 데 사용할 수 있습니다 . 종료 이벤트 중에 생성 된 전환은 현재 전환 ID를 상속하므로 이전에 예약 된 새로운 전환을 재정의하지 않습니다.
주제에 대한이 포럼 스레드를 참조하십시오. 대한 를 참조하십시오.
마지막으로 요소가 페이드 아웃 된 후 (전환이 완료된 후) 제거하려는 경우를 사용할 수 있습니다 transition.remove()
.
답변
Mike Bostock의 v3 용 솔루션 ( 작은 업데이트 포함) :
function endall(transition, callback) {
if (typeof callback !== "function") throw new Error("Wrong callback in endall");
if (transition.size() === 0) { callback() }
var n = 0;
transition
.each(function() { ++n; })
.each("end", function() { if (!--n) callback.apply(this, arguments); });
}
d3.selectAll("g").transition().call(endall, function() { console.log("all done") });
답변
이제 d3 v4.0에는 이벤트 핸들러를 전환에 명시 적으로 연결하는 기능이 있습니다.
https://github.com/d3/d3-transition#transition_on
전환이 완료되었을 때 코드를 실행하려면 다음이 필요합니다.
d3.select("#myid").transition().style("opacity", "0").on("end", myCallback);
답변
여러 요소가 동시에 실행되는 많은 전환이있는 경우에도 작동하는 약간 다른 접근 방식 :
var transitions = 0;
d3.select("#myid").transition().style("opacity","0").each( "start", function() {
transitions++;
}).each( "end", function() {
if( --transitions === 0 ) {
callbackWhenAllIsDone();
}
});
답변
다음은 Mike Bostock 솔루션 의 또 다른 버전이며 @kashesandr의 답변에 대한 @hughes의 의견에서 영감을 받았습니다. 단일 콜백을 만듭니다.transition
의 끝에 .
drop
함수가 주어지면 …
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);
}
… 다음 d3
과 같이 확장 할 수 있습니다 .
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;
}
사용 transition.end(callback[, delayIfEmpty[, arguments...]])
:
transition.end(function() {
console.log("all done");
});
… 또는 transition
비어있는 경우 선택적 지연 :
transition.end(function() {
console.log("all done");
}, 1000);
… 또는 선택적 callback
인수 사용 :
transition.end(function(x) {
console.log("all done " + x);
}, 1000, "with callback arguments");
d3.transition.end
밀리 초 수가 지정 되거나 두 번째 인수가 진실 인 경우callback
비어있는 transition
경우 에도 전달 된 값을 적용합니다 . 또한 추가 인수를에 전달합니다 (및 해당 인수 만). 중요한 것은 이것은 기본적으로 if is empty를 적용 하지 않을 것이며 , 이는 아마도 그러한 경우에 더 안전한 가정 일 것입니다.callback
callback
transition
답변
D3 v5.8.0 +부터 .NET을 사용하는 공식적인 방법이 transition.end
있습니다. 문서는 다음과 같습니다.
https://github.com/d3/d3-transition#transition_end
Bostock의 실제 사례는 다음과 같습니다.
https://observablehq.com/@d3/transition-end
기본 아이디어는를 추가하는 것만으로도 .end()
전환이 모든 요소 전환이 완료 될 때까지 해결되지 않는 promise를 반환한다는 것입니다.
await d3.selectAll("circle").transition()
.duration(1000)
.ease(d3.easeBounce)
.attr("fill", "yellow")
.attr("cx", r)
.end();
자세한 내용은 버전 릴리스 정보를 참조하십시오.
답변
Mike Bostock의 솔루션 은 kashesandr + 콜백 함수에 인수를 전달 하여 개선되었습니다 .
function d3_transition_endall(transition, callback, arguments) {
if (!callback) callback = function(){};
if (transition.size() === 0) {
callback(arguments);
}
var n = 0;
transition
.each(function() {
++n;
})
.each("end", function() {
if (!--n) callback.apply(this, arguments);
});
}
function callback_function(arguments) {
console.log("all done");
console.log(arguments);
}
d3.selectAll("g").transition()
.call(d3_transition_endall, callback_function, "some arguments");