欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Vue + CSS實現(xiàn)漸變柵格進度條效果

 更新時間:2025年03月20日 15:54:52   作者:acheding  
基于Vue和CSS實現(xiàn)漸變柵格進度條,通過劃分柵格單元、顏色漸變、標(biāo)簽與刻度的絕對定位來實現(xiàn)高度靈活和交互性,進度條劃分為多個柵格,每個單元格顏色漸變并且連續(xù),可以根據(jù)不同的場景配置個性化屬性,具有極高的靈活度和交互性,感興趣的朋友一起看看吧

進度條作為可視化大屏系統(tǒng)中展示數(shù)據(jù)狀態(tài)的關(guān)鍵元素,其視覺效果直接影響用戶的使用體驗,而傳統(tǒng)的進度條往往呈現(xiàn)出固定的樣式,缺乏視覺吸引力。在這種場景下,一種基于Vue和CSS實現(xiàn)漸變柵格進度條的方法應(yīng)運而生,該方法將進度條劃分為多個柵格單元,每個單元格顏色漸變并且連續(xù),可以根據(jù)不同的場景配置個性化屬性,具有極高的靈活度和交互性,可以調(diào)整顏色、柵格數(shù)量、間隔、寬度、高度、圓角、數(shù)值、標(biāo)簽、刻度等屬性,并同時具有平滑的過渡效果,特別適用于可視化大屏系統(tǒng)中。

1 原理

1.1 劃分柵格單元

首先定義一個父容器,用于容納所有柵格,然而柵格的數(shù)量不定,所以需要設(shè)置彈性布局,使得任意數(shù)量的柵格能夠自動均勻平鋪。樣式合適位置預(yù)留響應(yīng)式變量,保證屬性的可配置性。

與此同時,給每個柵格加上平滑的過渡動畫,確保每次數(shù)據(jù)發(fā)生變化引起圖表變化時能夠平滑過渡,而并非跳躍式突變,增強了用戶的交互體驗和視覺感受,同時能夠引導(dǎo)用戶注意力,突出變化部分的重要內(nèi)容或功能。如下圖。

1.2 顏色漸變

為了解決漸變柵格百分比條中柵格之間存在空隙而顏色可以連續(xù)的問題,需要利用CSS的兩個重要屬性:background屬性和偽元素。

首先,將每個柵格的背景色設(shè)置相同。接著,調(diào)整background的size為柵格數(shù)量倍的寬度,調(diào)整position來指定背景的位置,將每個柵格的背景色都在上一個柵格的基礎(chǔ)上,偏移一個柵格的距離。為了實現(xiàn)這一效果,還需將柵格設(shè)置為溢出隱藏,并確保背景色不重復(fù),如下圖。

由于進度條分為已完成和未完成兩部分,而上述過程僅實現(xiàn)了所有柵格的連續(xù)漸變,無法突顯出進度,所以需要控制漸變色在指定位置結(jié)束。然而,目前的方案似乎無法實現(xiàn)漸變色截斷的效果,因此我們嘗試使用遮罩。具體而言,就是將每個柵格都增加一個偽元素,將其完全覆蓋在柵格上,根據(jù)計算的比例,已完成部分的偽元素背景色設(shè)置為透明,將漸變色顯示出來,未完成部分的則設(shè)置為默認(rèn)背景色,將下方的漸變色進行遮罩。

偽元素可以通過CSS自定義屬性進行變量的綁定,在字符串前加上兩根連接線“–”,可以將該字符串聲明為CSS自定義屬性,然后通過var()函數(shù)讀取變量,最后使用Vue的動態(tài)style和模板字符串傳入,這樣,這個動態(tài)屬性便可以根據(jù)數(shù)據(jù)的變化動態(tài)的渲染偽元素了。如下圖。

1.3 標(biāo)簽與刻度

為了最大程度上不影響原有柵格進度條的層級結(jié)構(gòu),標(biāo)簽與刻度這種附加屬性我們選擇了絕對定位。新建一個盒子,保持與柵格的父容器寬度相同,添加進度開始值、結(jié)束值作為左右刻度,結(jié)合當(dāng)前值可以計算出進度的百分比,同時根據(jù)柵格間距和當(dāng)前值等屬性可以計算出標(biāo)簽的位置。如下圖。

2 實現(xiàn)方法

有了前面的思路鋪墊,現(xiàn)在來著手實現(xiàn)。

2.1 可配置屬性

首先我們需要配置用戶可自定義修改的屬性,并給予默認(rèn)值,這些屬性通過綁定響應(yīng)式變量的方式來實現(xiàn)實時刷新。

最小值、最大值即進度條最左側(cè)和最右側(cè)的位置,默認(rèn)為0和2,當(dāng)前值即進度所在的位置,默認(rèn)為1.66。

柵格數(shù)量指的是總共劃分多少個柵格,數(shù)量不同,每個柵格所代表的比例也將發(fā)生改變,默認(rèn)為10。

柵格間距是每個柵格之間空余的距離,單位為百分比,默認(rèn)為2%。

漸變色是從起始顏色到終止顏色的色彩變化,形成一種流暢的過渡效果,增強視覺吸引力,默認(rèn)為#6AE5BB到#3C7DDF的過渡。

背景色則可以認(rèn)為是進度未完成的部分,默認(rèn)使用顏色#AAAAAA作為區(qū)分。

數(shù)值的展示方式分為真實值和百分比值兩種,切換后標(biāo)簽和刻度隨之改變,其字體、字號、顏色、小數(shù)點也可自定義。

此外,柵格的圓角、高度、標(biāo)簽的偏移及其顯隱等屬性也在相應(yīng)位置插入了變量提供給用戶自定義修改。

2.2 數(shù)據(jù)初始化

在頁面加載之前,需要進行數(shù)據(jù)的初始化,提前計算部分屬性。

通過最小值、最大值、當(dāng)前值計算出當(dāng)前值所占比例(valuePercent),默認(rèn)比例為(1.66-0)/(2-0)*100%=83%。

通過柵格的個數(shù)計算每個柵格代表的比例(perGridPercent),默認(rèn)每個柵格代表100%/10=10%。

通過valuePercent和perGridPercent得到完整顯示漸變色的柵格個數(shù)(completeGridNum)。Math.floor(83%/10%)=8,也就意味著前8個柵格的偽元素遮罩層的背景色,可以直接設(shè)置透明。

而余下的一個不足以完整顯示漸變色的柵格,我們需要計算漸變色的部分占整個柵格的比例(remainingGridPercent)。用completeGridNum乘以perGridPercent,得到完整顯示的比例,再用valuePercent減去完整顯示的比例,得到剩余需要覆蓋的部分,最后除以perGridPercent,即(83%-8*10%)/10%=30%,也就是說,余下的漸變色只需占據(jù)一個柵格的30%。

通過柵格間隔(interval)和柵格數(shù)量(number)得到每個柵格的實際寬度(perGridWidth),即用100%減去interval乘以number-1,得到所有柵格的實際寬度,隨后除以number,interval默認(rèn)為2%,(100%-2%*(10-1))/10=8.2%。Vue的計算屬性可以根據(jù)依賴關(guān)系進行計算并緩存,所以我們可以用computed來計算柵格的實際寬度,由于柵格的間隔和數(shù)量都是響應(yīng)式變量,所以寬度也是響應(yīng)式的。

通過(completeGridNum+ remainingGridPercent)perGridWidth+completeGridNuminterval,不難算出標(biāo)簽絕對定位下距離左端的位置,即(8+30%)8.2%+82%=84.06%。

2.3 開始繪制

通過Vue的v-for指令,得到指定數(shù)量的柵格。通過:style=“`–barWidth:${perGridWidth}`”,將實際寬度傳入組件內(nèi)部,然后使用該值給柵格和偽元素遮罩的寬度賦值,具體為"width:var(–barWidth)"。

接下來,利用CSS從左至右的線性漸變色,均勻的平鋪到所有的柵格上,即 “background:linear-gradient(to right,${beginColor},${overColor}) ${(i-1)perGridWidth}/${number100}% no-repeat”。這里的beginColor,overColor為漸變起始和終止顏色,i為柵格的序號。每個柵格的背景色都為擴展了number倍的漸變色,不同的則是各自的偏移量,都偏移了(i-1)*perGridWidth。

然后就是添加遮罩層,通過computed計算屬性,可以根據(jù)i值大小,動態(tài)返回背景色的字符串。當(dāng)小于等于completeGridNum時,返回透明色;當(dāng)?shù)扔赾ompleteGridNum+1時,通過線性漸變,按百分比分配透明色和背景色,即`linear-gradient(to right,transparent r e m a i n i n g G r i d P e r c e n t , {remainingGridPercent}, remainingGridPercent,{backColor} ${remainingGridPercent})`,其中backColor為柵格背景色,意味著從左側(cè)開始,直到達(dá)到remainingGridPercent指定的位置時,顏色保持透明色。在remainingGridPercent位置之后,顏色保持為背景色;其他情況下返回背景色。

最后,為柵格和其偽元素遮罩添加"transition: all 1s"的過渡動畫。

核心代碼

<div class="grid-progress-container">
  <div
    class="grid-progress-bar"
    v-for="i in state.mergedConfig.bar.number"
    :style="`--barRadius:${state.mergedConfig.bar.radius}px;
    --barHeight:${state.mergedConfig.bar.height}px;
    --barWidth:${perGridWidth}%;
    --barBackground:${renderBack(i)};
    background:linear-gradient(to right,${state.mergedConfig.bar.preColor},${state.mergedConfig.bar.suffixColor}) ${
      (i - 1) * perGridWidth
    }% / ${state.mergedConfig.bar.number * 100 + '%'} no-repeat;`"
  ></div>
</div>
const initData = () => {
  // 當(dāng)前值所占比例(100%)
  state.valuePercent =
    ((state.mergedConfig.dataset.value - state.mergedConfig.dataset.min) /
      (state.mergedConfig.dataset.max - state.mergedConfig.dataset.min)) *
    100
  // 每一個柵格比例(100%)
  state.perGridPercent = 100 / state.mergedConfig.bar.number
  // 完整渲染的柵格個數(shù)
  state.renderGridNum = Math.floor(state.valuePercent / state.perGridPercent)
  // 不完整渲染的柵格剩余比例(1)
  state.remainingGridPercent = (state.valuePercent - state.renderGridNum * state.perGridPercent) / state.perGridPercent
}
const perGridWidth = computed(() => {
  return (100 - state.mergedConfig.bar.interval * (state.mergedConfig.bar.number - 1)) / state.mergedConfig.bar.number
})
const renderBack = (i: number) => {
  if (state.remainingGridPercent === 0) {
    if (i <= state.renderGridNum) return 'transparent'
    else return `${state.mergedConfig.bar.backColor}`
  } else {
    if (i <= state.renderGridNum) {
      return 'transparent'
    } else if (i === state.renderGridNum + 1) {
      return `linear-gradient(to right,transparent ${state.remainingGridPercent * 100}%,${
        state.mergedConfig.bar.backColor
      } ${state.remainingGridPercent * 100}%)`
    } else {
      return `${state.mergedConfig.bar.backColor}`
    }
  }
}
.grid-progress-container {
    width: 100%;
    padding: 60px;
    display: flex;
    justify-content: space-between;
    .grid-progress-bar {
      height: var(--barHeight);
      width: var(--barWidth);
      border-radius: var(--barRadius);
      transition: all 1s;
      position: relative;
      &::before {
        position: absolute;
        content: '';
        height: 100%;
        width: 100%;
        background: var(--barBackground);
        border-radius: var(--barRadius);
        transition: all 1s;
      }
    }
  }

到此這篇關(guān)于Vue + CSS實現(xiàn)漸變柵格進度條的文章就介紹到這了,更多相關(guān)vue漸變柵格進度條內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • vue使用canvas手寫輸入識別中文

    vue使用canvas手寫輸入識別中文

    這篇文章主要介紹了vue使用canvas手寫輸入識別中文,工作時遇到一些項目如:系統(tǒng)上的輸入法使用不方便,客戶要求做一個嵌入web網(wǎng)頁的手寫輸入法。下面我們來看看文章得具體描述吧
    2021-11-11
  • Vue3?props的使用示例詳解

    Vue3?props的使用示例詳解

    這篇文章主要介紹了Vue3?props的使用詳解,本文通過示例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-10-10
  • Vue監(jiān)聽使用方法和過濾器實現(xiàn)

    Vue監(jiān)聽使用方法和過濾器實現(xiàn)

    這篇文章主要介紹了Vue監(jiān)聽使用方法和過濾器實現(xiàn),過濾器為頁面中數(shù)據(jù)進行強化,具有局部過濾器和全局過濾器
    2022-06-06
  • vue3?vscode插件volar配置教程

    vue3?vscode插件volar配置教程

    這篇文章主要介紹了vue3?vscode插件volar配置,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-07-07
  • 詳解如何使用vue實現(xiàn)頁面訪問攔截

    詳解如何使用vue實現(xiàn)頁面訪問攔截

    這篇文章主要為大家詳細(xì)介紹了如何使用vue實現(xiàn)頁面訪問攔截功能,文中的示例代碼講解詳細(xì),具有一定的參考價值,需要的可以了解一下
    2023-08-08
  • vue接入ts基本方法

    vue接入ts基本方法

    這篇文章主要介紹了vue接入ts基本方法,關(guān)于ts,也出了很久,下面我們就來簡單學(xué)習(xí)了下ts并且在原有項目上接入基本ts語法,也算是一個初級嘗試,簡單梳理下基礎(chǔ)的接入配置和已經(jīng)遇到的問題,供需要的小伙伴們參考
    2022-01-01
  • 淺談Vue-cli單文件組件引入less,sass,css樣式的不同方法

    淺談Vue-cli單文件組件引入less,sass,css樣式的不同方法

    下面小編就為大家分享一篇淺談Vue-cli單文件組件引入less,sass,css樣式的不同方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-03-03
  • vue項目創(chuàng)建步驟及路由router

    vue項目創(chuàng)建步驟及路由router

    本文主要給大家分享了vue項目的創(chuàng)建步驟以及vue路由router的相關(guān)知識點,非常的實用,有需要的小伙伴可以來參考下
    2020-01-01
  • Vue注冊組件命名時不能用大寫的原因淺析

    Vue注冊組件命名時不能用大寫的原因淺析

    這段時間一直在弄vue,當(dāng)然也遇到很多問題,這里就來跟大家分享一些注冊自定義模板組件的心得 ,需要的朋友可以參考下
    2019-04-04
  • Vue 中 a標(biāo)簽上href無法跳轉(zhuǎn)的解決方式

    Vue 中 a標(biāo)簽上href無法跳轉(zhuǎn)的解決方式

    今天小編大家分享一篇Vue 中 a標(biāo)簽上href無法跳轉(zhuǎn)的解決方式,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2019-11-11

最新評論