2013-06-01 2 views
8

질문의 제목은 내 특별한 경우 뒤에 궁극적 인 문제라고 생각하는 것을 표현합니다.요청시 javascript로 DOM 다시 그리기

내 케이스 : 클릭 처리기 내에서 바쁜 기능이 시작되기 바로 전에 이미지를 표시 ('로딩'애니메이션)하고 싶습니다. 그런 다음 함수가 완료된 후에 다시 보이지 않게하려고합니다. 내가 예상했던 것 대신에 이미지가 결코 보이지 않는다는 것을 깨달았습니다. 나는 그것이 어떤 재작 성 (나는 거기에 좋은 성능 이유가 있다고 확신한다)을 할 수 있기 전에 이것은 처리기가 끝날 때까지 기다리는 브라우저 때문인 것 같다.

(이 바이올린의 : http://jsfiddle.net/JLmh4/2/) 코드

HTML :

<img id="kitty" src="http://placekitten.com/50/50" style="display:none"> 
<div><a href="#" id="enlace">click to see the cat</a> </div> 

JS : 나는 sleepStupidly 기능이 있음을 보여 직후 alert 전화를 추가 한

$(document).ready(function(){ 
    $('#enlace').click(function(){ 
     var kitty = $('#kitty'); 
     kitty.css('display','block'); 

     // see: http://unixpapa.com/js/sleep.html 
     function sleepStupidly(usec) 
     { 
      var endtime= new Date().getTime() + usec; 
      while (new Date().getTime() < endtime) 
       ; 
     } 

     // simulates bussy proccess, calling some function... 

     sleepStupidly(4000); 

     // when this triggers the img style do refresh! 
     // but not before 
     alert('now you do see it'); 

     kitty.css('display','none'); 
    }); 
}); 

그 휴식의 순간에, 브라우저는 다시 그리지 만 이전에는 그렇지 않습니다. 나는 'display'를 'block'으로 설정 한 직후에 무의식적으로 다시 그리기를 기대했다.

레코드의 경우이 코드에 표시되거나 숨기는 이미지 대신 html 태그를 추가하거나 CSS 클래스를 바꿔 보았습니다. 같은 결과.

내 모든 연구가 끝나면 브라우저가을 다시 그려야하고 그 때까지 다른 모든 작업을 중단하도록하는 능력이 필요하다고 생각합니다.

가능합니까? 크로스 브라우저 방식으로 가능합니까? 어떤 플러그인을 찾지 못했을 수도 있습니다 ...?

'jquery css callback'(이 질문에서와 같이 : In JQuery, Is it possible to get callback function after setting new css rule?)이 트릭을 수행 할 것이라고 생각했지만 존재하지 않습니다.

나는 또한 동일한 이벤트에 대한 다른 핸들러에서 표시, 함수 호출 및 숨기기를 분리하려고 시도했지만 아무 것도하지 않았습니다. 또한 setTimeout을 추가하여 기능 실행을 지연하십시오 (여기에서 권장하는대로 : Force DOM refresh in JavaScript).

감사합니다. 다른 사람들에게도 도움이되기를 바랍니다.

하비에르

EDIT (내 원하는 답변을 설정 한 후) : 나는 window.setTimeout 전략을 선택한 이유

그냥 더 설명하기를. 내 실제 사용 사례에서 나는 페이지를 다시 그리기 위해 브라우저 시간을 충분히 제공하기 위해 약 1000 밀리 초 (바이올린 예제의 경우 50 개 이상)를 제공해야한다는 것을 깨달았습니다. 이것은 내가 생각하기에 더 깊은 DOM 트리 (실제로 불필요하게 깊음) 때문입니다. setTimeout let 접근 방식을 사용하면이를 수행 할 수 있습니다.

+1

'window.setTimeout()'이 도움이되지 않았습니까? –

+0

더 이상 시간 초과 지연을 사용할 필요가 없습니다. 당신이 필요로하는 것은 아마도 이미지를 미리 보여 주어 즉시 보여줄 수있을 것입니다. –

+0

나는 본다. 그러나 이미지가 브라우저에 의해 처음부터로드되지 않은 경우 (이것이'display : none' 이래로 합리적인 것이 무엇인지, 나는 짐작할 수있다). 처음부터 이미지를로드하는 크롬은 개발자 도구에서 볼 때 그렇습니다. 나는 여전히 내가 생각하고있는 레거시 마크 업 (많은 임베디드 테이블들 ...)에 의존한다고 생각한다. 실제로 파이어 폭스가 더 잘한다. (더 적은 시간이 필요하다.) ... 이해가 되니? 다시 한 번 감사드립니다. 안부 – javigzz

답변

5

약간 짧은 눈에 띄지 지연 사용 window.setTimeout() 느린 기능을 실행 :

$(document).ready(function() { 
    $('#enlace').click(function() { 
     showImage(); 

     window.setTimeout(function() { 
      sleepStupidly(4000); 
      alert('now you do see it'); 
      hideImage(); 
     }, 50); 
    }); 
}); 

Live demo

7

JQuery showhide 콜백 (또는 fadeIn/fadeOut과 같은 다른 방법으로 표시)을 사용하십시오.

http://jsfiddle.net/JLmh4/3/

$(document).ready(function() { 
    $('#enlace').click(function() { 
     var kitty = $('#kitty'); 


     // see: http://unixpapa.com/js/sleep.html 
     function sleepStupidly(usec) { 
      var endtime = new Date().getTime() + usec; 
      while (new Date().getTime() < endtime); 
     } 

     kitty.show(function() { 

      // simulates bussy proccess, calling some function... 
      sleepStupidly(4000); 

      // when this triggers the img style do refresh! 
      // but not before 
      alert('now you do see it'); 

      kitty.hide(); 
     }); 
    }); 
}); 
+0

당신의 답변을 주셔서 감사합니다 내가 제안한 경우에도 작동합니다. 그래서 나는 또한 당신을 upvoted (희망은 규칙에 위배되지 않습니다!). 나는 Marat에 의해 대답을 선택했다. 왜냐하면 그것은 좀 더 복잡했던 나의 '실제 사례'에 더 잘 맞았 기 때문이다. 그러므로 저는 좀 더 일반적이라고 생각합니다. 문안 인사 – javigzz

0

내가 가지고있는이 (귀하의 경우 작동하는지 모르겠어요 테스트하지는 않았지만), JavaScript/jQuery를 사용하여 CSS를 조작 할 때 특정 요소를 다시 그리도록 강제해야 할 때가 있습니다 변경 사항이 적용됩니다.

단순히 CSS 속성을 요청하면됩니다.

귀하의 경우에는 setTimeout을 사용하기 전에 함수 호출 전에 kitty.position().left;을 넣으려고합니다.

1

강제로 다시 그리려면 offsetHeight 또는 getComputedStyle()을 사용할 수 있습니다.

var foo = window.getComputedStyle(el, null); 

또는

var bar = el.offsetHeight; 

"엘"은 다음과 같은 설정되어 나를 위해 일한 무엇 DOM 요소

0

인 : 당신은 당신이 원하는대로 할 수있는 그 후

$(element).css('display','none'); 

을 , 결국 원하는 작업 :

$(element).css('display','block');