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

如何实现带自定义逻辑的弧形无限滚动跑马灯及视口背景切换

实现弧形无限跑马灯+中心触发背景切换

核心思路

  1. 弧形布局:通过CSS变换(rotate + translate)让旗帜沿圆弧排列,模拟弧形轨道。
  2. 无缝滚动:复制一份旗帜列表,让两组列表连续滚动,当第一组完全移出视口时,第二组刚好接上,实现无限循环。
  3. 中心触发逻辑:实时检测每个旗帜的位置,当旗帜中心与视口中心重合时,切换背景色/背景图。

分步实现

1. HTML结构

<div class="bg-container"></div>
<div class="marquee-container">
  <div class="marquee-track">
    <!-- 原始旗帜列表 -->
    <div class="flag" data-bg="#ff4444">旗帜1</div>
    <div class="flag" data-bg="#00C851">旗帜2</div>
    <div class="flag" data-bg="#33b5e5">旗帜3</div>
    <div class="flag" data-bg="#ffbb33">旗帜4</div>
    <!-- 复制一份用于无缝滚动 -->
    <div class="flag" data-bg="#ff4444">旗帜1</div>
    <div class="flag" data-bg="#00C851">旗帜2</div>
    <div class="flag" data-bg="#33b5e5">旗帜3</div>
    <div class="flag" data-bg="#ffbb33">旗帜4</div>
  </div>
</div>

2. CSS布局

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

.bg-container {
  position: fixed;
  top: 0;
  left: 0;
  width: 100vw;
  height: 100vh;
  background: #ff4444;
  transition: background 0.3s ease;
  z-index: 1;
}

.marquee-container {
  position: relative;
  width: 100vw;
  height: 400px;
  overflow: hidden;
  z-index: 2;
  margin-top: 200px;
}

.marquee-track {
  position: absolute;
  display: flex;
  gap: 80px;
  white-space: nowrap;
}

.flag {
  width: 120px;
  height: 180px;
  background: white;
  border-radius: 8px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-weight: bold;
  box-shadow: 0 4px 12px rgba(0,0,0,0.15);
}

3. GSAP动画与逻辑实现

// 初始化GSAP
gsap.registerPlugin(ScrollTrigger);

const track = document.querySelector('.marquee-track');
const flags = document.querySelectorAll('.flag');
const bgContainer = document.querySelector('.bg-container');

// 1. 将旗帜排列成弧形
const arcRadius = 300; // 弧形半径,可调整
const totalFlags = flags.length / 2; // 原始旗帜数量
flags.forEach((flag, index) => {
  // 计算每个旗帜的角度(只针对前半部分,复制的部分同步)
  const angle = (index % totalFlags) * (360 / totalFlags);
  // 旋转并沿圆弧定位
  gsap.set(flag, {
    rotate: angle - 90, // 调整角度让旗帜朝向外侧
    y: arcRadius * Math.cos((angle * Math.PI) / 180),
    x: arcRadius * Math.sin((angle * Math.PI) / 180),
    transformOrigin: 'center center'
  });
});

// 2. 创建无限滚动动画
const trackWidth = track.offsetWidth;
gsap.to(track, {
  x: -trackWidth / 2, // 滚动距离为原始列表宽度
  duration: 15, // 滚动时长,可调整
  repeat: -1, // 无限循环
  ease: 'linear' // 匀速滚动
});

// 3. 检测旗帜是否到达中心,切换背景
function checkFlagCenter() {
  const centerX = window.innerWidth / 2;
  flags.forEach(flag => {
    const flagRect = flag.getBoundingClientRect();
    const flagCenterX = flagRect.left + flagRect.width / 2;
    // 允许±10px的误差范围
    if (Math.abs(flagCenterX - centerX) < 10) {
      const targetBg = flag.dataset.bg;
      if (bgContainer.style.background !== targetBg) {
        bgContainer.style.background = targetBg;
      }
    }
  });
}

// 每帧检测一次
gsap.ticker.add(checkFlagCenter);

关键细节说明

  • 弧形调整:修改arcRadius可以改变弧形的弧度大小,调整rotate值可以改变旗帜的朝向。
  • 滚动速度:修改GSAP动画的duration参数,数值越小滚动越快。
  • 背景切换触发:通过getBoundingClientRect()获取旗帜的实时位置,与视口中心对比,误差范围可以根据需求调整。
  • 无缝滚动:复制原始旗帜列表是为了避免滚动到末尾出现空白,确保视觉上的无限循环。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 17:55:15