前端实现:鼠标滚动,页面盒子丝滑上升的效果

lxf2023-03-11 18:10:01

鼠标滚动,盒子缓慢上移

这是一种很常见的页面效果,有这种效果加持的页面用户体验感更佳,来尝试在你的项目中添加这个效果吧!先上效果视频

效果如下

前端实现:鼠标滚动,页面盒子丝滑上升的效果

HTML

先给出基本的结构,页面当中多个p模拟多个板块,同时阻止a链接触发默认事件:javascript:void(0)

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <link rel="stylesheet" href="css/test.css">
</head>
<body>
    <p class="div1"><a href='javascript:void(0)'>1</a></p>
    <p class="div2"><a href='javascript:void(0)'>2</a></p>
    <p class="div1"><a href='javascript:void(0)'>3</a></p>
    <p class="div2"><a href='javascript:void(0)'>4</a></p>
    <p class="div1"><a href='javascript:void(0)'>5</a></p>
    <p class="div2"><a href='javascript:void(0)'>6</a></p>
    <p class="div1"><a href='javascript:void(0)'>7</a></p>
    <p class="div2"><a href='javascript:void(0)'>8</a></p>
    <p class="div1"><a href='javascript:void(0)'>9</a></p>
    <p class="div2"><a href='javascript:void(0)'>10</a></p>
    <p class="div1"><a href='javascript:void(0)'>11</a></p>
    <p class="div2"><a href='javascript:void(0)'>12</a></p>
    <p class="div1"><a href='javascript:void(0)'>13</a></p>
    <p class="div2"><a href='javascript:void(0)'>14</a></p>
    <p class="div1"><a href='javascript:void(0)'>15</a></p>
    <script src="./js/test.js"></script>
</body>
</html>

CSS

  1. 给 body 设置 margin:0,padding:0 是清空间隙。
  2. em 单位是 以父元素的字体大小为基准,这里p元素的父元素是body,因此是以body的字体为准,10em就是 10*14px=140px;

而 rem是以根元素的字体大小为基准,这也是笔试面试高频考题。

  1. 利用 transofom 中的 translate 属性,做出位移的效果;
  2. 利用 animation 对 opacity 有效果,做出淡入淡出的感觉。
  3. 利用 奇偶选择器 对相邻板块之间做背景颜色的区分,效果更加明显。
  • 大致代码如下:
body {
  margin: 0;
  padding: 0;
  font-size: 14px;
}
p {
  height: 10em;
  text-align: center;
  vertical-align: middle;
  line-height: 10em;
  font-size: 1.5em;
  margin: 2em 1em;
}
p.div1 {
  background: pink;
  color: #00abee;
}
p.div2 {
  background: skyblue;
  color: #000;
}
.come-in {
  opacity: 1;
  transform: translateY(150px);
  animation: come-in 1s ease forwards;
}
.come-in:nth-child(odd) {
  animation-duration: 1s;
}
.already-visible {
  opacity: 1;
  transform: translateY(0);
  animation: none;
}
@keyframes come-in {
  100% {
    transform: translateY(0);
  }
}
.opaque {
  opacity: 0;
}

JavaScript

  1. 使用立即执行函数防止变量污染;
  2. 判断浏览器是否支持 IntersectionObserver

IntersectionObserver 接口提供了一种异步观察目标元素与其祖先元素或顶级文档视口交叉状态方法。当观察对象到达窗口可视区交界处时,就会触发方法,特别适合用于做懒加载,以后可更文详细讲解。

  1. 基本思路是一旦观察对象到达可视区窗口交叉处时,可以通过 IntersectionObserver 观察到,然后为交接处的元素添加事先在CSS中写好的动画类名,最后记得移除类名,并取消观察。
!function (win) {
    //辅助函数
    function $(ele) {
        return document.querySelectorAll(ele);
    }
    /**
      * 判断浏览器是否支持IntersectionObserver
      * @returns  返回当前浏览器对于IntersectionObserver的支持情况,支持返回true,反之false;
      */
    function isSupportIntersectionObserver() {
        return (typeof IntersectionObserver).toLowerCase() === "function";
    }
    //核心函数
    window.addEventListener("load", function () {
        if (isSupportIntersectionObserver()) {
            hideAll();
            observerFunc();
        } else {
            win.alert("不支持");
        }
    });
//  取到一个数组
    var allDIv = $('p');
    function hideAll() {
        allDIv.forEach((e) => {
//  透明度设为0
            e.classList.add('opaque');
            judge(e);
        });

    }
    function judge(ele) {
        var h = ele.getBoundingClientRect().top;
        if (h < window.innerHeight) {
            ele.classList.add('already-visible');
        }
    }
    function observerFunc() {
        var observer = new IntersectionObserver(callback);
        var allDIv = $('p');
        //绑定
        allDIv.forEach((e) => {
            observer.observe(e);
        });

        function callback(entries) {
            entries.forEach(entry => {
                if (entry.isIntersecting) {
                    var divE = entry.target;
                    divE.classList.remove("opaque");
                    divE.classList.add("come-in");
                    observer.unobserve(divE);
                }
            })
        }
    }
}(window);