sticky妙用之官网视觉差滚动实现

2021-12-03  本文已影响0人  硅谷干货

本项目是用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)
};

点赞加关注,永远不迷路

上一篇下一篇

猜你喜欢

热点阅读