Vieritä alaspäin
Kortit saavat luokan, kun ne tulevat näkyviin. Seuraa konsolia.
1
2
3
4
5
6
Näkyviin tulleita:
0
CSS
/* Esikatselualue määrittelee sekä taustan että tekstin värin, jotta pari on varmasti luettava kummassakin teemassa. */ #alue { background-color: #ffffff; color: #1a1a1a; padding: 0.5rem; } @media (prefers-color-scheme: dark) { #alue { background-color: #1e1e1e; color: #f0f0f0; } } /* Vieritettävä alue, jotta esimerkki toimii pienessä kehyksessä. Sama toimii koko sivulla ilman tätä. */ #ikkuna { height: 12rem; overflow-y: auto; border: 1px solid currentColor; padding: 0.5rem; } .kortti { height: 5rem; margin-bottom: 0.5rem; border: 1px solid currentColor; display: flex; align-items: center; justify-content: center; font-size: 2rem; /* lähtötila: näkymätön ja siirretty sivuun */ opacity: 0; transform: translateX(2rem); transition: opacity 0.4s, transform 0.4s; } .kortti.nakyvissa { opacity: 1; transform: translateX(0); } /* Kunnioitetaan käyttäjän asetusta liikkeen vähentämisestä */ @media (prefers-reduced-motion: reduce) { .kortti { transition-duration: 0.01ms; } }
HTML
<div id="alue"> <h2>Vieritä alaspäin</h2> <p>Kortit saavat luokan, kun ne tulevat näkyviin. Seuraa konsolia.</p> <div id="ikkuna"> <div class="kortti">1</div> <div class="kortti">2</div> <div class="kortti">3</div> <div class="kortti">4</div> <div class="kortti">5</div> <div class="kortti">6</div> </div> <p>Näkyviin tulleita: <output id="laskuri">0</output></p> </div>
Javascript
/* suorita tämä koodi Run-painikkeella */ /* Vaihtoehto tälle olisi scroll-tapahtuma, ja se on huono: tapahtuma laukeaa kymmeniä kertoja sekunnissa, ja jokaisessa käsittelijässä pitäisi laskea elementin sijainti - mikä pakottaa selaimen laskemaan asettelun uudelleen. Tarkkailija tekee saman selaimen omalla aikataululla. */ const ikkuna = document.getElementById("ikkuna"); const laskuri = document.getElementById("laskuri"); let havaittu = 0; /* Nollataan tila, jotta Run-painike voi ajaa esimerkin uudelleen */ for (const kortti of ikkuna.querySelectorAll(".kortti")) { kortti.classList.remove("nakyvissa"); } laskuri.textContent = "0"; const tarkkailija = new IntersectionObserver(function (havainnot) { /* Takaisinkutsu saa TAULUKON: kaikki muuttuneet elementit kerralla */ for (const havainto of havainnot) { /* isIntersecting kertoo suunnan - sama takaisinkutsu laukeaa sekä saapumisesta että poistumisesta */ if (!havainto.isIntersecting) { continue; } havainto.target.classList.add("nakyvissa"); havaittu += 1; laskuri.textContent = havaittu; console.log("näkyviin tuli kortti", havainto.target.textContent, "| näkyvä osuus", havainto.intersectionRatio.toFixed(2)); /* Kertaluontoinen asia: lopeta tämän elementin tarkkailu heti */ tarkkailija.unobserve(havainto.target); } }, { /* root kertoo, minkä sisällä näkyvyyttä tarkkaillaan. Oletus on selainikkuna; tässä se on vieritettävä alue. */ root: ikkuna, /* rootMargin kasvattaa aluetta: elementti huomataan hieman ennen kuin se tulee näkyviin. Kokeile arvoa "200px". */ rootMargin: "0px", /* threshold: 0 = yksi pikseli riittää, 1 = koko elementin on näyttävä. Kokeile arvoa 1. */ threshold: 0 }); for (const kortti of ikkuna.querySelectorAll(".kortti")) { tarkkailija.observe(kortti); } console.log("tarkkailu alkoi");
Konsoli