Как реализовать parallax не привязанный к window.pageYOffset
Здравствуйте. Подскажите пожалуйста как решить следующую задачу.
Реализован следующий функционал parallax. Сейчас он воздействует на элементы сразуже при скролле. Как мне реализовать следующее, начинать воздействие на элементы только при появлении их во viewport. А затем в обратном направлении. CodePen https://codepen.io/s24344/pen/WgmVbP <section class="anime__section"> <div class="anime__large"> <div class="anime__small"></div> </div> </section> <section class="anime__section"> <div class="anime__large"> <div class="anime__small"></div> </div> </section> var parallax = (function() { var bg = document.querySelectorAll('.anime__small'); return { move: function(block, windowScroll, strafeAmount) { var strafe = windowScroll / -strafeAmount + '%'; var transformString = 'translate3d(0,' + strafe + ', 0)'; var elements = [...block]; elements.forEach(item => { item.style.transform = transformString; item.style.webkitTransform = transformString; }); style.transform = transformString; style.webkitTransform = transformString; }, init: function(wScroll) { this.move(bg, wScroll, 20); } }; })(); window.onscroll = function() { var wScroll = window.pageYOffset; parallax.init(wScroll); }; |
s24344,
делали бы макет целиком |
CodePen
https://codepen.io/s24344/pen/WgmVbP Сейчас parallax начинает работать сразу же при скролле (т.к. расчет идет this.wScroll) на все выбранные элементы (data-hero-bg="hero-bg"). Мне же нужно, чтобы он начинал работать при появлении anime__section во viewport. |
parallax class
s24344,
не знаю какого эффекта вы хотите достичь, но можно так ... <!DOCTYPE html><html lang='en' class=''> <head> <meta charset='UTF-8'> <style class="cp-pen-styles">.app__content { padding: 200px 0; } .anime__section { display: flex; justify-content: flex-end; } .anime__large { position: relative; width: 705px; height: 694px; background: #61bfad; } .anime__small { width: 250px; height: 250px; background: #055a5b; position: absolute; bottom: -125px; left: -125px; } </style></head><body> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> </head> <body> <div class="parallax-app" data-component="parallax"> <section class="anime__section"> <div class="anime__large"> <div class="anime__small hero__bg" data-hero-bg="hero-bg"></div> </div> </section> <section class="app__content"> <p> Lorem ipsum dolor sit amet consectetur adipisicing elit. Recusandae, asperiores assumenda vel itaque cumque eveniet adipisci, laboriosam nulla ipsum ea, mollitia fugit minima natus amet! Deleniti recusandae nam reprehenderit atque? </p> </section> <section> <p> Lorem ipsum dolor sit amet consectetur adipisicing elit. Recusandae, asperiores assumenda vel itaque cumque eveniet adipisci, laboriosam nulla ipsum ea, mollitia fugit minima natus amet! Deleniti recusandae nam reprehenderit atque? </p> </section> <section class="anime__section"> <div class="anime__large"> <div class="anime__small" data-hero-bg="hero-bg"></div> </div> </section> <section class="app__content"> <p> Lorem ipsum dolor sit amet consectetur adipisicing elit. Recusandae, asperiores assumenda vel itaque cumque eveniet adipisci, laboriosam nulla ipsum ea, mollitia fugit minima natus amet! Deleniti recusandae nam reprehenderit atque? </p> </section> <section class="app__content"> <p> Lorem ipsum dolor sit amet consectetur adipisicing elit. Recusandae, asperiores assumenda vel itaque cumque eveniet adipisci, laboriosam nulla ipsum ea, mollitia fugit minima natus amet! Deleniti recusandae nam reprehenderit atque? </p> </section> <section class="app__content"> <p> Lorem ipsum dolor sit amet consectetur adipisicing elit. Recusandae, asperiores assumenda vel itaque cumque eveniet adipisci, laboriosam nulla ipsum ea, mollitia fugit minima natus amet! Deleniti recusandae nam reprehenderit atque? </p> </section> <section> <p> Lorem ipsum dolor sit amet consectetur adipisicing elit. Recusandae, asperiores assumenda vel itaque cumque eveniet adipisci, laboriosam nulla ipsum ea, mollitia fugit minima natus amet! Deleniti recusandae nam reprehenderit atque? </p> </section> <section class="anime__section"> <div class="anime__large"> <div class="anime__small" data-hero-bg="hero-bg"></div> </div> </section> <section class="app__content"> <p> Lorem ipsum dolor sit amet consectetur adipisicing elit. Recusandae, asperiores assumenda vel itaque cumque eveniet adipisci, laboriosam nulla ipsum ea, mollitia fugit minima natus amet! Deleniti recusandae nam reprehenderit atque? </p> </section> <section class="app__content"> <p> Lorem ipsum dolor sit amet consectetur adipisicing elit. Recusandae, asperiores assumenda vel itaque cumque eveniet adipisci, laboriosam nulla ipsum ea, mollitia fugit minima natus amet! Deleniti recusandae nam reprehenderit atque? </p> </section> <section class="anime__section"> <div class="anime__large"> <div class="anime__small" data-hero-bg="hero-bg"></div> </div> </section> <section class="app__content"> <p> Lorem ipsum dolor sit amet consectetur adipisicing elit. Recusandae, asperiores assumenda vel itaque cumque eveniet adipisci, laboriosam nulla ipsum ea, mollitia fugit minima natus amet! Deleniti recusandae nam reprehenderit atque? </p> </section> </div> </body> </html> <script >class AppParallax { constructor(el) { this.el = el; this.strafeAmount = 230; this.heroBg = [...this.el.querySelectorAll('[data-hero-bg="hero-bg"]')]; this.move = this.move.bind(this); this.init(); } init() { window.addEventListener('scroll', this.move); } checkViewport(el) { var rect = el.getBoundingClientRect(); var y = rect.bottom / (innerHeight + rect.bottom - rect.top); return y } move() { this.heroBg.forEach(item => { let parent = item.parentNode; let y = this.checkViewport(parent); let strafe = -y * this.strafeAmount + '%'; let transformString = 'translateY('+strafe+')'; item.style.transform = transformString; item.style.webkitTransform = transformString; }); }} const appParallax = new AppParallax( document.querySelector('[data-component="parallax"]')); </script> </body></html> |
В предложенном вами решении, при первом скролле вниз происходит резкий скачек элемента (на котором parallax), а затем он движется вниз (у меня же он со своей изначальной позиции движется вверх при сколле вниз, а затем возвращается обратно). Я же пытаюсь достичь, что бы вне зависимости от расположения виджета (контейнера) на странице везде был эффект, как на самом верхнем. Я немного изменил pen, но по прежнему не понимаю как избавится от this.wScroll в this.strafe = this.wScroll / -this.strafeAmount + '%'; У вас работает примерно как мне нужно, но как-то наоборот плюс скачок, как я выше описал.
https://codepen.io/s24344/pen/WgmVbP |
s24344,
не могу понять что вам нужно, так? <!DOCTYPE html><html lang='en' class=''> <head> <meta charset='UTF-8'> <style class="cp-pen-styles">.app__content { padding: 200px 0; } .anime__section { display: flex; justify-content: flex-end; } .anime__large { position: relative; width: 705px; height: 694px; background: #61bfad; } .anime__small { width: 250px; height: 250px; background: #055a5b; position: absolute; bottom: -125px; left: -125px; } </style></head><body> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> </head> <body> <div class="parallax-app" data-component="parallax"> <section class="anime__section"> <div class="anime__large"> <div class="anime__small hero__bg" data-hero-bg="hero-bg"></div> </div> </section> <section class="app__content"> <p> Lorem ipsum dolor sit amet consectetur adipisicing elit. Recusandae, asperiores assumenda vel itaque cumque eveniet adipisci, laboriosam nulla ipsum ea, mollitia fugit minima natus amet! Deleniti recusandae nam reprehenderit atque? </p> </section> <section> <p> Lorem ipsum dolor sit amet consectetur adipisicing elit. Recusandae, asperiores assumenda vel itaque cumque eveniet adipisci, laboriosam nulla ipsum ea, mollitia fugit minima natus amet! Deleniti recusandae nam reprehenderit atque? </p> </section> <section class="anime__section"> <div class="anime__large"> <div class="anime__small" data-hero-bg="hero-bg"></div> </div> </section> <section class="app__content"> <p> Lorem ipsum dolor sit amet consectetur adipisicing elit. Recusandae, asperiores assumenda vel itaque cumque eveniet adipisci, laboriosam nulla ipsum ea, mollitia fugit minima natus amet! Deleniti recusandae nam reprehenderit atque? </p> </section> <section class="app__content"> <p> Lorem ipsum dolor sit amet consectetur adipisicing elit. Recusandae, asperiores assumenda vel itaque cumque eveniet adipisci, laboriosam nulla ipsum ea, mollitia fugit minima natus amet! Deleniti recusandae nam reprehenderit atque? </p> </section> <section class="app__content"> <p> Lorem ipsum dolor sit amet consectetur adipisicing elit. Recusandae, asperiores assumenda vel itaque cumque eveniet adipisci, laboriosam nulla ipsum ea, mollitia fugit minima natus amet! Deleniti recusandae nam reprehenderit atque? </p> </section> <section> <p> Lorem ipsum dolor sit amet consectetur adipisicing elit. Recusandae, asperiores assumenda vel itaque cumque eveniet adipisci, laboriosam nulla ipsum ea, mollitia fugit minima natus amet! Deleniti recusandae nam reprehenderit atque? </p> </section> <section class="anime__section"> <div class="anime__large"> <div class="anime__small" data-hero-bg="hero-bg"></div> </div> </section> <section class="app__content"> <p> Lorem ipsum dolor sit amet consectetur adipisicing elit. Recusandae, asperiores assumenda vel itaque cumque eveniet adipisci, laboriosam nulla ipsum ea, mollitia fugit minima natus amet! Deleniti recusandae nam reprehenderit atque? </p> </section> <section class="app__content"> <p> Lorem ipsum dolor sit amet consectetur adipisicing elit. Recusandae, asperiores assumenda vel itaque cumque eveniet adipisci, laboriosam nulla ipsum ea, mollitia fugit minima natus amet! Deleniti recusandae nam reprehenderit atque? </p> </section> <section class="anime__section"> <div class="anime__large"> <div class="anime__small" data-hero-bg="hero-bg"></div> </div> </section> <section class="app__content"> <p> Lorem ipsum dolor sit amet consectetur adipisicing elit. Recusandae, asperiores assumenda vel itaque cumque eveniet adipisci, laboriosam nulla ipsum ea, mollitia fugit minima natus amet! Deleniti recusandae nam reprehenderit atque? </p> </section> </div> </body> </html> <script >class AppParallax { constructor(el) { this.el = el; this.strafeAmount = 190; this.heroBg = [...this.el.querySelectorAll('[data-hero-bg="hero-bg"]')]; this.move = this.move.bind(this); this.init(); } init() { window.addEventListener('scroll', this.move); } checkViewport(el) { var rect = el.getBoundingClientRect(); var y = rect.top ; return rect.top < innerHeight && rect.top > -innerHeight ? rect.top/innerHeight : 0 } move() { this.heroBg.forEach((item, i) => { let parent = item.parentNode; let y = this.checkViewport(parent); let strafe = y * this.strafeAmount + '%'; let transformString = 'translateY('+strafe+')'; if(y){ item.style.transform = transformString; item.style.webkitTransform = transformString; } }); }} const appParallax = new AppParallax( document.querySelector('[data-component="parallax"]')); </script> </body></html> |
Рони, спасибо Вам за помощь. Небольшое несовпадение с позицией элемента есть, но это уже ерунда. Можно поиграться со значениями this.strafeAmount. Вы очень помогли.
|
Часовой пояс GMT +3, время: 04:00. |