- 做者:陳大魚頭
- github: KRISACHAN
進度條是一個很是常見的功能,實現起來也不難,通常咱們都會用 div
來實現。html
做爲一個這麼常見的需求, whatwg 確定是不會沒有原生組件提供(雖然有咱們也不必定會用),那麼就讓咱們來康康有哪些有意思的進度條實現方式。git
這是比較常規的實現方式,先看效果:github
源碼以下:web
<style> .progress1 { height: 20px; width: 300px; background-color: #f5f5f5; border-bottom-right-radius: 10px; border-top-right-radius: 10px; } .progress1::before { counter-reset: progress var(--percent, 0); content: counter(progress) '%\2002'; display: block; height: 20px; line-height: 20px; width: calc(300px * var(--percent, 0) / 100); font-size: 12px; color: #fff; background-color: #2486ff; text-align: right; white-space: nowrap; overflow: hidden; border-bottom-right-radius: 10px; border-top-right-radius: 10px; } .btn { margin-top: 30px; } </style> <div id="progress1" class="progress1"></div> <button id="btn" class="btn">點我一下嘛~</button> <script> 'use strict'; let startTimestamp = (new Date()).getTime(); let currentPercentage = 0; let maxPercentage = 100; let countDelay = 100; let timer = null; let start = false; const percentageChange = () => { const currentTimestamp = (new Date()).getTime(); if (currentTimestamp - startTimestamp >= countDelay) { currentPercentage++; startTimestamp = (new Date()).getTime(); progress1.style = `--percent: ${currentPercentage}`; }; if (currentPercentage < maxPercentage) { timer = window.requestAnimationFrame(percentageChange); } else { window.cancelAnimationFrame(timer); }; }; const clickHander = () => { if (!start) { start = true; percentageChange(); }; }; btn.addEventListener('click', clickHander); </script>
這種方法的核心就是以當前盒子爲容器,以 ::before
爲內容填充。用 <div>
的好處就是實現簡單,兼容性強,拓展性高,可是美中不足的是標籤語義化不強。瀏覽器
<input />
是一個很是實用的替換元素,不一樣的 type 能夠作不一樣的事情。第二種就是用 <input type="range" />
來實現的。首先咱們來看看效果:app
源碼以下:ide
<style> .progress2[type='range'] { display: block; font: inherit; height: 20px; width: 300px; pointer-events: none; background-color: linear-gradient(to right, #2376b7 100%, #FFF 0%); } .progress2[type='range'], .progress2[type='range']::-webkit-slider-thumb { -webkit-appearance: none; }; .progress2[type='range']::-webkit-slider-runnable-track { border: none; border-bottom-right-radius: 10px; border-top-right-radius: 10px; height: 20px; width: 300px; } .btn { margin-top: 30px; } </style> <input id="progress2" class="progress2" type='range' step="1" min="0" max="100" value="0"/> <button id="btn" class="btn">點我一下嘛~</button> <script> 'use strict'; let startTimestamp = (new Date()).getTime(); let currentPercentage = 0; let maxPercentage = 100; let countDelay = 100; let timer = null; let start = false; let percentageGap = 10; const percentageChange = () => { const currentTimestamp = (new Date()).getTime(); if (currentTimestamp - startTimestamp >= countDelay) { currentPercentage++; startTimestamp = (new Date()).getTime(); progress2.value = currentPercentage; progress2.style.background = `linear-gradient(to right, #2376b7 ${currentPercentage}%, #FFF 0%`; }; if (currentPercentage < maxPercentage) { timer = window.requestAnimationFrame(percentageChange); } else { window.cancelAnimationFrame(timer); }; }; const clickHander = () => { if (!start) { start = true; percentageChange(); }; }; btn.addEventListener('click', clickHander); </script>
寫完這個 demo 才發現,<input type="range" />
並不適合作這個功能。。一個是實現困難,這個 type 組件的每一個元件均可以單獨修改樣式,可是效果並非很好。spa
另外一個是由於 range 有專屬語意 —— 範圍,因此它更適合作下面這種事:code
以上demo來自:https://developer.mozilla.org...htm
固然,上述兩種方式都是模擬進度條,實際上咱們並不須要模擬,由於 whatwg 有爲咱們提供原生的進度條標籤 —— <progress>
。
咱們先看效果:
實現以下:
<style> .progress3 { height: 20px; width: 300px; -webkit-appearance: none; display: block; } .progress3::-webkit-progress-value { background: linear-gradient( -45deg, transparent 33%, rgba(0, 0, 0, .1) 33%, rgba(0,0, 0, .1) 66%, transparent 66% ), linear-gradient( to top, rgba(255, 255, 255, .25), rgba(0, 0, 0, .25) ), linear-gradient( to left, #09c, #f44); border-radius: 2px; background-size: 35px 20px, 100% 100%, 100% 100%; } .btn { margin-top: 30px; } </style> <progress id="progress3" class="progress3" max="100" value="0"></progress> <button id="btn" class="btn">點我一下嘛~</button> <script> 'use strict'; let startTimestamp = (new Date()).getTime(); let currentPercentage = 0; let maxPercentage = 100; let countDelay = 100; let timer = null; let start = false; const percentageChange = () => { const currentTimestamp = (new Date()).getTime(); if (currentTimestamp - startTimestamp >= countDelay) { currentPercentage++; startTimestamp = (new Date()).getTime(); progress3.setAttribute('value', currentPercentage); }; if (currentPercentage < maxPercentage) { timer = window.requestAnimationFrame(percentageChange); } else { window.cancelAnimationFrame(timer); }; }; const clickHander = () => { if (!start) { start = true; percentageChange(); }; }; btn.addEventListener('click', clickHander); </script>
雖然有原生的進度條標籤,可是規範裏並無規定它的具體表現,因此各個瀏覽器廠商徹底能夠按照本身的喜愛去定製,樣式徹底不可控,因此標籤雖好。。可用性卻不強,有點惋惜。
固然,可以實現進度條功能的標籤,除了上面所說的,還有 <meter>
標籤。先看效果:
代碼以下:
<style> .progress4 { display: block; font: inherit; height: 50px; width: 300px; pointer-events: none; } .btn { margin-top: 30px; } </style> <meter id="progress4" class="progress4" low="60" high="80" min="0" max="100" value="0"></meter> <button id="btn" class="btn">點我一下嘛~</button> <script> 'use strict'; let startTimestamp = (new Date()).getTime(); let currentPercentage = 0; let maxPercentage = 100; let countDelay = 100; let timer = null; let start = false; const percentageChange = () => { const currentTimestamp = (new Date()).getTime(); if (currentTimestamp - startTimestamp >= countDelay) { currentPercentage++; startTimestamp = (new Date()).getTime(); progress4.value = currentPercentage; }; if (currentPercentage < maxPercentage) { timer = window.requestAnimationFrame(percentageChange); } else { window.cancelAnimationFrame(timer); }; }; const clickHander = () => { if (!start) { start = true; percentageChange(); }; }; btn.addEventListener('click', clickHander); </script>
這個標籤可能比較陌生,實際上它跟 <input type="range">
的語義是同樣的,用來顯示已知範圍的標量值或者分數值。不同的就是。。。它樣式改起來更麻煩。
本文測評了4種實現進度條的方式,得出的結論就是 —— <div>
賽高。。。雖然有的時候想優雅一點追求標籤語義化,可是資源不支持,也很尷尬。
嗯,萬能的 <div>
。
以上 demo 均可以個人 codepen 上查看:https://codepen.io/krischan77...