本项目是用vue3做一个炫酷的类苹果官网的项目,很多地方有视觉差滚动特效,所以首先想到了css3中
sticky
属性,因为项目庞大而且是多人参与,所以每个人都是其中一个拆分vue组件中开发,所以需要抽取一个公众的计算方法,对想做的动画步骤进行拆解,能形成统一比较统一效果。
注意
在自定义组件中,内容去外层还需要再包一层div,而且要大于内容区的高度,这时候stikcy
才有效果,所以样式部分这样写:
.page-section {
height: 300vh;
background-color: white;
}
.stick-box{
width: 100%;
// height: 100vh;
padding: 5.56vh 270px;
overflow: hidden;
position: sticky;
top: 0;
}
重点
然后重点来了,配合sticky
的计算方法就派上用场了
// 默认初始值
const defaultV = -10;
// 方式一:推荐
const getScrollRatio = (sectionEl: HTMLElement):number => {
// 判空处理
if (!sectionEl) {
return defaultV;
}
// 获取窗口滚动条高度
const scrollTop = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop;
// 获取浏览器可视区的高度
const clientHeight = document.documentElement.clientHeight || document.body.clientHeight;
// section元素的高度
const elClientHeight = sectionEl.clientHeight;
// 距离顶部高度少了一屏的高度 卷起 可视区域 一部分高度,大于等于0
let ps = Math.floor(sectionEl.offsetTop - clientHeight);
ps = ps < 0 ? 0 : ps;
// 每一个section头部滚动到底部 0 ----> 1的变化
return (scrollTop - ps) / elClientHeight;
}
// 方式二:次推荐
const getScrollProgress = (sectionEl: HTMLElement):number => {
// 判空处理
if (!sectionEl) {
return defaultV;
}
// const remommendPageDom = document.getElementById('remommendPage');
let windowInnerHeight = window.innerHeight;
let domOffsetHeight = sectionEl.offsetHeight;
let domClientRectTop = sectionEl.getBoundingClientRect().top;
return (windowInnerHeight - domClientRectTop) / domOffsetHeight;
}
// 方式三:普通
const getScrollRate = (sectionEl: HTMLElement):number => {
// 判空处理
if (!sectionEl) {
return defaultV;
}
// 视口高度
const innerHeight = window.innerHeight
// 获取滚动位置
const scrollTop = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop
// 自身内容的高度
// const offsetHeight = sectionEl.offsetHeight;
// 获取dom偏移量
const offsetTop = sectionEl.offsetTop;
// 从rect中获取元素的高度
const { height: rectHeight } = sectionEl.getBoundingClientRect();
// 获取粘性高度H值和粘性Y值
const stickyH = rectHeight - innerHeight;
// 滚动的相对位置
const stickyY = scrollTop - offsetTop;
// 计算滚动比例
return stickyY / stickyH;
}
// 设置透明度
const setOpacityCallback = ({ratio,count}, callBack)=> {
for (let i = 0; i < count; i++) {
const start = 1 / count * i;
const end = 1 / count * (i + 1);
let progress = (ratio - start) / (end - start);
if (progress >= 1) progress = 1;
if (progress <= 0) progress = 0;
callBack && callBack(i, progress);
}
}
// 对外统一暴露计算位置方法
export const useCalPos = ()=> {
return {
getScrollRatio,
getScrollProgress,
getScrollRate,
setOpacityCallback
}
}
使用
在监听滚动的方法中做个打印试试,是不是你想要的输出
const onScroll = () => {
const el = document.querySelector(`.page-section`);
const ratio = getScrollRatio(el);
const count = opacityList.length;
setOpacityCallback({ ratio, count }, setOpacity);
};
const setOpacity = (i, progress) => {
opacityList[i] = progress;
console.log(i, progress)
};
点赞加关注,永远不迷路
网友评论