HarmonyOS三方库的使用

发布于:2025-09-01 ⋅ 阅读:(22) ⋅ 点赞:(0)

三方库基本使用

1.如何获取三方库

目前提供了两种途径获取开源三方库:

● Gitee三方库资源汇总:https://gitee.com/openharmony-tpc/tpc_resource
● OpenHarmony三方库中心仓:https://ohpm.openharmony.cn

2. 常用三方库介绍

常用的三方库可以分为UI、动画、网络、图片、多媒体、数据存储、安全、工具等。
● UI库:
○ @ohos/textlayoutbuilder:可以定制任一样式的文本构建工具,包括字体间距、大小、颜色、富文本高亮显示等。
○ @ohos/roundedimageview:可以生成圆角矩形、或者椭圆形等图片形状。
● 网络库:
○ @ohos/axios:可以运行在node.js 和浏览器中,基于Axios 原库v1.3.4版本进行适配,并沿用其现有用法和特性。
● 动画库:
○ @ohos/lottie:可以解析Adobe After Effects软件通过Bodymovin插件导出的json格式的动画,并在移动设备上进行本地渲染。
○ @ohos/svg:可以解析SVG图片并渲染到页面上。
三方库在系统能力的基础上,提供了更加方便的使用,在许多场景下,能够极大提升开发者的开发效率。

3. 下载命令行工具

请前往下载中心获取并下载命令行工具Command Line Tools。 根据系统需要下载对应的命令行工具,我这里用的是Mac(ARM)版本。

在这里插入图片描述

4. 配置命令行工具

下载好了命令行工具(Command Line Tools)之后,需要将其配置到系统环境变量下;

4.1 Windows系统配置

  1. 解压 command-line-tools 压缩包找到其bin目录
  2. 将command-line-tools/bin目录配置到环境变量中
    在这里插入图片描述

4.2 Mac系统配置

  1. 将下载后的命令行工具解压到本地。
  2. 打开终端工具,执行以下命令,根据输出结果分别执行不同命令。
echo $SHELL

echo命令执行完之后,结果可能是/bin/bash 或者 /bin/zsh,表示当前你的系统使用的是哪个配置文件。

  • 如果输出结果为/bin/bash,则执行以下命令,打开.bash_profile文件。
vi ~/.bash_profile
  • 如果输出结果为/bin/zsh,则执行以下命令,打开.zshrc文件。
vi ~/.zshrc
  1. 单击字母“i”,进入Insert模式。输入以下内容,在PATH路径下添加环境变量。
export PATH=~/command-line-tools/bin:$PATH
  1. 编辑完成后,单击Esc键,退出编辑模式,然后输入“:wq”,单击Enter键保存
  2. 执行以下命令,使配置的环境变量生效。
  • 如果步骤a时打开的是.bash_profile文件,请执行如下命令:
source ~/.bash_profile
  • 如果步骤a时打开的是.zshrc文件,请执行如下命令:
source ~/.zshrc

5.使用三方库@ohos/lottie

5.1 什么是@ohos/lottie

@ohos/lottie是基于lottie-web开发,集成在三方库社区内的开源版本,是HarmonyOS系统中复杂动画的一种解决方案。
动画是传达想法和创造更好的用户交互体验的工具,常见使用动画的场景如下:
● 启动动画:APP logo动画的播放。
● 加载动画:网络请求的loading动画。
● 上下拉刷新动画:请求更多资源时的刷新动画。
● 按钮动画:切换按钮、编辑按钮、播放按钮等按钮的切换过渡动画。
● 视图转场动画:一些场景的转场添加动画能够提升用户体验。
@ohos/lottie提供了使用JSON动画文件的解决方案,开发者可以在原生应用中像使用静态图像一样使用动画,而不用关注动画的实现过程,并且@ohos/lottie具有一套完整的API控制动画的行为,可以让动画更具有交互性。接下来将介绍@ohos/lottie的安装和基本使用。

5.2 @ohos/lottie的安装与卸载

● 安装@ohos/lottie
通过ohpm执行对应的指令,将lottie安装到项目中(建议在项目的模块根目录下安装)。

ohpm install @ohos/lottie

安装完成后,在模块根目录下的oh-packagejson5文件中可以找到@ohos/lottie的配置信息;在
oh_modules/@ohos目录中找到lottie包的存放位置。

在这里插入图片描述

  • 卸载@ohos/lottie通过ohpm执行卸载指令,将lottie从项目中删除,其程序包和配置信息将会从项目中移除。
ohpm uninstall @ohos/lottie

5.3 使用@ohos/lottie

5.3.1 @ohos/lottie 使用步骤

● @ohos/lottie的引入
通过import指令在项目中引入@ohos/lottie到文件中。

import lottie from '@ohos/lottie'

● 构建Canvas画布
@ohos/lottie解析JSON动画文件的数据需要基于Canvas 画布进行2D渲染,所以在加载JSON动画之前,要先初始化渲染上下文,并在画面中创建Canvas画布区域,将对应的渲染上下文renderingContext传递给Canvas。

// 初始化渲染上下文  
private renderingSettings: RenderingContextSettings = new RenderingContextSettings(true) // 设置开启抗锯齿
private renderingContext: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.renderingSettings)  // 创建2D渲染上下文


// 加载Canvas画布   
Canvas(this.renderingContext)
  ...

● 使用@ohos/lottie加载JSON动画
加载JSON动画需要用到loadAnimation方法,在方法中需配置相应的初始设置,包括渲染上下文、渲染方式以及JSON动画资源的路径等。可以直接使用lottie.loadAnimation方法,也可以用一个animationItem实例来接收返回的animationItem对象。

// 用animationItem实例接收
let animationItem = lottie.loadAnimation({
  container: this.renderingContext,            // 渲染上下文
  renderer: 'canvas',                          // 渲染方式
  loop: true,                                  // 是否循环播放,默认true
  autoplay: true,                              // 是否自动播放,默认true
  path: 'common/lottie/data.json',             // json路径
})      
lottie.loadAnimation({                               // 或者直接使用
  container: this.renderingContext,            // 渲染上下文
  renderer: 'canvas',                          // 渲染方式
  loop: true,                                  // 是否循环播放,默认true
  autoplay: true,                              // 是否自动播放,默认true
  path: 'common/lottie/data.json',             // json路径
})

● @ohos/lottie控制动画
@ohos/lottie内封装了包括状态控制,进度控制,播放设置控制和属性控制等多个API,用户可以利用这些API完成对动画的控制,实现更加灵活的交互效果。

// 播放、暂停、停止、销毁  可以使用lottie,也可以使用animationItem实例进行控制
lottie.play();        // 从目前停止的帧开始播放
lottie.stop();        // 停止播放,回到第0帧
lottie.pause();       // 暂停该动画,在当前帧停止并保持
lottie.togglePause(); // 切换暂停/播放状态
lottie.destroy();     // 删除该动画,移除相应的元素标签等。在unmount的时候,需要调用该方法


// 播放进度控制
animationItem.goToAndStop(value, isFrame); // 跳到某个时刻/帧并停止。isFrame(默认false)指示value表示帧还是时间(毫秒)
animationItem.goToAndPlay(value, isFrame); // 跳到某个时刻/帧并进行播放
animationItem.goToAndStop(30, true);       // 例:跳转到第30帧并停止
animationItem.goToAndPlay(300);            // 例:跳转到第300毫秒并播放


// 控制帧播放
animationItem.setSegment(5,15);             // 限定动画资源播放时的整体帧范围,即设置动画片段
animationItem.resetSegments(5,15);          // 重置播放的动画片段
animationItem.playSegments(arr, forceFlag); // arr可以包含两个数字或者两个数字组成的数组,forceFlag表示是否立即强制播放该片段
animationItem.playSegments([10,20], false); // 例:播放完之前的片段,播放10-20帧
animationItem.playSegments([[5,15],[20,30]], true); //例: 直接播放5-15帧和20-30帧


// 动画基本属性控制
lottie.setSpeed(speed);         // 设置播放速度,speed为1表示正常速度
lottie.setDirection(direction); // 设置播放方向,1表示正向播放,-1表示反向播放


// 获取动画帧数属性
animationItem.getDuration();    //获取动画时长
5.3.2 @ohos/lottie 应用案例

在这里插入图片描述


import lottie, { AnimationItem } from '@ohos/lottie';

@Entry
  @Component
  export struct Index {
    private renderingSettings: RenderingContextSettings = new RenderingContextSettings(true);
    private renderingContext: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.renderingSettings);
    private animateName: string = 'data';
    private animateItem: AnimationItem | null = null;
    @State canvasTitle: string = '';

    aboutToDisappear(): void {
      lottie.destroy();
    }

    onPageShow(): void {
      lottie.play();
    }

    onPageHide(): void {
      lottie.pause();
    }

    build() {
      Flex({
        direction: FlexDirection.Column,
        justifyContent: FlexAlign.SpaceBetween
      }) {
        // Canvas area
        Column() {
          Canvas(this.renderingContext)
            .width('100%')
            .aspectRatio(1.76)
            .backgroundImage($r('app.media.canvasBg'))
            .backgroundImageSize(ImageSize.Cover)
            .onDisAppear(() => {
              lottie.destroy(this.animateName);
            })
          Text(this.canvasTitle)
            .width('100%')
            .fontSize(14)
            .textAlign(TextAlign.Center)
            .fontWeight(FontWeight.Bold)
            .fontColor('#182431')
            .margin({ top: 12 })
            .opacity(0.4)
        }
        .margin({
          top: 10,
          left: 10,
          right: 10
        })

        // Buttons area
        Column({ space: 12 }) {
          Button() {
            Text('动画加载')
              .fontSize(16)
              .fontColor('#007dff')
              .fontWeight(FontWeight.Bold)
          }
          .width('100%')
            .height(40)
            .backgroundColor('#dedbdb')
            .onClick(() => {
              if (this.animateItem !== null) {
                this.animateItem.destroy();
                this.animateItem = null;
              }
              this.canvasTitle = '加载动画';
              this.animateItem = lottie.loadAnimation({
                container: this.renderingContext,
                renderer: 'canvas',
                loop: 10,
                autoplay: true,
                name: this.animateName,
                path: 'lottie/data.json'
              });
            })

          Button() {
            Text('结束并回到第0帧')
              .fontSize(16)
              .fontColor('#007dff')
              .fontWeight(FontWeight.Bold)
          }
          .width('100%')
            .height(40)
            .backgroundColor('#dedbdb')
            .onClick(() => {
              if (this.animateItem === null) {
                return;
              }
              this.canvasTitle = '结束并回到第0帧'
              this.animateItem.goToAndPlay(0, true);
            })

          Flex({ justifyContent: FlexAlign.SpaceBetween }) {
            Button() {
              Text('播放')
                .fontSize(16)
                .fontColor('#007dff')
                .fontWeight(FontWeight.Bold)
            }
            .width('49%')
              .height(40)
              .backgroundColor('#dedbdb')
              .onClick(() => {
                if (this.animateItem === null) {
                  return;
                }
                this.canvasTitle = '播放';
                lottie.play();
          })

          Button() {
            Text('暂停')
              .fontSize(16)
              .fontColor('#007dff')
              .fontWeight(FontWeight.Bold)
          }
          .width('49%')
          .height(40)
          .backgroundColor('#dedbdb')
          .onClick(() => {
            if (this.animateItem === null) {
              return;
            }
            this.canvasTitle = '暂停';
            lottie.pause();
          })
        }
      }
      .padding({
        left: 23,
        right: 23,
        bottom: 41
      })
    }
    .height('100%')
  }
}

6.使用第三方库@ohos/axios

6.1 axios简介

Axios ,是一个基于 promise 的网络请求库,可以运行 node.js 和浏览器中。本库基于Axios 原库v1.3.4版本进行适配,使其可以运行在 OpenHarmony,并沿用其现有用法和特性。

● http 请求
● Promise API
● request 和 response 拦截器
● 转换 request 和 response 的 data 数据
● 自动转换 JSON data 数据

6.2 下载安装axios

ohpm install @ohos/axios

6.3 申请权限

{
  "module": {
    "requestPermissions": [
      {
        "name": "ohos.permission.INTERNET"
      }
    ]
  }
}

6.4 导入@ohos/axios模块

import axios from '@ohos/axios'

6.5 axios快速入门

axios支持泛型参数,由于ArkTS不再支持any类型,需指定参数的具体类型。
如:axios<T, R = AxiosResponse, D>(url)
● T: 是响应数据类型。当发送一个 POST 请求时,客户端可能会收到一个 JSON 对象。T 就是这个 JSON 对象的类型。
● R: 是响应体的类型。当服务器返回一个响应时,响应体通常是一个 JSON 对象。R 就是这个 JSON 对象的类型。默认情况下,R 是 AxiosResponse,这意味着响应体是一个 AxiosResponse 对象,它的 data 属性是 T 类型的
● D: 是请求体的参数类型(data的类型)。当发送一个 GET 请求时,可能会在 URL 中添加一些查询参数。参数为空情况下,D 是 null类型。

6.5.1 数据模型
interface Student {
  id?: number
  name: string
  phoneNumber: string
  birthdate: string
  chineseScore: number
  mathScore: number
  englishScore: number
  hobbies: string
  createTime?: string
  updateTime?: string
}
6.5.2 配置方式发起请求
  • 发起get请求
axios<string, AxiosResponse<string>, null>({
  url: 'http://10.0.2.2:8080/student/get',
  method: "get",
  params: {
    id: 1
  }
}).then((res: AxiosResponse<string>) => {
  this.result = JSON.stringify(res.data)
})
  • 发起post请求
axios<string, AxiosResponse<string>, Student>({
  url: 'http://10.0.2.2:8080/student/add',
  method: "post",
  data:{
      name: 'HarmonyOS Next',
      chineseScore: 99,
      mathScore: 99,
      englishScore: 99,
      birthdate: '1991-10-10',
      phoneNumber: '10100659988',
      hobbies: '运动,唱歌,阅读'
  }
}).then((res: AxiosResponse<string>) => {
  this.result = JSON.stringify(res.data)
})
6.5.3 别名方式发起请求
  • 发送一个get请求
axios.get<string, AxiosResponse<string>, number>('http://10.0.2.2:8080/student/get', {
  params: {
    id: 3
  }
}).then((res: AxiosResponse<string>) => {
  console.info('result:' + JSON.stringify(res.data));
}).catch((error:AxiosError) => {
  console.info(JSON.stringify(error))
})
  • 发送一个post请求
axios.post<string, AxiosResponse<string>, Student>("http://10.0.2.2:8080/student/add",{
  name:'dd',
  chineseScore:80,
  mathScore:99,
  englishScore:100,
  birthdate:'2020-10-10',
  phoneNumber:'10100659988',
  hobbies:'运动,唱歌,阅读'
}).then((res: AxiosResponse<string>) => {
  console.info('result:' + JSON.stringify(res.data));
}).catch((error:AxiosError) => {
  console.info(JSON.stringify(error))
})
  • 发送put请求
axios.put<string, AxiosResponse<string>, Student>("http://10.0.2.2:8080/student/update/condition", {
  id: 6,
  name: 'HarmonyOS',
  chineseScore: 100,
  mathScore: 100,
  englishScore: 100,
  phoneNumber: '13100659988',
  birthdate: '1991-10-10',
  hobbies: '吃饭,睡觉,打游戏'
}).then((res: AxiosResponse<string>) => {
  console.info('result:' + JSON.stringify(res.data));
}).catch((error: AxiosError) => {
  console.info('error:' + JSON.stringify(error))
})
  • 发送delete请求
axios.delete<string, AxiosResponse<string>, number[]>("http://10.0.2.2:8080/student/delete", {
  params: {
    ids: '1,2,3'
  }
}).then((res: AxiosResponse<string>) => {
  console.info('result:' + JSON.stringify(res.data));
}).catch((error: AxiosError) => {
  console.info('error:' + JSON.stringify(error))
})

6.6 上传文件

  • 上传图片:将/resources/rawfile/a.png图片上传到服务器
//1.获取文件呢绒
let byteArray = getContext(this).resourceManager.getRawFileContentSync('a.png')
//2.创建表单数据
let formData = new FormData()
//3.发送请求
formData.append("file", byteArray.buffer,{filename:'a.png'})
axios.post<string, AxiosResponse<string>, FormData>('http://10.0.2.2:8080/common/upload', formData, {
  headers: { 'Content-Type': 'multipart/form-data' },
  context: getContext(this),
  onUploadProgress: (progressEvent: AxiosProgressEvent): void => {
    console.info(progressEvent && progressEvent.loaded && progressEvent.total ?
      Math.ceil(progressEvent.loaded / progressEvent.total * 100) + '%' : '0%');
  },
}).then((res: AxiosResponse) => {
  console.info("result" + JSON.stringify(res.data));
}).catch((error: AxiosError) => {
  console.error("error:" + JSON.stringify(error));
})
  • 上传文件
let formData = new FormData()
let cacheDir = getContext(this).cacheDir
try {
  // 写入
  let path = cacheDir + '/hello.txt';
  let file = fs.openSync(path, fs.OpenMode.CREATE | fs.OpenMode.READ_WRITE)
  fs.writeSync(file.fd, "hello, world"); // 以同步方法将数据写入文件
  fs.fsyncSync(file.fd); // 以同步方法同步文件数据。
  fs.closeSync(file.fd);

  // 读取
  let file2 = fs.openSync(path, 0o2);
  let stat = fs.lstatSync(path);
  let buf2 = new ArrayBuffer(stat.size);
  fs.readSync(file2.fd, buf2); // 以同步方法从流文件读取数据。
  fs.fsyncSync(file2.fd);
  fs.closeSync(file2.fd);

  formData.append('file', buf2);
  // formData.append('file', buf2, { filename: 'text.txt', type: 'text/plain'}); 设置多部分表单数据的数据名称和数据类型类型
} catch (err) {
  console.info('err:' + JSON.stringify(err));
}
// 发送请求
axios.post<string, AxiosResponse<string>, FormData>('http://10.0.2.2:8080/common/upload', formData, {
  headers: { 'Content-Type': 'multipart/form-data' },
  context: getContext(this),
  onUploadProgress: (progressEvent: AxiosProgressEvent): void => {
    console.info(progressEvent && progressEvent.loaded && progressEvent.total ? Math.ceil(progressEvent.loaded / progressEvent.total * 100) + '%' : '0%');
  },
}).then((res: AxiosResponse) => {
  console.info("result" + JSON.stringify(res.data));
}).catch((error: AxiosError) => {
  console.error("error:" + JSON.stringify(error));
})