前端 滚动到目标元素位置 VUE 版本

请叫我海龟先生
• 阅读 1647

1、前言

想起之前一次在写一个小程序商城时候,详情页的类似锚点的跳转花了我不少时间,因为刚写,对小程序滚动,滚动距离那套不熟悉加之本身对什么滚动高度元素距离顶部距离不是很了解,花了挺长时间的,这几天有空,就研究了下。

2、先看效果

前端 滚动到目标元素位置  VUE 版本 额,tab点击没有加效果,看着不明显,你懂我的意思就行 哈哈,电商里面最常见了

3、页面搭建

先搞一个 tab,然后下面就是 几个对应的div盒子

// 标题
 <div class="tab" >
      <span v-for="item in 4" 
              :key="item" @click="toView(item)" >
          {{`滚到${item}去`}}
      </span>
</div>
//内容
// 这是采用动态绑定ref 方便获取对应 dom 距离顶部的距离
// 同时也动态绑定元素的背景色和高度,便于区分
<div v-for="item in 4" :key="item" 
        :ref="'scrollView'+item" :id="'tab'+item" 
        class="item_box" :style="getStyle(item)" >
            {{item}}
</div>

4、动态绑定如下:

// getRandomArbitrary 用于生产指定区间的随机数
 computed:{
   getStyle(){
        return function (index){
            // 高度我就 *对应的 index来递增了
            let height = this.getRandomArbitrary(110,300)*index
            return {
                'background':
                   `linear-gradient(rgb(240,255,240),rgb(${this.getRandomArbitrary(230,255)}, ${this.getRandomArbitrary(230,240)}, ${this.getRandomArbitrary(240,255)}))`,
               height:`${height}px`
           }
        }
    }
},

5、开始实现:

目前用了三种方式:

  1. 锚点跳转
  2. ele.scrollIntoView() api跳转
  3. 老老实实用 window.scrollTo

5、1 锚点

//  锚点简单,搞个a标签,href指向对应盒子的 id就可以了,但是有个毛病
//:8080/anchor#tab1,路由也变成了这样,而且还添加到了页面历史记录中了
anchorWay(){
      let link = document.createElement("a")
       link.href = '#'+'tab'+index
       link.click()
       link.removeChild()
},

5.2、scrollIntoView

//这个也简单,想要跳转到哪个元素,就在这个元素上调用此api就行了
//还支持动画,不过ios不支持
// 这个有个弊端就是,他只能让元素滚动到页面顶部,或者元素底部在页面底部
// 一般我们上面还有个导航的 所以跳转后还需要动态去改变下距离顶部距离
scrIntoView(ele){
  // ele.scrollIntoView({behavior: "smooth", block: "start"})
    ele.scrollIntoView(true)
},

5.3、window.scrollTo

这个最方便了,直接找好需要滚动的位置,传入即可window.scrollTo(x,y)
我想来个动画呢
window.requestAnimationFrame

这个api之前有写过,有兴趣可看看之前写的,简单说下,这个api是请求开启一个动画,接收一个函数,会自动以 浏览器刷新的频率去执行,也就是说 如果我们,不断的改变 传入 window.scrollTo(x,y)中的 y值,这样就可以呈现动画的效果了。 好比 1+10+9+8+7+....+0.1 总有一天会加到100

分成几个小步骤

5.3.1、点击tab时

主要目的,获取需要的目标盒子距离顶部的距离(对应元素距离屏幕顶部),同时,当该元素距离顶部的距离 == 顶部导航高度(一般可以已知)时,不进行滚动

// 点击 tab
toView(index){
     let refV = `scrollView${index}`
     let scrView = this.$refs[refV][0]
     // 目标盒子 距离顶部距离
     let viewTop = parseInt( scrView.getBoundingClientRect().top )
     // 31 为顶部导航高度,可灵活变更 已在导航下方 return
     if( Math.abs(viewTop) < 32 ) return
     this.winScrllToView(viewTop - 31)
 },

5.3.2、获取当前window已滚动距离和需要滚动的目标位置

// y 目标元素距离顶部的距离(已减去导航高度)
 winScrllToView(y){
      // 页面当前滚动距离
      let sTop = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop
      // 页面滚动目标位置
      this.sTarget = parseInt (sTop + y)
      // 页面滚动当前位置
      this.nowLocation = parseInt(sTop)

      this.animaScrll()
  },

5.3.3、动画函数

已经知道了滚动的目标位置,和当前滚动位置,接下来就是实现滚动距离的累加(累减,上滚动时)

  // 动画函数
  animaScrll(){
  // 累加值 为 目标位置 - 已经滚动距离 / 8 呈现累加值递减
   let addDis =  (this.sTarget - this.nowLocation) / 8 

   this.nowLocation += addDis 
   window.scrollTo(0,this.nowLocation)
    // 类似定时器 会返回一个id 用来清除
   this.aniTimer = window.requestAnimationFrame(this.animaScrll)
    // 理想状态是  目标值  == 累加滚动的值 实际上不肯的,边界值可以自行判断
   if( Math.abs(this.sTarget  - this.nowLocation) <= 2 ) {
       window.cancelAnimationFrame(this.aniTimer)
       this.nowLocation = 0
       this.aniTimer = null
   }
}

好了,整个过程就完了,总的来说还是 window.scrollTo 来的直接暴力。requestAnimationFrame也存在部分兼容问题

点赞
收藏
评论区
推荐文章
blmius blmius
2年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Karen110 Karen110
2年前
一篇文章带你了解JavaScript日期
日期对象允许您使用日期(年、月、日、小时、分钟、秒和毫秒)。一、JavaScript的日期格式一个JavaScript日期可以写为一个字符串:ThuFeb02201909:59:51GMT0800(中国标准时间)或者是一个数字:1486000791164写数字的日期,指定的毫秒数自1970年1月1日00:00:00到现在。1\.显示日期使用
Jacquelyn38 Jacquelyn38
2年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
Easter79 Easter79
2年前
Taro小程序自定义顶部导航栏
微信自带的顶部导航栏是无法支持自定义icon和增加元素的,在开发小程序的时候自带的根本满足不了需求,分享一个封装好的组件,支持自定义icon、扩展dom,适配安卓、ios、h5,全面屏。我用的是京东的Taro多端编译框架写的小程序,原生的也可以适用,用到的微信/taro的api做调整就行,实现效果如下。!在这里插入图片描述(https://i
Stella981 Stella981
2年前
KVM调整cpu和内存
一.修改kvm虚拟机的配置1、virsheditcentos7找到“memory”和“vcpu”标签,将<namecentos7</name<uuid2220a6d1a36a4fbb8523e078b3dfe795</uuid
Stella981 Stella981
2年前
Python之time模块的时间戳、时间字符串格式化与转换
Python处理时间和时间戳的内置模块就有time,和datetime两个,本文先说time模块。关于时间戳的几个概念时间戳,根据1970年1月1日00:00:00开始按秒计算的偏移量。时间元组(struct_time),包含9个元素。 time.struct_time(tm_y
Easter79 Easter79
2年前
Twitter的分布式自增ID算法snowflake (Java版)
概述分布式系统中,有一些需要使用全局唯一ID的场景,这种时候为了防止ID冲突可以使用36位的UUID,但是UUID有一些缺点,首先他相对比较长,另外UUID一般是无序的。有些时候我们希望能使用一种简单一些的ID,并且希望ID能够按照时间有序生成。而twitter的snowflake解决了这种需求,最初Twitter把存储系统从MySQL迁移
Wesley13 Wesley13
2年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Wesley13 Wesley13
2年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
3个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这