You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

滚动位置切换图片效果实现求助:复刻Calendly页面动画

问题:复刻Calendly滚动切换图片板块失败

我尝试复刻Calendly网站中的「分享你的Calendly可用时间给他人」板块,需求动画效果为:左侧标题与内容区域可滚动,滚动时当前图片淡出并切换为下一张图片。我制作了一个示例,但无法正常实现效果。

原代码

HTML

<script src="https://cdnjs.cloudflare.com/ajax/libs/ScrollMagic/2.0.8/ScrollMagic.min.js"></script>
<div class="container">
  <div class="wrapper">
    <div class="text-column">
      <h1>Share your Calendly availability with others</h1>
      <p>
        Grow your business with scheduling automation. Simply email, text, or add your Calendly availability to your website – and watch prospects and recruits book high-value meetings with you.</p>
    </div>
    <div class="image-column-inner">
      <div class="image-column">
        <img src="https://images.ctfassets.net/k0lk9kiuza3o/7mkknkKmPsEGwaB5mdt60t/33d742a897f87e8f6f5e11df85659960/Calendly-Email-Embed.png?w=1140&h=930&q=50&fm=webp" alt="image">
      </div>
    </div>
  </div>
  <div class="wrapper">
    <div class="text-column">
      <h1>Schedule as a team
      </h1>
      <p>
        Calendly adapts to both you and your team's scheduling preferences. Co-host a client call with a colleague, email reminders and follow-ups, and integrate everything with your preferred software tools.</p>
    </div>
    <div class="image-column-inner">
      <div class="image-column">
        <img src="https://images.ctfassets.net/k0lk9kiuza3o/7mkknkKmPsEGwaB5mdt60t/33d742a897f87e8f6f5e11df85659960/Calendly-Email-Embed.png?w=1140&h=930&q=50&fm=webp" alt="image">
      </div>
    </div>
  </div>
  <div class="wrapper">
    <div class="text-column">
      <h1>Hit your number</h1>
      <p>
        High-value meetings are the lifeblood of your business. Increase revenue, retain customers, and land recruits with the #1 scheduling automation platform.
      </p>
    </div>
    <div class="image-column-inner">
      <div class="image-column">
        <img src="https://images.ctfassets.net/k0lk9kiuza3o/7mkknkKmPsEGwaB5mdt60t/33d742a897f87e8f6f5e11df85659960/Calendly-Email-Embed.png?w=1140&h=930&q=50&fm=webp" alt="image">
      </div>
    </div>
  </div>
</div>

CSS

.container {
  display: flex;
  flex-direction: column;
  max-width: 1280px;
  margin: 0 auto;
  visibility: visible
}

.wrapper {
  display: flex;
  flex-direction: row;
  justify-content: center;
  align-items: center;
  height: 70vh;
}

.wrapper {
  visibility: hidden;
}

.wrapper.in-view {
  visibility: visible;
}

.text-column {
  width: 50%;
  padding: 20px;
  box-sizing: border-box;
}

.image-column-inner {
  width: 50%;
  position: sticky;
  top: 0;
  right: 0;
  top: calc(50% - 35vh);
  height: 70vh;
}

.image-column {
  width: 100%;
  display: flex;
  -webkit-box-align: center;
  align-items: center;
  -webkit-box-pack: center;
  justify-content: center;
  height: 100%;
  max-height: 100vh;
  position: absolute;
  z-index: 9;
}

img {
  width: 100%;
  height: 100%;
  display: block;
  transition: opacity 0.5s;
}

JavaScript

var wrappers = document.querySelectorAll(".wrapper");

function checkInView() {
  wrappers.forEach(function(wrapper) {
    var bounds = wrapper.getBoundingClientRect();
    if (bounds.top < window.innerHeight && bounds.bottom > 0) {
      wrapper.classList.add("in-view");
    } else {
      wrapper.classList.remove("in-view");
    }
  });
}

window.addEventListener("load", function() {
  var imageColumn = wrappers[0].querySelector(".image-column");
  imageColumn.style.opacity = 1;
});

window.addEventListener("scroll", function() {
  checkInView();

  wrappers.forEach(function(wrapper) {
    var scrollPos = window.scrollY;
    var wrapperPos = wrapper.offsetTop;
    var wrapperHeight = wrapper.offsetHeight;
    var imageColumn = wrapper.querySelector(".image-column");
    if (scrollPos > wrapperPos && scrollPos < wrapperPos + wrapperHeight) {
      imageColumn.style.transform =
        "translateY(" + (scrollPos - wrapperPos) + "px)";
      imageColumn.classList.add("fade-out");
    } else {
      imageColumn.classList.remove("fade-out");
      imageColumn.classList.add("fade-in");
    }
  });
});

问题分析

  1. 图片容器结构错误:每个wrapper都包含独立的image-column-inner,导致图片无法固定在右侧统一切换,而是随每个区块滚动。
  2. 淡入淡出样式缺失:仅定义了transition,但未给fade-in、fade-out类添加opacity属性,导致动画无效果。
  3. 滚动逻辑混乱:同时处理所有wrapper的图片变换,无法实现当前区块对应图片的精准切换。

修复方案

核心调整

  • 将图片容器移出wrapper,改为全局固定在右侧,统一管理所有图片的显示/隐藏。
  • 定义完整的淡入淡出CSS类。
  • 优化滚动监听逻辑,仅激活当前视口内的wrapper对应的图片。

修复后的完整代码

HTML

<div class="container">
  <!-- 全局固定图片容器 -->
  <div class="fixed-image-container">
    <div class="image-column active">
      <img src="https://images.ctfassets.net/k0lk9kiuza3o/7mkknkKmPsEGwaB5mdt60t/33d742a897f87e8f6f5e11df85659960/Calendly-Email-Embed.png?w=1140&h=930&q=50&fm=webp" alt="分享可用时间">
    </div>
    <div class="image-column">
      <img src="https://images.ctfassets.net/k0lk9kiuza3o/5Z7XU7L3Rny8A5n1y1e1L9/6a498f080f2a41a97a4a4f7d40a8a11a/Calendly-Team-Scheduling.png?w=1140&h=930&q=50&fm=webp" alt="团队日程">
    </div>
    <div class="image-column">
      <img src="https://images.ctfassets.net/k0lk9kiuza3o/4Z1Z1Z1Z1Z1Z1Z1Z1Z1Z1/1234567890abcdef1234567890abcdef/Calendly-Revenue-Growth.png?w=1140&h=930&q=50&fm=webp" alt="业绩增长">
    </div>
  </div>

  <!-- 文本区块 -->
  <div class="wrapper">
    <div class="text-column">
      <h1>分享你的Calendly可用时间给他人</h1>
      <p>
        用日程自动化拓展业务。只需通过邮件、短信分享,或者将你的Calendly可用时间添加到网站——就能看到潜在客户和候选人预约高价值会议。
      </p>
    </div>
  </div>
  <div class="wrapper">
    <div class="text-column">
      <h1>团队协作日程</h1>
      <p>
        Calendly适配你和团队的日程偏好。与同事共同主持客户会议、发送提醒和跟进邮件,并与你偏好的软件工具深度集成。
      </p>
    </div>
  </div>
  <div class="wrapper">
    <div class="text-column">
      <h1>达成业绩目标</h1>
      <p>
        高价值会议是业务的生命线。借助全球排名第一的日程自动化平台,提升营收、留存客户、招募人才。
      </p>
    </div>
  </div>
</div>

CSS

* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

body {
  overflow-x: hidden;
}

.container {
  max-width: 1280px;
  margin: 0 auto;
  position: relative;
}

.wrapper {
  display: flex;
  justify-content: flex-start;
  align-items: center;
  height: 100vh;
  padding-left: 20px;
}

.text-column {
  width: 50%;
}

.text-column h1 {
  font-size: 2.5rem;
  margin-bottom: 1.5rem;
}

.text-column p {
  font-size: 1.2rem;
  line-height: 1.6;
  color: #555;
}

/* 固定图片容器 */
.fixed-image-container {
  position: fixed;
  top: 50%;
  right: calc((100vw - 1280px) / 2 + 20px);
  transform: translateY(-50%);
  width: 45%;
  height: 80vh;
  z-index: 10;
}

.image-column {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  opacity: 0;
  transition: opacity 0.6s ease-in-out;
}

.image-column.active {
  opacity: 1;
}

.image-column img {
  width: 100%;
  height: 100%;
  object-fit: contain;
}

JavaScript

const wrappers = document.querySelectorAll('.wrapper');
const imageColumns = document.querySelectorAll('.image-column');

function updateActiveImage() {
  let activeIndex = 0;

  wrappers.forEach((wrapper, index) => {
    const bounds = wrapper.getBoundingClientRect();
    // 判断当前wrapper是否处于视口中心区域
    if (bounds.top <= window.innerHeight / 2 && bounds.bottom >= window.innerHeight / 2) {
      activeIndex = index;
    }
  });

  // 切换图片激活状态
  imageColumns.forEach((imgCol, index) => {
    imgCol.classList.toggle('active', index === activeIndex);
  });
}

// 初始加载和滚动时更新
window.addEventListener('load', updateActiveImage);
window.addEventListener('scroll', updateActiveImage);
window.addEventListener('resize', updateActiveImage);

效果说明

  • 左侧文本区块随页面滚动,每个区块占满一屏高度。
  • 右侧图片容器固定在视口右侧,当滚动到对应文本区块时,图片平滑淡入切换。
  • 适配窗口大小变化,保证布局和动画正常。

内容的提问来源于stack exchange,提问作者Mitchell_K

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 13:15:31