Elakkan garis tatal daripada menatal apabila melintasi blok
P粉038856725
P粉038856725 2024-03-29 23:23:06
0
1
357

Saya ada 3 blok, blok kedua ada garisan dan bulatan bergolek. Bulatan akan menatal dengan skrol utama, dan apabila menatal berhenti, bulatan akan melekat pada titik terdekat, iaitu pusat setiap blok

Tetapi saya mempunyai masalah ini di sini, apabila skrol utama melintasi blok kedua, bulatan berhenti menatal dan berkelakuan tidak betul pada halaman

Adakah mungkin untuk melengkapkan skrip supaya apabila skrol utama melintasi block2 时,圆圈将自动坚持最后一个案例并完全停止滚动?当我们返回并穿过 block2 , sewajarnya, ia akan berfungsi semula

Secara amnya masalahnya ialah kes terakhir, apabila skrol mencapainya, bulatan tidak bergerak lebih jauh, mungkin ada penyelesaian lain daripada pilihan yang saya cadangkan

Saya memerlukan tatal dari block2mula hingga akhir agar lancar dan apabila tatal berhenti, bulatan harus melekat pada tengah kes terdekat

Dalam contoh saya inilah yang berlaku sekarang, jika anda berhenti menatal maka ia kekal di tempat yang sepatutnya, tetapi bagi saya ia tidak menatal dengan betul hingga akhir

const circle = document.querySelector(".circle");
const cases = document.querySelectorAll(".case");
let timer = null;

const detectCase = () => {
  const circleCenter = circle.offsetTop + circle.offsetHeight / 2;
  let activeCase = null,
    minDist = Infinity;
  cases.forEach((elem) => {
    const caseCenter = elem.offsetTop + elem.offsetHeight / 2;
    const dist = Math.abs(caseCenter - circleCenter);
    if (dist < minDist) {
      minDist = dist;
      activeCase = elem;
    }
  });
  return activeCase;
};

const handleScroll = () => {
  const {
    height: blockHeight
  } = document.querySelector(".block2").getBoundingClientRect();
  const maxTop = cases[cases.length - 1].offsetTop;
  const minTop = cases[0].offsetTop;
  let {
    height: startTop
  } = cases[0].getBoundingClientRect();
  let scrollDist = startTop / 2 + window.scrollY;
  scrollDist = scrollDist > maxTop ? maxTop : scrollDist < minTop ? minTop : scrollDist;
  circle.style.top = `${scrollDist}px`;
  circle.style.backgroundSize = `15px ${blockHeight}px`;
  circle.style.backgroundPosition = `0 ${-scrollDist}px`;
  if (timer) return;
  timer = setTimeout(() => {
    const active = detectCase();
    const activePos = active.offsetTop + active.offsetHeight / 2;
    circle.style.top = `${activePos}px`;
    circle.style.backgroundPosition = `0 ${-activePos}px`;
    circle.style.transition = "0.5s";
    timer = null;
  }, 800);
  circle.style.transition = "";
};

const handleWindowSize = () => {
  if (window.innerWidth >= 991) {
    window.addEventListener("scroll", handleScroll);
    window.addEventListener("resize", handleScroll);
  } else {
    window.removeEventListener("scroll", handleScroll);
    window.removeEventListener("resize", handleScroll);
  }
};

handleScroll();
handleWindowSize();
window.addEventListener("resize", handleWindowSize);
.block1 {
  height: 200px;
  background-color: gray;
}

.block3 {
  height: 600px;
  background-color: gray;
}

.block2 {
  height: 100%;
  position: relative;
}

.block2,
.block2 .circle {
  background: linear-gradient(214deg, rgba(79, 142, 255, 0) 0%, #4f8eff 10%, #f5e550 90%, rgba(79, 142, 255, 0) 100%) center/3px calc(100% - 100px) no-repeat;
}

.block2 .circle {
  width: 15px;
  height: 15px;
  left: calc(50% - 8px);
}

.block2 .circle,
.block2 .circle::before {
  position: absolute;
  border-radius: 50%;
}

.block2 .circle::before {
  content: "";
  inset: 3px;
  background-color: white;
}

.text {
  text-align: center;
  padding: 200px 50px;
}
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.3.0/css/bootstrap.min.css" integrity="sha512-t4GWSVZO1eC8BM339Xd7Uphw5s17a86tIZIj8qRxhnKub6WoyhnrxeCIMeAqBPgdZGlCcG2PrZjMc+Wr78+5Xg==" crossorigin="anonymous" referrerpolicy="no-referrer"
/>
<div class="block1"></div>
<div class="block2">
  <div class="circle"></div>
  <div class="case">
    <div class="row">
      <div class="col-5 text">Text 1</div>
      <div class="col-2"></div>
      <div class="col-5 text">Text 1</div>
    </div>
  </div>
  <div class="case">
    <div class="row">
      <div class="col-5 text">Text 2</div>
      <div class="col-2"></div>
      <div class="col-5 text">Text 2</div>
    </div>
  </div>
  <div class="case">
    <div class="row">
      <div class="col-5 text">Text 3</div>
      <div class="col-2"></div>
      <div class="col-5 text">Text 3</div>
    </div>
  </div>
</div>
<div class="block3"></div>

P粉038856725
P粉038856725

membalas semua(1)
P粉674876385

Jika saya memahami soalan anda dengan betul, saya rasa anda boleh menambah separuh ketinggian kes terakhir pada maxTop pengiraan seperti ini:

let {
    height: lastCaseHeight
  } = cases[cases.length - 1].getBoundingClientRect();
  maxTop = maxTop + (lastCaseHeight / 2)

Dengan cara ini, kedudukan teratas maksimum bulatan akan berada di tengah-tengah kes terakhir. Sila semak coretan kod yang dikemas kini:

const circle = document.querySelector(".circle");
const cases = document.querySelectorAll(".case");
let timer = null;

const detectCase = () => {
  const circleCenter = circle.offsetTop + circle.offsetHeight / 2;
  let activeCase = null,
    minDist = Infinity;
  cases.forEach((elem) => {
    const caseCenter = elem.offsetTop + elem.offsetHeight / 2;
    const dist = Math.abs(caseCenter - circleCenter);
    if (dist  {
  const {
    height: blockHeight
  } = document.querySelector(".block2").getBoundingClientRect();
  let maxTop = cases[cases.length - 1].offsetTop;
  const minTop = cases[0].offsetTop;
  let {
    height: startTop
  } = cases[0].getBoundingClientRect();
  
  let {
    height: lastCaseHeight
  } = cases[cases.length - 1].getBoundingClientRect();
  maxTop = maxTop + (lastCaseHeight / 2)
  
  let scrollDist = startTop / 2 + window.scrollY;
  scrollDist = scrollDist > maxTop ? maxTop : scrollDist  {
    const active = detectCase();
    const activePos = active.offsetTop + active.offsetHeight / 2;
    circle.style.top = `${activePos}px`;
    circle.style.backgroundPosition = `0 ${-activePos}px`;
    circle.style.transition = "0.5s";
    timer = null;
  }, 800);
  circle.style.transition = "";
};

const handleWindowSize = () => {
  if (window.innerWidth >= 991) {
    window.addEventListener("scroll", handleScroll);
    window.addEventListener("resize", handleScroll);
  } else {
    window.removeEventListener("scroll", handleScroll);
    window.removeEventListener("resize", handleScroll);
  }
};

handleScroll();
handleWindowSize();
window.addEventListener("resize", handleWindowSize);
.block1 {
  height: 200px;
  background-color: gray;
}

.block3 {
  height: 600px;
  background-color: gray;
}

.block2 {
  height: 100%;
  position: relative;
}

.block2,
.block2 .circle {
  background: linear-gradient(214deg, rgba(79, 142, 255, 0) 0%, #4f8eff 10%, #f5e550 90%, rgba(79, 142, 255, 0) 100%) center/3px calc(100% - 100px) no-repeat;
}

.block2 .circle {
  width: 15px;
  height: 15px;
  left: calc(50% - 8px);
}

.block2 .circle,
.block2 .circle::before {
  position: absolute;
  border-radius: 50%;
}

.block2 .circle::before {
  content: "";
  inset: 3px;
  background-color: white;
}

.text {
  text-align: center;
  padding: 200px 50px;
}

Text 1
Text 1
Text 2
Text 2
Text 3
Text 3
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan