简体   繁体   English

CSS 过渡百分比(用于进度条)

[英]CSS percentage of transition (for progress bar)

I'm trying to make a "progress bar" with animation that changes the background colour of the bar.我正在尝试使用 animation 制作一个“进度条”,以更改进度条的背景颜色。

The bar should start with red at 0% and as it progresses across the element it changes to green at 100%.该条应以 0% 的红色开始,随着它在元素上的进展,它会在 100% 变为绿色。 I've got this working for 100% (and no, the colour is not great, but that's a future problem)...我已经 100% 工作了(不,颜色不是很好,但这是未来的问题)......

 setTimeout(function(){ var bar = document.getElementById("bar"); bar.style.width = "100%"; bar.classList.add("show"); },10);
 #progress { border:1px solid #888; background-color:#eee; height: width:100%; } #bar { height:30px; background-color:red; width:0; transition: all ease 1s; } #bar.show { background-color:lightgreen; }
 <div id="progress"><div id="bar"></div></div>

The problem is that (for example) at 50% I cannot get the bar to "stop" at the 50% transition state between the red and the green.问题是(例如)在 50% 时,我无法让条形图在红色和绿色之间的 50% 过渡 state 处“停止”。

Is there a way to either calculate the colour as it would be at 50% or get CSS to stop the transition at a particular point?有没有办法计算颜色为 50% 或让 CSS 在特定点停止过渡?

You can see what happens if I have a 50% value... where it still goes all the way to green but stops at the 50% width, but what I want it to do is stop at the 50% transition colour (ie going from red to mid-way between red and green)...你可以看到如果我有一个 50% 的值会发生什么......它仍然一直到绿色但在 50% 宽度处停止,但我想要它做的是在 50% 过渡颜色处停止(即从红色到红色和绿色之间的中间)......

 setTimeout(function(){ var bar = document.getElementById("bar"); bar.style.width = "50%"; bar.classList.add("show"); },10);
 #progress { border:1px solid #888; background-color:#eee; height: width:100%; } #bar { height:30px; background-color:red; width:0; transition: all ease 1s; } #bar.show { background-color:lightgreen; }
 <div id="progress"><div id="bar"></div></div>

Additional Info (as requested by 0stone0 ) the percentage value will not be known at the time the page is loaded, but will be provided via an AJAX call.附加信息(由0stone0请求)在页面加载时将不知道百分比值,但将通过 AJAX 调用提供。

'Stopping' a gradient transition could be quite difficult. “停止”渐变过渡可能非常困难。

Please consider an alternative approach, one where you manually calculate the desired final color.请考虑另一种方法,您可以手动计算所需的最终颜色。 Use this color value as the target for the transition .将此颜色值用作transition的目标。 This way there's no need to 'stop' the transition, since the final colour is already proportional to the percentage.这样就不需要“停止”过渡,因为最终颜色已经与百分比成正比。

I've used this function to calculate the gradient between green and red, based on the percentage.我使用这个 function根据百分比计算绿色和红色之间的梯度。

To ensure the bar is always clickable, we've moved the onClick to the .progress div so we can render the .bar at 0 width.为确保栏始终可点击,我们将onClick移至.progress div,以便我们可以将.bar渲染为 0 宽度。

(Updated answer, based on comments) (更新的答案,基于评论)

 function load(progress, perc) { var bar = progress.getElementsByClassName("bar")[0]; bar.style.width = perc.toString() + "%"; bar.style.backgroundColor = getGradient(perc / 100); } function getGradient(ratio) { var color1 = '90ee90'; // lightgreen var color2 = 'FF0000'; // red var hex = function(x) { x = x.toString(16); return (x.length == 1)? '0' + x: x; }; var r = Math.ceil(parseInt(color1.substring(0,2), 16) * ratio + parseInt(color2.substring(0,2), 16) * (1-ratio)); var g = Math.ceil(parseInt(color1.substring(2,4), 16) * ratio + parseInt(color2.substring(2,4), 16) * (1-ratio)); var b = Math.ceil(parseInt(color1.substring(4,6), 16) * ratio + parseInt(color2.substring(4,6), 16) * (1-ratio)); return '#' + hex(r) + hex(g) + hex(b); }
 .progress { border:1px solid #888; background-color:#eee; height:30px; width:100%; }.bar { height:30px; background-color:red; width:0; transition: all ease 1s; }
 Click to run...<br/> <div class="progress" onclick='load(this, 25)'><div class="bar">25%</div></div> <div class="progress" onclick='load(this, 50)'><div class="bar">50%</div></div> <div class="progress" onclick='load(this, 75)'><div class="bar">75%</div></div> <div class="progress" onclick='load(this, 100)'><div class="bar">100%</div></div>

(Original answer) (原答案)

 function load(bar, until) { var p = 0; setInterval(function() { // Clear on complete if (p > until) { clearInterval(this); return; } // Update Bar bar.innerHTML = p; bar.style.background = getGradient((p/1)/100); bar.style.width = p + "%"; // Bump percentage p++; }, 100); } function getGradient(ratio) { var color1 = '90ee90'; // lightgreen var color2 = 'FF0000'; // red var hex = function(x) { x = x.toString(16); return (x.length == 1)? '0' + x: x; }; var r = Math.ceil(parseInt(color1.substring(0,2), 16) * ratio + parseInt(color2.substring(0,2), 16) * (1-ratio)); var g = Math.ceil(parseInt(color1.substring(2,4), 16) * ratio + parseInt(color2.substring(2,4), 16) * (1-ratio)); var b = Math.ceil(parseInt(color1.substring(4,6), 16) * ratio + parseInt(color2.substring(4,6), 16) * (1-ratio)); return '#' + hex(r) + hex(g) + hex(b); }
 .progress { border:1px solid #888; background-color:#eee; height: 50px; width:100%; }.bar { height:100%; width:100%; }
 <div class="progress"><div onClick='load(this, 100)' class="bar"></div></div> <div class="progress"><div onClick='load(this, 50)' class="bar"></div></div>

You can do something like this by getting the computed styles and setting those to your bar element (on click of a button) or when we reach the percentage width of progress element by using polling via setInterval like so:-您可以通过获取计算的 styles 并将其设置为您的bar元素(单击按钮)或当我们通过setInterval使用轮询达到progress元素的percentage宽度来执行此类操作,如下所示:-

 var bar = document.getElementById("bar"); setTimeout(function(){ bar.style.width = "100%"; bar.classList.add("show"); },10); function stopProgressAt(percentage){ let interval = setInterval(()=>{ const progress = document.getElementById("progress"); const width = getComputedStyle(bar).getPropertyValue('width'); if((parseInt(width) * 100)/(Math.floor(progress.offsetWidth)) >= percentage ){ pauseTransition(); setTimeout(()=>clearInterval(interval),0); } },0) } function pauseTransition(){ const bgColor = getComputedStyle(bar).getPropertyValue('background-color'); const width = getComputedStyle(bar).getPropertyValue('width'); bar.style.width=width; bar.style.backgroundColor=bgColor; ;} stopProgressAt(66);
 #progress { border:1px solid #888; background-color:#eee; height: width:100%; } #bar { height:30px; background-color:red; width:0; transition: all ease 1s; } #bar.show { background-color:lightgreen; }
 <div id="progress"><div id="bar"></div></div> <button onclick="pauseTransition()">Pause</button>

use an opaque overlay, like this:使用不透明的叠加层,如下所示:

 setTimeout(function() { const hue = 120; const size = 0.7; const H = hue * size; const L = (size <.5? 1 - size: size) * 50; const hsl = `hsl(${H}, 100%, ${L}%)`; const progress = document.getElementById('progress'); progress.style.setProperty('--size', size); progress.style.setProperty('--hsl', hsl); }, 500);
 #progress { --size: 0; --hsl: hsl(0, 100%, 50%); position: relative; overflow: hidden; width: 200px; height: 20px; border: 1px solid #888; background-color: var(--hsl); transition: background-color 1s; } #bar { width: 100%; height: 100%; background: white; transition: margin-left 1s; margin-left: calc(var(--size) * 100%); }
 <div id="progress"><div id="bar"></div></div>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM