背景及简介
在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