ArKTS: Canvas Typing effect

 

/**
 # encoding: utf-8
 # 版权所有  2025 ©涂聚文有限公司™ ®
 # 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
 # 描述: Typing effect
 # Author    : geovindu,Geovin Du 涂聚文.
 # IDE       : DevEco Studio 5.1.1  HarmonyOS ArKTS
 # os        : windows 10
 # database  : mysql 9.0 sql server 2019, postgreSQL 17.0  Oracle 21c Neo4j
 # Datetime  : 2025/8/17 10:55
 # User      :  geovindu
 # Product   : DevEco Studio
 # Project   : sqliteAppHelper
 # File      : CanvasRenderNode.ets
 **/
import { NodeController, FrameNode, RenderNode, DrawContext } from '@kit.ArkUI'
import { text } from '@kit.ArkGraphics2D'


/**
 * 创建一个CanvasRenderNode类,并实现打字机效果
 */
export class CanvasRenderNode extends RenderNode {
  // 完整文本内容
  private fullText: string ="《水调歌头 · 明月几时有》\n\n" +

    "作者:宋 · 苏轼\n\n  明月几时有?把酒问青天。\n\n" +

    "不知天上宫阙,今夕是何年。\n\n" +

    "我欲乘风归去,又恐琼楼玉宇,\n\n" +

    "高处不胜寒。\n\n" +

    "起舞弄清影,何似在人间?\n\n" +

    "转朱阁,低绮户,照无眠。\n\n" +

    "不应有恨,何事长向别时圆?\n\n" +

    "人有悲欢离合,月有阴晴圆缺,\n\n" +
    "此事古难全,\n\n" +
    "但愿人长久,千里共婵娟。";
  // 当前显示的字符长度
  private currentLength: number = 0;

  // 打字速度(毫秒)
  private typeSpeed: number = 100;

  // 定时器ID
  private timerId: number | null = null;

  constructor() {
    super();
    this.startTyping();
  }

  // 开始打字效果
  private startTyping() {
    // 清除可能存在的定时器
    if (this.timerId) {
      clearInterval(this.timerId);
    }

    // 重置显示长度
    this.currentLength = 0;

    // 设置定时器,逐字显示
    this.timerId = setInterval(() => {
      this.currentLength++;
      // 当显示完所有文字后清除定时器
      if (this.currentLength >= this.fullText.length) {
        this.currentLength = this.fullText.length;
        if (this.timerId) {
          clearInterval(this.timerId);
          this.timerId = null;
        }
      }
      // 触发重绘
      this.invalidate();
    }, this.typeSpeed);
  }

  async draw(context: DrawContext) {
    let canvas = context.canvas;

    let fontCollection = text.FontCollection.getGlobalInstance();
    // 注册自定义字体
    fontCollection.loadFontSync('myFamilyName', 'file:///system/fonts/NotoSansMalayalamUI-SemiBold.ttf')
    // 方式二:确保已经将自定义字体myFontFile.ttf文件放在本应用工程的entry/src/main/resources/rawfile目录
    fontCollection.loadFontSync('maozidong',$rawfile('maozedong.ttf'))

    // 使用自定义字体
    let myFontFamily: Array<string> = ["maozidong"];
    let myTextStyle: text.TextStyle = {
      color: {
        alpha: 255,
        red: 255,
        green: 0,
        blue: 0
      },
      fontSize: 50,
      fontFamilies: myFontFamily
    };

    let myParagraphStyle: text.ParagraphStyle = {
      textStyle: myTextStyle,
      align: text.TextAlign.LEFT,
      maxLines: 23, // 设置最大行数
      wordBreak: text.WordBreak.BREAK_WORD
    };

    // 只显示到当前长度的文本
    let displayText = this.fullText.substring(0, this.currentLength);

    let paragraphBuilder = new text.ParagraphBuilder(myParagraphStyle, fontCollection);
    paragraphBuilder.pushStyle(myTextStyle);
    paragraphBuilder.addText(displayText); // 使用当前应显示的文本
    let paragraph = paragraphBuilder.build();
    paragraph.layoutSync(1250);
    paragraph.paint(canvas, 10, 0);
  }
}



/**
 # encoding: utf-8
 # 版权所有  2025 ©涂聚文有限公司™ ®
 # 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
 # 描述:
 # Author    : geovindu,Geovin Du 涂聚文.
 # IDE       : DevEco Studio 5.1.1  HarmonyOS ArKTS
 # os        : windows 10
 # database  : mysql 9.0 sql server 2019, postgreSQL 17.0  Oracle 21c Neo4j
 # Datetime  : 2025/8/17 10:57
 # User      :  geovindu
 # Product   : DevEco Studio
 # Project   : sqliteAppHelper
 # File      : CanvasNodeContainer.ets
 **/

import { NodeController, FrameNode, RenderNode, DrawContext } from '@kit.ArkUI'
import { UIContext } from '@kit.ArkUI'


/**
 * CanvasNodeContainer类,用于管理节点
 */
export class CanvasNodeController extends NodeController {
  private rootNode: FrameNode | null = null;

  makeNode(uiContext: UIContext): FrameNode {
    this.rootNode = new FrameNode(uiContext)
    if (this.rootNode == null) {
      return this.rootNode
    }
    const renderNode = this.rootNode.getRenderNode()
    if (renderNode != null) {
      renderNode.frame = {
        x: 0,
        y: 0,
        width: 10,
        height: 500
      }
      renderNode.pivot = { x: 50, y: 50 }
    }
    return this.rootNode
  }

  addNode(node: RenderNode): void {
    if (this.rootNode == null) {
      return
    }
    const renderNode = this.rootNode.getRenderNode()
    if (renderNode != null) {
      renderNode.appendChild(node)
    }
  }

  clearNodes(): void {
    if (this.rootNode == null) {
      return
    }
    const renderNode = this.rootNode.getRenderNode()
    if (renderNode != null) {
      renderNode.clearChildren()
    }
  }
}

  

/**
 # encoding: utf-8
 # 版权所有  2025 ©涂聚文有限公司™ ®
 # 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
 # 描述: 自定义字体页面  https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/complex-text-arkts
 # Author    : geovindu,Geovin Du 涂聚文.
 # IDE       : DevEco Studio 5.1.1  HarmonyOS ArKTS
 # os        : windows 10
 # database  : mysql 9.0 sql server 2019, postgreSQL 17.0  Oracle 21c Neo4j
 # Datetime  : 2025/8/17 11:02
 # User      :  geovindu
 # Product   : DevEco Studio
 # Project   : sqliteAppHelper
 # File      : CanvasTextPage.ets
 **/

import { CanvasNodeController } from '../utils/CanvasNodeController'
import { CanvasRenderNode } from '../utils/CanvasRenderNode'

// 创建一个CanvasRenderNode对象
const textNode = new CanvasRenderNode()
// 定义节点的像素格式
textNode.frame = {
  x: 0,
  y: 0,
  width: 400,
  height: 600
}
textNode.pivot = { x: 0.2, y: 0.8 }
textNode.scale = { x: 1, y: 1 }



let myNodeController: CanvasNodeController = new CanvasNodeController()

async function performTask() {
  myNodeController.clearNodes()
  myNodeController.addNode(textNode)
}

@Entry
@Component
struct CanvasTextPage {
  @State src: Resource = $r('app.media.startIcon')

  build() {
    Column({space: 10}) {
      Row() {
        NodeContainer(myNodeController)
          .height('100%')
          .width('100%')
        Image(this.src)
          .width('0%').height('0%')
          .onComplete(
            () => {
              performTask();
            })
      }
      .width('100%')
      .height('100%')
      .justifyContent(FlexAlign.Center)
      .margin({ top: 0, bottom: 0, left: 15, right: 0})
      .padding(5)
    }
    .width('100%')
    .height('100%')
    .alignItems(HorizontalAlign.Center)
    .justifyContent(FlexAlign.Center)

  }
}

  

a2e1c66dee7645d865dc61c636a8ccc9

 

 

https://developer.huawei.com/consumer/cn/market/prod-list?origin=template&ha_source=yzc&ha_sourceId=89000071

@tencent/wechat_open_sdk

ohpm i @tencent/wechat_open_sdk

  

开发者您好,可能有些Kit更新替换了,该方案可参考的实现步骤:

1.使用Account Kit创建儿童账号,绑定家庭组,实现家人共享功能,且该Kit有未成年人模式,具体可参考文档:https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/account-kit-guide

2.使用Screen Time Guard Kit设置应用限额和停用时间,锁定屏幕和应用。

① GuardService(屏幕时间守护服务)API:https://developer.huawei.com/consumer/cn/doc/harmonyos-references/screentimeguard-guardservice

② 可参考demo:https://developer.huawei.com/consumer/cn/codelabsPortal/carddetails/tutorials_ScreenTimeGuardKit-AppsRestriction

3.利用Service Ability和持续通知保持APP后台运行,防止被系统终止。

① 后台服务保活:https://developer.huawei.com/consumer/cn/doc/harmonyos-references/js-apis-resourceschedule-backgroundtaskmanager

② 持续状态通知:https://developer.huawei.com/consumer/cn/doc/harmonyos-references/js-apis-notificationmanager

4.通过分布式能力实现远程控制,如使用Distributed Data Management Kit在控制端和被控端同步指令。https://developer.huawei.com/consumer/cn/doc/harmonyos-references/js-apis-distributeddevicemanager

5.处理必要的权限,如网页1提到的MANAGE_SCREEN_TIME_GUARD权限,以及后台运行所需的权限。

posted @ 2025-08-17 11:13  ®Geovin Du Dream Park™  阅读(6)  评论(0)    收藏  举报