gpt4 book ai didi

javascript - 事件 'transitionend' 被调用得太早,它延迟渲染

转载 作者:可可西里 更新时间:2023-11-01 02:11:54 25 4
gpt4 key购买 nike

我在做什么,哪里出了问题

当我点击一个按钮时,会出现一个 slider 。 ( here is an example of what it looks like , 不要关注这段代码)

slider 通过动画显示。动画完成后,我应该包含一个从服务器加载的 HTML 页面。我需要在动画之后在 slider 中应用 HTML,否则动画将停止(重新计算 DOM)。

我的算法

  1. 启动请求以获取要在 slider 内显示的 HTML
  2. 开始动画
  3. 等待数据准备好转换完成

    为什么?如果我在动画期间应用 HTML,它会在新 HTML 添加到 DOM 时停止动画。所以我在第 4 步之前等待两者都结束。

  4. 在 slider 内应用 HTML

这里是缩短的代码:

// Start loading data & animate transition
var count = 0;
var data = null;

++count;
$.get(url, function (res) {
data = res;
cbSlider();
});

// Animation starts here

++count;
$(document).on('transitionend', '#' + sliderId, function () {
$(document).off('transitionend', '#' + sliderId);
cbSlider()
});

function cbSlider() {
--count;
// This condition is only correct when both GET request and animation are finished
if (count == 0) {
// Attempt to enforce the frame to finish (doesn't work)
window.requestAnimationFrame(() => { return });

$('#' + sliderId + ' .slider-content').html(data);
}
}

详细问题

transitionend 过早调用。它使最后一个动画帧太长(477.2 毫秒)并且在 transitionend 事件中最后一帧未呈现

Google Chrome Timeline

从 Google 文档中,我可以告诉您 Pixel Pipeline 的 Paint 和 Composite 步骤在Event(transitionend)之后调用:

Pixel Pipe Line

也许我想多了。

我应该如何处理这种动画?

如何等待动画完全完成并渲染?

最佳答案

我不确定为什么 transitionend 在最后一帧渲染之前被触发,但在这个(非常粗糙的)测试中似乎 setTimeout 确实 帮助...

第一个示例显示了 html 计算和注入(inject)是如何过早发生的。第二个示例将长时间运行的方法包装在 setTimeout 中,并且似乎没有触发动画中的任何中断。

示例 1:重现您的问题

var ended = 0;
var cb = function() {
ended += 1;

if (ended == 2) {
$(".animated").html(createLongHTMLString());
}
}

$(".load").click(function() {
$(".animated").addClass("loading");
$(".animated").on("transitionend", cb);
setTimeout(cb, 100);
});

function createLongHTMLString() {
var str = "";
for (var i = 0; i < 100000; i += 1) {
str += "<em>Test </em>";
}
return str;
};
.animated,
.target {
width: 100px;
height: 100px;
position: absolute;
text-align: center;
line-height: 100px;
overflow: hidden;
}
.target,
.animated.loading {
transform: translateX(300%);
}
.animated {
background: green;
z-index: 1;
transition: transform .2s linear;
}
.target {
background: red;
z-index: 0;
}
.wrapper {
height: 100px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<div class="wrapper">
<div class="animated">Loading</div>
<div class="target"></div>
</div>

<button class="load">load</button>

示例 2:其中 setTimeout 似乎可以修复它

setTimeout 围绕 html 注入(inject)代码。

var ended = 0;
var cb = function() {
ended += 1;

if (ended == 2) {
setTimeout(function() {
$(".animated").html(createLongHTMLString());
});
}
}

$(".load").click(function() {
$(".animated").addClass("loading");
$(".animated").on("transitionend", cb);
setTimeout(cb, 100);
});

function createLongHTMLString() {
var str = "";
for (var i = 0; i < 100000; i += 1) {
str += "<em>Test </em>";
}
return str;
};
.animated,
.target {
width: 100px;
height: 100px;
position: absolute;
text-align: center;
line-height: 100px;
overflow: hidden;
}
.target,
.animated.loading {
transform: translateX(300%);
}
.animated {
background: green;
z-index: 1;
transition: transform .2s linear;
}
.target {
background: red;
z-index: 0;
}
.wrapper {
height: 100px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<div class="wrapper">
<div class="animated">Loading</div>
<div class="target"></div>
</div>

<button class="load">load</button>

关于javascript - 事件 'transitionend' 被调用得太早,它延迟渲染,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39167044/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com