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

标签 javascript css animation css-animations

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

当我点击一个按钮时,会出现一个 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/

相关文章:

javascript - Jquery Cookie 通过模态显示/隐藏菜单

html - 在某些单词周围添加引号,但仅在复制粘贴时添加 - 与 q 标签相反

javascript - 在用户按下以 Bootstrap 模式提交表单后,如何显示成功消息?

iphone - 通过从右侧移动到其原始位置来对 UIButton 序列进行动画处理

javascript - 动态填充 Promise.all()

javascript - 为什么在声明状态后我的 React 渲染两次?

javascript - AngularJS 客户端 MVC 模式?

javascript - jqGrid 在输入附近添加标签

javascript - 添加幻灯片回调以动画 Jquery

javascript - 如何验证页面转换?