我目前正在使用 CSS 滚动驱动动画 和新的
animation-timeline
属性。我所指的技术示例可以在这里看到:图像显示示例。
但是,我面临一个问题:我想添加动画延迟以使动画平滑,尤其是在用鼠标滚动时。目前,动画看起来有点断断续续,因为 PC 上的鼠标滚动可能不太流畅,并且会以较大的即时步骤发生。
我尝试过使用传统的CSS属性animation-delay,但与滚动驱动的动画和
animation-timeline
属性一起使用时似乎没有任何效果。
以下是我想要的动画感觉的示例:
// Initialize Lenis
const lenis = new Lenis();
// Listen for the scroll event and log the event data
lenis.on('scroll', (e) => {
console.log(e);
});
// Use requestAnimationFrame to continuously update the scroll
function raf(time) {
lenis.raf(time);
requestAnimationFrame(raf);
}
requestAnimationFrame(raf);
.animation-element-wrapper {
display: grid;
justify-content: center;
background-color: green;
}
.animation-element {
background-color: red;
height: 50px;
width: 50px;
animation: move;
animation-timeline: view(block);
}
@keyframes move {
from {
transform: translateY(0) rotate(0deg);
}
to {
transform: translateY(-150px) rotate(360deg);
}
}
// Smooth scroll styling
html.lenis, html.lenis body {
height: auto;
}
.lenis.lenis-smooth {
scroll-behavior: auto !important;
}
.lenis.lenis-smooth [data-lenis-prevent] {
overscroll-behavior: contain;
}
.lenis.lenis-stopped {
overflow: hidden;
}
.lenis.lenis-smooth iframe {
pointer-events: none;
}
<script src="https://unpkg.com/[email protected]/dist/lenis.min.js"></script>
<h1>Hello World!</h1>
<h1>Hello World!</h1>
<h1>Hello World!</h1>
<h1>Hello World!</h1>
<h1>Hello World!</h1>
<h1>Hello World!</h1>
<h1>Hello World!</h1>
<h1>Hello World!</h1>
<h1>Hello World!</h1>
<div class="animation-element-wrapper">
<div class="animation-element"></div>
</div>
<h1>Hello World!</h1>
<h1>Hello World!</h1>
<h1>Hello World!</h1>
<h1>Hello World!</h1>
<h1>Hello World!</h1>
<h1>Hello World!</h1>
<h1>Hello World!</h1>
<h1>Hello World!</h1>
<h1>Hello World!</h1>
在本例中,我使用 JavaScript 库来实现整个页面的平滑滚动。我的目标是为基于 CSS 滚动的动画应用类似的平滑、缓慢移动的效果而不使用 JS 库。
为了突出这个问题,这是另一个没有平滑滚动效果的示例:
.animation-element-wrapper {
display: grid;
justify-content: center;
background-color: green;
}
.animation-element {
background-color: red;
height: 50px;
width: 50px;
animation: move;
animation-timeline: view(block);
}
@keyframes move {
from {
transform: translateY(0) rotate(0deg);
}
to {
transform: translateY(-150px) rotate(360deg);
}
}
<h1>Hello World!</h1>
<h1>Hello World!</h1>
<h1>Hello World!</h1>
<h1>Hello World!</h1>
<h1>Hello World!</h1>
<h1>Hello World!</h1>
<h1>Hello World!</h1>
<h1>Hello World!</h1>
<h1>Hello World!</h1>
<div class="animation-element-wrapper">
<div class="animation-element"></div>
</div>
<h1>Hello World!</h1>
<h1>Hello World!</h1>
<h1>Hello World!</h1>
<h1>Hello World!</h1>
<h1>Hello World!</h1>
<h1>Hello World!</h1>
<h1>Hello World!</h1>
<h1>Hello World!</h1>
<h1>Hello World!</h1>
流动性的差异是显而易见的,我想使用纯CSS复制更流畅的体验。
有没有办法仅使用 CSS 来引入延迟或平滑此动画行为,还是仍然需要 JavaScript?我主要寻找基于 CSS 的解决方案。
我已经能够仅使用 CSS 来解决这个问题:
@property --scroll-position {
syntax: '<number>';
inherits: true;
initial-value: 0;
}
@property --scroll-position-delayed {
syntax: '<number>';
inherits: true;
initial-value: 0;
}
@keyframes adjust-pos {
to {
--scroll-position: 1;
--scroll-position-delayed: 1;
}
}
.animation-element-wrapper {
animation: adjust-pos linear both;
animation-timeline: view(block);
display: grid;
justify-content: center;
background-color: green;
}
.animation-element {
transition: --scroll-position-delayed 0.15s linear;
}
.red-square {
background-color: red;
height: 50px;
width: 50px;
transform: translateY(calc(-150px * var(--scroll-position-delayed)));
}
/* Display debugging information */
#debug {
position: fixed;
top: 50%;
left: 75%;
translate: -50% -50%;
background: white;
border: 1px solid #ccc;
padding: 1rem;
& li {
list-style: none;
}
counter-reset: scroll-position calc(var(--scroll-position) * 100) scroll-position-delayed calc(var(--scroll-position-delayed) * 100);
[data-id="--scroll-position"]::after {
content: "--scroll-position: " counter(scroll-position);
}
[data-id="--scroll-position-delayed"]::after {
content: "--scroll-position-delayed: " counter(scroll-position-delayed);
}
}
<h1>Hello World!</h1>
<h1>Hello World!</h1>
<h1>Hello World!</h1>
<h1>Hello World!</h1>
<h1>Hello World!</h1>
<h1>Hello World!</h1>
<h1>Hello World!</h1>
<h1>Hello World!</h1>
<h1>Hello World!</h1>
<div class="animation-element-wrapper">
<div class="animation-element">
<div class="red-square"></div>
<div id="debug">
<ul>
<li data-id="--scroll-position"></li>
<li data-id="--scroll-position-delayed"></li>
</ul>
</div>
</div>
</div>
<h1>Hello World!</h1>
<h1>Hello World!</h1>
<h1>Hello World!</h1>
<h1>Hello World!</h1>
<h1>Hello World!</h1>
<h1>Hello World!</h1>
<h1>Hello World!</h1>
<h1>Hello World!</h1>
<h1>Hello World!</h1>
这一切都归功于这篇文章:https://www.bram.us/2023/10/23/css-scroll-detection/#lerp-effects
解释.
这里,滚动位置是从红方块的父级获取(并设置动画)的:
@keyframes adjust-pos {
to {
--scroll-position: 1;
--scroll-position-delayed: 1;
}
}
.animation-element-wrapper {
animation: adjust-pos linear both;
animation-timeline: view(block);
这里滚动位置被延迟(负责平滑度)。
.animation-element {
transition: --scroll-position-delayed 0.15s linear;
}
这里延迟的滚动位置用于为“红方块”设置动画:
.red-square {
background-color: red;
height: 50px;
width: 50px;
transform: translateY(calc(-150px * var(--scroll-position-delayed)));
}