Home > database >  Forcing gaussian function to wrap around
Forcing gaussian function to wrap around

Time:08-11

I'm trying to make a cool effect with photos fading in and out when scrolling

Here is my current setup (press shift and scroll down to see the effect):

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
  })
})
body {
  height: 100vh;
  margin: 0;
}

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

Everything works fine except for that white screen and that "snap" between the first and the last pictures.

The problem is with the gaussian function that I am using to calculate opacity. It just snaps in one place instead of looping.

const canvas = document.querySelector('canvas')
const ctx = canvas.getContext('2d')

const numberOfImages = 4

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)
}

let current = 0

const updateCanvas = () => {
  ctx.clearRect(0, 0, canvas.width, canvas.height)

  ctx.beginPath()

  for (let i = 0; i < numberOfImages; i  = 0.1) {
    const fn = i == 0 ? ctx.moveTo : ctx.lineTo
    const x = i * 50
    const y = gauss(i, 1, current, 0.3) * -100   canvas.height
    if (i == 0) {
      ctx.moveTo(x, y)
    } else {
      ctx.lineTo(x, y)
    }
  }

  ctx.stroke()
}

updateCanvas()

addEventListener('mousewheel', ({
  deltaY
}) => {
  current = (numberOfImages   current   deltaY / 1000) % numberOfImages

  updateCanvas()
})
body {
  height: 100vh;
  margin: 0;
}
<canvas></canvas>

How to make this function teleport to the beginning?

CodePudding user response:

Try appending another loop frequency parameter to the gauss function,

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

Then:

const opacity = gauss(i, 1, current, 0.3, images.length)
  • Related