简体   繁体   中英

How to display and transition when scroll position reaches element position in the screen?

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?

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM