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.