【问题标题】:How to display and transition when scroll position reaches element position in the screen?当滚动位置到达屏幕中的元素位置时如何显示和过渡?
【发布时间】:2017-07-22 17:21:40
【问题描述】:

假设这是我的模板:

<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>

我想分别在视口中显示RowOne, RowTwo and RowThree 并为其设置动画。就像在Laracasts website 中一样,当滚动位置达到元素偏移量时,元素就会出现并动画。是否可以使用 Vue.js 和 javascript?

【问题讨论】:

  • 看看我下面的答案,它也有一个工作的sn-p。
  • 你见过vue-scroll-reveal吗?

标签: javascript vue.js vuejs2


【解决方案1】:

您可以使用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
  }  
})

当元素在视口中可见时,您需要将v-vpshow 指令添加到要为其设置动画的元素。

例如:

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

该指令使用两个类。

1)before-enter:默认隐藏元素,指令绑定元素时自动添加。

2) enter: 这个应该包含你想要在元素变得可见时应用的过渡。

一旦元素在视口中变得可见(触发动画后),v-vpshow 将自动解除绑定,删除在bind 上设置的所有数据和事件侦听器。

这是一个工作示例。

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>

【讨论】:

  • 是的,这行得通。谢谢你。附带问题,为什么binding.inViewport(el) 不起作用,但binding.def.inViewport(el) 起作用?您能否为此提供参考,对我有帮助吗?
  • 在控制台中检查binding后,我实际上知道我们应该使用binding.ref。我发现它有一个 def 对象,其中包含我提供的所有指令定义。我查看了官方文档,并没有找到关于这个def 的任何信息。所以我猜它没有记录在案。
  • 哦,他们应该记录下来的。而且我从未尝试在控制台中检查它。再次感谢你!现在我有了更好的理解。
【解决方案2】:

是的,应该是。当您检测到用户滚动了一定距离时,您只需要将 none 中的 display 属性设置为可见。

这是另一个问题的答案,可以帮助您实现: Show div on scrollDown after 800px

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-04-26
    • 1970-01-01
    • 2011-08-13
    • 1970-01-01
    • 2019-02-17
    • 2015-07-03
    相关资源
    最近更新 更多