滚动滚动图像

时间:2019-01-31 14:48:19

标签: javascript vue.js

我的目的是使图像以滚动方式闪烁3次(例如依次亮起然后熄灭,以1秒的延迟连续闪烁3次),然后一直保持直到用户向下滚动超过3600像素为止。

我添加了事件监听器:

created() {
  window.addEventListener('scroll', this.scrollAnimation)
}

在滚动时,我触发方法scrollAnimation

methods: {
  scrollAnimation() {
    let currentPos = window.pageYOffset
    if (currentPos > 3000 && currentPos < 3600) {
      this.$refs.supportOff.style.display = 'none'
      this.$refs.supportOn.style.display = 'block'
    } else {
      this.$refs.supportOff.style.display = 'block'
      this.$refs.supportOn.style.display = 'none'
    }
  }
}

这是图像的模板:

<div class="support__image-wrapper">
  <img ref="supportOff" class="support__image support__image_on" src="../../assets/images/247-off.png">
  <img ref="supportOn" class="support__image support__image_off" src="../../assets/images/247-on.png">
</div>

现在此代码有效,当我向下滚动3000像素但不低于3600像素时,它将显示247-on图像并隐藏247-off图像。但是,闪烁会出现问题,如果我使用setInterval,则每当用户在3000至3600 px之间滚动时,都会触发该问题。实现闪烁的最佳方法是什么?

2 个答案:

答案 0 :(得分:2)

一些尝试...

  1. 不要开始操纵与DOM $ref

相反,创建一个变量,它在DOM

的变化触发
methods: {
  scrollAnimation() {
    this.showSupport = window.pageYOffset > 3000 && window.pageYOffset < 3600
  }
}
<div>
  <img v-if="showSupport" class="blink" src="../../assets/images/247-on.png">
  <img v-else src="../../assets/images/247-off.png">
</div>
  1. 闪烁,我建议您使用CSS动画(@keyframes)。这样,您就可以控制眨眼的时间,而不在脚本什么。它只是立即开始闪烁,因为它是在页面上可见。
.blink {
  animation: blink 1s infinite;
}

@keyframes blink {
    0% {opacity: 0}
    49%{opacity: 0}
    50% {opacity: 1}
}

希望这会有所帮助。

答案 1 :(得分:1)

仅基于t3__rry's comment,为未优化/去抖动的基于滚动的事件如何导致严重的性能问题,为未来的读者添加一个快速演示;以及Mulhoon's nice advice,以及如何使用CSS @keyframes来使动画闪烁:

new Vue({
  el: '#app',

  data() {
    return {
      blinkRate: 1000,
      blinkCount: 3,
      blinking: false,
      blinkTimeoutId: -1,

      state: false,
      currentPos: window.pageYOffset
    }
  },

  mounted() {
    window.addEventListener('scroll', _.debounce(() => {
      this.currentPos = window.pageYOffset;

      if (this.currentPos > 3000 && this.currentPos < 3600) {
        this.state = true;
      } 
      else {
        this.state = false;
      }
    }), 100);
  },

  methods: {
    blink() {
      if (this.blinkTimeoutId > -1) {
        clearTimeout(this.blinkTimeoutId);
      }

      this.blinking = true;

      this.blinkTimeoutId = setTimeout(() => {
        this.blinking = false;

      }, 1000 * this.blinkCount);
    }
  },

  watch: {
    state() {
      this.blink();
    }
  }
});
#app {
  background-color: gainsboro;
  height: 2000vh;
  padding: 10px;
}

.page-offset {
  position: fixed;
  top: 20px;
  right: 20px;
}

.blinker > div {
  border-radius: 50%;
  border: 2px solid white;
  color: white;
  font-weight: bold;
  height: 35px;
  left: 20px;
  line-height: 35px;
  padding: 5px;
  position: fixed;
  text-align: center;
  top: 20px;
  vertical-align: middle;
  width: 35px;
}

.blinker.animate > div {
  animation: blink 1s infinite;
}

.blinker .on {
  background-color: green;
}

.blinker .off {
  background-color: crimson;
}

@keyframes blink {
  0% {
    opacity: 0
  }
  49% {
    opacity: 0
  }
  50% {
    opacity: 1
  }
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>

<div id="app">
  <div :class="['blinker', { 'animate': blinking } ]">
    <div class="on" v-if="state">ON</div>
    <div class="off" v-else>OFF</div>
  </div>

  <code class="page-offset">pageYOffset: {{Math.floor(currentPos)}}</code>
</div>