추가 된 요소에서 CSS 전환 트리거
이 질문에서 알 수 있듯이 새로 추가 된 요소에 대한 즉각적인 CSS 전환은 어떻게 든 무시됩니다. 전환의 최종 상태는 즉시 렌더링됩니다.
예를 들어, 다음 CSS가 주어지면 (여기서 접두사는 생략 됨) :
.box {
opacity: 0;
transition: all 2s;
background-color: red;
height: 100px;
width: 100px;
}
.box.in { opacity: 1; }
이 요소의 불투명도는 즉시 1로 설정됩니다.
// Does not animate
var $a = $('<div>')
.addClass('box a')
.appendTo('#wrapper');
$a.addClass('in');
예상되는 동작을 얻기 위해 전환을 트리거하는 몇 가지 방법을 보았습니다.
// Does animate
var $b = $('<div>')
.addClass('box b')
.appendTo('#wrapper');
setTimeout(function() {
$('.b').addClass('in');
},0);
// Does animate
var $c = $('<div>')
.addClass('box c')
.appendTo('#wrapper');
$c[0]. offsetWidth = $c[0].offsetWidth
$c.addClass('in');
// Does animate
var $d = $('<div>')
.addClass('box d')
.appendTo('#wrapper');
$d.focus().addClass('in');
동일한 방법이 바닐라 JS DOM 조작에 적용됩니다. 이것은 jQuery 특정 동작이 아닙니다.
편집-Chrome 35를 사용하고 있습니다.
JSFiddle (바닐라 JS 예제 포함).
- 추가 된 요소에 대한 즉각적인 CSS 애니메이션이 무시되는 이유는 무엇입니까?
- 이러한 방법은 어떻게 그리고 왜 작동합니까?
- 다른 방법이 있습니까?
- 어떤 솔루션이 선호됩니까?
새로 추가 된 요소에 애니메이션을 적용하지 않는 원인은 브라우저에서 리플 로우를 일괄 처리하기 때문입니다.
요소가 추가되면 리플 로우가 필요합니다. 클래스 추가에도 동일하게 적용됩니다. 그러나 단일 자바 스크립트 라운드 에서 두 가지를 모두 수행하면 브라우저가 첫 번째를 최적화 할 수 있습니다. 이 경우 단일 (초기 및 최종) 스타일 값만 있으므로 전환이 발생하지 않습니다.
이 setTimeout
트릭은 다른 자바 스크립트 라운드에 대한 클래스 추가를 지연시키기 때문에 작동하므로 렌더링 엔진에 두 개의 값이 있으며, 첫 번째 값이 사용자에게 표시되는 시점이 있으므로 계산해야합니다.
배치 규칙에는 또 다른 예외가 있습니다. 브라우저에 액세스하려는 경우 즉시 값을 계산해야합니다. 이 값 중 하나는offsetWidth
입니다. 액세스 할 때 리플 로우가 트리거됩니다. 다른 하나는 실제 디스플레이 중에 별도로 수행됩니다. 다시 말하지만, 우리는 두 가지 다른 스타일 값을 가지고 있으므로 그것들을 제 시간에 보간 할 수 있습니다.
이것은이 행동이 바람직 할 때 매우 드문 경우 중 하나입니다. 대부분의 경우 DOM 수정 사이에 리플 로우를 유발하는 속성에 액세스하면 심각한 속도 저하가 발생할 수 있습니다.
선호하는 솔루션은 사람마다 다를 수 있지만 나에게는 offsetWidth
(또는 getComputedStyle()
) 액세스 가 가장 좋습니다. setTimeout
사이에 스타일 재 계산없이 실행 되는 경우가 있습니다 . 대부분로드 된 사이트에서 드물지만 발생합니다. 그러면 애니메이션을 얻을 수 없습니다. 계산 된 스타일에 액세스하면 브라우저가 실제로이를 계산하게됩니다.
사용 jQuery
(이 시도 여기에 예. )
var $a = $('<div>')
.addClass('box a')
.appendTo('#wrapper');
$a.css('opacity'); // added
$a.addClass('in');
Vanilla javaScript를 사용하여 다음을 시도하십시오.
var e = document.createElement('div');
e.className = 'box e';
document.getElementById('wrapper').appendChild(e);
window.getComputedStyle(e).opacity; // added
e.className += ' in';
간략한 아이디어 :
getComputedStyle ()는 따라서 보류중인 모든 스타일의 변화와 힘 요소의 현재 상태를 계산하는 레이아웃 엔진을, 플러시 ) .CSS ( 유사한 방식으로 작동합니다.
소개 css()
에서 jQuery
사이트 :
.css () 메서드는 특히 브라우저가 대부분의 속성에 액세스하는 다양한 방법 (표준 기반 브라우저 의 getComputedStyle () 메서드와 currentStyle 및 runtimeStyle)을 고려할 때 첫 번째 일치 요소에서 스타일 속성을 가져 오는 편리한 방법입니다. Internet Explorer의 속성) 및 특정 속성에 대해 브라우저가 사용하는 다른 용어.
getComputedStyle()/css()
대신 사용할 수 있습니다 setTimeout
. 또한 이 기사 에서 몇 가지 세부 정보 및 예를 읽을 수 있습니다 .
아래 코드를 사용하고 "focus ()"를 사용하십시오.
Jquery
var $a = $('<div>')
.addClass('box a')
.appendTo('#wrapper');
$a.focus(); // focus Added
$a.addClass('in');
자바 스크립트
var e = document.createElement('div');
e.className = 'box e';
document.getElementById('wrapper').appendChild(e).focus(); // focus Added
e.className += ' in';
@Frizi's solution works, but at times I've found that getComputedStyle
has not worked when I change certain properties on an element. If that doesn't work, you can try getBoundingClientRect()
as follows, which I've found to be bulletproof:
Let's assume we have an element el
, on which we want to transition opacity
, but el
is display:none; opacity: 0
:
el.style.display = 'block';
el.style.transition = 'opacity .5s linear';
// reflow
el.getBoundingClientRect();
// it transitions!
el.style.opacity = 1;
Rather than trying to force an immediate repaint or style calculation, I tried using requestAnimationFrame()
to allow the browser to paint on its next available frame.
In Chrome + Firefox, the browser optimizes rendering too much so this still doesn't help (works in Safari).
I settled on manually forcing a delay with setTimeout()
then using requestAnimationFrame()
to responsibly let the browser paint. If the append hasn't painted before the timeout ends the animation might be ignored, but it seems to work reliably.
setTimeout(function () {
requestAnimationFrame(function () {
// trigger the animation
});
}, 20);
I chose 20ms because it's larger than 1 frame at 60fps (16.7ms) and some browsers won't register timeouts <5ms.
Fingers crossed that should force the animation start into the next frame and then start it responsibly when the browser is ready to paint again.
I prefer requestAnimationFrame + setTimeout (see this post).
const child = document.createElement("div");
child.style.backgroundColor = "blue";
child.style.width = "100px";
child.style.height = "100px";
child.style.transition = "1s";
parent.appendChild(child);
requestAnimationFrame(() =>
setTimeout(() => {
child.style.width = "200px";
})
);
Try it here.
Unlike Brendan, I found that requestAnimationFrame()
worked in Chrome 63, Firefox 57, IE11 and Edge.
var div = document.createElement("div");
document.body.appendChild(div);
requestAnimationFrame(function () {
div.className = "fade";
});
div {
height: 100px;
width: 100px;
background-color: red;
}
.fade {
opacity: 0;
transition: opacity 2s;
}
참고URL : https://stackoverflow.com/questions/24148403/trigger-css-transition-on-appended-element
'Development Tip' 카테고리의 다른 글
오류 : 'style-loader'모듈을 해결할 수 없습니다. (0) | 2020.11.27 |
---|---|
PowerShell Copy-Item의 제외 목록이 작동하지 않는 것 같습니다. (0) | 2020.11.27 |
find (), findOrFail (), first (), firstOrFail (), get (), list (), toArray ()의 차이점은 무엇입니까? (0) | 2020.11.26 |
Lucene QueryParser에서 두 개의 필드를 지정하는 방법은 무엇입니까? (0) | 2020.11.26 |
Xcode 4에서“Run> Stop on Objective-C 예외”? (0) | 2020.11.26 |