是否有 JS 事件来查看用户是否已滚动到滑块末尾?

Is there a JS event to see if user has scrolled to end of slider?

提问人:Jord van Eldik 提问时间:4/13/2023 最后编辑:Jord van Eldik 更新时间:4/13/2023 访问量:63

问:

我正在做一个大学项目,我必须制作一个电影票网站。我现在为主页准备的简化版本可以在下面看到。练习的一部分是将ajax / fetch合并到网站中,我想通过以下方式执行此操作:

  1. 用户在主页上看到 10 部电影
  2. 用户滚动到此电影数组的末尾
  3. AJAX 或 Fetch 请求从服务器再看 5 部电影
  4. 该网站现在显示 15 部电影,用户可以继续滚动

我在第 2 步中遇到了问题;我需要从可滚动的 flexbox 触发某种 “” 事件。我做了一些搜索,找不到这样的东西。有谁可能知道这是怎么做到的?任何帮助都是值得赞赏的!reached-end

class Movie {
  constructor(title, image, description, duration, release, age, schedule, seats) {
    this.title = title;
    this.image = image;
    this.description = description;
    this.duration = duration;
    this.release = release;
    this.age = age;
    this.schedule = schedule; //dictionary met alle tijden per dag.
    this.seats = seats;
  }
}

const blankMovie = new Movie(
  "Blank",
  "https://upload.wikimedia.org/wikipedia/commons/thumb/b/b1/Grey_background.jpg/636px-Grey_background.jpg?20140113173544",
  "blank",
  "0 minutes",
  100
);

var allMovies = [];

for (let i = 0; i < 10; i++) {
  allMovies.push(blankMovie)
}

function populatewith(movies) {
  const homePage = document.getElementById("movie-slider");

  for (let i = 0; i < allMovies.length; i++) {
    const movieDiv = document.createElement("div");
    movieDiv.className = "movie-banner";

    const movieTitle = document.createElement("span");
    movieTitle.className = "movie-banner__title";
    movieTitle.textContent = allMovies[i].title;

    const movieImage = document.createElement("img");
    movieImage.className = "movie-banner__image";
    movieImage.src = allMovies[i].image;

    const movieDur = document.createElement("span");
    movieDur.className = "movie-banner__desc";
    movieDur.textContent = allMovies[i].duration;

    homePage.appendChild(movieDiv);
    movieDiv.appendChild(movieTitle);
    movieDiv.appendChild(movieImage);
    movieDiv.appendChild(movieDur);
  }
}

populatewith(allMovies);
body {
  margin: 0;
  font-family: 'Teko', sans-serif;
}

.float-right {
  float: right;
}

.content {
  transition: margin-top 0.4s;
}

.content {
  background: fixed;
  background-image: url("/images/homepage_background.jpg");
  background-position: center;
  background-size: cover;
  min-height: 100vh;
}

#movie-slider {
  display: flex;
  flex-direction: row;
  align-items: end;
  overflow: auto;
  gap: 10px;
  padding: 10vh 10%;
}

.movie-banner {
  margin-top: 50px;
  margin-bottom: 150px;
  flex-basis: 250px;
  flex-shrink: 0;
  display: flex;
  flex-direction: column;
}

.movie-banner__image {
  object-fit: cover;
  height: 400px;
}

.movie-banner__title {
  color: wheat;
  text-align: center;
  font-family: 'Bebas Neue', cursive;
  font-size: 1.5em;
  padding: 10px
}

.movie-banner__desc {
  color: wheat;
  font-size: 1.3em;
  text-align: center;
}
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <title>Movie Tickets</title>
  <link rel="preconnect" href="https://fonts.googleapis.com">
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
  <link href="https://fonts.googleapis.com/css2?family=Bebas+Neue&family=Teko:wght@300&display=swap" rel="stylesheet">
  <link rel="stylesheet" href="/css/index.css">
  <link rel="stylesheet" href="/css/general.css">
</head>

<body>
  <article class="content">
    <section id="movie-slider">
    </section>
  </article>
  <script src="/js/index.js" type="module"></script>
  <script src="/js/general.js" type="module"></script>
</body>

</html>

JavaScript HTML CSS 节点 .js 事件

评论

3赞 A Haworth 4/13/2023
IntersectionObseerver(在第 10 张幻灯片上开始)会有所帮助吗?

答:

1赞 Oskar Grosser 4/13/2023 #1

您可以确定某个元素是否已在侦听器中完全滚动,以用于 scroll(或 scrollend)事件。例:

const scrollableElement = document.querySelector(".scrollable");
scrollableElement.addEventListener("scroll", ({ target }) => {
  const isTotallyScrolled =
    Math.abs(target.scrollHeight - target.clientHeight - target.scrollTop) < 1;
    
  if (isTotallyScrolled) {
    console.log("Element is totally scrolled");
  }
});
.scrollable {
  border: 1px solid black;
  max-height: 200px;
  overflow: auto;
}
.scrollable>div {
  height: 400px;
}
<div class="scrollable">
  <div></div>
</div>

或者,您可以使用 Intersection Observer API如@AHaworth建议)和 DOMRects。例:

const scrollableElement = document.querySelector(".scrollable");
const lastElement = scrollableElement.lastElementChild;

const observerOptions = {
  root: scrollableElement,
  threshold: 1.0 // Requires last element to be smaller than scroll container
};
const observerHandler = entries => {
  entries.forEach(({ boundingClientRect, rootBounds, target }) => {
    // Technically redundant: target is only fully in view when root is totally scrolled
    const isTotallyScrolled = boundingClientRect.bottom === rootBounds.bottom;
    if (isTotallyScrolled) {
      console.log("Element is totally scrolled");
    }
  });
};
const observer = new IntersectionObserver(observerHandler, observerOptions);

observer.observe(lastElement);
.scrollable {
  border: 1px solid black;
  max-height: 200px;
  overflow: auto;
}
.scrollable>.tall {
  height: 400px;
}
.scrollable>.short {
  height: 100px;
}
<div class="scrollable">
  <div class="tall"></div>
  <div class="short"></div>
</div>

注意:使用 Intersection Observer API 时,请确保在添加更多元素后使用新的最后一个元素。您可能希望使用前面的最后一个元素。observe()unobserve()