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

如何让高斯函数(Gaussian Function)实现循环包裹效果?

滚动图片循环淡入淡出问题解决

问题背景

我想要实现滚动时图片淡入淡出的炫酷效果,当前实现按Shift键并向下滚动可查看效果,但首尾图片切换时会出现白屏和“跳变”现象——问题出在计算透明度的高斯函数无法实现循环衔接,而是直接跳变。

当前实现代码

JavaScript

const urls = [
  'https://img.freepik.com/premium-zdjecie/piekny-krajobraz-z-gorskim-jeziorem-i-wysokimi-skalami-z-oswietlonymi-szczytami-odbiciem-zielonej-wody-blekitnym-czystym-niebem-i-zoltym-jesiennym-wschodem-slonca_75780-1924.jpg?w=2000',
  'https://img.freepik.com/darmowe-wektory/krajobraz-zachod-slonca-gory-i-jeziora-realistyczne-drzewo-w-sylwetki-lasow-i-gor-wieczorna-panorama-drewna-ilustracja-tlo-dzikiej-przyrody_1150-39419.jpg?w=2000',
  'https://i1.adis.ws/i/canon/get-inspired-landscape-photography-tips-1-16.9_e7ae10efb78c4526801d6037f80ab177',
  'https://ansee.pl/wp-content/uploads/2021/03/hay-399686_1920-1080x675.jpg'
]

const gauss = (x, a, b, c) => {
  const t1 = (x - b) ** 2
  const t2 = 2 * (c ** 2)
  const t = -t1 / t2
  return a * Math.exp(t)
}

const images = urls.map((url, i) => {
  const img = document.createElement('img')
  img.src = url
  img.className = 'image'
  document.body.appendChild(img)
  return img
})

let current = 0

addEventListener('mousewheel', ({
  deltaY
}) => {
  current = (images.length + current + deltaY / 1000) % images.length
  images.forEach((image, i) => {
    const opacity = gauss(i, 1, current, 0.3)
    image.style.opacity = opacity
  })
})

CSS

body {
  height: 100vh;
  margin: 0;
}

.image {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  object-fit: cover;
  width: 100%;
  height: 100%;
}

问题分析

原高斯函数中计算的是线性距离:(x - b) ** 2。当current从接近images.length(模运算后接近0)时,最后一张图(索引images.length-1)和第一张图(索引0)的距离会突然从接近1变为接近images.length-1,导致透明度直接跳变,无法形成平滑的循环过渡。

解决方案

修改高斯函数,计算循环中的最短距离:对于每个图片索引i,取i到current的最短路径(考虑首尾衔接的情况),再用这个最短距离计算高斯值。

完整修改后的JavaScript代码

const urls = [
  'https://img.freepik.com/premium-zdjecie/piekny-krajobraz-z-gorskim-jeziorem-i-wysokimi-skalami-z-oswietlonymi-szczytami-odbiciem-zielonej-wody-blekitnym-czystym-niebem-i-zoltym-jesiennym-wschodem-slonca_75780-1924.jpg?w=2000',
  'https://img.freepik.com/darmowe-wektory/krajobraz-zachod-slonca-gory-i-jeziora-realistyczne-drzewo-w-sylwetki-lasow-i-gor-wieczorna-panorama-drewna-ilustracja-tlo-dzikiej-przyrody_1150-39419.jpg?w=2000',
  'https://i1.adis.ws/i/canon/get-inspired-landscape-photography-tips-1-16.9_e7ae10efb78c4526801d6037f80ab177',
  'https://ansee.pl/wp-content/uploads/2021/03/hay-399686_1920-1080x675.jpg'
]

// 新增total参数,传入图片总数以计算循环最短距离
const gauss = (x, a, b, total, c) => {
  const diff = Math.abs(x - b)
  // 取循环中的最短距离:要么直接差值,要么绕到另一端的差值
  const shortestDiff = Math.min(diff, total - diff)
  const t1 = shortestDiff ** 2
  const t2 = 2 * (c ** 2)
  const t = -t1 / t2
  return a * Math.exp(t)
}

const images = urls.map((url, i) => {
  const img = document.createElement('img')
  img.src = url
  img.className = 'image'
  document.body.appendChild(img)
  return img
})

const totalImages = images.length
let current = 0

addEventListener('mousewheel', ({ deltaY }) => {
  current = (totalImages + current + deltaY / 1000) % totalImages
  images.forEach((image, i) => {
    // 传入totalImages参数计算循环透明度
    const opacity = gauss(i, 1, current, totalImages, 0.3)
    image.style.opacity = opacity
  })
})

效果说明

修改后,当滚动到首尾衔接的位置时,高斯曲线会以循环的方式平滑过渡,最后一张图和第一张图的透明度变化自然衔接,不会再出现白屏和跳变现象。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 21:06:24