1、首先, 整体为一个div,滚动效果在div内部实现,每个数据为一个单独的li。

     <div id="scroll" :v-model="dataPopRadio" class="solidUl" @scroll="scrollChange">
            <ul>
              <li
                v-for="(item, index) in dataPopOption"
                :key="index"
              >{{item.label}}</li>
            </ul>
//滚动过程中滚动到的所需位置
            <div class="backgroundFloat"></div>
     </div>

2、在data中定义数据

dataPopOption : [{
          name: '年假',
          label: '年假'
        }, {
          name: '事假',
          label: '事假'
        }, {
          name: '病假',
          label: '病假'
        }, {
          name: '倒休假',
          label: '倒休假'
        }, {
          name: '婚假',
          label: '婚假'
        }, {
          name: '产假',
          label: '产假'
        }, {
          name: '产检假',
          label: '产检假'
        },
      ]

3、在method里边定义滚动事件 

scrollChange(e){
//首先获取到li元素
      var lis=document.getElementsByTagName('li')
//对li元素进行遍历
      for(var i=0;i<lis.length;i++){
//offsetTop返回当前元素相对于节点顶部偏移量,scrollTop返回一个元素垂直滚动的距离
//在滚动过程中,lis[i].offsetTop-e.target.scrollTop可获取到当前元素距离顶部的位置
//打印出结果自己对比,选择自己需要范围的值,我给li设置的高度为40px,因此185与225之间相差40,
//而185与225是我实际输出对比测量的我需要元素滚动到该位置时设置样式。
        if((lis[i].offsetTop-e.target.scrollTop) > 185&& (lis[i].offsetTop-e.target.scrollTop) < 225){
//当元素滚动到当前位置时,先将元素原来为"active2"的class属性去掉
//再给元素增加"active"的属性
          lis[i].classList.remove("active2")
          lis[i].classList.add("active")
//给当前元素以上的元素动态设置文字大小,离当前文字越远,文字大小越小
          for(var j=1;j<=i;j++){
            lis[i-j].style.fontSize = (20-2*j)+'px'
          }
//给当前元素以下的元素动态设置文字大小,离当前文字越远,文字大小越小
          for(var a=1;a<lis.length-i;a++){
            lis[i+a].style.fontSize = (20-2*a)+'px'
          }
//当没滚动到期待位置时,也就是其他所有元素,移除"active"的样式,增加"active2"的样式
        }else{
          lis[i].classList.remove("active")
          lis[i].classList.add("active2")
        }
      }
    },

4、style标签内设置相关样式

.solidUl{
  padding-top: 40px;
  margin-top: 15px;
  height: 350px;
//滚动设置在div内
  overflow-y: scroll;
//增加滚动的流畅性
  touch-action: pan-y;
  -webkit-overflow-scrolling: touch;
}
ul {
      padding: 80px 0 230px 0;
      margin: 0;
      background-color: #fff;
      li {
        list-style: none;
        font-size: 18px;
        line-height: 20px;
        text-align: center;
        opacity: 0.3;
        height: 40px;
        background-color: #fff;
      }
    }
.active {
  font-weight: 400;
  font-size: 20px !important;
  color: #333;
//不透明度需要高点,因为有backgroundFloat颜色的影响
  opacity: 1.2 !important;
  top: 150px;
}
.active2 {
  color: #333;
//设置不透明度
  opacity: 0.6 !important;
}
//给滚动到的所需位置增加背景色等样式
.backgroundFloat{
  width: 100%;
  height: 40px;
  background-color: #d1d1d1;
//降低不透明度,以防遮挡文字
  opacity: 0.2;
  position: absolute;
  top: 190px;
}

5、在所需触发滚动的事件中给滚动条定位。如果同时有数据的渲染则需要回调nextTick函数对异步进行处理。若没有数据的更新渲染则不需要nextTick函数,之间设置即可。

//vue中数据和dom渲染是异步的,this.$nextTick函数是在dom更新循环之后进行回调
      this.$nextTick(() =>{
//滚动到指定位置。不然未触发滚动事件的时候样式字体大小的效果不对
//scrollTop() 方法设置或返回被选元素的垂直滚动条位置
        document.getElementById("scroll").scrollTop = 80
      })

我这里有数据更新,不处理则会报错vue.esm.js?a026:628 [Vue warn]: Error in v-on handler (Promise/async): "TypeError: Cannot set properties of null (setting 'scrollTop')",如下:

6、最终效果。文字会随着滚动而改变,滚动到背景为灰色位置时文字大小最大。

Logo

前往低代码交流专区

更多推荐