HarmonyOS JS UI 自定義icon組件
背景及簡介
在HarmonyOS JS UI官方提供的組件中沒有圖標組件,要使用圖標的話需要使用image組件引入圖片資源,如果圖標狀態或者樣式需要改變時,就需要使用另一張圖片來替換,操作起來比較麻煩。移動端使用圖標的場景會比較多,如果全部使用圖片來實現效果,會增加很多圖片資源引用,對于代碼開發也會有很多的不便,在此背景下想能實現一個圖標的組件,能夠自定義樣式便于修改和引用,也能動態的切換圖標樣式。
此項目使用官方的 badge 組件和 canvas 組件來實現圖標的繪制,通過封裝自定義組件,可以對組件大小、樣式、背景、角標、禁用等屬性進行配置,從而實現圖標的繪制,此自定義組件完全使用代碼實現,沒有引用任何外部資源或文件,可以很方便的被各種項目引用。
項目介紹
- 項目名稱:OpenHarmony-JS-Icon
- 項目源地址:https://gitee.com/chenqiao002/open-harmony-js-icon
- 所屬系列:OpenHarmony下的的JS 自定義組件開發示例
- 開發版本:OpenHarmony-SDK-6,DevEco Studio 2.2.0.200
- 項目作者和維護人:陳喬
- 郵箱:chenqiao002@chinasoftinc.com
- 本示例基于OpenHarmony下的JavaScript UI框架,通過使用常用組件、畫布組件和自定義組件等來實現一個自定義的icon組件,通過本示例可以基本了解和使用該組件。
- 本項目是基于OpenHarmony項目而不是HarmonyOS項目,請注意運行環境。
- 請參考OpenHarmony項目配置方法進行項目配置和運行。
- 如果你不熟悉OpenHarmony的JS開發,請參考該項目的開發講解。
文件目錄
在Pages目錄下,只有一個index首頁,在首頁中展示了icon自定義組件的使用樣例。
在common文件夾下的icon文件夾是自定義的icon組件,在icon文件夾中js文件夾是icon繪制使用到的方法和數據。
使用說明
項目預覽
下載OpenHarmony-JS-Icon項目,啟動 DevEco Studio并打開工程。
進入entry->src->main->js->default->pages->index,打開index.hml點擊Previewer進行預覽。
引入
在index.hml的第一行,引用自定義組件,這里我們將name屬性設置為icon。
- <element src="../../common/icon/icon.hml" name="icon"></element>
基礎用法
通過設置icon組件的name屬性來展示不同的圖標。
- <icon name="chat_o" size="48"></icon>
角標提示
通過設置icon組件的badge-config屬性來對角標信息進行設置。
- <icon name="chat_o" size="48" badge-config="{{ badgeConfig }}"></icon>
- badgeConfig: {
- config: {
- badgeColor: "#0a59f7",
- textColor: "#ffffff",
- },
- count: 0,
- visible: true,
- },
圖標顏色和背景顏色
通過設置icon組件的color屬性來設置,background-color可以設置圖標的背景顏色。
- <icon name="chat_o" size="48" color="#ED6F21" background-color="#ddddddd" ></icon>
圖標大小
通過設置icon組件的size屬性來控制圖標的大小。
- <icon name="chat_o" size="24"></icon>
圖標禁用
通過設置icon組件的disabled屬性控制圖標是否禁用,disabled默認為false,禁用狀態設置為true時圖標為灰色,color和badge-config屬性只有在disabled為false時生效。
- <icon name="chat_o" disabled="true" onclick="iconClick" color="red" size="48" badge-config="{{ badgeConfig }}"></icon>
圖片繪制
通過設置icon組件的name屬性設置為圖片的地址。
- <icon name="common/images/huawei.png" size="48"></icon>
API
props
代碼示例:
- export default {
- props: {
- // icon 名稱
- name: {
- default: ''
- },
- // icon 樣式前綴
- classPrefix: {
- default: 'hos-icon'
- },
- // icon 尺寸
- size: {
- default: 24,
- },
- // icon 顏色
- color: {
- default: "#333333"
- },
- // icon 背景顏色
- backgroundColor: {
- default: "#ffffff"
- },
- // 角標配置
- badgeConfig: {
- default: {
- config: {
- badgeColor: "#0a59f7",
- textColor: "#ffffff",
- },
- placement: "rightTop",
- count: 0,
- maxcount: 99,
- visible: false,
- label: "",
- }
- },
- // icon 圖標禁用
- disabled: {
- default: false
- },
- // icon 點擊方法攜帶的參數
- dataClick: {
- default: null
- }
- }
- }
Events
代碼示例:
hml文件,icon組件綁定點擊事件和綁定點擊實現參數:
- <icon name="fail" size="48" onclick="iconClick" data-click="點擊fail圖標" ></icon>
js文件,在iconClick方法上接收參數的detail屬性為綁定的數據:
- iconClick(data) {
- console.log("iconClick");
- console.log(data.detail);
- }
執行結果:
繪制原理
所有的圖標繪制均是基于HarmonyOS JS API 畫布組件 來實現的,根據官方提供的繪制方法自定義封裝繪制圖形,基本實現了以下幾種基礎圖形繪制的封裝。
繪制直線
直線的繪制主要用到了lineTo(x,y)方法,下面示例中的 ctx.beginPath() 是創建一個新的繪制路徑,ctx.moveTo(10, 10) 是當前路徑起始點移動到指定點,ctx.lineTo(280, 160)則是繪制直線到終止點,ctx.stroke()是進行邊框繪制操作,每次畫布繪制都是一條透明的路徑,沒有stroke的話是不會顯示繪制的路徑的;
參數:
示例:

- ctx.beginPath();
- ctx.moveTo(10, 10);
- ctx.lineTo(280, 160);
- ctx.stroke();
繪制圓弧
繪制圓弧有兩個api,arc() 和 arcTo() ,其中我們主要看看arc(x,y,radius,startAngle,endAngle,anticlockwise)方法是如何繪制圓弧的。
參數:
示例:

- ctx.beginPath();
- ctx.arc(100, 75, 50, 0, 6.28);
- ctx.stroke();
繪制橢圓弧
繪制橢圓弧使用 ellipse() ,下面示例中繪制了一段橢圓弧,但是在實際操作中我發現,如果是繪制一個完整的橢圓,startAngle設置為Math.PI * 0,endAngle設置為Math.PI * 2 并不能繪制一個完整的橢圓,畫布上什么也沒畫,在此我是使用一個中間角度然后調用兩次ellipse()方法才得到一個完整的圓弧,不知道有沒有大佬遇到過相同的問題或者知道根本原因能交流一下。
參數:
示例:

- ctx.beginPath();
- ctx.ellipse(200, 200, 50, 100, Math.PI * 0.25, Math.PI * 0.5, Math.PI, 1);
- ctx.stroke();
繪制矩形
官方繪制矩形使用rect()方法,此方法功能比較單一,一般我們在使用矩形的時候可能會有圓角的需求,在此項目中并沒有使用到官方的方法繪制,而是使用lineTo()直線和arc()圓弧兩個api封裝的一個可以繪制帶圓角的矩形,詳情可以查看源碼封裝
參數:
示例:

- ctx.rect(20, 20, 100, 100); // Create a 100*100 rectangle at (20, 20)
- ctx.stroke(); // Draw it
繪制三次貝賽爾曲線
三次貝賽爾曲線的繪制主要用到了bezierCurveTo()
參數:
- ctx.beginPath();
- ctx.moveTo(20, 20);
- ctx.quadraticCurveTo(100, 100, 200, 20);
- ctx.stroke();
繪制二次貝賽爾曲線
二次貝賽爾曲線的繪制主要用到了quadraticCurveTo() ,其實不管是三次的還是二次的都是使用額外的控制點來控制線條的走向,線條繪制用到了高階數學中的函數求導的方式來計算,因此控制點的具體值不能很快速的能得到精確的結果,只有不斷的使用和反復的嘗試才能熟練掌握控制點的設置。
參數:
示例:
- ctx.beginPath();
- ctx.moveTo(20, 20);
- ctx.quadraticCurveTo(100, 100, 200, 20);
- ctx.stroke();
繪制圖片
繪制圖片會使用到 drawImage() ,單純的繪制圖片其實意義不大,因為有image組件,這個功能主要作用是能對圖片在前端進行裁剪,而不需要使用到后臺服務來操作。
參數:
示例:

- var test = this.$element('drawImage');
- var ctx = test.getContext('2d');
- var img = new Image();
- img.src = 'common/image/test.jpg';
- ctx.drawImage(img, 50, 80, 80, 80);
繪制文字
文字繪制使用fillText()方法,其中ctx.font主要是對文字的樣式、大小,粗細,字體系列等進行設置。
參數:
示例:

- ctx.font = '35px sans-serif';
- ctx.fillText("Hello World!", 20, 60);
以上就是本項目主要使用到的幾種api,為了便于圖標數據結構的清晰配置,所有的api都經過了二次封裝,數據結構和封裝結果可以查看項目源碼。
注意事項
- 可以使用角標,使用時需將所有的badge屬性作為一個對象用badge-config名稱傳入,這個用法參考了官方badge組件。
- 可以繪制圖片,在name屬性上設置圖片路徑,路徑必須是絕對路徑或者云路徑,不能使用"./“或者”…/"等開頭的相對路徑,而且圖片尺寸需和icon的size值一樣,不然可能會導致繪制不完整,官方有image組件,這個功能有點雞肋。
- 雖然圖標顏色可以設置透明色,但是不建議設置透明色,透明色可能會導致部分圖標繪制的效果與預期相差較大。
- 圖標的形式參考了市面上主流的圖標形式,全部的圖標繪制均為canvas繪制,無任何代碼參考,使用的api均為鴻蒙JS UI官方api。
- 圖標繪制使用的是canvas,雖然在一些特別細節的地方可能還比不上矢量圖標清晰度,但是此庫理論上可以實現任意圖標,大家有需求或者有新的圖標需要繪制的請評論留言,謝謝。
- 目前圖標已繪制了230+,已基本完成計劃實現的圖標,還會繼續更新,敬請關注。
- 此項目使用canvas繪制圖標,其實圖標可以參考自定義字體樣式來實現字體圖標,相對來說字體圖標文件更小、圖標更清晰、也更利于更新管理,有需要的可以看看Vant Openharmony