javascript - GSAP:当进度条击中元素时固定进度条+进度条不准确

标签 javascript jquery css gsap scrolltrigger

我正在尝试创建一个进度条,显示用户还剩多少特定元素可以查看。以下是一些详细信息:

  • .postProgressBar 默认显示在 .postHeroImage
  • 当用户滚动时,我希望 .postProgressBar 根据剩余的 .spacer 元素的滚动量慢慢填满。
  • .postProgressBar 到达 header 底部时,我希望它固定header 底部 (并在 .postHeroImage 再次出现时取消修复)。

查看我当前的方法:

$(function() {

gsap.registerPlugin(ScrollTrigger);

  $(window).scroll(function() {
    var scroll = $(window).scrollTop();
    if (scroll >= 1) {
      $(".header").addClass("fixed");
    } else {
      $(".header").removeClass("fixed");
    }
  });
  
    var action = gsap.set('.postProgressBar', { position:'fixed', paused:true});

  gsap.to('progress', {
    value: 100,
    ease: 'none',
    scrollTrigger: {
      trigger: "#startProgressBar",
      scrub: 0.3,
      markers:true,
      onEnter: () => action.play(),
      onLeave: () => action.reverse(),
      onLeaveBack: () => action.reverse(),
      onEnterBack: () => action.reverse(),
    }
  });

});
body {
  background-color: lightblue;
  --white: #FFFFFF;
  --grey: #002A54;
  --purple: #5D209F;
}

.header {
  position: absolute;
  top: 0;
  width: 100%;
  padding: 20px 15px;
  z-index: 9999;
  background-color: var(--white);
}
.header.fixed {
  position: fixed;
  background-color: var(--white);
  border-bottom: 1px solid var(--grey);
}

.postHeroImage {
  padding: 134px 0 0 0;
  margin-bottom: 105px;
  position: relative;
}
.postHeroImage__bg {
  background-size: cover;
  background-repeat: no-repeat;
  width: 100%;
  min-height: 400px;
}

progress {
  position: absolute;
  bottom: -15px;
  left: 0;
  -webkit-appearance: none;
  appearance: none;
  width: 100%;
  height: 15px;
  border: none;
  background: transparent;
  z-index: 9999;
}

progress::-webkit-progress-bar {
  background: transparent;
}

progress::-webkit-progress-value {
  background: var(--purple);
  background-attachment: fixed;
}

progress::-moz-progress-bar {
  background: var(--purple);
  background-attachment: fixed;
}

.spacer {
  height: 1000vh;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.9.0/gsap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.9.0/ScrollTrigger.min.js"></script>

<link href="https://cdn.jsdelivr.net/npm/<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="43212c2c37303731223303766d736d71" rel="noreferrer noopener nofollow">[email protected]</a>/dist/css/bootstrap.min.css" rel="stylesheet">


<body>

  <header class="header">Header</header>

  <section class="postHeroImage" id="startProgressBar">

    <progress class="postProgressBar" max="100" value="0"></progress>

    <div class="container">
      <div class="row">
        <div class="col-12">
          <div class="postHeroImage__bg" style="background-image: url( 'https://picsum.photos/200/300' );" loading="lazy"></div>
        </div>
      </div>
    </div>
  </section>

  <div class="spacer">lorum ipsum</div>

</body>

当前问题:

  1. .postProgressBar 不会变为固定(在检查模式下看不到固定内联样式)
  2. .postProgressBar 显示的进度根据剩余滚动的 .spacer 数量并不准确。

最佳答案

  1. 职位 sticky在这里非常有用。您可以将其用于标题和进度栏。它会毫不费力地将元素固定在顶部。
  2. 为了获得准确的位置,您需要使用 scrollTriggerstartend 属性。这将告诉 gsap 何时开始动画以及何时结束。最后,我们需要向滚动添加 64px(标题高度),因为我们的容器距视口(viewport)顶部下方 64px。
    演示:

$(function() {
  //read the css variable
  let bodyStyles = window.getComputedStyle(document.body);
  let headerHeight = bodyStyles.getPropertyValue('--header-height'); 

  gsap.registerPlugin(ScrollTrigger);
  gsap.to('progress', {
    value: 100,
    ease: 'none',
    scrollTrigger: {
      trigger: "#startProgressBar",
      scrub: 0.3,
      start: 'start 0px',
      end: 'bottom' + headerHeight,
      markers: true,
    }
  });
});
body {
  background-color: lightblue;
  --white: wheat;
  --grey: #002A54;
  --purple: #5D209F;
  /* 40px padding top and bottom + 24px line height*/
  --header-height: 64px;
}

.header {
  /* position: absolute;*/
  position: sticky;
  top: 0;
  width: 100%;
  padding: 20px 15px;
  z-index: 9999;
  background-color: var(--white);
}

.postHeroImage {
  padding: 134px 0 0 0;
  margin-bottom: 105px;
  position: relative;
}

.postHeroImage__bg {
  background-size: cover;
  background-repeat: no-repeat;
  width: 100%;
  min-height: 400px;
}

progress {
  position: sticky;
  top: var(--header-height);
  left: 0;
  -webkit-appearance: none;
  appearance: none;
  width: 100%;
  height: 15px;
  border: none;
  background: transparent;
  /*z-index: 9999;*/
}

progress::-webkit-progress-bar {
  background: transparent;
}

progress::-webkit-progress-value {
  background: var(--purple);
  background-attachment: fixed;
}

progress::-moz-progress-bar {
  background: var(--purple);
  background-attachment: fixed;
}

.spacer {
  height: 1000vh;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.9.0/gsap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.9.0/ScrollTrigger.min.js"></script>
<link href="https://cdn.jsdelivr.net/npm/<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="6c0e0303181f181e0d1c2c59425c425e" rel="noreferrer noopener nofollow">[email protected]</a>/dist/css/bootstrap.min.css" rel="stylesheet">


<header class="header">Header</header>
<section class="postHeroImage" id="startProgressBar">
  <progress class="postProgressBar" max="100" value="0"></progress>
  <div class="container">
    <div class="row">
      <div class="col-12">
        <div class="postHeroImage__bg" style="background-image: url( 'https://picsum.photos/id/705/300/200' );" loading="lazy"></div>
      </div>
    </div>
  </div>
</section>

<div class="spacer">lorum ipsum</div>

您可以使用开始和结束属性。如果您只想跟踪内容的进度,请将 trigger 更改为 '.container'


无粘性的解决方案 这里我使用了固定位置:

$(function() {
  //read the css variable
  let bodyStyles = window.getComputedStyle(document.body);
  let headerHeight = bodyStyles.getPropertyValue('--header-height');

  gsap.registerPlugin(ScrollTrigger);

  var action = gsap.set('.postProgressBar', {
    position: 'fixed',
    paused: true
  });

  ScrollTrigger.create({
    trigger: '.postProgressBar',
    start: 'top 64px',
    onEnter: () => action.play(),
    onLeaveBack: () => action.reverse(),
  });

  gsap.to('progress', {
    value: 100,
    ease: 'none',
    scrollTrigger: {
      trigger: "#mainContent",
      scrub: 0.3,
      end: 'bottom 110%',
      markers: false,
    }
  });
});
* {
  margin: 0;
  padding: 0;
}

body {
  background-color: lightblue;
  --white: wheat;
  --grey: #002A54;
  --purple: #5D209F;
  /* 40px padding top and bottom + 24px line height*/
  --header-height: 64px;
  position: relative;
  height:100%
}

.header {
  position: fixed;
  top: 0;
  width: 100%;
  padding: 20px 15px;
  z-index: 9999;
  background-color: var(--white);
}

.postHeroImage {
  padding: 134px 0 0 0;
  margin-bottom: 105px;
  position: relative;
  margin-top: var(--header-height);
}

.postHeroImage__bg {
  background-size: cover;
  background-repeat: no-repeat;
  width: 100%;
  min-height: 400px;
}

progress {
  position: static;
  top: var(--header-height);
  left: 0px;
  -webkit-appearance: none;
  appearance: none;
  width: 100%;
  height: 15px;
  border: none;
  background: transparent;
  /*z-index: 9999;*/
}

progress::-webkit-progress-bar {
  background: transparent;
}

progress::-webkit-progress-value {
  background: var(--purple);
  background-attachment: fixed;
}

progress::-moz-progress-bar {
  background: var(--purple);
  background-attachment: fixed;
}

.spacer {
  height: 1000vh;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.9.0/gsap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.9.0/ScrollTrigger.min.js"></script>
<link href="https://cdn.jsdelivr.net/npm/<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="c0a2afafb4b3b4b2a1b080f5eef0eef2" rel="noreferrer noopener nofollow">[email protected]</a>/dist/css/bootstrap.min.css" rel="stylesheet">


<header class="header">Header</header>
<section class="postHeroImage" id="startProgressBar">
  <div class="container">
    <div class="row">
      <div class="col-12">
        <div class="postHeroImage__bg" style="background-image: url( 'https://picsum.photos/id/705/300/200' );" loading="lazy"></div>
      </div>
    </div>
  </div>
  <progress class="postProgressBar" max="100" value="0"></progress>
</section>

<div id="mainContent" class="spacer">lorum ipsum</div>

关于javascript - GSAP:当进度条击中元素时固定进度条+进度条不准确,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70481727/

相关文章:

来自 PHP 的 JavaScript 转义字符

javascript - 通过id合并两个数组的有效方法,不重复

javascript - 是否有 JavaScript 性能比较图表可用?

jquery - 与另一个 div + 100px 高度相同的 div

html - 删除输入框

javascript - 用圆形颜色动画填充div

javascript - Angular UI 网格日期格式不正确

javascript - 在函数中传递参数

javascript - 如何使用 Javascript 检测区域的宽度并应用正确的菜单间距

css - 如何让 CSS float 在一行中?