h5软盘占位把定位内容往上顶_「H5」三种滚动吸顶效果实现方案以及性能优化...

方案

滑动吸顶效果的常见实现方式有以下几种:

1.positon: sticky

2.监听元素的滚动事件,使用offset判断

3.obj.getBoundingClientRect().top

下面依次介绍

positon: sticky

postion: sticky 属性值是css3新加入的属性,近似于relative和fixed的结合体

sticky被称为粘性定位元素,postion属性值为sticky的元素在目标区域内时表现的和position: relative时无异。

当元素满足粘性定位的要求时(如top: 100px),他的表现与position: fixed无异

元素固定的相对偏移是相对于离它最近的具有滚动框的祖先元素,如果祖先元素都不可以滚动,那么是相对于viewport来计算元素的偏移量。

使用条件:

父元素不能设置为 overflow:hidden/auto

如果要实现fixed的效果,必须要指定 top,bottom,right,left之一,不然其表现与relative无异

父元素的高度不能低于skicky元素的高度

坑:

sticky元素是容齐相关的,它只在自己的符合条件的祖先容器内生效。

sticky元素虽然在满足粘性条件时表现position: fixed 无异,但是并不会触发BFC

sticky元素对于写在样式表中的z-index是无效的,如果想用z-index属性可以写在行内样式中

兼容性:

ad472a0e12f2219aba9a0122b8ca414d.png

兼容性不太友善,ios虽然支持度还行但是刘海屏的表现暂时待定

使用方式:

.sticky{

positon: sticky;

top: 10px

}

复制代码

监听滚动事件——offset

首先来复习以下offset值的含义:

距离拥有相对定位的父级元素的顶部偏移量

那么offset并不一定表示元素距离页面顶部的距离,也可能是与拥有相对定位的父级元素的顶部距离

假设我们需要的吸顶效果是在body的顶部,我们可以如下改造一个方法

getOffset(obj,direction) {

let offsetL = 0;

let offsetT = 0;

// 依次获取父级元素的offsetLeft/offsetTop

while( obj!== window.document.body && obj !== null ){

offsetL += obj.offsetLeft;

offsetT += obj.offsetTop;

obj = obj.offsetParent;

}

if(direction === 'left'){

return offsetL;

}else {

return offsetT;

}

}

handleScroll(e) {

let scrollTop = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop;

let offsetTop = getOffset(e.target,'top');

if(scrollTop > offsetTop){

// fixed

}

}

复制代码

优势:兼容性优秀

劣势:存在性能问题,最好搭配节流函数使用

监听滚动事件——obj.getBoundingClientRect().top

定义:返回某个元素相对浏览器视窗上下左右的距离

也就是说,这个api完全可以取代上面那个函数...

兼容性:

62ed3a055a29755c17ab37424876714f.png

优势:简 洁 , 兼 容 性 极 佳

劣势:没有解决reflow过多的性能问题

性能优化

众所周知,所有的scroll问题都逃不过高强度reflow带来的性能压力

解决方法也非常明确——牺牲平滑度,减少触发次数

throttle

在通常情况下,我们可以直接使用节流函数直接来限制触发次数,比如这么做

// 假设你封装好了一个throttle(func,time)的节流函数

window.addEventListener('scroll', throttle(handleScroll, 20));

复制代码

但这么使用有一个问题。。那就是会出现吸顶时有一定卡顿的情况,就不够润。

那咋办呢?

我们不妨换种思路。。。不如精确控制handleScroll()函数的触发时机?

自然我们就想到了 IntersectionObserver API

IntersectionObserver API

IntersectionObserver API 的使用教程请移步这里

这个api的主要目的是用来判断一个元素是否在可视范围内(并可以控制触发时机)

兼容性:

28ec35712a26d74825a356f7ae24e9c8.png

不难发现还是有那么一点兼容性问题的。所以我们不如将throttle和IntersectionObserver 方案结合起来使用

结合方案

this.flag == false

scrollFunc(e) {

if( IntersectionObserver ){

const observer = new IntersectionObserver(function(){

const offsetTop = e.target.getBoundingClientRect().top;

if(offsetTop < 0){

// 吸顶

this.flag == true

}else{

this.flag == false

}

}, {

// 100%时触发回调函数

threshold: [1]

});

observer.observe(e.target);

} else {

window.addEventListener('scroll', throttle(()=>{

let offsetTop = e.target.getBoundingClientRect().top;

if(offsetTop < 0){

// 吸顶

this.flag == true

}else{

this.flag == false

}

}, 20));

}

}

复制代码

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值