Vue Parallax, проблема с увеличением скорости - PullRequest
0 голосов
/ 24 июня 2019

Я адаптировал руководство по параллаксу, которое я нашел в Интернете, для работы в моей ситуации, в основном я устранил необходимость жестко кодировать ширину и высоту контейнера параллакса, я предпочитаю, чтобы контент управлял этим.

Однако у меня возникают проблемы с ускорением и замедлением эффекта, так как увеличение числа отправляет изображение с экрана.

Я потратил часы на то, чтобы разобраться с расчетами, чтобы исправить это, но я изо всех сил, я добавил эффект ниже и преобразовал мои .vue файлы во встроенные компоненты.

Мне не удалось преобразовать мои * .vue-файлы во встроенные компоненты, появляется ошибка о том, что вычисленные свойства не определены, может кто-нибудь сказать мне, как решить эту проблему, чтобы основная проблема могла бытьрешен?

Ожидаемый результат

Имеет компонент Vue, который добавляет эффект параллакса в div, чтобы CSS мог контролировать фон и добавлять контент.Но также есть регулируемая скорость прокрутки для эффекта параллакса.

Фактический результат

Эффект параллакса, когда для значения factor установлено значение 0.5, но изображение уходит с экрана, например, при установке высоты на 0.9, что должно вызвать появление изображениячтобы прокрутить больше.

const ParallaxElement = Vue.component('ParallaxElement', {
  inject: ['parallaxContainer'],
  props: {
    factor: {
      default: 0.25,
      type: Number,
    },
  },
  computed: {
    offset() {
      const {
        height,
        scrollFactor
      } = this.parallaxContainer;
      // The offset is relative to the height of
      // the element. This means, if the factor is
      // 0.5, the element is moved half its height
      // over the full scroll distance of the viewport.
      return scrollFactor * (height / 2) * this.factor;
    }
  },
  template: `
    <div :style="{ transform: translate3d(0, ${offset}px, 0) }" class="ParallaxElement">
      <slot></slot>
    </div>
  `
});

const ParallaxImage = Vue.component('ParallaxImage', {
  name: 'ParallaxImage',
  components: {
    ParallaxElement,
  },
  props: {
    factor: {
      default: 0.5,
      type: Number,
    },
  },
  data() {
    return {
      innerHeight: 0,
      width: 0,
      height: 0
    };
  },
  computed: {
    aspectRatio() {
      return this.height / 2;
    },
    compensatedFactor: function() {
      // Because the parallax effect is relative
      // to the containers height and because we
      // shrink the containers height by the given
      // factor, we have to compensate this by
      // increasing the factor.
      return this.factor * 2;
    },
    compensatedHeight: function() {
      // We want the image to scroll inside of a
      // container to prevent the image scrolling
      // above its sourounding elements. The
      // container must be shrinked by the given
      // factor to make sure we don't have any
      // whitespace when scrolling.
      return this.innerHeight - (this.innerHeight * this.factor);
    },
    template: `
    <div :style="{ height: ${compensatedHeight}px }" class="parallax__image">
      <ParallaxElement :factor="compensatedFactor" :style="{ paddingTop: ${aspectRatio}% }" class="parallax__aspect-ratio-wrap" >
        <div ref="inside" class="parallax__aspect-ratio-inside">
          <slot></slot>
        </div>
      </ParallaxElement>
  </div>
  `
  },
  mounted() {

    this.height = this.$parent.$el.getBoundingClientRect().height;
    this.width = this.$parent.$el.getBoundingClientRect().width;

    this.$nextTick(() => {
      this.setInnerHeight();
    });

    const eventHandler = () => requestAnimationFrame(this.setInnerHeight);
    window.addEventListener('resize', eventHandler);
    this.$on('hook:destroyed', () => {
      window.removeEventListener('resize', eventHandler);
    });
  },
  methods: {
    setInnerHeight() {
      this.innerHeight = this.$refs.inside.getBoundingClientRect().height;
    },
  },
});

const ParallaxContainer = Vue.component('parallax', {
  name: 'ParallaxContainer',
  provide() {
    return {
      parallaxContainer: this.data,
    };
  },
  data() {
    return {
      data: {
        height: 0,
        scrollFactor: 0,
        width: 0,
      },
    };
  },
  template: '<button v-on:click="count++">You clicked me {{ count }} times.</button>',
  mounted() {
    this.calcParallax();

    // We're using a `requestAnimationFrame()`
    // for optimal performance.
    const eventHandler = () => requestAnimationFrame(this.calcParallax);
    window.addEventListener('resize', eventHandler);
    window.addEventListener('scroll', eventHandler);
    // Remove the scroll hanlder when the
    // component is destroyed.
    this.$on(`hook:destroyed`, () => {
      window.removeEventListener('resize', eventHandler);
      window.removeEventListener('scroll', eventHandler);
    });
    this.$nextTick(() => {
      requestAnimationFrame(this.calcParallax);
    });
  },
  methods: {
    calcParallax() {
      const containerRect = this.$el.getBoundingClientRect();

      this.data.height = containerRect.height;
      this.data.width = containerRect.width;

      const viewportOffsetTop = containerRect.top;
      const viewportOffsetBottom = window.innerHeight - viewportOffsetTop;

      this.data.scrollFactor = viewportOffsetBottom / (window.innerHeight + this.data.height);
    },
  },
  template: `
  <div class="ParallaxContainer">
        <slot></slot>
    </div>
  `
});

Vue.component('parallax', {
  components: {
    ParallaxContainer,
    ParallaxElement,
    ParallaxImage
  }
});

new Vue('#app');
.parallax__overlay {
  position: relative;
  z-index: 2;
  padding: 30px 0;
  box-sizing: border-box;
}
.parallax__image {
  position: absolute;
  top: 0;
  width: 100%;
  z-index: 1;
  height: 100%;
  background-size: cover;
  background: url('https://i.ytimg.com/vi/pXs8DFC9ALw/maxresdefault.jpg') center center no-repeat;
}

.html1 {
  margin-top: 120vh;
  margin-bottom: 120vh;
  display:block;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>

<div id='app'>
  <parallax class="app row-block html1">
    <div class="parallax__overlay">
      <div class="wrapper">
        <div class="container">
          <div class="row">
            <h1>Welcome to <span>Somewhere</span></h1>
            <h2>Simple. Friendly. Affordable</h2>
            <a href="#" class="button" title="Visit our showroom">Visit Our Showroom</a>
          </div>
        </div>
      </div>
    </div>
    <parallax-image :factor="0.5">
      <div class="image"></div>
    </parallax-image>
  </parallax>
</div>
...