.animate () 콜백이 두 번 호출됩니다.


103

scrollTop-animation을 추가했기 때문에 콜백의 일부가 두 번 호출됩니다.

$('html, body').animate({scrollTop: '0px'}, 300,function() {
    $('#content').load(window.location.href, postdata, function() {                 
        $('#step2').addClass('stepactive').hide().fadeIn(700, function() {
            $('#content').show('slide',800);                    
        });
    });
});

그것은 단지를 반복하는 것 같습니다 .show(), 적어도 나는 load()또는 .fadeIn()두 번째로 호출되는 인상을 가지고 있지 않습니다 . 는 .show()즉시이 처음으로 끝난 반복됩니다. 0그런데 scrollTop 애니메이션 속도를 설정하는 것은 도움이되지 않았습니다!

나는 그것이 애니메이션 대기열과 관련이 있다고 가정하지만 해결 방법을 찾는 방법과 특히 이것이 발생하는 이유 를 알 수 없습니다 .

답변:


162

animate호출 하는 집합의 각 요소대해 한 번씩 콜백 을 호출 animate합니다.

공급하면 start, step, progress, complete, done, fail, 및 always콜백이 호출된다 당 요소를 기준으로 ...

두 개의 요소 ( html요소와 body요소)에 애니메이션을 적용 하고 있으므로 두 개의 콜백이 발생합니다. ( OP가두 가지 요소에 애니메이션을 적용 하는지 궁금한 사람에게는 애니메이션이 body일부 브라우저에서는 작동 하지만 html다른 브라우저 에서는 작동하기 때문 입니다.)

애니메이션이 완료되었을 때 단일 콜백 을 얻으려면 animate문서에서 promise메서드를 사용 하여 애니메이션 대기열에 대한 약속을 얻은 다음을 사용 then하여 콜백을 대기열에 넣도록 지시합니다.

$("html, body").animate(/*...*/)
    .promise().then(function() {
        // Animation complete
    });

(참고 : Kevin B는 질문이 처음 질문되었을 때 그의 답변 에서이 점 지적했습니다 . 4 년 후 누락 된 것을 발견하고 추가 한 다음 Kevin의 답변을봤을 때까지 말하지 않았습니다. 나는 이것이 받아 들여지는 대답이기 때문에 그것을 남겨 두어야한다고 생각했습니다.)

다음은 개별 요소 콜백과 전체 완료 콜백을 모두 보여주는 예입니다.

jQuery(function($) {

  $("#one, #two").animate({
    marginLeft: "30em"
  }, function() {
    // Called per element
    display("Done animating " + this.id);
  }).promise().then(function() {
    // Called when the animation in total is complete
    display("Done with animation");
  });

  function display(msg) {
    $("<p>").html(msg).appendTo(document.body);
  }
});
<div id="one">I'm one</div>
<div id="two">I'm two</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>


2
그래 그게 이유 였고 실제로 내가 왜 썼는지 기억할 수 없다 html, body. 내 두뇌를 다시 켜야 할 시간입니다. 감사합니다
Anonymous

21
아마도 html 애니메이션은 Webkit에서는 작동하지 않고 body는 Opera에서 작동하지 않기 때문일 것입니다. 둘 다 사용하면 항상 작동하지만 Firefox에서는 콜백이 두 번 트리거됩니다. (브라우저를 잘못 이해했을 수 있습니다 ...)
Jon

2
htmlIE에는 필수이며 대부분의 다른 브라우저에서는 콜백이 두 번 실행됩니다. 나는 같은 문제에 대한 해결책을 찾으려고 노력하고 있습니다.
Simon Robb

9
나는 깃발을 만들어서 처리했다. var ranOne = false; $('body,html').animate({ scrollTop: scrollTo }, scrollTime, 'swing', function () { if (ranOne) { ...action... ranOne = false; } else { ranOne = true; } }); 그것은 엉뚱한 느낌이 들지만, "body, html"을 사용해야한다는 것은 애초에 일종의 해키이다. (줄 바꿈이 없어서 죄송합니다. 댓글에 표시되지 않는 것 같습니다.)
spinn a

1
믿을 수 없는! 두 번 실행되지 않도록 $ ( "html, body")를 사용하여 스크롤링 애니메이션이 제대로 작동하도록 몇 시간을 보냈습니다.이 답변이 저를 구했습니다! 감사!
Vasily Hall

172

여러 요소 애니메이션 완료를위한 단일 콜백을 얻으려면 지연된 객체를 사용하십시오.

$(".myClass").animate({
  marginLeft: "30em"
}).promise().done(function(){
  alert("Done animating");
});

PromiseDeferred Objects에 대한 자세한 설명은 jQuery API를 참조하십시오 .


이건 우리가 애니메이션을 완성 할 때하고 싶은 일에 대한 문제를 해결했지만, 두 번 호출해서 +1을 받았는데, 애니메이션 프로세스가 두 번 호출되는지 아닌지 모르겠어요?!
QMaster

1
애니메이션 프로세스는 두 번 호출되지 않으며 콜백은 선택한 각 요소에 대해 한 번씩 호출됩니다. 따라서 8 개의 목록 항목을 선택하고 왼쪽으로 애니메이션하면 콜백이 8 번 실행됩니다. 내 솔루션은 8 개가 모두 완료되면 단일 콜백을 제공합니다.
Kevin B

@KevinB, 좋은 솔루션이며 내 콜백 문제도 해결하는 데 도움이되었습니다. 감사.
lislis

나는 이것이 흥미로운 대답이라고 생각했지만 불행히도 의도하지 않은 결과를 초래했습니다. 약속은 jQuery 세트의 요소가 현재 애니메이션을 완료 할 때까지 콜백 실행을 지연시키는 것이 아닙니다. 세트의 모든 보류중인 애니메이션 이 완료된 후에 만 해결됩니다 . 따라서 첫 번째 애니메이션이 실행되는 동안 두 번째 애니메이션이 설정된 경우 첫 번째 애니메이션에 대한 콜백은 두 번째 애니메이션이 끝날 때까지 실행되지 않습니다. 이 빈을 참조하십시오 .
hashchange

1
맞습니다 . 선택한 요소에 대해 현재 모든 애니메이션이 완료 될 때까지 기다립니다 . 그것은 사람이 체인의 시작 (도 아니다이어야 함) 만 대기 스마트 것만으로는 충분하지 않습니다
케빈 B
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.