h5實現手機端等級進度條

龍恩0707發表於2015-04-16

h5實現等級進度條

 需求如下: 實現一個動畫進度條,頁面一開啟實現一個進度條動畫,因為App這個頁面會經常改,所以沒有使用原審Android或者IOS來實現,希望通過H5來做;

 伺服器端返回如下資料:

var Config = {
    // 等級大圖片url地址
    courierRankBigUrl:  'images/grade2-icon.png',

    // 配送員等級名稱
    courierRankName: '3級鮮鋒官',

    // 同時可接單數
    courierCanPackgeCountDoing:  '10',

    // 積分陣列1,2,3,4,5;50,100,150,200,250
    integrationRankString:  '1,2,3,4,5;0,100,150,200,250',

    // 經驗豆陣列1,2,3,4,5;50,100,150,200,250
    experienceBeanRankString: '',

    // 本月累計積分
    monthCompletedWaybills:  '150'
};

需要我們前端把各個資料渲染出來及 實現進度條效果;

實現進度條基本原理如下:

 因為頁面分了5個等級,所以為了相容各個手機端瀏覽器,因此把進度條總寬度設定為100%;那麼每段就是20%的寬度了。

假如第一段50分 第二段100分 第三段300分 第四段500分,第五段積分就是第四段的2倍;那麼假如伺服器返回的是375分,那麼在瀏覽器下佔比如下
由於頁面分了5段,每段顯示20%的寬度; 遍歷陣列[50,100,300,500],定義一個遍歷count = 0;
如果陣列任何一段小於伺服器返回375的話,那麼count自加1,因此count=3
因此演算法比例如下:(375 - 300) / (500 - 300) + 3 = 3/8 + 3 = 3.375; 最後 3.375 / 5 * 100%= 67.5%;
 記住 因為陣列arrs去掉了第一項了 所以curNum要減去1 即:curNum - 1;

JS實現程式碼如下

/*
 * @todo 計算進度條的百分比
 * @param {score,arrs} 伺服器返回的總分 伺服器返回的陣列
 */
 var count = 0;
 function percent(score,arrs) {
     var tempCount = 0;
     var percent;
     //  如果積分大於陣列最後一個總積分的話, 那麼進度條就是最大的
     if(score*1 > arrs[arrs.length -1] * 1) {
          score = arrs[arrs.length -1];
     }
     for(var i = 0; i < arrs.length; i+=1) {
         if(score*1 > arrs[i]*1) {
                tempCount++;
          }
     }
     count = tempCount;
     if(tempCount*1 < 1) {
          percent = (score / arrs[0]) / 5 * 100;
     }else {
          percent = ((score - arrs[tempCount - 1]) / (arrs[tempCount] - arrs[tempCount - 1]) + tempCount) / 5 * 100;
     }
             
     return percent + "%";
}

實現動畫效果還是使用CSS3哦!

JS實現進度條程式碼如下:

<script>
/* 伺服器返回的資料如下 */ var Config = { // 等級大圖片url地址 courierRankBigUrl: 'images/grade2-icon.png', // 配送員等級名稱 courierRankName: '3級鮮鋒官', // 同時可接單數 courierCanPackgeCountDoing: '10', // 積分陣列1,2,3,4,5;50,100,150,200,250 integrationRankString: '1,2,3,4,5;0,100,150,200,250', // 經驗豆陣列1,2,3,4,5;50,100,150,200,250 experienceBeanRankString: '', // 本月累計積分 monthCompletedWaybills: '150' }; </script>
/* 切記:實現進度條的JS程式碼一定要放在頭部,如果放在尾部的話,在手機端瀏覽器下是沒有進度條的動畫效果的,因為頁面先載入完後,就已經設定了寬度 */ <script> function setStyle(obj,css){ for(var i in css){ obj.style[i] = css[i]; } } var scores = Config.integrationRankString.split(";")[1].split(','); // 後臺返回的積分 var score = Config.monthCompletedWaybills; /* * 進度條的寬度百分比的計算方式設計如下: * 假如第一段50分 第二段100分 第三段300分 第四段500分 那麼假如伺服器返回的是375分,那麼在瀏覽器下佔比如下 * 由於頁面分了5段,每段顯示20%的寬度; 遍歷陣列[50,100,300,500],定義一個遍歷count = 0; * 如果陣列任何一段小於伺服器返回375的話,那麼count自加1,因此count=3 * 比例如下:(375 - 300) / (500 - 300) + 3 = 3/8 + 3 = 3.375; 最後 3.375 / 5 * 100%= 67.5%; * 記住 因為陣列arrs去掉了第一項了 所以curNum要減去1 即:curNum - 1 */ /* * @todo 計算進度條的百分比 * @param {score,arrs} 伺服器返回的總分 伺服器返回的陣列 */ var count = 0; function percent(score,arrs) { var tempCount = 0; var percent; // 如果積分大於陣列最後一個總積分的話, 那麼進度條就是最大的 if(score*1 > arrs[arrs.length -1] * 1) { score = arrs[arrs.length -1]; } for(var i = 0; i < arrs.length; i+=1) { if(score*1 > arrs[i]*1) { tempCount++; } } count = tempCount; if(tempCount*1 < 1) { percent = (score / arrs[0]) / 5 * 100; }else { percent = ((score - arrs[tempCount - 1]) / (arrs[tempCount] - arrs[tempCount - 1]) + tempCount) / 5 * 100; } return percent + "%"; } if(scores[0] == 0) { scores.shift(); } // 返回第五段的值 計算方法 val fiveVal = arrs[arrs.length - 1] * 2 var fiveVal = scores[scores.length - 1] * 2 + ""; scores.push(fiveVal); var width = percent(score,scores); var dynamic = document.getElementById("dynamic"); dynamic.innerHTML = '@-webkit-keyframes load {0% {width: 0%;}100% {width: '+width+';}}'; window.onload = function(){ var bar = document.getElementById("progress-bar"); setStyle(bar,{width:width}); } </script>

其他實現頁面的JS如下:

<script>
        function $Id(id){
            return document.getElementById(id);
        };
        function hasClass(obj, cls) {  
            return obj.className.match(new RegExp('(\\s|^)' + cls + '(\\s|$)'));  
        }  
  
        function addClass(obj, cls) {  
            if (!hasClass(obj, cls)) obj.className += " " + cls;  
        }  
        var bar = $Id("progress-bar"),                 // 進度條id 
            gradeImg = $Id("grade-img"),               // 等級圖片icon
            courierRankName = $Id("courierRankName"),  // 配送員等級名稱
            gradeAmount = $Id("grade-amount"),         // 可同時接單數
            monthScore = $Id("monthScore"),            // 本月累計積分
            scoreGrade = $Id("progree-nums"),          // 等級id
            progressScore = $Id("progress-score"),     // 積分id
            divisionBar = $Id("division-bar");         // 進度條分隔條

        // 伺服器返回的等級圖片
        gradeImg.style.backgroundImage="url("+Config.courierRankBigUrl+")";

        // 伺服器返回的等級名稱
        courierRankName.innerHTML = Config.courierRankName;

        // 可同時接單數
        gradeAmount.innerHTML = Config.courierCanPackgeCountDoing;

        // 本月累計積分
        monthScore.innerHTML = "(" + Config.monthCompletedWaybills + "分" + ")";
        if(Config.monthCompletedWaybills *1 < 0) {
            var minMonthScore = $Id("minMonthScore");
            if(!hasClass(minMonthScore,'current')) {
                addClass(minMonthScore,'current');
            }
        }
        // 伺服器返回的等級和積分陣列
        var grades = Config.integrationRankString.split(";")[0].split(','),
            scores = Config.integrationRankString.split(";")[1].split(','),
            gradesHTML = '';
            scoresHTML = '';
        for(var i = 0; i < grades.length; i++) {
            gradesHTML += '<span>'+grades[i]+'級</span>';
        }
        scoreGrade.innerHTML = gradesHTML;
        for(var j = 0; j < scores.length; j++) {
            if(j == 0) {
                scoresHTML += '<i>'+scores[j]+'</i>';
            }else {
                scoresHTML += '<span>'+scores[j]+'分</span>';
            }
        }
        progressScore.innerHTML = scoresHTML;
        var divisionBarSpans = divisionBar.getElementsByTagName("span");
        // 後臺返回的積分
        var score2 = Config.monthCompletedWaybills;

        var curIndex = scores.indexOf(score2);
        if(count*1 > 0) {
             for(var i = 0; i < count; i++) {
                if(!hasClass(divisionBarSpans[i],'current')) {
                    // 比如返回積分是200 正好陣列也有200這個積分 正好相等的話 ,那麼就不新增current類名
                    if(i !== curIndex) {
                        (function(i){
                            setTimeout(function(){
                                addClass(divisionBarSpans[i],'current');
                            },2500);
                        })(i)
                    }
                }
             } 
        }
    </script>

demo如下可以下載

相關文章