为基于 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 框的进度条设置动画时出现一个奇怪的故障的主要内容,如果未能解决你的问题,请参考以下文章
从 UINavigationController (IOS 5) 弹出 UIViewController 时出现奇怪的动画