HarmonyOS JS UI 自定义icon组件 原创 精华
背景及简介
在HarmonyOS JS UI官方提供的组件中没有图标组件,要使用图标的话需要使用image组件引入图片资源,如果图标状态或者样式需要改变时,就需要使用另一张图片来替换,操作起来比较麻烦。移动端使用图标的场景会比较多,如果全部使用图片来实现效果,会增加很多图片资源引用,对于代码开发也会有很多的不便,在此背景下想能实现一个图标的组件,能够自定义样式便于修改和引用,也能动态的切换图标样式。
此项目使用官方的 badge 组件和 canvas 组件来实现图标的绘制,通过封装自定义组件,可以对组件大小、样式、背景、角标、禁用等属性进行配置,从而实现图标的绘制,此自定义组件完全使用代码实现,没有引用任何外部资源或文件,可以很方便的被各种项目引用。
项目介绍
-
项目名称:OpenHarmony-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
属性名称 | 值类型 | 描述 |
---|---|---|
name | String | icon 名称 |
class-prefix | String | icon 样式前缀(目前无效果) |
size | Number | icon 尺寸,默认大小24px,元素是一个正方形 |
color | String | icon 颜色,默认#333333,可以使用16进制和rgba |
background-color | String | icon 背景颜色,默认#FFFFFF,可以使用16进制和rgba |
badge-config | Object | icon 角标配置,详细配置参考官方文档 |
disabled | Boolean | icon 禁用配置,默认false |
dataClick | any | icon 自定义点击事件绑定数据,默认为null |
代码示例:
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
方法名称 | 参数 | 描述 |
---|---|---|
click | dataClick | 自定义的点击事件调用方法,默认参数为null,在disabled属性为true的时候不会触发此方法 |
代码示例:
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的话是不会显示绘制的路径的;
参数:
参数 | 类型 | 描述 |
---|---|---|
x | number | 指定位置的x坐标。 |
y | number | 指定位置的y坐标。 |
示例:
ctx.beginPath();
ctx.moveTo(10, 10);
ctx.lineTo(280, 160);
ctx.stroke();
绘制圆弧
绘制圆弧有两个api,arc() 和 arcTo() ,其中我们主要看看arc(x,y,radius,startAngle,endAngle,anticlockwise)方法是如何绘制圆弧的。
参数:
参数 | 类型 | 描述 |
---|---|---|
x | number | 弧线圆心的x坐标值。 |
y | number | 弧线圆心的y坐标值。 |
radius | number | 弧线的圆半径。 |
startAngle | number | 弧线的起始弧度。 |
endAngle | number | 弧线的终止弧度。 |
anticlockwise | boolean | 是否逆时针绘制圆弧。 |
示例:
ctx.beginPath();
ctx.arc(100, 75, 50, 0, 6.28);
ctx.stroke();
绘制椭圆弧
绘制椭圆弧使用 ellipse() ,下面示例中绘制了一段椭圆弧,但是在实际操作中我发现,如果是绘制一个完整的椭圆,startAngle设置为Math.PI * 0,endAngle设置为Math.PI * 2 并不能绘制一个完整的椭圆,画布上什么也没画,在此我是使用一个中间角度然后调用两次ellipse()方法才得到一个完整的圆弧,不知道有没有大佬遇到过相同的问题或者知道根本原因能交流一下。
参数:
参数 | 类型 | 描述 |
---|---|---|
x | number | 椭圆圆心的x轴坐标。 |
y | number | 椭圆圆心的y轴坐标。 |
radiusX | number | 椭圆x轴的半径长度。 |
radiusY | number | 椭圆y轴的半径长度。 |
rotation | number | 椭圆的旋转角度,单位为弧度。 |
startAngle | number | 椭圆绘制的起始点角度,以弧度表示。 |
endAngle | number | 椭圆绘制的结束点角度,以弧度表示。 |
anticlockwise | number | 是否以逆时针方向绘制椭圆,0为顺时针,1为逆时针。(可选参数,默认为0) |
示例:
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封装的一个可以绘制带圆角的矩形,详情可以查看源码封装
参数:
参数 | 类型 | 描述 |
---|---|---|
x | number | 指定矩形的左上角x坐标值。 |
y | number | 指定矩形的左上角y坐标值。 |
width | number | 指定矩形的宽度。 |
height | number | 指定矩形的高度。 |
示例:
ctx.rect(20, 20, 100, 100); // Create a 100*100 rectangle at (20, 20)
ctx.stroke(); // Draw it
绘制三次贝赛尔曲线
三次贝赛尔曲线的绘制主要用到了bezierCurveTo()
参数:
参数 | 类型 | 描述 |
---|---|---|
cp1x | number | 第一个贝塞尔参数的x坐标值。 |
cp1y | number | 第一个贝塞尔参数的y坐标值。 |
cp2x | number | 第二个贝塞尔参数的x坐标值。 |
cp2y | number | 第二个贝塞尔参数的y坐标值。 |
x | number | 路径结束时的x坐标值。 |
y | number | 路径结束时的y坐标值。 |
ctx.beginPath();
ctx.moveTo(20, 20);
ctx.quadraticCurveTo(100, 100, 200, 20);
ctx.stroke();
绘制二次贝赛尔曲线
二次贝赛尔曲线的绘制主要用到了quadraticCurveTo() ,其实不管是三次的还是二次的都是使用额外的控制点来控制线条的走向,线条绘制用到了高阶数学中的函数求导的方式来计算,因此控制点的具体值不能很快速的能得到精确的结果,只有不断的使用和反复的尝试才能熟练掌握控制点的设置。
参数:
参数 | 类型 | 描述 |
---|---|---|
cpx | number | 贝塞尔参数的x坐标值。 |
cpy | number | 贝塞尔参数的y坐标值。 |
x | number | 路径结束时的x坐标值。 |
y | number | 路径结束时的y坐标值。 |
示例:
ctx.beginPath();
ctx.moveTo(20, 20);
ctx.quadraticCurveTo(100, 100, 200, 20);
ctx.stroke();
绘制图片
绘制图片会使用到 drawImage() ,单纯的绘制图片其实意义不大,因为有image组件,这个功能主要作用是能对图片在前端进行裁剪,而不需要使用到后台服务来操作。
参数:
参数 | 类型 | 描述 |
---|---|---|
image | Image | 图片资源,请参考Image对象。 |
sx | number | 裁切源图像时距离源图像左上角的x坐标值。 |
sy | number | 裁切源图像时距离源图像左上角的y坐标值。 |
sWidth | number | 裁切源图像时需要裁切的宽度。 |
sHeight | number | 裁切源图像时需要裁切的高度。 |
dx | number | 绘制区域左上角在x轴的位置。 |
dy | number | 绘制区域左上角在y 轴的位置。 |
dWidth | number | 绘制区域的宽度。 |
dHeight | number | 绘制区域的高度。 |
示例:
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主要是对文字的样式、大小,粗细,字体系列等进行设置。
参数:
参数 | 类型 | 描述 |
---|---|---|
text | string | 需要绘制的文本内容。 |
x | number | 需要绘制的文本的左下角x坐标。 |
y | number | 需要绘制的文本的左下角y坐标。 |
示例:
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
更多原创内容请关注:中软国际 HarmonyOS 技术学院
入门到精通、技巧到案例,系统化分享HarmonyOS开发技术,欢迎投稿和订阅,让我们一起携手前行共建鸿蒙生态。
很全面的讲解,感谢分享。
谢谢大家的关注,在鸿蒙JS UI中使用图标的话个人还是建议使用字体图标,另外有大佬使用字体图标做了一个一样的icon组件,比较推荐大家去看看,地址:https://gitee.com/vant-openharmony
这地址里没有demo,不知道怎么使用呀????
可以看一下这个地址:https://gitee.com/vant-openharmony/example,下载下来就可以在ide里面运行了,这个里面是直接可以通过npm安装使用的
主要用法跟自定义组件的用法是一样的,通过element引入就可以直接使用
不知道为啥,我的就是不出来
你安装依赖了吗?在example\entry\src\main\js\default文件夹下运行npm install安装依赖之后就可以了
嘻嘻,有文档的哦~
https://vant-openharmony.gitee.io/vant/#/quickstart
https://vant-openharmony.gitee.io/vant/#/icon