Saya cuba melaksanakan animasi FLIP untuk melihat sama ada saya memahaminya dengan betul.
Dalam codepen ini (maafkan kod buruk, saya hanya mengacau), jika saya mengulas tidur, peralihan yang lancar tidak lagi berfungsi. Div bertukar kedudukan secara tiba-tiba. Ini pelik kerana masa tidur ialah 0ms.
import React, { useRef, useState } from "https://esm.sh/react@18"; import ReactDOM from "https://esm.sh/react-dom@18"; let first = {} let second = {} const sleep = async (ms) => new Promise((resolve) => setTimeout(resolve, ms)); const App = () => { const [start, setStart] = useState(true); const boxRefCb = async el => { if (!el) return; el.style.transition = ""; const x = parseInt(el?.getBoundingClientRect().x, 10); const y = parseInt(el?.getBoundingClientRect().y, 10); first = { x: second.x, y: second.y }; second = { x, y }; const dx = first.x - second.x; const dy = first.y - second.y; const transStr = `translate(${dx}px, ${dy}px)`; el.style.transform = transStr; await sleep(0); // comment me out el.style.transition = "transform .5s"; el.style.transform = ""; } return ( <> <div style={{ display: "flex", gap: "1rem", padding: "3rem"}}> <div ref={ start ? boxRefCb : null } style={{ visibility: start ? "" : "hidden", width: 100, height: 100, border: "solid 1px grey" }}></div> <div ref={ !start ? boxRefCb : null } style={{ visibility: !start ? "" : "hidden", width: 100, height: 100, border: "solid 1px grey" }}></div> </div> <button style={{ marginLeft: "3rem"}} onClick={() => setStart(start => !start)}>start | {start.toString()}</button> </> ); } ReactDOM.render(<App />, document.getElementById("root"))
Saya mengesyaki ini adalah sihir gelung peristiwa yang saya tidak faham. Bolehkah seseorang menjelaskan perkara ini kepada saya?
Anda menggunakan penyelesaian JavaScript biasa untuk masalah ini, tetapi React menggunakan DOM maya dan menjangkakan elemen DOM akan dipaparkan semula apabila keadaan berubah. Oleh itu, saya mengesyorkan memanfaatkan keadaan React untuk mengemas kini kedudukan XY elemen dalam DOM maya, tetapi masih menggunakan CSS.
Demo kerja di siniatau kod boleh didapati di sini:
Dalam
sleep
期间,浏览器可能有时间重新计算 CSSOM 框(也称为“执行回流”)。没有它,您的transform
peraturan tidak benar-benar terpakai.Malah, penyemak imbas akan menunggu sehingga ia benar-benar diperlukan untuk menggunakan perubahan anda dan mengemas kini keseluruhan model kotak halaman, kerana berbuat demikian boleh menjadi sangat mahal.
Apabila anda melakukan sesuatu seperti ini
Semua CSSOM akan melihat status terkini,
“绿色”
. Dua lagi dibuang.Jadi dalam kod anda, apabila anda tidak membiarkan gelung acara benar-benar gelung, anda tidak akan melihat nilai
transStr
sama ada.Namun, bergantung pada 0ms
setTimeout
adalah panggilan masalah, tiada apa-apa untuk memastikan gaya dikira semula pada masa itu. Sebaliknya, lebih baik untuk memaksa pengiraan semula secara manual. Beberapa kaedah/sifat DOM melakukan ini secara serentak. Tetapi perlu diingat bahawa aliran semula boleh menjadi operasi yang sangat mahal, jadi pastikan anda menggunakannya sekali-sekala, dan jika terdapat berbilang tempat dalam kod anda yang memerlukan operasi ini, pastikan anda menyambung semuanya supaya aliran semula tunggal boleh dilakukan. p>