为基于 flex 框的进度条设置动画时出现一个奇怪的故障

Posted

技术标签:

【中文标题】为基于 flex 框的进度条设置动画时出现一个奇怪的故障【英文标题】:A bizarre glitch when animating a flex box-based progress bar 【发布时间】:2019-09-10 02:53:43 【问题描述】:

我正在尝试通过实现进度条来学习 flexbox。 一切正常,直到我尝试用 jquery 为它制作动画......

在宽度设置为至少 75% 后,Animate 似乎不适用于右半部分。

另外,就像绿色条设置为非常大的宽度,因为它实际上需要大约一秒钟才能从 100%+ 恢复。

我不确定是因为我不太了解 flexbox 还是 jQuery 出于某种原因吓坏了……

这是一个已知问题吗?我做错什么了吗?这是我页面的代码。

这是我的代码:

button 
  height: 50px;
  margin: 10px;
  width: 50px;


.b9k-progress 
  border: solid black 2px;
  flex-direction: row;
  display: flex;
  height: 50px;
  margin: 10px;
  padding: 5px;


.b9k-left,
.b9k-right 
  height: inherit;
  padding: 0;
  margin: 0;


.b9k-left 
  background-color: green;
  opacity: 1;


.b9k-right 
  background: orangered;
  flex-grow: 1;
<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>

<div style="width: 80%;margin: 20px 10% ;">
  <button onclick='$("#the-progress-bar>.b9k-left").animate("width": "0",2000);'>ZERO</button>
  <button onclick='$("#the-progress-bar>.b9k-left").animate("width": "20%",2000);'>25%
    </button>
  <button onclick='$("#the-progress-bar>.b9k-left").animate("width": "50%",2000);'>50%
    </button>
  <button onclick='$("#the-progress-bar>.b9k-left").animate("width": "75%",2000);'>75%
    </button>
  <button onclick='$("#the-progress-bar>.b9k-left").animate("width": "100%",2000);'>100%
    </button>
</div>


<div id="the-progress-bar" class="b9k-progress">
  <div class="b9k-left"></div>
  <div class="b9k-right"></div>
</div>

这是一个已知问题吗?我是不是做错了什么?

【问题讨论】:

既然可以轻松使用 CSS 过渡,为什么还要使用 jQuery animate(和内联 JS)? ^ 当你只能使用一个元素时,为什么要使用两个元素? @Terry 我还没有涉足 CSS 过渡 :) @TemaniAfif 我打算在 div 中添加一些内容,例如百分比文本或类似的东西,所以我想让 div 保持“可居住” 我认为您可能发现了该版本的 jQuery animate 中的错误;对于可以简化代码的价值,它没有明显的错误。 (如果你在开发工具中观察,你会发现当它从高值动画到低值时,它是在动画 px 而不是 % 值,这在 flexbox 中是错误的。) 【参考方案1】:

这是因为当您将 CSS flexbox 与基于百分比的宽度结合使用 时,您会迫使浏览器在尝试确定元素的最终宽度时进行多次遍历。这会导致在 jQuery 正确地将其设置为目标值之前,该栏最初会超出其宽度至 >100%。

解决方案 1:使用 CSS 过渡

您甚至根本不需要使用 jQuery 的动画功能。使用起来可能很麻烦,并且有人们不知道的包罗万象(例如使用.stop(true, true) 来清除您没有使用的队列)。您想要实现的目标完全可以单独使用 CSS 过渡

$(function() 
  $('.button').on('click', function() 
    $('#the-progress-bar > .b9k-left').width($(this).data('target-width'));
  );
);
button 
  height: 50px;
  margin: 10px;
  width: 50px;


.b9k-progress 
  border: solid black 2px;
  flex-direction: row;
  display: flex;
  height: 50px;
  margin: 10px;
  padding: 5px;


.b9k-left,
.b9k-right 
  height: inherit;
  padding: 0;
  margin: 0;
  
  /* Enable transition of width */
  transition: width 2s ease-in-out;


.b9k-left 
  background-color: green;
  opacity: 1;
  
  /* Give the width a starting value */
  width: 0;


.b9k-right 
  background: orangered;
  flex-grow: 1;
<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>

<div style="width: 80%;margin: 20px 10% ;">
  <button class="button" data-target->ZERO</button>
  <button class="button" data-target->25%
    </button>
  <button class="button" data-target->50%
    </button>
  <button class="button" data-target->75%
    </button>
  <button class="button" data-target->100%
    </button>
</div>


<div id="the-progress-bar" class="b9k-progress">
  <div class="b9k-left"></div>
  <div class="b9k-right"></div>
</div>

解决方案 2:不要使用 flexbox

解决这个问题的一种方法是实际上只是删除 CSS flexbox 的使用,而是将橙色背景分配给父元素:

button 
  height: 50px;
  margin: 10px;
  width: 50px;


.b9k-progress 
  background-color: orangered;
  border: solid black 2px;
  box-shadow: inset 0 0 0 5px white;
  height: 50px;
  margin: 10px;
  padding: 5px;


.b9k-left 
  height: inherit;
  padding: 0;
  margin: 0;


.b9k-left 
  background-color: green;
  opacity: 1;
<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>

<div style="width: 80%;margin: 20px 10% ;">
  <button onclick='$("#the-progress-bar>.b9k-left").animate("width": "0",2000);'>ZERO</button>
  <button onclick='$("#the-progress-bar>.b9k-left").animate("width": "20%",2000);'>25%
    </button>
  <button onclick='$("#the-progress-bar>.b9k-left").animate("width": "50%",2000);'>50%
    </button>
  <button onclick='$("#the-progress-bar>.b9k-left").animate("width": "75%",2000);'>75%
    </button>
  <button onclick='$("#the-progress-bar>.b9k-left").animate("width": "100%",2000);'>100%
    </button>
</div>


<div id="the-progress-bar" class="b9k-progress">
  <div class="b9k-left"></div>
</div>

【讨论】:

谢谢!这是一些有价值的见解。实际上,我预计即使是基本的 CSS 过渡也会非常复杂。你的回答很有解释性。【参考方案2】:

您可以尝试使用 CSS 动画,只需切换元素上的类:

<div id="the-progress-bar" class="b9k-progress">
    <div class="the-progress-bar-progress"></div>
</div>

.the-progress-bar 
    background-color: orangered;


.the-progress-bar-progress  
    position: relative;
    width: 100%; height: 100%; 
    background-color: green;
    transition: transform 2s;
    transform: scaleX(0);
    transform-origin: 0 0;

.the-progress-bar-progress--25perc   transform: scaleX(.25); 
.the-progress-bar-progress--50perc   transform: scaleX(.5);  
.the-progress-bar-progress--75perc   transform: scaleX(.75); 
.the-progress-bar-progress--100perc  transform: scaleX(1);   

您可以使用这个示例函数来简单地更改应用于进度的类:

function changeProgress(e) 
    var progressBar = document.getElementById('the-progress-bar');
    progressBar.classList = 'b9k-progress';

    var targetClass = e.target.getAttribute('data-progressClass');
    if(targetClass && targetClass != '')  
        progressBar.classList.add(targetClass);
    ;
;

<button onclick='changeProgres();' data-progressClass="">ZERO</button>
<button onclick='changeProgres();' data-progressClass="the-progress-bar-progress--25perc">25%</button>
<button onclick='changeProgres();' data-progressClass="the-progress-bar-progress--50perc">50%</button>

function changeProgress(progressClass__string) 
    var targetClass = progressClass__string || '';
    document.getElementById('the-progress-bar').classList = 'b9k-progress ' + progressClass__string;
;

<button onclick="changeProgres();">ZERO</button>
<button onclick="changeProgres('the-progress-bar-progress--25perc');">25%</button>
<button onclick="changeProgres('the-progress-bar-progress--50perc');">50%</button>

【讨论】:

谢谢。这与我最初的想法完全不同。我很感激! 很高兴它有帮助。祝你好运! :)

以上是关于为基于 flex 框的进度条设置动画时出现一个奇怪的故障的主要内容,如果未能解决你的问题,请参考以下文章

更改 NavigationItem 提示时出现奇怪的动画

从 UINavigationController (IOS 5) 弹出 UIViewController 时出现奇怪的动画

在 Chrome 中的页面上使用动画时出现奇怪的背景故障

如何在 Bootstrap 3 中为进度条设置动画?

基于JQuery的进度条实现

为剪辑区域设置动画时清除画布时出现问题