vue2子元素进入父元素可视区域添加动画

6 阅读1分钟
      <div class="dom-item" :data-item="i" :ref="`item-${i}`" v-for="i in 100" :key="i"></div>
    </div>

scss代码

  @keyframes dom-item-animation {
    0% {
      transform: translate(300px, -150px);
    }
    100% {
      transform: translate(0px);
    }
  }
  @keyframes dom-item-animation2 {
    0% {
      transform: translate(-300px, -150px);
    }
    100% {
      transform: translate(0px);
    }
  }
  .dom-box {
    .dom-item {
      width: 200px;
      height: 50px;
      margin: 10px auto;
      box-sizing: border-box;
    }
    /* 触发动画的类 */
    .itemanimate {
      box-shadow: 1px 0px 5px rgba(255, 255, 255, 0.521);
      background-color: #fff;
      /* 定义动画属性,但动画不会自动播放 */
      animation: dom-item-animation 2.6s linear;
      animation-fill-mode: forwards;
      animation-play-state: running; /* 当添加这个类时,动画开始播放 */
    }
    .itemanimat2 {
      box-shadow: 1px 0px 5px rgba(255, 255, 255, 0.521);
      background-color: #fff;
      /* 定义动画属性,但动画不会自动播放 */
      animation: dom-item-animation2 2.6s linear;
      animation-fill-mode: forwards;
      animation-play-state: running; /* 当添加这个类时,动画开始播放 */
    }
    box-sizing: border-box;
    position: fixed;
    top: 100px;
    left: 50%;
    width: 1000px;
    height: 500px;
    overflow-y: auto;
    overflow-x: hidden;
    background-color: #110c0c2c;
    transform: translate(-50%);
    box-shadow: 1px 0px 5px rgba(0, 0, 0, 0.07);
    border-radius: 5px;
  }
</style>

mounted函数调用

      this.initObserver();
    },

js函数监听

      initObserver() {
        this.observer = new IntersectionObserver(
          (entries) => {
            entries.forEach((entry) => {
              // console.log(entry);
              if (entry.isIntersecting) {
                let n = entry.target.getAttribute('data-item');
                // 元素进入可视区域
                console.log('元素进入可视区域:', entry.target.getAttribute('data-item'));
                console.log();
                if (n % 2 === 0) {
                  // 可以添加自定义逻辑,如懒加载、高亮等
                  entry.target.classList.add('itemanimate');
                } else {
                  entry.target.classList.add('itemanimat2');
                }
              } else {
                let n = entry.target.getAttribute('data-item');
                // 元素进入可视区域
                console.log('元素进入可视区域:', entry.target.getAttribute('data-item'));
                console.log();
                if (n % 2 === 0) {
                  // 可以添加自定义逻辑,如懒加载、高亮等
                  entry.target.classList.remove('itemanimate');
                } else {
                  entry.target.classList.remove('itemanimat2');
                }
              }
            });
          },
          {
            root: this.$refs.scrollContainer, // 指定滚动容器
            rootMargin: '0px',
            threshold: 0.1 // 当元素10%可见时触发
          }
        );

        // 观察所有列表项
        this.$nextTick(() => {
          for (let index = 0; index < 100; index++) {
            let item = index;
            const el = this.$refs[`item-${item}`];
            console.log(el, 'el');

            if (el) {
              this.observer.observe(el[0] || el);
            }
          }
        });
      },