视差滚动效果实现

视差滚动效果实现

视差滚动是一种在网页设计和视频游戏中常见的视觉效果技术,它通过在不同速度上移动页面或屏幕上的多层图像,创造出深度感和动感。

这种效果通过前景、中景和背景以不同的速度移动来实现,使得近处的对象看起来移动得更快,而远处的对象移动得较慢。

在官网中适当的使用视差效果,可以增加视觉吸引力,提高用户的参与度,从而提升网站和品牌的形象。本文通过JavaScript、CSS多种方式并在React框架下进行了视差效果的实现,供你参考指正。

实现方式1、background-attachment通过配置该 CSS 属性值为fixed可以达到背景图像的位置相对于视口固定,其他元素正常滚动的效果。但该方法的视觉表现单一,没有纵深,缺少动感。

代码语言:css复制.parallax-box {

width: 100%;

height: 100vh;

background-image: url("https://picsum.photos/800");

background-size: cover;

background-attachment: fixed;

display: flex;

justify-content: center;

align-items: center;

}点击访问完整在线代码

2、Transform 3D在 CSS 中使用 3D 变换效果,通过将元素划分至不同的纵深层级,在滚动时相对视口不同距离的元素,滚动所产生的位移在视觉上就会呈现越近的元素滚动速度越快,相反越远的元素滚动速度就越慢。

为方便理解,你可以想象正开车行驶在公路上,汽车向前移动,你转头看向窗外,近处的树木一闪而过,远方的群山和风景慢慢的渐行渐远,逐渐的在视野中消失,而天边的太阳却只会在很长的一段距离细微的移动。

点击访问完整在线代码

代码语言:css复制.parallax {

perspective: 1px; /* 设置透视效果,为3D变换创造深度感 */

overflow-x: hidden;

overflow-y: auto;

height: 100vh;

}

.parallax__group {

transform-style: preserve-3d; /* 保留子元素3D变换效果 */

position: relative;

height: 100vh;

}

.parallax__layer {

position: absolute;

inset: 0;

display: flex;

justify-content: center;

align-items: center;

}

/* 背景层样式,设置为最远的层 */

.parallax__layer--back {

transform: translateZ(-2px) scale(3);

z-index: 1;

}

/* 中间层样式,设置为中等距离的层 */

.parallax__layer--base {

transform: translateZ(-1px) scale(2);

z-index: 2;

}

/* 前景层样式,设置为最近的层 */

.parallax__layer--front {

transform: translateZ(0px);

z-index: 3;

}实现原理

通过设置 perspective 属性,为整个容器创建一个 3D 空间。

使用 transform-style: preserve-3d 保持子元素的 3D 变换效果。

将内容分为多个层(背景、中间、前景),使用 translateZ() 将它们放置在 3D 空间的不同深度。

对于较远的层(如背景层),使用 scale() 进行放大,以补偿由于距离产生的视觉缩小效果。

当用户滚动页面时,由于各层位于不同的 Z 轴位置,它们会以不同的速度移动,从而产生视差效果。

3、ReactScrollParallax想得到更炫酷的滚动视差效果,纯 CSS 的实现方式就会有些吃力。

如下是在 React 中实现示例,通过监听滚动事件,封装统一的视差组件,来达到多样的动画效果。

点击访问完整在线代码

代码语言:javascript复制const Parallax = ({ children, effects = [], speed = 1, style = {} }) => {

// 状态hooks:用于存储动画效果的当前值

const [transform, setTransform] = useState("");

useEffect(() => {

if (!Array.isArray(effects) || effects.length === 0) {

console.warn("ParallaxElement: effects should be a non-empty array");

return;

}

const handleScroll = () => {

// 计算滚动进度

const scrollProgress =

(window.scrollY /

(document.documentElement.scrollHeight - window.innerHeight)) *

speed;

let transformString = "";

// 处理每个效果

effects.forEach((effect) => {

const { property, startValue, endValue, unit = "" } = effect;

const value =

startValue +

(endValue - startValue) * Math.min(Math.max(scrollProgress, 0), 1);

switch (property) {

case "translateX":

case "translateY":

transformString += `${property}(${value}${unit}) `;

break;

case "scale":

transformString += `scale(${value}) `;

break;

case "rotate":

transformString += `rotate(${value}${unit}) `;

break;

// 更多的动画效果...

default:

console.warn(`Unsupported effect property: ${property}`);

}

});

// 更新状态

setTransform(transformString);

};

window.addEventListener("scroll", handleScroll);

// 初始化位置

handleScroll();

return () => {

window.removeEventListener("scroll", handleScroll);

};

}, [effects, speed]);

// 渲染带有计算样式的子元素

return

{children}
;

};在此基础上你可以添加缓动函数使动画效果更加平滑;以及使用requestAnimationFrame获得更高的动画性能。

requestAnimationFrame 带来的性能提升

同步浏览器渲染周期:requestAnimationFrame 会在浏览器下一次重绘之前调用指定的回调函数。这确保了动画更新与浏览器的渲染周期同步,从而产生更流畑的动画效果。提高性能:与使用 setInterval 或 setTimeout 相比,requestAnimationFrame 可以更高效地管理动画。它只在浏览器准备好进行下一次重绘时才会执行,避免了不必要的计算和重绘。优化电池使用:在不可见的标签页或最小化的窗口中,requestAnimationFrame 会自动暂停,这可以节省 CPU 周期和电池寿命。适应显示器刷新率:requestAnimationFrame 会自动适应显示器的刷新率。这意味着在 60Hz、120Hz 或其他刷新率的显示器上,动画都能保持流畑。避免丢帧:由于与浏览器的渲染周期同步,使用 requestAnimationFrame 可以减少丢帧现象,特别是在高负荷情况下。更精确的时间控制:requestAnimationFrame 提供了一个时间戳参数,允许更精确地控制动画的时间。

4、组件库方案在当前成熟的前端生态中,想要获得精彩的视差动画效果,你可以通过现有的开源组件库来高效的完成开发。

以下是一些你可以尝试的主流组件库:

rellax (Lightweight, vanilla javascript parallax library)react-scroll-parallaxframer-motion...引用参考MDN - background-attachment

MDN - transform-style

Pure CSS Parallax Websites

How to create parallax scrolling with CSS

视差滚动实践

原地址文