requestAnimationFrame 会干扰 CSS 转换吗?
Does requestAnimationFrame interfere CSS transitions?
是否有可能 requestAnimationFrame
阻止其他 CSS 转换工作?
我有一个requestAnimationFrame
函数,可以移动div容器的位置。更新是在每个帧请求上完成的。 div 容器包含一个 CSS 动画:
.container {
...
animation: pulse 2s infinite;
...
}
@keyframes pulse {
0% { transform: scale(1); opacity: 1; }
70% { transform: scale(3); opacity: 0; }
100% { transform: scale(1); opacity: 0; }
}
只要我不调用 requestAnimationFrame
或停止发出请求,CSS 动画就可以正常工作。
此外,调用 requestAnimationFrame
还会阻止其他转换工作,这些转换超出了动画容器的范围,例如导航抽屉,我将其用作侧边菜单。
作为导航抽屉的解决方案,我必须按如下方式包装请求:
this.animationId = requestAnimationFrame((timestamp) => {
setTimeout(() => {
this.animateContainer(timestamp)
}, 50)
})
里面的setTimeout
用来延迟下一个动画让抽屉滑进去
但是,这对容器动画没有帮助。每当绘制新帧时,CSS 动画就会开始并随着每个新帧重置,因此动画会闪烁。
编辑:
为什么要使用 requestAnimationFrame 和 CSS 动画?
requestAnimationFrame
用于插入地图上标记的坐标。 X 和 Y 的实际位置由地图根据 canvas 计算得出。然后使用 CSS 动画为该标记设置动画。
您代码中的问题原因与 requestAnimationFrame
无关,而是由 rAF
调用的函数引起的。
在 animateMarker
中,每次调用 requestAnimationFrame
时都添加相同的标记。这应该是可能的。但是,因为您想在标记上显示 CSS 关键帧动画,所以它不起作用。这是因为每次调用 marker.addTo(map)
时,标记都会被快速移除并重新添加,并且还会 重置 您的关键帧动画。
将标记添加到 函数 animateMarker
之外的地图,仅更改标记的位置。这将防止标记被重置并获得您想要的结果。
var map = new mapboxgl.Map({
container: 'map',
style: 'mapbox://styles/mapbox/streets-v11',
center: [0, 0],
zoom: 2
});
var el = document.createElement('div');
var dot = document.createElement('div');
dot.className = 'mapboxgl-user-location-dot';
el.appendChild(dot);
// Set radius globally.
var radius = 20;
// Add marker before animate loop.
var marker = new mapboxgl.Marker(el)
.setLngLat(
Math.cos(0 / 1000) * 20,
Math.sin(0 / 1000) * 20
]);
.addTo(map);
// Change only the position in the animation loop without re-adding the marker.
function animateMarker(timestamp) {
// Update the data to a new position based on the animation timestamp. The
// divisor in the expression `timestamp / 1000` controls the animation speed.
marker.setLngLat([
Math.cos(timestamp / 1000) * radius,
Math.sin(timestamp / 1000) * radius
]);
// Request the next frame of the animation.
requestAnimationFrame(animateMarker);
}
// Start the animation.
requestAnimationFrame(animateMarker);
是否有可能 requestAnimationFrame
阻止其他 CSS 转换工作?
我有一个requestAnimationFrame
函数,可以移动div容器的位置。更新是在每个帧请求上完成的。 div 容器包含一个 CSS 动画:
.container {
...
animation: pulse 2s infinite;
...
}
@keyframes pulse {
0% { transform: scale(1); opacity: 1; }
70% { transform: scale(3); opacity: 0; }
100% { transform: scale(1); opacity: 0; }
}
只要我不调用 requestAnimationFrame
或停止发出请求,CSS 动画就可以正常工作。
此外,调用 requestAnimationFrame
还会阻止其他转换工作,这些转换超出了动画容器的范围,例如导航抽屉,我将其用作侧边菜单。
作为导航抽屉的解决方案,我必须按如下方式包装请求:
this.animationId = requestAnimationFrame((timestamp) => {
setTimeout(() => {
this.animateContainer(timestamp)
}, 50)
})
里面的setTimeout
用来延迟下一个动画让抽屉滑进去
但是,这对容器动画没有帮助。每当绘制新帧时,CSS 动画就会开始并随着每个新帧重置,因此动画会闪烁。
编辑:
为什么要使用 requestAnimationFrame 和 CSS 动画?
requestAnimationFrame
用于插入地图上标记的坐标。 X 和 Y 的实际位置由地图根据 canvas 计算得出。然后使用 CSS 动画为该标记设置动画。
您代码中的问题原因与 requestAnimationFrame
无关,而是由 rAF
调用的函数引起的。
在 animateMarker
中,每次调用 requestAnimationFrame
时都添加相同的标记。这应该是可能的。但是,因为您想在标记上显示 CSS 关键帧动画,所以它不起作用。这是因为每次调用 marker.addTo(map)
时,标记都会被快速移除并重新添加,并且还会 重置 您的关键帧动画。
将标记添加到 函数 animateMarker
之外的地图,仅更改标记的位置。这将防止标记被重置并获得您想要的结果。
var map = new mapboxgl.Map({
container: 'map',
style: 'mapbox://styles/mapbox/streets-v11',
center: [0, 0],
zoom: 2
});
var el = document.createElement('div');
var dot = document.createElement('div');
dot.className = 'mapboxgl-user-location-dot';
el.appendChild(dot);
// Set radius globally.
var radius = 20;
// Add marker before animate loop.
var marker = new mapboxgl.Marker(el)
.setLngLat(
Math.cos(0 / 1000) * 20,
Math.sin(0 / 1000) * 20
]);
.addTo(map);
// Change only the position in the animation loop without re-adding the marker.
function animateMarker(timestamp) {
// Update the data to a new position based on the animation timestamp. The
// divisor in the expression `timestamp / 1000` controls the animation speed.
marker.setLngLat([
Math.cos(timestamp / 1000) * radius,
Math.sin(timestamp / 1000) * radius
]);
// Request the next frame of the animation.
requestAnimationFrame(animateMarker);
}
// Start the animation.
requestAnimationFrame(animateMarker);