HarmonyOS 鸿蒙Next中如何实现Row组件及其子组件持续缩放效果?
HarmonyOS 鸿蒙Next中如何实现Row组件及其子组件持续缩放效果? 如何实现Row组件及其子组件持续缩放效果?
方案一:使用 animateTo 实现持续缩放
@Entry
@Component
struct RowScaleAnimation {
@State scaleValue: number = 1;
private isAnimating: boolean = false;
// 持续缩放动画
startContinuousScale() {
if (this.isAnimating) return;
this.isAnimating = true;
this.animateScale();
}
animateScale() {
animateTo({
duration: 1000,
curve: Curve.EaseInOut,
iterations: -1, // -1 表示无限循环
playMode: PlayMode.Alternate, // 往返播放
onFinish: () => {
// 动画结束回调(无限循环时不会触发)
}
}, () => {
this.scaleValue = this.scaleValue === 1 ? 1.2 : 1;
})
}
build() {
Column() {
Row() {
Text('Item 1')
.fontSize(20)
.margin(10)
Text('Item 2')
.fontSize(20)
.margin(10)
Text('Item 3')
.fontSize(20)
.margin(10)
}
.width('80%')
.height(100)
.backgroundColor(Color.Pink)
.justifyContent(FlexAlign.SpaceAround)
.scale({ x: this.scaleValue, y: this.scaleValue }) // 应用缩放
Button('开始持续缩放')
.onClick(() => {
this.startContinuousScale();
})
.margin({ top: 20 })
}
.width('100%')
.height('100%')
.justifyContent(FlexAlign.Center)
}
}
方案二:使用 animation 修饰符实现
@Entry
@Component
struct RowScaleAnimationV2 {
@State scaleValue: number = 1;
private timer: number = -1;
aboutToAppear() {
// 页面加载时自动开始动画
this.startAnimation();
}
aboutToDisappear() {
// 清理定时器
if (this.timer !== -1) {
clearInterval(this.timer);
}
}
startAnimation() {
this.timer = setInterval(() => {
// 在 1.0 和 1.2 之间切换
this.scaleValue = this.scaleValue === 1 ? 1.2 : 1;
}, 1000);
}
build() {
Column() {
Row() {
Text('Item 1')
.fontSize(20)
.margin(10)
.backgroundColor(Color.Orange)
.padding(10)
Text('Item 2')
.fontSize(20)
.margin(10)
.backgroundColor(Color.Yellow)
.padding(10)
Text('Item 3')
.fontSize(20)
.margin(10)
.backgroundColor(Color.Green)
.padding(10)
}
.width('80%')
.height(100)
.backgroundColor(Color.Pink)
.justifyContent(FlexAlign.SpaceAround)
.scale({ x: this.scaleValue, y: this.scaleValue })
.animation({
duration: 1000,
curve: Curve.EaseInOut,
iterations: -1, // 无限循环
playMode: PlayMode.Alternate // 往返播放
})
}
.width('100%')
.height('100%')
.justifyContent(FlexAlign.Center)
}
}
方案三:子组件独立缩放效果
@Entry
@Component
struct RowChildrenScaleAnimation {
@State scale1: number = 1;
@State scale2: number = 1;
@State scale3: number = 1;
aboutToAppear() {
// 三个子组件错开时间开始缩放
setTimeout(() => this.animateItem1(), 0);
setTimeout(() => this.animateItem2(), 300);
setTimeout(() => this.animateItem3(), 600);
}
animateItem1() {
animateTo({
duration: 1000,
curve: Curve.EaseInOut,
iterations: -1,
playMode: PlayMode.Alternate
}, () => {
this.scale1 = this.scale1 === 1 ? 1.3 : 1;
})
}
animateItem2() {
animateTo({
duration: 1000,
curve: Curve.EaseInOut,
iterations: -1,
playMode: PlayMode.Alternate
}, () => {
this.scale2 = this.scale2 === 1 ? 1.3 : 1;
})
}
animateItem3() {
animateTo({
duration: 1000,
curve: Curve.EaseInOut,
iterations: -1,
playMode: PlayMode.Alternate
}, () => {
this.scale3 = this.scale3 === 1 ? 1.3 : 1;
})
}
build() {
Column() {
Row() {
Text('Item 1')
.fontSize(20)
.backgroundColor(Color.Orange)
.padding(20)
.borderRadius(10)
.scale({ x: this.scale1, y: this.scale1 })
Text('Item 2')
.fontSize(20)
.backgroundColor(Color.Yellow)
.padding(20)
.borderRadius(10)
.scale({ x: this.scale2, y: this.scale2 })
.margin({ left: 10, right: 10 })
Text('Item 3')
.fontSize(20)
.backgroundColor(Color.Green)
.padding(20)
.borderRadius(10)
.scale({ x: this.scale3, y: this.scale3 })
}
.width('90%')
.justifyContent(FlexAlign.SpaceAround)
}
.width('100%')
.height('100%')
.justifyContent(FlexAlign.Center)
}
}
方案四:呼吸式缩放(更平滑)
@Entry
@Component
struct RowBreathingAnimation {
@State scaleValue: number = 1;
aboutToAppear() {
this.startBreathing();
}
startBreathing() {
// 使用 animateTo 实现平滑的呼吸效果
this.breatheIn();
}
breatheIn() {
animateTo({
duration: 1500,
curve: Curve.Smooth,
onFinish: () => {
this.breatheOut();
}
}, () => {
this.scaleValue = 1.15;
})
}
breatheOut() {
animateTo({
duration: 1500,
curve: Curve.Smooth,
onFinish: () => {
this.breatheIn(); // 循环
}
}, () => {
this.scaleValue = 1;
})
}
build() {
Column() {
Row() {
Image($r('app.media.icon'))
.width(50)
.height(50)
Text('呼吸式缩放')
.fontSize(24)
.margin({ left: 10 })
}
.width('80%')
.height(100)
.backgroundColor('#FFE6F0FF')
.borderRadius(20)
.justifyContent(FlexAlign.Center)
.scale({ x: this.scaleValue, y: this.scaleValue })
.shadow({
radius: 20,
color: '#40000000',
offsetX: 0,
offsetY: 5
})
}
.width('100%')
.height('100%')
.justifyContent(FlexAlign.Center)
.backgroundColor('#F5F5F5')
}
}
方案五:复杂波浪式缩放
@Entry
@Component
struct RowWaveScaleAnimation {
@State scales: number[] = [1, 1, 1, 1, 1];
private currentIndex: number = 0;
aboutToAppear() {
this.startWaveAnimation();
}
startWaveAnimation() {
setInterval(() => {
// 重置当前索引的缩放
let newScales = [...this.scales];
// 设置新的缩放值
for (let i = 0; i < newScales.length; i++) {
if (i === this.currentIndex) {
newScales[i] = 1.4;
} else {
newScales[i] = 1;
}
}
animateTo({
duration: 300,
curve: Curve.EaseInOut
}, () => {
this.scales = newScales;
})
// 移动到下一个
this.currentIndex = (this.currentIndex + 1) % this.scales.length;
}, 400);
}
build() {
Column() {
Row() {
ForEach([0, 1, 2, 3, 4], (index: number) => {
Text(`${index + 1}`)
.fontSize(24)
.fontWeight(FontWeight.Bold)
.width(50)
.height(50)
.textAlign(TextAlign.Center)
.backgroundColor(Color.Orange)
.borderRadius(25)
.scale({ x: this.scales[index], y: this.scales[index] })
.margin(5)
})
}
.width('100%')
.justifyContent(FlexAlign.Center)
Text('波浪式缩放效果')
.fontSize(16)
.margin({ top: 30 })
}
.width('100%')
.height('100%')
.justifyContent(FlexAlign.Center)
}
}
方案六:可控制的持续缩放
@Entry
@Component
struct ControllableRowScaleAnimation {
@State scaleValue: number = 1;
@State isAnimating: boolean = false;
private animationTimer: number = -1;
// 开始动画
startAnimation() {
if (this.isAnimating) return;
this.isAnimating = true;
this.animationTimer = setInterval(() => {
animateTo({
duration: 500,
curve: Curve.EaseInOut
}, () => {
this.scaleValue = this.scaleValue === 1 ? 1.2 : 1;
})
}, 500);
}
// 停止动画
stopAnimation() {
if (!this.isAnimating) return;
this.isAnimating = false;
if (this.animationTimer !== -1) {
clearInterval(this.animationTimer);
this.animationTimer = -1;
}
// 恢复到原始大小
animateTo({
duration: 300,
curve: Curve.EaseOut
}, () => {
this.scaleValue = 1;
})
}
aboutToDisappear() {
this.stopAnimation();
}
build() {
Column() {
// 动画目标
Row() {
Text('持续')
.fontSize(20)
.fontColor(Color.White)
Text('缩放')
.fontSize(20)
.fontColor(Color.White)
.margin({ left: 10 })
Text('动画')
.fontSize(20)
.fontColor(Color.White)
.margin({ left: 10 })
}
.width(200)
.height(80)
.backgroundColor(this.isAnimating ? Color.Red : Color.Blue)
.borderRadius(10)
.justifyContent(FlexAlign.Center)
.scale({ x: this.scaleValue, y: this.scaleValue })
// 控制按钮
Row() {
Button('开始缩放')
.onClick(() => this.startAnimation())
.enabled(!this.isAnimating)
.backgroundColor(Color.Green)
.margin({ right: 10 })
Button('停止缩放')
.onClick(() => this.stopAnimation())
.enabled(this.isAnimating)
.backgroundColor(Color.Orange)
}
.margin({ top: 50 })
}
.width('100%')
.height('100%')
.justifyContent(FlexAlign.Center)
}
}
关键参数说明
scale 属性
.scale({ x: number, // X 轴缩放比例 y: number, // Y 轴缩放比例 z?: number, // Z 轴缩放比例(3D) centerX?: number, // 缩放中心点 X 坐标 centerY?: number // 缩放中心点 Y 坐标 })
animation 参数
.animation({ duration: number, // 动画时长(毫秒) curve: Curve, // 动画曲线 delay?: number, // 延迟时间 iterations: number, // 迭代次数(-1 为无限) playMode: PlayMode, // 播放模式 tempo?: number, // 播放速度 onFinish?: () => void // 完成回调 })
PlayMode 选项
- PlayMode.Normal - 正常播放
- PlayMode.Reverse - 反向播放
- PlayMode.Alternate - 往返播放(推荐用于持续缩放)
- PlayMode.AlternateReverse - 反向往返播放
Curve 动画曲线
- Curve.Linear - 线性
- Curve.EaseInOut - 缓入缓出(推荐)
- Curve.Smooth - 平滑(推荐用于呼吸效果)
- Curve.FastOutSlowIn - 快出慢入
- Curve.Friction - 阻尼
更多关于HarmonyOS 鸿蒙Next中如何实现Row组件及其子组件持续缩放效果?的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
在HarmonyOS Next中,使用Row组件结合animation属性实现持续缩放效果。通过scale动画类型设置目标缩放值,例如{ scale: { x: 1.2, y: 1.2 } }。配置动画参数duration(时长)、iterations(迭代次数,-1表示无限循环)和easing(缓动函数)。将动画绑定到Row或其子组件的animation属性即可实现自动持续缩放。
在HarmonyOS Next中,可以通过animateTo结合插值计算实现Row及其子组件的持续缩放效果。以下是一个核心实现示例:
// 引入必要模块
import { Curves } from '@kit.ArkUI';
@Entry
@Component
struct ScaleAnimationExample {
@State scaleValue: number = 1.0;
aboutToAppear() {
// 启动循环动画
this.startContinuousScale();
}
startContinuousScale() {
// 使用animateTo实现缩放动画循环
animateTo({
duration: 1000, // 动画时长1秒
curve: Curves.EaseInOut, // 缓动曲线
iterations: -1, // 无限循环
playMode: PlayMode.Alternate // 交替播放
}, () => {
this.scaleValue = this.scaleValue === 1.0 ? 0.5 : 1.0; // 在1.0和0.5之间切换
})
}
build() {
Row() {
// 子组件示例
Text('缩放内容')
.fontSize(20)
.fontColor(Color.White)
.backgroundColor(Color.Blue)
.padding(10)
}
.scale({ x: this.scaleValue, y: this.scaleValue }) // 应用缩放
.justifyContent(FlexAlign.Center)
.width('100%')
.height('100%')
}
}
关键点说明:
- 使用
animateTo动画API,设置iterations: -1实现无限循环 - 通过
PlayMode.Alternate使缩放值在1.0和0.5之间来回切换 scale修饰符应用缩放变换到Row容器- 子组件会自动继承容器的缩放效果
可通过调整duration控制动画速度,修改curve改变动画缓动效果。

