MST

星途 面试题库

面试题:JavaScript处理文档滚动边界时优化动画过渡效果

假设页面中有一个元素,当文档滚动到距离顶部一定距离(如200px)时,该元素以平滑的动画效果出现;当滚动到距离底部一定距离(如300px)时,该元素以另一种平滑动画效果消失。使用JavaScript实现该功能,并解释如何优化动画性能以避免卡顿。
21.1万 热度难度
编程语言JavaScript

知识考点

AI 面试

面试题答案

一键面试

HTML 部分

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

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>元素滚动动画</title>
    <style>
        #target {
            display: none;
            width: 200px;
            height: 200px;
            background-color: lightblue;
        }
    </style>
</head>

<body>
    <div id="target"></div>
    <script src="script.js"></script>
</body>

</html>

JavaScript 部分

window.addEventListener('scroll', function () {
    const target = document.getElementById('target');
    const scrollTop = window.pageYOffset || document.documentElement.scrollTop;
    const windowHeight = window.innerHeight;
    const documentHeight = document.documentElement.scrollHeight;

    if (scrollTop >= 200) {
        target.style.display = 'block';
        target.style.animation = 'fadeIn 1s ease-in-out';
    } else {
        target.style.animation = 'none';
        target.style.display = 'none';
    }

    if (documentHeight - scrollTop - windowHeight <= 300) {
        target.style.animation = 'fadeOut 1s ease-in-out';
    }
});

// 定义动画关键帧
document.createElement('style').innerHTML = `
    @keyframes fadeIn {
        from {
            opacity: 0;
        }
        to {
            opacity: 1;
        }
    }

    @keyframes fadeOut {
        from {
            opacity: 1;
        }
        to {
            opacity: 0;
        }
    }
`;

优化动画性能避免卡顿的方法

  1. 使用 requestAnimationFrame:如果动画逻辑更复杂,使用 requestAnimationFrame 来控制动画的每一帧,它会在浏览器下一次重绘之前调用回调函数,确保动画与浏览器的刷新频率同步,减少卡顿。例如:
function handleScroll() {
    const target = document.getElementById('target');
    const scrollTop = window.pageYOffset || document.documentElement.scrollTop;
    const windowHeight = window.innerHeight;
    const documentHeight = document.documentElement.scrollHeight;

    if (scrollTop >= 200) {
        target.style.display = 'block';
        requestAnimationFrame(() => {
            target.style.animation = 'fadeIn 1s ease-in-out';
        });
    } else {
        target.style.animation = 'none';
        target.style.display = 'none';
    }

    if (documentHeight - scrollTop - windowHeight <= 300) {
        requestAnimationFrame(() => {
            target.style.animation = 'fadeOut 1s ease-in-out';
        });
    }
}

window.addEventListener('scroll', handleScroll);
  1. 减少重排和重绘:尽量避免在动画过程中频繁改变元素的布局属性(如 widthheightmargin 等),因为这些改变会触发重排和重绘,消耗性能。在上述代码中,通过 display 控制元素显示隐藏,animation 控制动画,减少对布局属性的动态修改。
  2. 硬件加速:使用 will-change 属性提前告知浏览器元素即将发生变化,让浏览器有机会提前优化。例如:
#target {
    will-change: opacity;
}
  1. 优化 CSS 动画:使用 transformopacity 来实现动画,因为这两个属性触发的是合成层动画,不会触发重排和重绘,性能较好。上述代码中 fadeInfadeOut 动画使用 opacity 就是基于这个考虑。