前言
当前项目周期需要泳道图拖拽功能为前提下,对多泳道,多标题进行滚动制定展示功能,本人开始进行研究如果是想滚动多标题吸顶
css粘性布局
1.position:sticky
在兼容此样式的浏览器下,效果极好,推荐指数✨✨✨✨✨
使用css提供的css方法进行滚动吸顶功能,下图是此css效果的兼容性,在ios6+以上有比较好的性能
css粘性布局的几个条件:
1.元素不会脱离文档流,当元素被黏在页面顶部时,在原来文档流中仍然占据位置,类似relative定位
2.元素相对其最近可滚动的祖先元素粘性定位,如果其祖先元素都不能滚动,则相对于位置定位
3.元素最近祖先元素定位设置为visible时候,则元素相对于祖先元素进行sticky定位,若是祖先设置为overflow:hidden,则元素不会sticky定位
移动端粘性布局兼容参考文章: www.cnblogs.com/gopark/p/90…
2.scroll监听单需求
单独的导航栏或者标题栏效果,本文档使用reactHooks写法,实现
useEffect(() => {
let tit = document.getElementById("nav");
//占位符的位置,添加占位符让fixed抖动效果减少(本人未复现此功能,还是会有抖动效果)
const rect = tit.getBoundingClientRect(); //获得页面中导航条相对于浏览器视窗的位置
let inser = document.createElement("div");
tit.parentNode.replaceChild(inser, tit);
inser.appendChild(tit);
inser.style.height = rect.height + "px";
let titleTop = tit.offsetTop;
window.addEventListener("scroll", (e) => {
const btop =
document.body.scrollTop || document.documentElement.scrollTop;
//如果滚动距离大于导航条据顶部的距离
if (btop > titleTop) {
//为导航条设置fixed效果,css代码不提供咯
tit.className = "fix";
} else {
//移除fixed
tit.className = "";
}
});
}, []);
单独滚动制定效果参考网站: www.cnblogs.com/liuyk-code/…
fixed引起的抖动问题修复: blog.csdn.net/zx_001/arti…
3.多标题滚动吸顶实现JS篇
1.方式同单标题实现方式一样
注意事项:因为多标题滚动问题,有fixed布局的标题或者导航栏会脱离文档流,因为我们需要提前记住每一个元素渲染完以后的offsetTop位置便于计算
具体代码如下:
//首次进入是否需要提前计算元素的位置
let flag = false;
//滚动元素数据保存数组
let offestList = [];
const handleScroll = (e) => {
//当前scroll滚动的距离
const hasScrollTop = e.target.scrollTop;
//fixed或脱离文档流,给予当前数据宽度,100%不然是整个屏幕宽度(作者左右布局分开了)
const hasClientWidth = e.target.clientWidth;
const domList = document.querySelectorAll('.laneBoard_title');
if (!flag) {
domList?.forEach((item) => {
offestList.push({
offsetTop: item.offsetTop,
node: item,
});
});
if (offestList.length) {
flag = true;
}
}
let modifyDom = null;
offestList.forEach((item, index) => {
const nodeItem = item;
//判断是否有下一个titleDom
const currentNode = item?.offsetTop;
const nextNode = offestList[index + 1]?.offsetTop || -1;
if (hasScrollTop > currentNode && hasScrollTop < nextNode + 10) {
modifyDom = item.node;
}
if (hasScrollTop > currentNode && nextNode === -1) {
modifyDom = item.node;
}
//每次滚动需要清空上次滚动的
if (item?.node?.id !== modifyDom?.id) {
nodeItem.node.style.position = '';
}
});
if (modifyDom?.style && modifyDom.style.position !== 'fixed') {
modifyDom.style = `position:fixed;top:180px;width:${hasClientWidth}px`;
}
};
const dom = document.querySelector('.laneBoardIndex');
dom.addEventListener('scroll', handleScroll);
return () => {
dom.removeEventListener('scroll', handleScroll);
};
另外如果标题宽度不是固定的情况下我们需要监听resize去控制标题宽度的变化
结尾
最终本人还是使用了position:sticky 粘性布局,并且在浏览器中判断当前浏览器版本配合 多标题滚动JS去实现了当前功能,防着功能在低配浏览器内部不兼容的问题