0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

玩嗨OpenHarmony:基于OpenHarmony的ArkUI翻页时钟

共熵服务中心 来源:未知 2022-12-05 20:15 次阅读
原文引自:51CTO 开源基础软件社区 #夏日挑战赛# OpenHarmony - 《ArkUI(TS)开发翻页时钟

63824d32-7496-11ed-8abf-dac502259ad0.png

1. 项目背景

翻页时钟(Flip Clock)是一种有趣的机电数字计时设备,用电脑动画的方式实现翻页时钟,也是一种特别的复古UI交互体验。

本项目岂在通过OpenHarmony的ArkUI框架,用TS扩展的声明式开发范式eTS,来实现翻页时钟的体验。

本项目的开发环境如下:

  • 工具版本:DevEco Studio 3.0 Beta4

  • SDK版本:3.1.6.6(API Version 8 Release)

具体实现的效果是这样的:

63a47eca-7496-11ed-8abf-dac502259ad0.gif

本项目的主要知识点如下:

  • UI状态:@Prop、@Link、@Watch

  • 形状裁剪属性:clip

  • 显式动画:animateTo

2. eTS开发范式基于eTS的声明式开发范式的方舟开发框架是一套开发极简、高性能、跨设备应用的UI开发框架,支持开发者高效的构建跨设备应用UI界面。

使用基于eTS的声明式开发范式的方舟开发框架,采用更接近自然语义的编程方式,让开发者可以直观地描述UI界面,不必关心框架如何实现UI绘制和渲染,实现极简高效开发。开发框架不仅从组件、动效和状态管理三个维度来提供UI能力,还提供了系统能力接口,实现系统能力的极简调用。

63e5af44-7496-11ed-8abf-dac502259ad0.png

关于语法和概念详细请直接看官网官方文档地址:

https://docs.openharmony.cn/pages/v3.1/zh-cn/application-dev/ui/ui-ts-overview.md/

3. 实现思路时钟翻页效果,用到四个Text组件,使用堆叠容器Stack。底层:用到两个裁剪过后的Text上下显示;顶层:也是用两个裁剪后的Text做动画效果,进行X轴角度旋转。

3.1 裁剪Text

裁剪前:

63fc5e4c-7496-11ed-8abf-dac502259ad0.png

裁剪后:

64170030-7496-11ed-8abf-dac502259ad0.png

使用形状裁剪属性clip

裁剪Text上半部:从坐标(0,0)往下裁剪,clip(new Rect({ width: this.width, height: this.height / 2 }))

裁剪Text下半部:从坐标(0,height / 2)往下裁剪,clip(new Path().commands(this.bottomPath))

@Entry
@Component
struct Test {
  private width = 90
  private height = 110
  private fontSize = 70
  private defaultBgColor = '#ffe6e6e6'
  private borderRadius = 10


  // 下半部裁剪路径
  private bottomPath = `M0 ${vp2px(this.height / 2)}
  L${vp2px(this.width)} ${vp2px(this.height / 2)}
  L${vp2px(this.width)} ${vp2px(this.height)}
  L0 ${vp2px(this.height)} Z`


  build() {
    Row() {


      Text('24')
        .width(this.width)
        .height(this.height)
        .fontColor(Color.Black)
        .fontSize(this.fontSize)
        .textAlign(TextAlign.Center)
        .borderRadius(this.borderRadius)
        .backgroundColor(this.defaultBgColor)
        .clip(new Rect({ width: this.width, height: this.height / 2 }))


      Text('25')
        .margin({left:20})
        .width(this.width)
        .height(this.height)
        .fontColor(Color.Black)
        .fontSize(this.fontSize)
        .textAlign(TextAlign.Center)
        .borderRadius(this.borderRadius)
        .backgroundColor(this.defaultBgColor)
        .clip(new Path().commands(this.bottomPath))


    }.width('100%')
    .height('100%')
    .justifyContent(FlexAlign.Center)
  }
}
3.2放入堆叠容器

四个裁剪后的Text放入到堆叠容器中(代码片段):

    Stack() {
      // 底层文字上部
      Text(this.newValue)
        ......
        .clip(new Rect({ width: this.width, height: this.height / 2 }))


      // 底层文字下部
      Text(this.oldValue)
        ......
        .clip(new Path().commands(this.bottomPath))


      // 顶层文字上部动画
      Text(this.oldValue)
        ......
        .clip(new Rect({ width: this.width, height: this.height / 2 }))
        .rotate({ x: 1, centerY: '50%', angle: this.angleTop })


      // 顶层文字下部动画
      Text(this.newValue)
        ......
        .margin({ top: 3 })
        .clip(new Path().commands(this.bottomPath))
        .rotate({ x: 1, centerY: '50%', angle: this.angleBottom })
    }
3.3使用显式动画

先顶层上部的动画,上部旋转角度从0到90停止,接下来执行顶层下部的动画,下部旋转角度从-90到0停止,停止完后重置初始状态,上部旋转角度 = 0、下部旋转角度 = -90(代码片段)

  /**
   * 启动顶层文字上部动画
   */
  startTopAnimate() {
    animateTo({
      duration: 400,
      onFinish: () => {
        this.startBottomAnimate()
        this.animateBgColor = '#ffededed'
      }
    }, () => {
      this.angleTop = 90
      this.animateBgColor = '#ffc5c5c5'
    })
  }


  /**
   * 启动顶层文字下部动画
   */
  startBottomAnimate() {
    animateTo({
      duration: 400,
      onFinish: () => {
        this.angleTop = 0
        this.angleBottom = -90
        this.animateBgColor = this.defaultBgColor
        this.oldValue = this.newValue
      }
    }, () => {
      this.angleBottom = 0
      this.animateBgColor = this.defaultBgColor
    })
  }
3.4组件封装

翻页逻辑封装成组件,提供给外部调用,根据外部传入的双向数据绑定:newValue,监听数据变化,有变化则启动翻页动画(代码片段):

@Component
export struct FlipPage {
  // 顶层上部动画角度
  @State angleTop: number = 0
  // 顶层下部动画角度
  @State angleBottom: number = -90
  // 旧值
  @Prop oldValue: string
  // 新值,加入监听
  @Link @Watch('valueChange') newValue: string


  /**
   * 监听新值变化
   */
  valueChange() {
    if (this.oldValue === this.newValue) return
    this.startTopAnimate()
  }


  build() {
    Stack() {
      // 底层文字上部
      Text(this.newValue)
        ......
        .clip(new Rect({ width: this.width, height: this.height / 2 }))


      // 底层文字下部
      Text(this.oldValue)
        ......
        .clip(new Path().commands(this.bottomPath))


      // 顶层文字上部动画
      Text(this.oldValue)
        ......
        .clip(new Rect({ width: this.width, height: this.height / 2 }))
        .rotate({ x: 1, centerY: '50%', angle: this.angleTop })


      // 顶层文字下部动画
      Text(this.newValue)
        ......
        .margin({ top: 3 })
        .clip(new Path().commands(this.bottomPath))
        .rotate({ x: 1, centerY: '50%', angle: this.angleBottom })
    }
  }
  /**
  * 启动顶层文字上部动画
  */
  startTopAnimate() {
    ......
  }
3.5外部调用

界面加载成功后,开启循环定时器setInterval、间隔1秒更新时间。更改newValue的值,翻页组件内部进行动画翻页。

import { FlipPage } from '../componet/FlipPage'


@Entry
@Component
struct Index {
  // 小时-旧值
  @State oldHours: string = ''
  // 小时-新值
  @State newHours: string = ''
  // 分钟-旧值
  @State oldMinutes: string = ''
  // 分钟-新值
  @State newMinutes: string = ''
  // 秒数-旧值
  @State oldSeconds: string = ''
  // 秒数-新值
  @State newSeconds: string = ''


  @Builder Colon() {
    Column() {
      Circle().width(8).height(8).fill(Color.Black)
      Circle().width(8).height(8).fill(Color.Black).margin({ top: 10 })
    }.padding(10)
  }


  build() {
    Row() {
      // 翻页组件-显示小时
      FlipPage({ oldValue: this.oldHours, newValue: $newHours })
      // 冒号
      this.Colon()
      // 翻页组件-显示分钟
      FlipPage({ oldValue: this.oldMinutes, newValue: $newMinutes })
      // 冒号
      this.Colon()
      // 翻页组件-显示秒数
      FlipPage({ oldValue: this.oldSeconds, newValue: $newSeconds })
    }
    .justifyContent(FlexAlign.Center)
    .width('100%')
    .height('100%')
    .onAppear(() => {
      // 开启定时器
      this.initDate()
      setInterval(() => {
        this.updateDate()
      }, 1000)
    })
  }


  /**
   * 初始化时间
   */
  initDate() {
    let date = new Date()
    // 设置小时
    this.oldHours = this.format(date.getHours())
    // 设置分钟
    this.oldMinutes = this.format(date.getMinutes())
    // 设置秒数
    this.oldSeconds = this.format(date.getSeconds())
    // 设置新的秒数
    this.newSeconds = date.getSeconds() + 1 === 60 ? '00' : this.format(date.getSeconds() + 1)
  }


  /**
   * 更新时间
   */
  updateDate() {
    let date = new Date()
    console.log(`${date.getHours()}${date.getMinutes()}${date.getSeconds()}秒`)
    // 当新值改变,才有动画
    if (date.getSeconds() === 59) {
      this.newSeconds = '00'
      this.newMinutes = date.getMinutes() + 1 === 60 ? '00' : this.format(date.getMinutes() + 1)
      if (date.getMinutes() === 59) {
        this.newHours = date.getHours() + 1 === 24 ? '00' : this.format(date.getHours() + 1)
      }
    } else {
      this.newSeconds = this.format(date.getSeconds() + 1)
    }
  }


  /**
   * 不足十位前面补零
   */
  format(param) {
    let value = '' + param
    if (param < 10) {
      value = '0' + param
    }
    return value
  }
}
4.总结根据上面的实现思路和5个步骤流程,相信你也掌握了翻页时钟原理,拆分成一步一步还是很简单的,最主要还是对API的熟悉和声明式语法的掌握。HarmonyOS的API是根据OpenHarmony去更新的,两者区别语法都一样,只是OpenHarmony的API比较新,功能比较完善和成熟的,所以本项目直接使用OpenHarmony SDK开发。645d457c-7496-11ed-8abf-dac502259ad0.gif 本文完写在最后我们最近正带着大家玩嗨OpenHarmony。如果你有好玩的东东,欢迎投稿,让我们一起嗨起来!有点子,有想法,有Demo,立刻联系我们:合作邮箱:zzliang@atomsource.org
646c344c-7496-11ed-8abf-dac502259ad0.gif

6497e1fa-7496-11ed-8abf-dac502259ad0.png

64cde110-7496-11ed-8abf-dac502259ad0.png64de3970-7496-11ed-8abf-dac502259ad0.png6501ab08-7496-11ed-8abf-dac502259ad0.png

650cc628-7496-11ed-8abf-dac502259ad0.png

652c6190-7496-11ed-8abf-dac502259ad0.png

654d7074-7496-11ed-8abf-dac502259ad0.png

65721000-7496-11ed-8abf-dac502259ad0.png

65a1d57e-7496-11ed-8abf-dac502259ad0.png

65ca526a-7496-11ed-8abf-dac502259ad0.png

663c7336-7496-11ed-8abf-dac502259ad0.png

66afe622-7496-11ed-8abf-dac502259ad0.png

66c4d104-7496-11ed-8abf-dac502259ad0.png

66d3bbba-7496-11ed-8abf-dac502259ad0.png

66fd970a-7496-11ed-8abf-dac502259ad0.png

671687ba-7496-11ed-8abf-dac502259ad0.png

672c55fe-7496-11ed-8abf-dac502259ad0.png

674d70ea-7496-11ed-8abf-dac502259ad0.png

676f6902-7496-11ed-8abf-dac502259ad0.png

6781e2b2-7496-11ed-8abf-dac502259ad0.png


原文标题:玩嗨OpenHarmony:基于OpenHarmony的ArkUI翻页时钟

文章出处:【微信公众号:开源技术服务中心】欢迎添加关注!文章转载请注明出处。


声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 开源技术
    +关注

    关注

    0

    文章

    389

    浏览量

    7928
  • OpenHarmony
    +关注

    关注

    25

    文章

    3713

    浏览量

    16251

原文标题:玩嗨OpenHarmony:基于OpenHarmony的ArkUI翻页时钟

文章出处:【微信号:开源技术服务中心,微信公众号:共熵服务中心】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    第三届OpenHarmony技术大会星光璀璨、致谢OpenHarmony社区贡献者

    10月12日,在上海举办的第三届OpenHarmony技术大会上,32家高校OpenHarmony技术俱乐部璀璨亮相,30家高校OpenHarmony开发者协会盛大启幕。还分别致谢了年度星光TSG
    的头像 发表于 10-21 14:10 212次阅读

    OpenHarmony年度技术俱乐部、个人及活动评选结果公示

    2024年度技术俱乐部评选活动已经圆满结束。在此,OpenHarmony项目群技术指导委员会(TSC)对所有参与者的积极参与和辛勤付出表示感谢。经过严格的评选和审核,现将名单予以公示: 评选
    的头像 发表于 10-05 08:07 235次阅读

    基于ArkTS语言的OpenHarmony APP应用开发:HelloOpenharmony

    1、程序简介该程序是基于OpenHarmony标准系统编写的UI应用类:HelloOpenHarmony。本案例是基于API9接口开发。本案例已在OpenHarmony凌蒙派-RK3568开发
    的头像 发表于 09-15 08:09 369次阅读
    基于ArkTS语言的<b class='flag-5'>OpenHarmony</b> APP应用开发:Hello<b class='flag-5'>Openharmony</b>

    基于ArkTS语言的OpenHarmony APP应用开发:HelloOpenharmony

    1、程序简介 该程序是基于OpenHarmony标准系统编写的UI应用类:HelloOpenHarmony。 本案例是基于API 9接口开发。 本案例已在OpenHarmony凌蒙派-RK3568
    发表于 09-14 12:47

    鸿蒙开发ArkUI-X基础知识:【ArkUI代码工程及构建介绍】

    ArkUI作为OpenHarmony的默认开发框架,在本项目(ArkUI-X)中需要做到一套代码同时支持多平台构建,所以会采取共仓开发的方式,部分仓直接指向OpenHarmony相关开
    的头像 发表于 05-25 16:45 2069次阅读
    鸿蒙开发<b class='flag-5'>ArkUI</b>-X基础知识:【<b class='flag-5'>ArkUI</b>代码工程及构建介绍】

    鸿蒙OpenHarmony【基于Hi3516DV300开发板(时钟应用开发)】

    如何快速搭建基于OpenHarmony标准系统(Hi3516DV300开发板)的应用开发环境,并基于一个时钟APP示例逐步展示应用的创建、开发、调试和安装等流程。
    的头像 发表于 05-08 15:27 1158次阅读
    鸿蒙<b class='flag-5'>OpenHarmony</b>【基于Hi3516DV300开发板(<b class='flag-5'>时钟</b>应用开发)】

    鸿蒙OpenHarmony【创建工程并获取源码】

    在通过DevEco Device Tool创建OpenHarmony工程时,可自动下载相应版本的OpenHarmony源码。
    的头像 发表于 04-19 21:40 366次阅读
    鸿蒙<b class='flag-5'>OpenHarmony</b>【创建工程并获取源码】

    OpenHarmony南向能力征集令

    1、适配过程中缺少哪些接口能力或者南向能力,需要OpenHarmony去补齐的?例如内核、编译、器件适配、单板适配等; 2、对标linux,需要OpenHarmony提供哪些能力?比如V4L2
    发表于 04-09 15:32

    OpenHarmony内核编程实战

    编程入门[Hello,OpenHarmony]在正式开始之前,对于刚接触OpenHarmony的伙伴们,面对大篇幅的源码可能无从下手,不知道怎么去编码写程序,下面用一个简单的例子带伙伴们入门。▍任务
    的头像 发表于 03-27 08:31 804次阅读
    <b class='flag-5'>OpenHarmony</b>内核编程实战

    鸿蒙开发学习:【OpenHarmony HAR】

    OpenHarmony js/ts三方库使用的是OpenHarmony静态共享包,即HAR(Harmony Archive),可以包含js/ts代码、c++库、资源和配置文件。通过HAR,可以实现
    的头像 发表于 03-18 16:27 743次阅读

    浅谈兼容 OpenHarmony 的 Flutter

    OpenHarmony SIG 组织在 Gitee 开源了兼容 OpenHarmony 的 Flutter。该组织主要用于孵化 OpenHarmony 相关的开源生态项目。     ▲ 仓库地址
    的头像 发表于 02-02 15:22 607次阅读
    浅谈兼容 <b class='flag-5'>OpenHarmony</b> 的 Flutter

    鸿蒙开发OpenHarmony组件复用案例

    和响应速度。 在OpenHarmony应用开发时,自定义组件被@Reusable装饰器修饰时表示该自定义组件可以复用。在父自定义组件下创建的可复用组件从组件树上移除后,会被加入父自定义组件的可复用节点
    发表于 01-15 17:37

    OpenHarmony社区运营报告(2023年12月)

    加,线上直播观看人次累计超过 1.6 万。 四、技术发展 OpenHarmony 4.1 Beta1 于 2023 年底发布,版本不断优化系统能力,着重加强了 ArkUI 组件、图形窗口、应用框架
    发表于 01-10 15:44

    厦门大学OpenHarmony技术俱乐部正式揭牌成立

    点击蓝字 ╳ 关注我们 开源项目 OpenHarmony 是每个人的 OpenHarmony 12月29日下午,由OpenAtom OpenHarmony(简称“OpenHarmony
    的头像 发表于 01-04 21:15 557次阅读
    厦门大学<b class='flag-5'>OpenHarmony</b>技术俱乐部正式揭牌成立

    OpenHarmony Meetup 2023南京站亮点抢先看

    点击蓝字 ╳ 关注我们 开源项目 OpenHarmony 是每个人的 OpenHarmony 原文标题:OpenHarmony Meetup 2023南京站亮点抢先看 文章出处:【微信公众号:OpenAtom
    的头像 发表于 12-25 21:10 579次阅读
    <b class='flag-5'>OpenHarmony</b> Meetup 2023南京站亮点抢先看