
这是一款基于滚动的超酷 js 图片动画特效。该特效在使用鼠标滚动屏幕时,根据屏幕的当前位置,屏幕上的图片做出相应的动画效果,非常炫酷。
<div class="container">
<div class="image"></div>
<div class="image"></div>
<div class="image"></div>
<div class="image"></div>
<div class="image"></div>
<div class="image"></div>
<div class="image"></div>
<div class="image"></div>
<div class="image"></div>
<div class="image"></div>
</div>

// The container for all images
.container {
// 2 columns griddisplay: grid;
grid-template-columns: 1fr 1fr;
grid-gap: 0 10%;
justify-items: end; // This will align all items (images) to the right
// Fixed positioned, so it won't be affected by default scroll
// It will be moved using `transform`, to achieve a custom scroll behavior position: fixed; top: 0; left: 0; width: 100%;}// Styles for image elements// Mainly positioning and background styles.image { position: relative; width: 300px; height: 100vh; background-repeat: no-repeat; background-position: center; // This will align all even images to the left // For getting centered positioned images, respect to the viewport &:nth-child(2n) { justify-self: start; } // Set each `background-image` using a SCSS `for` loop @for $i from 1 through 10 { &:nth-child(#{$i}) {background-image: url('../img/image#{$i}.jpg');
} }}// Adjusting layout for small screens@media screen and (max-width: 760px) { .container { // 1 column grid grid-template-columns: 1fr; // Fix image centering justify-items: center; } // Fix image centering .image:nth-child(2n) { justify-self: center; }}// Easing function used for `translateX` animation// From: https://gist.github.com/gre/1650294function easeOutQuad (t) {
return t *_ (2 - t)
}// Returns a random number (integer) between __`min`__ and __`max`__function random (min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min_
}// Returns a random number as well, but it could be negative alsofunction randomPositiveOrNegative (min, max) {
return random(min, max) * (Math.random() > 0.5 ? 1 : -1)
}// Set CSS `tranform` property for an elementfunction setTransform (el, transform) {
el.style.transform = transform
el.style.WebkitTransform = transform
}// Current scroll positionvar current = 0
// Target scroll positionvar target = 0
// Ease or speed for moving from `current` to `target`var ease = 0.075
// Utility variables for `requestAnimationFrame`var rafId = undefined
var rafActive = false
// Container elementvar container = document.querySelector('.container')
// Array with `.image` elementsvar images = Array.prototype.slice.call(document.querySelectorAll('.image'))
// Variables for storing dimmensionsvar windowWidth, containerHeight, imageHeight
// Variables for specifying transform parameters (max limits)var rotateXMaxList = []
var rotateYMaxList = []
var translateXMax = -200
// Popullating the `rotateXMaxList` and `rotateYMaxList` with random valuesimages.forEach(function () {
rotateXMaxList.push(randomPositiveOrNegative(20, 40))
rotateYMaxList.push(randomPositiveOrNegative(20, 60))
})
// The `fakeScroll` is an element to make the page scrollable// Here we are creating it and appending it to the `body`var fakeScroll = document.createElement('div')
fakeScroll.className = 'fake-scroll'
document.body.appendChild(fakeScroll)
// In the `setupAnimation` function (below) we will set the `height` properly// The styles for a `div` element (inserted with Javascript)// Used to make the page scrollable// Will be setted a proper `height` value using Javascript.fake-scroll {
position: absolute;
top: 0;
width: 1px;
}// Geeting dimmensions and setting up all for animationfunction setupAnimation () {
// Updating dimmensionswindowWidth = window.innerWidth
containerHeight = container.getBoundingClientRect().height
imageHeight = containerHeight / (windowWidth > 760 ? images.length / 2 : images.length)
// Set `height` for the fake scroll elementfakeScroll.style.height = containerHeight + 'px'
// Start the animation, if it is not running alreadystartAnimation()
}// Update scroll `target`, and start the animation if it is not running alreadyfunction updateScroll () {
target = window.scrollY || window.pageYOffset
startAnimation()
}// Listen for `scroll` event to update `target` scroll positionwindow.addEventListener('scroll', updateScroll)
// Start the animation, if it is not running alreadyfunction startAnimation () {
if (!rafActive) {
rafActive = true
rafId = requestAnimationFrame(updateAnimation)
}}// Do calculations and apply CSS `transform`s accordinglyfunction updateAnimation () {
// Difference between `target` and `current` scroll positionvar diff = target - current
// `delta` is the value for adding to the `current` scroll position // If `diff < 0.1`, make `delta = 0`, so the animation would not be endlessvar delta = Math.abs(diff) < 0.1 ? 0 : diff * ease
if (delta) { // If `delta !== 0`
// Update `current` scroll position current += delta // Round value for better performancecurrent = parseFloat(current.toFixed(2))
// Call `update` again, using `requestAnimationFrame`rafId = requestAnimationFrame(updateAnimation)
} else { // If `delta === 0`
// Update `current`, and finish the animation loop current = targetrafActive = false
cancelAnimationFrame(rafId)
} // Update images (explained below)updateAnimationImages()
// Set the CSS `transform` corresponding to the custom scroll effectsetTransform(container, 'translateY('+ -current +'px)')
}// Calculate the CSS `transform` values for each `image`, given the `current` scroll positionfunction updateAnimationImages () {
// This value is the `ratio` between `current` scroll position and images `height`var ratio = current / imageHeight
// Some variables for using in the loopvar intersectionRatioIndex, intersectionRatioValue, intersectionRatio
var rotateX, rotateXMax, rotateY, rotateYMax, translateX
// For each `image` element, make calculations and set CSS `transform` accordinglyimages.forEach(function (image, index) {
// Calculating the `intersectionRatio`, similar to the value provided by // the IntersectionObserver APIintersectionRatioIndex = windowWidth > 760 ? parseInt(index / 2) : index
intersectionRatioValue = ratio - intersectionRatioIndex
intersectionRatio = Math.max(0, 1 - Math.abs(intersectionRatioValue))
// Calculate the `rotateX` value for the current `image`rotateXMax = rotateXMaxList[index]
rotateX = rotateXMax - (rotateXMax _ intersectionRatio)
rotateX = rotateX.toFixed(2)
// Calculate the _`rotateY`_ value for the current _`image`_rotateYMax = rotateYMaxList_[_index]
rotateY = rotateYMax - (rotateYMax _ intersectionRatio)
rotateY = rotateY.toFixed(2)
// Calculate the `translateX` value for the current `image`if (windowWidth > 760) {
translateX = translateXMax - (translateXMax * easeOutQuad(intersectionRatio))
translateX = translateX.toFixed(2)
} else {
translateX = 0
} // Invert `rotateX` and `rotateY` values in case the image is below the center of the viewport // Also update `translateX` value, to achieve an alternating effectif (intersectionRatioValue < 0) {
rotateX = -rotateX
rotateY = -rotateY
translateX = index % 2 ? -translateX : 0
} else {
translateX = index % 2 ? 0 : translateX
} // Set the CSS `transform`, using calculated valuessetTransform(image, 'perspective(500px) translateX('+ translateX +'px) rotateX('+ rotateX +'deg) rotateY('+ rotateY +'deg)')
})
}// Listen for `resize` event to recalculate dimmensionswindow.addEventListener('resize', setupAnimation)
// Initial setupsetupAnimation()
Github 网址:https://github.com/lmgonzalves/scroll-based-animation
| 演示地址 | 下载地址 |
专业提供WordPress主题安装、深度汉化、加速优化等各类网站建设服务,详询在线客服!
