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)