本文同步发表于我的微信公众号,微信搜索 程语新视界 即可关注,每个工作日都有文章更新
一、属性动画核心概念
1. 功能定位
- 作用:通过平滑过渡改变组件的样式属性(如宽高、透明度、位置等)。
- 与显式动画区别:
特性 属性动画 显式动画(animateTo) 控制粒度 精确到单个属性变化 整体组件变化 性能 更高(底层属性驱动) 依赖UI线程重绘 适用场景 复杂属性联动、精准控制 简单过渡效果
2. 动画属性支持
属性类型 | 示例 | 备注 |
---|---|---|
布局属性 | width, height, margin | 需启用动画过渡(animationMode) |
外观属性 | opacity, backgroundColor | 颜色需用RGB或字符串格式 |
变换属性 | scale, rotate, translate | 支持3D变换(API 12+) |
二、基础使用与常用API
1. 创建属性动画
import curves from '@ohos.curves';
import { Animator, AnimatorOptions } from '@ohos.animator';
// 定义动画参数
const options: AnimatorOptions = {
duration: 1000, // 动画时长(ms)
curve: curves.springMotion() // 弹性曲线(API 12+)
};
// 创建动画实例
const animator = new Animator(options);
// 绑定组件属性
animator.on('frame', (fraction: number) => {
this.angle = fraction * 360; // 0~1映射到0~360度
});
// 启动动画
animator.start();
关键API:
new Animator(options)
:创建动画控制器。on('frame', callback)
:逐帧回调,fraction
为0~1的进度值。start()/stop()/pause()
:控制动画生命周期。
2. 直接驱动组件属性
// 旋转动画示例
@State angle: number = 0;
Button('旋转按钮')
.rotate({ angle: this.angle })
.onClick(() => {
const animator = new Animator({ duration: 1000 });
animator.on('frame', (fraction) => {
this.angle = fraction * 180; // 0~180度旋转
});
animator.start();
})
三、高级功能详解
1. 多属性联动动画
// 同时改变宽高和透明度
@State scale: number = 1;
@State alpha: number = 1;
Animator.runAnimator({
duration: 800,
onFrame: (fraction) => {
this.scale = 1 + fraction * 0.5; // 放大1.5倍
this.alpha = 1 - fraction * 0.5; // 透明度减半
}
})
// 组件绑定
Image($r('app.media.logo'))
.scale({ x: this.scale, y: this.scale })
.opacity(this.alpha)
2. 路径动画(API 12+)
import { PathAnimator } from '@ohos.animator';
// 定义贝塞尔曲线路径
const path = new Path();
path.moveTo(0, 0);
path.bezierCurveTo(100, 50, 200, -50, 300, 0);
// 沿路径移动
const pathAnimator = new PathAnimator({
path: path,
duration: 2000
});
pathAnimator.on('frame', (point) => {
this.posX = point.x; // 更新X坐标
this.posY = point.y; // 更新Y坐标
});
pathAnimator.start();
3. 动画曲线与缓动函数
import curves from '@ohos.curves';
// 使用内置曲线
const options = {
curve: curves.cubicBezier(0.1, 0.8, 0.2, 1) // 自定义贝塞尔曲线
};
// 或使用预设曲线
const presetCurves = {
linear: curves.linear,
easeIn: curves.easeIn,
spring: curves.springMotion(0.5, 100) // 弹性动画(刚度、质量)
};
四、案例:下拉刷新动画
@Entry
@Component
struct RefreshExample {
@State rotateAngle: number = 0;
@State pullDistance: number = 0;
private refreshAnimator: Animator | null = null;
// 下拉时同步更新距离和旋转
handlePull(dy: number) {
this.pullDistance = Math.min(dy, 100);
this.rotateAngle = (dy / 100) * 360;
}
// 释放时执行弹性动画
handleRelease() {
this.refreshAnimator = new Animator({
duration: 1000,
curve: curves.springMotion()
});
this.refreshAnimator.on('frame', (fraction) => {
this.pullDistance = 100 * (1 - fraction); // 回弹到顶部
});
this.refreshAnimator.start();
}
build() {
Column() {
Image($r('app.media.arrow'))
.rotate({ angle: this.rotateAngle })
.margin({ top: this.pullDistance })
List() {
// 列表内容...
}
.onTouch((event) => {
if (event.type === TouchType.Move) {
this.handlePull(event.offsetY);
} else if (event.type === TouchType.Up) {
this.handleRelease();
}
})
}
}
}
五、调试与性能优化
1. 动画监控工具
// 打印动画帧率
animator.on('frame', (fraction) => {
console.log(`Frame: ${Date.now()}, Progress: ${fraction}`);
});
2. 性能优化建议
场景 | 优化方案 |
---|---|
复杂动画 | 使用Animator 替代animateTo |
多组件动画 | 合并属性更新减少渲染次数 |
页面跳转时 | 调用animator.stop() 释放资源 |
六、总结对比
功能 | API/方法 | 适用场景 |
---|---|---|
基础属性动画 | Animator + on('frame') | 单个属性精细控制 |
路径动画 | PathAnimator (API 12+) | 复杂运动轨迹 |
物理动画 | curves.springMotion() | 弹性、惯性效果 |