輕鬆實現進度條的方法之 meter

先看來一張圖片,一張帶有進度條效果的圖片,或者美化一下,你能夠當作是充電效果的圖。css

這張圖是繼上篇文章《這樣寫 step 步驟條就輕鬆了》而延伸出來的,在上一篇中提到使用 progress 標籤來實現一個進度條的效果,並無提供任何相對比較具象的 demo。此次,不只有了一個比較具象的 demo(雖然不是特別炫酷),同時,還將會介紹一個新的標籤,一個比 progress 更強大的標籤。html

波浪動畫效果

這個效果其實就是兩個標籤元素疊加而成,爲了造成那種所謂的波浪的效果,會對兩個元素作細微的差別處理,以及在不一樣進度值顯示不一樣的顏色值。web

在這兩張圖中,咱們可以發現不一樣的點是:segmentfault

  • 圓角的幅度各異;
  • 兩個元素的透明度不一樣;
  • 兩個元素彷佛有錯落感;
  • 兩張圖的顏色不一樣;

考慮到但願是經過一個 HTML 元素標籤來實現效果的,那麼這裏用到的波浪就用 ::before::after 了。用這兩個也是有一些其餘緣由,由於咱們有一個動畫效果須要使用 animation 屬性,可是在僞元素中,後面提到的幾個僞元素在 Chrome 中不支持,不過在 Safari 中倒是能夠的。app

圓角的處理

這個圓角是修改了 border-radius 的八個值所得,具體是怎麼樣的一個值,徹底是看心情,好比我是這樣的。less

圖中所示的小工具是很早以前折騰的一個處理圓角的小工具,用這個小工具就是能夠直接拖拉每一個角,而後獲得效果,就不用一個值一個值的手動修改了。工具

透明的處理

直接使用不一樣的 opacity 值,疊加一下就行了。優化

錯落感

結合 opacity 屬性,再經過 left 或者 margin-left 等值進行位置偏移,最終結合不一樣的 border-radius 就能夠了。動畫

不一樣顏色

這個就是要結合咱們接下來要提到的 HTML 元素了,該元素可讓咱們在不一樣的 value 值展現不一樣的顏色效果。相比較 progress 元素,會有更多的可配置性。spa

meter 標籤

這個就是咱們要了解的 meter 標籤,相比較 progress 而言,多了幾個階段標識,從而也就是有了不一樣的顏色值。

一樣的 meter 標籤在打開 shdow DOM 查看的時候,也是可看到幾個僞元素的存在,相比較 progress 而言,咱們能夠發現,一樣是三層嵌套的結構,可是在 meter 的最後一層嵌套時,僞元素的類名是會根據 value 的狀況而改變的。正由於如此,纔會有不一樣階段的顏色值。

經常使用屬性列表

  • min
  • max
  • value
  • low
  • high
  • optimum

相比 progress 多了 lowhigh 以及 optimum 這三個可控制進度展現效果的屬性。不一樣的取值結果最終將直接影響顏色顯示效果。正常狀況下,通常建議是:min ≤ low ≤ high ≤ optimum ≤ max,是的,只是說正常狀況下,若是非正常狀況下,必定要讓 high 小於 low 也不是不能夠,只不過最終顏色的表示就呵呵了。若是 optimum 是在 minlow 的區間之間,那麼可能致使的結果就是兩種顏色互調。

僞元素列表

  • ::-webkit-meter-inner-element
  • ::-webkit-meter-bar

上述這兩個跟 progress 中的沒啥區別,就是層級嵌套,包裹着用的。而下面這三個就是有差別了。

  • ::-webkit-meter-optimum-value
  • ::-webkit-meter-even-less-good-value
  • ::-webkit-meter-suboptimum-value

從命名能夠看到,主要就是三種不一樣值的顏色表示方式。

  • even-less-good(紅色)
  • suboptimum(黃色)
  • optimum(綠色)

樣式優化

<meter min="0" max="10" low="3" high="6" optimum="7" value="2"></meter>

簡單清晰明瞭的 HTML 代碼,後面咱們須要改變就是 value 值就能夠了。

meter {
  position: relative;
  width: 200px;
  height: 50px;
  margin-top: 100px;
  border: 5px solid #000;
  border-radius: 16px;
  overflow: hidden;
  appearance: none;
}

這部分關鍵的主要就是 positionoverflow 以及 appearance 這三個,appearance 主要做用是爲了修改外觀樣式,而另外兩個則是在下面控制 ::before::after 的時候所使用的。

meter::after,
meter::before {
  content: '';
  position: absolute;
  top: -200%;
  left: var(--roundLeft);
  width: 200px;
  height: 200px;
  border-radius: 182px 171px 150px 202px / 200px 219px 141px 149px;
  background-color: var(--bgc);
  opacity: 0.3;
  z-index: 1;
  animation: 3s linear 0s infinite rotateItem;
}
meter::before {
  left: calc(var(--roundLeft) - 5%);
  border-radius: 151px 132px 178px 118px / 174px 129px 189px 172px;
  opacity: 0.5;
}

在這裏能夠看到,有一個 animation,因此,還須要補上一個 @keyframes 的關鍵幀。

@keyframes rotateItem {
  from {
    transform: rotate(1deg);
  }

  to {
    transform: rotate(360deg);
  }
}

也是很簡單的一段動畫樣式,就是爲了讓那個不規則的圓圈圈轉起來。

心細的你你確定還看到了 --roundLeft--bgc 這兩個 CSS 變量,以及在 ::before 中使用 calc() 計算偏移量的方式。這兩個 CSS 變量的主要做用是後面爲了經過屬性選擇符去控制每一個階段的顏色和位置,好比這樣:

meter[value="0"]::after,
meter[value="0"]::before {
  --roundLeft: -90%;
  --bgc: #f00;
}
/* 省略部分 */
meter[value="5"]::after,
meter[value="5"]::before {
  --roundLeft: -50%;
  --bgc: #f0f;
}
/* 省略部分 */
meter[value="10"]::after,
meter[value="10"]::before {
  --roundLeft: 0%;
  --bgc: #0f0;
}

前面咱們提到了,是能夠根據 value 值,直接經過三個不一樣的僞元素去改變顏色。若是咱們不是使用 ::before 或者 ::after 的話,的確是能夠的。可是咱們如今是使用了,所以那三個顏色值就沒什麼做用了,也沒法從這樣的層級結構中傳遞到外層做爲繼承使用。

因此,乾脆就直接把這三個顏色值透明化。

meter::-webkit-meter-bar,
meter::-webkit-meter-optimum-value,
meter::-webkit-meter-even-less-good-value,
meter::-webkit-meter-suboptimum-value {
  background-color: transparent;
}

這麼一折騰,最終咱們其實並無利用 meter 組件特性,反而只是結合 value 屬性,經過屬性選擇符而實現了位置的變化。可是這幾個僞元素始終是存在的,只不過這個 demo 沒法證實其可用性。或許是我過於指望想經過每一個值獲得效果,而且又想要加上 animation 動畫效果的關係。

假設,若是 Chrome 中可以很好支持 animation 的動畫效果,就能夠不用利用 ::before::after 來實現,也就有可能經過 Shadow DOM 中的僞元素了。

最後的效果

在最後,meter 標籤的主要做用是展現,而若是但願有互動效果的話,那麼咱們能夠作的大概可能就有:

  • 經過 N 個 :hover 僞類去實現鼠標滑過改變的效果;
  • 經過 :checked 實現點擊後切換不一樣顏色的效果;
  • 外部經過修改 input 輸入改變 metervalue 值,而這裏咱們使用了 type='range'input 來實現滑動拖拉改變值;
<input type='range' value="2" step="1" min="0" max="10" id="changeMeter" />
<script>
  const mv = document.getElementById('meterValue');
  const cm = document.getElementById('changeMeter');
  cm.onchange = function () {
    mv.value = cm.value;
  }
</script>

最後經過樣式,覆蓋在 meter 上,同時隱藏這個 input 就行了。

#changeMeter {
  width: 200px;
  height: 50px;
  position: absolute;
  top: 100px;
  left: 0;
  z-index: 5;
  opacity: 0;
}

相關閱讀:

首發我的公衆號: 志語自樂https://mp.weixin.qq.com/s/r_...
相關文章
相關標籤/搜索