Javascript-форум (https://javascript.ru/forum/)
-   Элементы интерфейса (https://javascript.ru/forum/dom-window/)
-   -   Как реализовать parallax не привязанный к window.pageYOffset (https://javascript.ru/forum/dom-window/75323-kak-realizovat-parallax-ne-privyazannyjj-k-window-pageyoffset.html)

s24344 21.09.2018 14:37

Как реализовать 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);
};

рони 21.09.2018 14:58

s24344,
делали бы макет целиком

s24344 22.09.2018 06:40

CodePen
https://codepen.io/s24344/pen/WgmVbP

Сейчас parallax начинает работать сразу же при скролле (т.к. расчет идет this.wScroll) на все выбранные элементы (data-hero-bg="hero-bg"). Мне же нужно, чтобы он начинал работать при появлении anime__section во viewport.

рони 22.09.2018 09:21

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>

s24344 22.09.2018 15:44

В предложенном вами решении, при первом скролле вниз происходит резкий скачек элемента (на котором parallax), а затем он движется вниз (у меня же он со своей изначальной позиции движется вверх при сколле вниз, а затем возвращается обратно). Я же пытаюсь достичь, что бы вне зависимости от расположения виджета (контейнера) на странице везде был эффект, как на самом верхнем. Я немного изменил pen, но по прежнему не понимаю как избавится от this.wScroll в this.strafe = this.wScroll / -this.strafeAmount + '%'; У вас работает примерно как мне нужно, но как-то наоборот плюс скачок, как я выше описал.
https://codepen.io/s24344/pen/WgmVbP

рони 22.09.2018 17:23

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>

s24344 22.09.2018 19:47

Рони, спасибо Вам за помощь. Небольшое несовпадение с позицией элемента есть, но это уже ерунда. Можно поиграться со значениями this.strafeAmount. Вы очень помогли.


Часовой пояс GMT +3, время: 04:00.