HarmonyOS 5 极致动效实验室: Canvas 高阶动画的实现

大家好,我是不想掉发的鸿蒙开发工程师城中的雾

前几期我们玩转了各种标准组件的动画。但在实际开发中,总有一些需求让设计师天马行空,让开发者头秃:"这个波浪起伏的效果怎么做?"、"这个像琴弦一样能拨动的线条怎么做?"、"那种黑客帝国的代码雨怎么做?"

这时候,标准的 ColumnRow 已经无能为力了。我们需要使用到高阶组件------Canvas(画布)

在 HarmonyOS 中,Canvas 组件提供了高性能的 2D 绘制能力。在这里,UI 不再是堆积木,而是用代码(数学公式)一笔一画"算"出来的。本期文章,带大家重拾三角函数和贝塞尔曲线,手绘出 "液态波浪""物理琴弦""代码雨" 等非常规的动效。

1. 为什么要用 Canvas?

标准的声明式 UI(如 ArkUI 的组件)本质上是盒子模型 。虽然你可以旋转、缩放它们,但你很难改变它们的形状结构

Canvas 的优势在于:

  • 像素级控制:你可以精确控制屏幕上的每一个点。
  • 形态自由:波浪、粒子、不规则图形,想画什么画什么。
  • 数学计算 :利用 Math.sinBezier Curve 等数学工具生成自然界的动态。

2. 核心原理:绘制循环

与声明式 UI 的"状态驱动"不同,Canvas 动画通常是 "逐帧重绘" 的。

  1. 清空画布ctx.clearRect(...) (或者用半透明矩形覆盖制造拖尾)。
  2. 计算下一帧数据:比如波浪的相位偏移、粒子的新坐标。
  3. 绘制图形ctx.beginPath(), ctx.moveTo(), ctx.fill()...
  4. 请求下一帧 :形成循环(通常使用 setIntervalrequestAnimationFrame)。

3. 实战一:液态波浪电池

这是一个经典的充电动画:圆球内部有水波在晃动,且水位随电量变化。

核心算法:正弦波

波浪的本质就是正弦曲线 y = A * sin(ωx + φ) + k

  • A (振幅):波浪有多高。
  • φ (相位):控制波浪的移动(动画的关键)。
  • k (偏距):控制水位的高度。

我们只需要在每一帧改变 φ (相位),波浪就会流动起来。

复制代码
// 每一帧的绘制逻辑
ctx.beginPath();
ctx.moveTo(0, height); // 左下角起点

// 从左到右画出正弦线
for (let x = 0; x <= width; x += 5) {
  // y = A * sin(B * x + C) + D
  const y = amplitude * Math.sin(frequency * x + phase) + waterLevel;
  ctx.lineTo(x, y);
}
// 封闭路径(形成水体)
ctx.lineTo(width, height);
ctx.lineTo(0, height);
ctx.fillStyle = '#007DFF';
ctx.fill();

4. 实战二:指尖琴弦

标准的动画库很难实现"软体"效果。比如一根绳子,你拉它一下,它会弯曲,松手后会像琴弦一样阻尼震荡

这需要结合 物理模型贝塞尔曲线

核心思路

  1. 绘制 :使用二次贝塞尔曲线 quadraticCurveTo(controlX, controlY, endX, endY)。其中 (controlX, controlY) 就是我们手指拉扯的控制点。

  2. 交互:手指拖动时,更新控制点坐标。

  3. 物理:松手后,利用弹簧公式(胡克定律)计算控制点的回弹运动。

    // 物理计算循环
    if (!isDragging) {
    const force = (targetY - controlY) * stiffness; // 弹性力
    velocityY += force;
    velocityY *= damping; // 阻尼衰减
    controlY += velocityY;
    }

    // 绘制曲线
    ctx.beginPath();
    ctx.moveTo(0, stringHeight); // 左端点
    // 控制点决定了绳子的弯曲程度
    ctx.quadraticCurveTo(controlX, controlY, canvasWidth, stringHeight);
    ctx.stroke();

5. 实战三:交互式水波纹

点击屏幕,产生扩散的水波纹。这涉及到 Canvas 的状态管理。我们需要维护一个"波纹数组",每一帧更新它们的半径和透明度,并剔除已经消失的波纹。

复制代码
// 渲染循环
ripples.forEach((r, index) => {
  r.radius += 5;      // 扩散
  r.opacity -= 0.02;  // 消失
  
  if (r.opacity <= 0) {
    ripples.splice(index, 1); // 移除死掉的波纹
  } else {
    // 绘制圆环
    ctx.beginPath();
    ctx.arc(r.x, r.y, r.radius, 0, Math.PI * 2);
    ctx.strokeStyle = `rgba(0, 125, 255, ${r.opacity})`;
    ctx.stroke();
  }
});

6. 实战四:黑客帝国代码雨

如何实现那种带有长长拖尾的绿色代码雨?

关键技巧:拖尾特效 (Trail Effect)

不要使用 clearRect 完全清空画布。相反,每一帧都画一个带透明度的黑色矩形覆盖全屏。

  • 上一帧的文字被覆盖了一层 5% 的黑,变暗了。

  • 上上帧的文字被覆盖了两层 5% 的黑,更暗了。

    这就自然形成了"渐隐拖尾"的效果。

    // 1. 制造拖尾 (关键!)
    ctx.fillStyle = 'rgba(0, 0, 0, 0.05)'; // 5% 透明度的黑
    ctx.fillRect(0, 0, width, height);

    // 2. 绘制新文字
    ctx.fillStyle = '#0F0'; // 亮绿色
    ctx.font = '16px monospace';
    drops.forEach((y, i) => {
    const text = String.fromCharCode(0x30A0 + Math.random() * 96);
    ctx.fillText(text, i * fontSize, y * fontSize);

    复制代码
    // 随机重置,造成参差不齐的下落感
    if (y * fontSize > height && Math.random() > 0.975) {
      drops[i] = 0;
    }
    drops[i]++; // 下落一行

    });

总结

Canvas 是动效开发的深水区。它虽然难(需要数学基础),但它能实现更多非常规的动画。

  1. 波浪 :用三角函数 (Math.sin)。
  2. 形变 :用贝塞尔曲线 (quadraticCurveTo)。
  3. 粒子:用数组管理状态。
  4. 拖尾:用半透明遮罩代替清屏。

下一期,我们将使用 HarmonyOS 的 粒子动画 (Particle) 实现满屏烟花和点赞气泡,达到视觉上的盛宴。

充电时间

如果您想系统深入地学习 HarmonyOS 开发或想考取HarmonyOS认证证书,欢迎加我的华为开发者学堂:

🔗 HarmonyOS第一课:官方认证培训

🔗 完整代码仓库

相关推荐
俩毛豆15 小时前
【鸿蒙生态共建】意图框架的使用-通过小艺调起京东发起搜索《精通HarmonyOS NEXT :鸿蒙App开发入门与项目化实战》读者福利
华为·harmonyos·小艺
Devil枫18 小时前
HarmonyOS 应用草稿箱功能设计方案(安全可靠+轻量化存储)
华为·harmonyos
C雨后彩虹1 天前
二维伞的雨滴效应
java·数据结构·算法·华为·面试
数智顾问1 天前
(111页PPT)华为业务变革框架及战略级项目管理(附下载方式)
大数据·运维·华为
芒鸽1 天前
windows上使用Lycium 交叉编译移植鸿蒙三方库指南
windows·华为·harmonyos
FrameNotWork1 天前
HarmonyOS 广告 SDK 封装实战:从原生 Ads Kit 到可复用广告组件
华为·harmonyos
木斯佳1 天前
[鸿蒙2025领航者闯关] 把养老院装进口袋:如何利用鸿蒙6新特性探索智慧医养场景
华为·harmonyos
wangxiaowu19862 天前
HarmonyOS NEXT和通用JSBridge
华为·harmonyos
cz追天之路2 天前
华为机考 ------ 识别有效的IP地址和掩码并进行分类统计
javascript·华为·typescript·node.js·ecmascript·less·css3
航Hang*2 天前
第五章:网络系统建设与运维(中级)——生成树协议
运维·服务器·网络·笔记·华为·ensp