首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >ArKTS: Canvas Typing effect

ArKTS: Canvas Typing effect

作者头像
geovindu
发布2026-06-18 17:06:03
发布2026-06-18 17:06:03
20
举报
代码语言:javascript
复制
/**
 # 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()
    }
  }
}

代码语言:javascript
复制
/**
 # 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)
 
  }
}
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2026-06-17,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档