最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How to display and transition when scroll position reaches element position in the screen? - Stack Overflow

programmeradmin0浏览0评论

Suppose this is my template:

<template>
    <div id="Test">
        <transition name="fade">
            <div class="row" id="RowOne">
                <p>Lorem ipsum dolor odit qui sit?</p>
            </div>
        </transition>
        <transition name="fade">
            <div class="row" id="RowTwo">
                <p>Lorem ipsum dolor sit amet, consectetur.</p>
            </div>
        </transition>
        <transition name="fade">
            <div class="row" id="RowThree">
                <p>Lorem ipsum dolor sit amet, tenetur!</p>
            </div>
        </transition>
    </div>
</template>

I want to display and animate RowOne, RowTwo and RowThree when it's in the displayed in the viewport, respectively. Like in the Laracasts website, the elements appear and animate when scroll position reaches the elements offset. Is it possible using Vue.js and javascript?

Suppose this is my template:

<template>
    <div id="Test">
        <transition name="fade">
            <div class="row" id="RowOne">
                <p>Lorem ipsum dolor odit qui sit?</p>
            </div>
        </transition>
        <transition name="fade">
            <div class="row" id="RowTwo">
                <p>Lorem ipsum dolor sit amet, consectetur.</p>
            </div>
        </transition>
        <transition name="fade">
            <div class="row" id="RowThree">
                <p>Lorem ipsum dolor sit amet, tenetur!</p>
            </div>
        </transition>
    </div>
</template>

I want to display and animate RowOne, RowTwo and RowThree when it's in the displayed in the viewport, respectively. Like in the Laracasts website, the elements appear and animate when scroll position reaches the elements offset. Is it possible using Vue.js and javascript?

Share Improve this question asked Jul 22, 2017 at 17:21 KakarKakar 5,59911 gold badges64 silver badges94 bronze badges 2
  • Look at my answer below, it has a working snippet too. – Ikbel Commented Jul 24, 2017 at 0:37
  • have you seen vue-scroll-reveal? – Eliran Malka Commented Apr 12, 2019 at 22:03
Add a comment  | 

2 Answers 2

Reset to default 17

Here is how you can do it with a directive.

Vue.directive('vpshow', {
  inViewport (el) {
    var rect = el.getBoundingClientRect()
    return !(rect.bottom < 0 || rect.right < 0 || 
             rect.left > window.innerWidth ||
             rect.top > window.innerHeight)
  },

  bind(el, binding) {
    el.classList.add('before-enter')
    el.$onScroll = function() {
      if (binding.def.inViewport(el)) {
        el.classList.add('enter')
        el.classList.remove('before-enter')
        binding.def.unbind(el, binding)        
      }
    }
    document.addEventListener('scroll', el.$onScroll)
  },

  inserted(el, binding) {
    el.$onScroll()  
  },

  unbind(el, binding) {    
    document.removeEventListener('scroll', el.$onScroll)
    delete el.$onScroll
  }  
})

You will need to add v-vpshow directive to the elements you want to animate when they become visible in the viewport.

For example:

<div class="row" id="RowOne" v-vpshow>...</div>

This directive uses two classes.

1) before-enter: it hides the element by default and is added automatically when the directive is bound to the element.

2) enter: this one should contain the transition you want to apply when the element becomes visible.

v-vpshow will unbind itself automatically once the element has become visible (after triggering the animation) in the viewport removing any data and events listeners that were set on bind.

Here is a working example.

Vue.directive('vpshow', {
  inViewport (el) {
    var rect = el.getBoundingClientRect()
    return !(rect.bottom < 0 || rect.right < 0 || 
             rect.left > window.innerWidth ||
             rect.top > window.innerHeight)
  },
  
  bind(el, binding) {
    el.classList.add('before-enter')
    el.$onScroll = function() {
      if (binding.def.inViewport(el)) {
        el.classList.add('enter')
        el.classList.remove('before-enter')
        binding.def.unbind(el, binding)        
      }
    }
    document.addEventListener('scroll', el.$onScroll)
  },
  
  inserted(el, binding) {
    el.$onScroll()  
  },
  
  unbind(el, binding) {    
    document.removeEventListener('scroll', el.$onScroll)
    delete el.$onScroll
  }  
})

new Vue({
  el: '#app',  
})
/* v-vpshow classes */
.before-enter {
  opacity: 0;
}

.enter {
  transition: opacity 2s ease;  
}
/* ---------------- */



.row {  
  display: flex;
  min-height: 500px;
  justify-content: center;
  font-size: 20px;
  font-family: tahoma;
}

#RowOne {
  background-color: yellow;  
}

#RowTwo {
  background-color: #5D576B;
}

#RowThree {
  background-color: #F7567C;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.4.2/vue.min.js"></script>

<div id="app">
    <div id="Test">
        <div class="row" id="RowOne" v-vpshow>
            <p>Lorem ipsum dolor sit amet, consectetur.</p>
        </div>
        <div class="row" id="RowTwo" v-vpshow>
            <p>Lorem ipsum dolor sit amet, consectetur.</p>
        </div>
        <div class="row" id="RowThree" v-vpshow>
            <p>Lorem ipsum dolor sit amet, tenetur!</p>
        </div>
    </div>
</div>

Yeah it should be. You should just have to set the display property from none to something visible when you detect that the user has scrolled a certain distance.

Here's another question with answers that will help you implement that: Show div on scrollDown after 800px

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论