[javascript] 전환이 끝날 때 콜백 호출

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;
}

JSFiddle로서 .

사용 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를 적용 하지 않을 것이며 , 이는 아마도 그러한 경우에 더 안전한 가정 일 것입니다.callbackcallbacktransition


답변

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();

자세한 내용은 버전 릴리스 정보를 참조하십시오.

https://github.com/d3/d3/releases/tag/v5.8.0


답변

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");