背景
以前我們製作柱狀圖都用echarts或者其他同型別的圖表外掛
這次是個移動端的需求,而且這個圖表需要動畫
使用echarts就會顯得過重,而且動畫達不到我想要的效果(主要是我自己愚蠢想不到好的動畫辦法)。
先來看下效果圖:
幾個柱狀圖分數不滿時:
幾個滿分柱圖:
還有完整的元素組合動畫效果:
ps:圓環+進度的效果製作,見下篇。
從最後一張圖中可以看出這個需求,柱狀圖是在一個swiper當中實現的。
swiper翻頁,柱狀圖逐個增長,圓環進度增長。
廢話不多說,看處理思路~
分析一波設計稿,得到解題思路:
看著是個圖表,但是是不是我們的思維都被圖表的形象給固化了呢?
因為如果我旋轉圖片將得到下面的樣子:
用微信看圖工具自帶的rotate功能旋轉原圖,我們再看到的就是4個進度條~
所以,我這個效果的核心,就是用進度條的思路做的。再把進度條的水平方向結構旋轉過來不就可以了。
進度條的核心是更改元素的寬度(橫向進度條的實現見這篇文章:《css案例 - 評分效果的星星✨外衣》)
我們現在改變為垂直方向,就需要更改元素的高度即可。
思路有了,我們先來實現一個柱狀圖:
重點看div.row的結構,分上中下三段:
上 - 分數 div.data-txt
中 - 柱狀圖 div.progress
實際分值(綵帶條)span.pg-data
下 - 文案 div.week
div.row的樣式:
div.row 正常的盒模型樣式
div.data-txt 正常的字型樣式
div.progress
- 初始化高度為零,也就是柱狀圖的高度就為0。
- transition監聽高度的變化,實現高度遞增動畫效果
- 後期資料變化,更改progress標籤上的style:height即可
div.row.ani > div.progress
每一個有ani樣式的div.row結構,其下邊的子元素div.progress的動畫延遲。
這裡用scss,快速建立了1-6條ani內部的progress的動畫延遲時間。這裡只是快捷寫法
編譯後的程式碼:
span.pg-data
就是一個綵帶條,塊級化後高度隨父親div.progress的高度。父親的高度隨真實資料。
div.week 底部文案正常的文字樣式
這個是沒有得分時,0分的狀態。屬於專案特殊需求,可有可無。
實現整個柱狀圖表:
一個柱圖有了,就把第一個迴圈得到四個。
但是他們需要水平方向平均分佈,於是我這裡用了flex。(ps:你也可以用float或者其他。就是佈局問題了)
都是一些讓四個div.row橫向兩端均勻排列
ps:可忽略中間對before的設定,是為了實現四個柱圖底部的橫線效果。
vue邏輯原始碼實現整個效果
其中:
Data為1-4周的資料,進行迴圈得到四個柱狀圖div.row
Points為實際得分。需要根據具體分值展示不同效果:
aniShow是指是否觸發動畫,如果否就是什麼都不展示,高度就為0。
如果是那就計算分值是否>=100:是的話就展示100,但這裡得把px轉換為rem單位,所以用100*1.5/100;
如果分值==0,因為設計稿的原因,還要漏出灰色一小段,所以強制改成0.04,;
剩下的0<積分值<100,那就用(實際積分值*1.5)/100。將分值進行百分比處理
原始碼如下:
1 .data01-charts 2 .row(v-for='item,index in Data' :key="index" :class='aniShow ? "ani":""') 3 .data-txt {{item.Points > 0 ? item.Points : '無資料'}} 4 .progress(:class='item.Points == 0 ? "nodata" : ""' 5 :style="'height: ' + (aniShow ? (item.Points >= 100 ? (100 * 1.5) / 100 : item.Points == 0 ? 0.04 : item.Points * 1.5 / 100) : 0) +'rem'") 6 span.pg-data 7 .week {{item.WeekName}}
公式:(100[實際分數] * 1.5[轉換為px高度]) / 100[轉化為rem高度],grade==0 : // 0分展示規則