ボックスをクリックし、次のスニペットを試してみて、実行してください。
const box = document.querySelector('.box')
box.addEventListener('click', e => {
if (!box.style.transform) {
box.style.transform = 'translateX(100px)'
new Promise(resolve => {
setTimeout(() => {
box.style.transition = 'none'
box.style.transform = ''
resolve('Transition complete')
}, 2000)
}).then(() => {
box.style.transition = ''
})
}
})
.box {
width: 100px;
height: 100px;
border-radius: 5px;
background-color: #121212;
transition: all 2s ease;
}
<div class = "box"></div>
何が起こることを期待します:
- クリックして起こります
- ボックスには、(このアクションは2秒かかります)100pxにすることにより、水平方向の変換を開始します
- クリックで、新しいの
Promise
も作成されます。内部は言ったPromise
、setTimeout
関数が2秒に設定されています - アクションは(2秒経過した)が完了した後、
setTimeout
そのコールバック関数とセットを実行しますtransition
誰にも負けません。それをやった後、setTimeout
また戻りますtransform
ので、元の場所に現れるようにボックスを描画する、元の値に。 - ボックスはありませんトランジション効果を元の場所に表示されますここでの問題
- これらの仕上げのすべての後に、設定
transition
を元の値にボックスバックの値を
見ることができるようにしかし、transition
価値があるように見えるしませんnone
実行している場合。私は、キーフレームを使用して例えば、上記を達成するための他の方法があることを知っているとtransitionend
、なぜこれが起こるのでしょうか?私は明示的に設定transition
のみ元の値に戻った後、setTimeout
このように約束を解決し、そのコールバックを終了します。
EDIT
イベントループバッチスタイル変更。あなたが1行に要素のスタイルを変更した場合、ブラウザはその変更をすぐに表示されません。それは次のアニメーションフレームまで待っています。これは、例えば、理由です
elm.style.width = '10px';
elm.style.width = '100px';
ちらつきが発生しません。ブラウザは、すべてのJavascriptが完了した後に設定されたスタイルの値を気に。
レンダリングが発生した後、すべてのJavascriptが、完了したマイクロタスクを含みます。.then
約束のマイクロタスクで発生する(効果的にすぐに他のすべてのJavascriptが終了したとしてとして実行されますが、何か他のものの前に-レンダリングなど-実行する機会がありました)。
あなたがやっていることは、あなたが設定しているあるtransition
にプロパティを''
ブラウザのによる変化をレンダリングを開始する前に、マイクロタスクにstyle.transform = ''
。
あなたが後に空の文字列への移行リセットした場合requestAnimationFrame
(すぐ隣の再描画の前に実行される)、その後、後にsetTimeout
(ちょうど次の再描画後に実行される)、それがうまくいくと予想通り:
const box = document.querySelector('.box')
box.addEventListener('click', e => {
if (!box.style.transform) {
box.style.transform = 'translateX(100px)'
setTimeout(() => {
box.style.transition = 'none'
box.style.transform = ''
// resolve('Transition complete')
requestAnimationFrame(() => {
setTimeout(() => {
box.style.transition = ''
});
});
}, 2000)
}
})
.box {
width: 100px;
height: 100px;
border-radius: 5px;
background-color: #121212;
transition: all 2s ease;
}
<div class="box"></div>