小程序實踐:基礎內容之progress,如何自定義一個環形進度條?

2020-12-14 石橋碼農

目錄

本文8475字,閱讀9分鐘,實踐40分鐘

文 / 石橋碼農

progress是進度條組件。

1)主要屬性

progress組件的主要屬性有:

progress進度條組件是一個很完備的組件了,不需要修改,就可以大部分場景需求。有兩點需要注意:

a)前景色activeColor

默認是與小程序中success圖標的顏色是相同的,都是「#09BB07」。雖然小程序框架給了開發者修改的自由,但是這個顏色並不能隨便修改。程序中的設計風格要保持一致性,在其它地方,「#09BB07」這個顏色表示完成,在進度條裡也應該作為前景完成色。如果想修改,所有地方都要修改。

在這張圖中共有五個顏色,分別用作小程序中五類信息的顏色。同類信息保持顏色的一致性,有助於向用戶提供清晰明確、主次分明的互動界面。

b)動畫啟動模式active-mode

這個屬性默認為「backwards」,這是不合適的。一個進度條往往指示一件事情的進度,所以最好的動畫啟動模式是「forwards」,即每次從上次結束處開始。

在啟用progress的active動畫後,每走一段都是一段動畫,每段動畫都是基於css的動畫繪製,都有時間。屬性duration用於標識行走1%需要花費的時間,默認值為30毫秒。這個值越大,動畫越細膩。

用於設計的標準屏幕寬度為375px,人類眼睛的動畫覺察閥值是200毫秒,以默認值30毫秒走掉1%計算,200毫秒會走掉大約25px。這個值不能大了,再大的話動畫看起來就不流暢,有卡頓。30毫秒可以視為是一個在體驗上可被允許的最小值。但也不可設置過大,設置大了會影響性能。

2)示例代碼與最佳實踐

wxml:

<progress bindtap="onTapProgressBar" stroke-width="2" percent="{{percentValue}}" active-mode="forwards" active show-info="{{false}}" bindactiveend="onProgressActiveEnd"/>

將寬度設置為2,啟用動畫,從數據源中以變量綁定動畫進度,使用「forwards」作為動畫啟動模式,不顯示百分比數字。其它顏色等,採用默認值。

js:

onTapProgressBar(e){

let progress = this.data.percentValue

if (progress < 100){

progress += 5

this.setData({percentValue:Math.min(100, progress)})

}

}

這個示例的動畫效果與文首的動畫相似,只是為了方便單擊演示,進度條寬度不同。

在progress組件中雖然沒有bindtap這個事情屬性,但tap事件是所有視圖組件的基礎事件,所以在這裡也可以綁定事情句柄。在這個示例中,碼農以onTapProgressBar這個單擊後觸發的函數模擬網絡加載的進度事件。

每單擊一次,進度+5,到100時停止。每次進度值變化,都附有一個動畫。動畫基本是連續和細膩的。但如果加載任務小,時間短,這個動畫也是一掃而過,基本是看不到的。

下面看一下相關問題:

1)如何實現一個下載文件並顯示動態進度條的功能?

有人在開發者社區問到這個問題,他想實現一個下載文件並顯示動態進度條的功能,但看了文檔發現percent這個必須要有固定的值(類似80),但進度是一直變化的,該如何讓它實現動態進度條呢?

示例代碼就可以滿足需求。當啟用active、並將active-mode設置為」forwards」後,動畫就會隨下載進度動起來。

通過文件下載的總大小和已完成大小,可以實時計算出percent數值。需要注意的是,percent屬性是動態綁定的,每次變化後,需要使用setData觸發視圖更新,不然動畫是看不到的。

2)progress已選進度條如何設置圓角?

代碼:

<progress border-radius="5" percent="20" show-info />

使用border-radius可以設置進度條外框的圓角大小,但是無法設置已選進度的圓角,即上面效果中綠色右端的圓角。

官方progress組件沒有提供修改已選進度條圓角值的屬性,有什麼辦法可以修改呢?

有人說,progress組件並不複雜,可以自己基於view組件實現一個。這也是一個辦法,但若實現像progress那樣功能完備的組件,沒有看起來那麼簡單;況且,微信團隊已經做好了一個,直接使用就是了,我們的目的是快速研發產品,沒有必要在一個小組件上浪費太多精力。

小程序界面是基於瀏覽器內核渲染的,這也就是說,所有組件都是有它本身的css樣式的。無奈微信開發者工具只開放了Wxml面板,屏蔽了Elements面板,沒有辦法直接查看progress組件的內部樣式。

我們可以從微信開發者工具的本地源碼中尋找辦法。在下面這個文件中:

~/Library/Application\ Support/微信開發者工具/WeappCode/package.nw/js/vendor/dev/wx-components.css

放置的都是官方小程序組件的樣式定義,其中有這樣一條:

.wx-progress-inner-bar { width: 0; height: 100%;}

它就是progress組件內部已選div的css類樣式。

知道了樣式類名就好辦了。在我們項目中wxss文件中,添加如下樣式:

.wx-progress-inner-bar { border-radius: 5px;}

給已選進度條加一個5px的圓角。看一下效果:

已經有圓角了。

progress本身有一個border-radius屬性,將這個屬性與上面樣式中的border-radius設置成一樣,就可以保證左右圓角一致。

這個方案在手機上測試,也有圓角效果。但它不是正規的路子,如果微信團隊修改了內部樣式類名,那麼這個hack就不好用了。

但對於小微信團隊和個人開發者來講,無所謂了,能達到效果就好了,即使官方有變化,不能再用了,也不過是一個樣式,不影響產品內容的展示。重要的是快速迭代,不在小問題上浪費太多時間。

3)已經加載完的進度條progress怎麼點擊某個按鈕讓它重新加載呢?

在這個使用示例中:

<progress bindtap="onTapProgressBar" stroke-width="2" percent="{{percentValue}}" active-mode="forwards" active show-info="{{false}}" bindactiveend="onProgressActiveEnd"/>

當進度條完成後,直接將percentValue再鎰設置為100,並不能讓動畫重新播放。

有人設想改變兩次,藉助nextTick或延時定時器分別在兩個渲染周期裡設置:

this.setData({ percentValue: 0 });

if (wx.canIUse('nextTick')) {

wx.nextTick(() => {

this.setData({ percentValue: 100 });

});

} else {

setTimeout(() => {

this.setData({ percentValue: 100 });

}, 17);

}

nextTick是基礎2.2.3版本以上支持的,所以這位開發者用了wx.canIUse判斷能不能使用這個Api。如果不能使用,則改用setTimeout設置一個延時定時器。

先將percentValue的值設置為0,過了一個渲染周期或17毫秒,再設置一次。這樣就可以得到動畫重新播放的效果。

其實每一次setData在底層都需要調用evaluateJavascript這個底層函數。這個函數用於邏輯層與視圖層的通訊,它的執行本來就需要時間,並不是馬上可以得到結果。因此,直接使用兩次setData:

<button bindtap="onTapReloadBtn">重新加載</button>

onTapReloadBtn(e){

this.setData({percentValue:0})

this.setData({percentValue:50})

}

也可以達到同樣的效果:

在這裡有一個問題,讀者朋友們請思考一下,為什麼上面setTimeout設置的延時定時器,要使用17毫秒呢?

這是因為目前小程序1秒內最大渲染60幀,每幀渲染約平均花費16.66毫秒,這是一個渲染周期最小的時間單位,17毫秒相當於延時一個nextTick的效果。

4)能否實現一個圓環形進度條呢?

官方的progress組件只支持常規場景,從左向左顯示進度。那麼,如何實現一個類似於這樣的環形進度條呢:

可以用Canvas繪製。

使用Component創建一個自定義組件circle-progress,在組件的wxml代碼裡放置一個canvas:

<view class='canvasBox'>

<view class='bigCircle'></view>

<view class='littleCircle'></view>

<canvas canvas-id="runCanvas" id="runCanvas" class='canvas'></canvas>

</view>

這個id為「runCanvas」的canvas將用於繪製兩個圓圈,下面是灰色的圓,上面是綠色的圓。

在自定義組件中,通過一個percent的屬性用於標識進度:

properties: {

percent: {

type: Number,

value: 50,

observer: function (newVal, oldVal) {

this.draw(newVal);

}

},

},

observer用於監聽屬性變化,當進度增加時,調用draw函數繪製新增的進度條。

在draw函數及後續調用的函數中,計算出需要繪製的弧度及使用Canvas Api arc進行繪製是關鍵:

var num = (2 * Math.PI / 100 * c) - 0.5 * Math.PI;that.ctx2.arc(w, h, w - 8, -0.5 * Math.PI, num)

circle-progress是一個獨立的組件。在使用時,先於json配置中聲明對組件的引用:

{ "usingComponents": { "circle-progress": "../circle-progress/index" }}

「circle-progress」是聲明的名稱。聲明後,在wxml中就可以這樣使用:

{

"usingComponents": {

"circle-progress": "../circle-progress/index"

}

}

在js代碼中模擬網絡改變進度值:

drawProgress(){

if (this.data.percentValue >= 100){

this.setData({

percentValue:0

})

}

this.setData({

percentValue:this.data.percentValue+10

})

}

運行效果就是上面問題起始處的gif圖片的效果。所有源碼在文未階段源碼中可以找到,位於:

miniprogram/pages/2.1/circle-progress

這個組件實現起來不複雜,但有兩點值得注意:

a)當在自定義組件中使用wx.createCanvasContext(canvasId)創建畫布的上下文繪製對象時,需要在第二個參數處傳遞this:

const ctx2 = wx.createCanvasContext(canvasId, this)

這樣才是在組件中查找,不然只是在主文件中查找畫布。

b)使用wx.createSelectorQuery().select(componentId)查找組件對象時,如果在自定義組件中,必須在查找前先調用一下in方法:

const query = wx.createSelectorQuery().in(this)

query.select('#'+id).boundingClientRect((res)=>{

...

}).exec()

不然,這個組件是查找不到的。默認組件查詢也僅是在主文件中查找,不涉及主文件中的子文件。

5)progress 右邊的進度百分比數字的顏色怎麼設置呢?

有兩個方法,最簡單直接的,是直接使用內聯樣式:

<progress percent="40" stroke-width="5" show-info style="color:red"/>

另一種方法,和第2個問題解決圓角的方法類似。就是在這個樣式文件中:

~/Library/Application\ Support/微信開發者工具/WeappCode/package.nw/js/vendor/dev/wx-components.css

找到百比比文字的樣式,然後在自己的wxss文件中將其重寫:

.wx-progress-info {

color: red;

}

現在所有progress組件的百分比文字都是紅色了。

6)progress組件右側的百分比文字,與左邊離得太近了,可否增加一個邊距?

就是感覺兩者離得太近了,想優化一下,這也是社區上有人提的一個問題。

這個問題很簡單,方法同問題5,直接修改樣式就好了。並且這樣的問題,涉及所有組件,最好是修改全局樣式:

.wx-progress-info {

color: red;

margin-left: 5px;

}

一處修改,所有progress組件都有效果了。

好了,我是石橋碼農,今天主要分享關於小程序開發中progress這個組件,以及如何自定義實現一個環形進度條組件。有什麼問題歡迎留言,也歡迎群內討論。

2020年03月27日

階段源碼:略

相關焦點

  • 詳解微信小程序自定義組件(一)
    好吧,突然發現學不完了,一下子,那就分開吧,由於時間太久,直接重新大致複習了一下微信小程序自定義組件微信小程序支持自定義組件下方的目錄其中,components為組件目錄,nodemodules為模塊目錄,pages為小程序的頁面目錄,utils為一些基礎功能的封裝。好比安裝的第三方百度統計功能在此。
  • 微信小程序開發button組件如何自定義樣式
    微信小程序開發一上線就受到了各界的喜愛,它不僅能快速的為用戶匹配到適合自己的小程序,還能幫企業、商家及其他組織進行文化宣傳。據統計,未來將會有90%的用戶被APP分割,而目前已經慢慢出現分化,有問題百度一下,找服務小程序搜索一下,這也是為什麼小程序目前如此之火的原因之一。
  • 小程序自定義標題欄從入門到放棄(總結)
    由於最近的開發需求需要自定義標題欄,開始研究一下這方面的知識。在網上查詢了一下資料,發現自定義標題欄還是挺簡單的。那麼如何自定義頭部呢?通過在app.js中設置navigationStyle屬性,默認值為『default』,自定義為『custom』。
  • 自定義 WorkManager —— 基礎概念
    對於絕大部分後臺執行任務來說,使用 WorkManager 是目前 Android 平臺上的最佳實踐。https://developer.android.google.cn/topic/libraries/architecture/workmanager/https://developer.android.google.cn/jetpack/目前為止本系列已經討論過:在本篇文章中,我們將會討論自定義配置相關的內容,包括:本系列的下一篇文章將對依賴注入和 Dagger 展開討論
  • html5中progress標籤(進度條)的詳細介紹
    本篇將介紹html5中progress標籤(進度條)的詳細用法,有興趣的朋友可以了解一下!在html5中新增了很多實用的標籤,今天小編介紹的就是其中一個,即progress標籤。學會progress標籤,可以讓我們很輕鬆的創建一個進度條,接下來跟著小編一起來學習吧!
  • 如何在macOS Big Sur自定義上修改應用程式圖標
    這些圖標更改中的一些已被證明是有爭議的,但是macOS Big Sur實際上使使用自定義應用程式圖標變得容易。運作方式如下。在哪裡可以找到自定義Mac應用程式圖標網絡上出現了一個新的macOS Icon Pack(https://macosicons.com/)網站,其中有近3,000種不同的圖標可供選擇。
  • 如何為安卓構建一個自定義鍵盤,教程在這裡
    在考慮構建安卓應用程式時,小編經常會想到屏幕和包含功能的內容。它可以是遊戲,也可以是執行常見任務的工具。但應用程式可以有各種形狀和大小。您可以構建一個在後臺運行的服務,並為你提供更輕鬆的使用方式。您可以創建窗口小部件或啟動器。比如構建一個自定義鍵盤。
  • 微信再出手扶持小程序:卡劵自定義入口將由小程序替代
    下線後,卡券創建流程中,「自定義入口」與「卡券詳情>立即使用跳轉」不再支持跳轉至網頁配置,你可嘗試使用跳轉小程序作為替代。本次調整僅針對券,會員卡原有能力暫時不變。」換句話,接下來微信卡劵自定義入口不再支持H5的連結,僅支持設置小程序。如果商戶並沒有小程序,後續卡劵將有點小難度。
  • Linux——Shell腳本中自定義變量的應用(基礎)2
    Shell腳本的應用2(基礎)簡介:這篇文檔為shell腳本變量的應用,詳細講解了自定義變量上篇文檔的連結地址:Linux——Shell腳本的應用1(基礎),也是shell腳本的基礎內容,可以通過連結地址查看。
  • 微信小程序又出新功能:可自定義分享卡片配圖
    【TechWeb報導】8月18日消息,據微信官方帳號微信公眾平臺消息,小程序又出新功能。小程序分享支持自定義封面圖,公眾號及小程序客服可發送小程序卡片。同時,還開放了獲取發票抬頭,指紋識別等更多能力。
  • 安卓自定義,如何恢復安卓設備的出廠設置及備份
    這是一個初學者的任務,小編將在這篇文章中教你如何在Android設備上執行恢復出廠設置。而且不僅僅是直接恢復出廠設置,小編還會先介紹一些在擦除之前備份數據的最佳做法,以及一些其他提示,以幫助儘快恢復從重置中恢復。如果您正在尋找恢復出廠設置以修復設備的問題,您可以在沒有恢復出廠設置的情況下修復設備。
  • 【Matlab基礎】 自定義函數
    在主程序中通過函數名和實參調用它,通過接口(即函數的輸入、輸出參數)來實現「通訊」。所以在調用函數時,你只要知道「被調用的函數是用來做什麼的」,以及「如何對應它的輸入、輸出參數」就行了。使用函數的好處:增加程序的可讀性(函數可獨立放在主程序之外)和重用性(一個函數可以多次被調用)。Matlab的自定義函數,常用的有:m文件定義函數、inline(內聯)函數、匿名函數。一、m文件定義函數(m-函數)1. Matlab函數的基本結構
  • C語言編程技巧:控制臺程序中自定義函數實現數組內容的特定顯示
    在用C語言編寫算法調試方面的程序中,經常會遇到這種情況,在不同地方需要對處理後的數組內容多次進行顯示,並且很多情況下並非顯示數組裡面的全部內容,而僅僅是想觀察數組中的部分數據內容,若每次顯示時都用printf函數寫的話,未免太過麻煩了。
  • useState 與 requestAnimationFrame 實現進度變化
    我們在之前的文章 如何構建自己的 react hooks 中實現過useInterval的自定義 hook。我們有個進度條,需要從進度 0 逐漸增加到固定的進度時,使用 useInterval 就可以實現。1.
  • 小程序如何對接公眾號?如何獲取appid
    小程序如何對接公眾號?打開微信公眾號後臺,選擇「設置 - 公眾號設置」,在「相關小程序」一欄點「查看」。而我要說的是有什麼不需要聯繫開發者,免費且實用的小程序來對接呢?在輸入小程序ID之前用微信公眾號平臺先登錄之前創建的小程序帳號,然後點擊右上角的頭像,在開發ID下會看到小程序ID,將ID複製到關聯小程序下點擊搜索,最後發送關聯邀請即可。
  • 【python基礎】python自定義函數五種用法
    函數的執行體程序代碼也要有適當的縮排。Python自定義函數的通用語法是:def   函數名稱(形參列表):執行體程序代碼Python自定義函數的5種常見形式:1、標準自定義函數:形參列表是標準的tuple數據類型2、沒有形參的自定義函數:該形式是標準自定義函數的特例。
  • 微信公眾號自定義菜單設置教程
    今天,給大家講解一個經常會被問到的問題-公眾號自定義菜單怎麼設置。大家在運營自己的公眾號時,有時會碰上需要設置公眾號自定義菜單的情況,所以今天帶來的分享,就是如何對公眾號的自定義菜單進行設置!首先在設置自定義菜單之前,我們需要對它有個基本的概念了解。
  • 如何開發一個微信查成績小程序?微信查成績小程序要怎麼做?
    為此微信查成績小程序也就成了不少老師們的剛需;那麼微信查成績小程序叫什麼?  回答這個問題之前,我們需要先了解一下查成績系統的製作流程,其實常規的查成績系統的製作成本高昂,需要專門定製化,自定義配置也較低、實現方式複雜繁瑣、用戶操作性較低,很多時候也只能PC端使用;當然,我們這裡提到的是傳統的查詢系統的製作方式了!對於技術高度發達的當代,自然也是有解決上述問題的方法了!
  • 基礎篇章:關於 React Native 之 Switch 和 ProgressBarAndroid 組件的講解
    【回復「1024」,送你一個特別推送】(友情提示:RN學習,從最基礎的開始,大家不要嫌棄太基礎,會的同學請自行略過