HarmonyOS鸿蒙Next中在关键帧动画的不同步骤怎么使用不同motionPath?
HarmonyOS鸿蒙Next中在关键帧动画的不同步骤怎么使用不同motionPath? 试了一些方法没成功,下面是测试代码
@Entry
@Component
struct KeyframeAnimateTo02 {
@State myScale: number = 1.0;
uiCtx?: UIContext = undefined;
@State kTranslateOpt: TranslateOptions = { x: 0, y: 0, z: 0 }
// 起点
@State x: number = 0
@State y: number = 0
reset() {
this.x = 0
this.y = 0
this.myScale = 1
this.kTranslateOpt = { x: 0, y: 0, z: 0 }
}
keyFrameAnimation() {
//安全校验
if (!this.uiCtx) {
console.info("no uiContext, keyframe failed");
return;
}
// this.myScale = 1;
// this.kTranslateOpt = { x: 0, y: 0, z: 0 }
this.uiCtx.keyframeAnimateTo({
iterations: 1, // 整体播放次数
expectedFrameRateRange: { min: 10, max: 120, expected: 60, },
// onFinish: () => this.reset()
}, [
{
duration: 1000, event: () => {
this.x = 300
}
}, // 第1段动画
{
duration: 1000, event: () => {
this.y = 300
}
}// 第2段动画
]);
}
aboutToAppear() {
this.uiCtx = this.getUIContext?.();
}
build() {
Stack() {
Text('方块')
.textAlign(TextAlign.Center)
.backgroundColor('#ffb5c5e1')
.size({ width: 50, height: 50 })
.scale({
x: this.myScale,
y: this.myScale,
centerX: 0,
centerY: 0
})
.position({ x: this.x, y: this.y, })
// .motionPath({ path: this.motionPaths[this.motionSection], })
// .attributeModifier(new Mod(this.motionSection))
}
.width(300)
.height(600)
.backgroundColor('#ffe3f1df')
.onClick((e) => this.keyFrameAnimation())
}
}
class Mod implements AttributeModifier<CommonAttribute> {
type: number
constructor(type: number) {
this.type = type
}
applyNormalAttribute(instance: CommonAttribute): void {
if (this.type == 1) {
instance.motionPath({ path: `M0 0 Q${(vp2px(100))} 0 ${vp2px(50)} ${vp2px(50)}` })
} else if (this.type == 2) {
instance.motionPath({ path: `M0 0 Q${(vp2px(100))} 0 ${vp2px(100)} ${vp2px(100)}` })
}
}
}
@Entry
@Component
struct KeyframeAnimateTo02 {
@State toggle: boolean = true;
@State myColor: Color = Color.Pink
@State pathParams: MotionPathOptions = {
path: 'Mstart.x start.y L10 100 L0 0 Lend.x end.y',
from: 0,
to: 1,
rotatable: false
};
@State x: number = 10;
@State y: number = 10;
setPosition() {
this.x = 200
this.y = 200
this.myColor = Color.Blue
}
setPosition2() {
this.x = 400
this.y = 400
this.myColor = Color.Green
}
keyFrameAnimation() {
this.getUIContext().keyframeAnimateTo({
iterations: 1, // 整体播放次数
expectedFrameRateRange: { min: 10, max: 120, expected: 60, },
}, [
{
duration: 1000, event: () => {
this.pathParams = {
path: 'M10 10 L10 200 L200 200',
from: 0,
to: 1,
rotatable: false
};
this.setPosition()
}
}
, // 第1段动画
{
duration: 1000, event: () => {
this.pathParams = {
path: 'M200 200 L400 400',
// path: 'M200 200 C300 200 350 400 400 400',
// path: `M0 0 Q${(vp2px(100))} 0 ${vp2px(50)} ${vp2px(50)}`,
from: 0,
to: 1,
rotatable: false
};
this.setPosition2()
}
}// 第2段动画
]);
}
build() {
Column() {
Button('点击').position({ x: 200 })
.onClick(() => {
this.toggle = !this.toggle
this.keyFrameAnimation()
})
Text('Hello')
.margin({ top: 50 })
.width(50)
.height(50)
.backgroundColor(this.myColor)
.motionPath(this.pathParams) // 设置路径动画
.position({ top: this.toggle ? 0 : this.y, left: this.toggle ? 0 : this.x }) // 根据toggle状态设置位置
}.backgroundColor('#ffa4cdb0')
.width('100%')
.height('100%') // 设置列的宽度和高度为100%
}
}
第2段测试代码的执行录屏见附件(先瞬移,然后执行第2段动画)
这段代码中的第2段动画换为曲线后比较明显,先瞬移,然后曲线移动,也就是第一段动画没有执行
更多关于HarmonyOS鸿蒙Next中在关键帧动画的不同步骤怎么使用不同motionPath?的实战教程也可以访问 https://www.itying.com/category-93-b0.html
可以在keyframeAnimateTo中分段设置motionPath移动路径,绑定文字路径动画,并使用状态变量设置位置,具体实现如下:
@Entry
@Component
struct MotionPathDemo {
@State toggle: boolean = true;
@State myColor: Color = Color.Pink
@State pathParams: MotionPathOptions = {
path: 'Mstart.x start.y L10 100 L0 0 Lend.x end.y',
from: 0,
to: 1,
rotatable: false
};
@State x: number = 10;
@State y: number = 10;
setPosition() {
this.x = 200
this.y = 200
this.myColor = Color.Blue
}
setPosition2() {
this.x = 400
this.y = 400
this.myColor = Color.Green
}
keyFrameAnimation() {
this.getUIContext().keyframeAnimateTo({
iterations: 1, // 整体播放次数
expectedFrameRateRange: { min: 10, max: 120, expected: 60, },
}, [
{
duration: 1000, event: () => {
this.pathParams = {
path: 'M10 10 L10 200 L200 200',
from: 0,
to: 1,
rotatable: false
};
this.setPosition()
}
}
, // 第1段动画
{
duration: 1000, event: () => {
this.pathParams = {
path: 'M200 200 L200 400 L400 400',
from: 0,
to: 1,
rotatable: false
};
this.setPosition2()
}
} // 第2段动画
]);
}
build() {
Column() {
Button('点击')
.onClick(() => {
this.toggle = !this.toggle
this.keyFrameAnimation()
})
Text('Hello')
.margin({ top: 50 })
.width(50)
.height(50)
.backgroundColor(this.myColor)
.motionPath(this.pathParams) // 设置路径动画
.position({ top: this.toggle ? 10 : this.y, left: this.toggle ? 10 : this.x }) // 根据toggle状态设置位置
}
.width('100%')
.height('100%') // 设置列的宽度和高度为100%
}
}
更多关于HarmonyOS鸿蒙Next中在关键帧动画的不同步骤怎么使用不同motionPath?的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
测试代码的执行录屏见附件(先瞬移,然后执行第2段动画) 这段代码中的第2段动画换为曲线后比较明显,先瞬移,然后曲线移动,也就是第一段动画没有执行,
Button('点击')
.onClick(() => {
// this.keyFrameAnimation()
this.getUIContext().animateTo({
duration: 1000,
onFinish: () => {
this.getUIContext().animateTo({
duration: 1000,
},() => {
this.pathParams = {
path: 'M200 200 L200 400 L400 400',
from: 0,
to: 1,
rotatable: false
};
this.setPosition2()
})
}
}, () => {
this.toggle = !this.toggle
this.pathParams = {
path: 'M10 10 L10 200 L200 200',
from: 0,
to: 1,
rotatable: false
};
this.setPosition()
})
})
有要学HarmonyOS AI的同学吗,联系我:https://www.itying.com/goods-1206.html
开发者您好,为了更快解决您的问题,请您这边提供下动画的效果视频吧
这里不是发不了视频吗?,
视频是我失败的效果还是期望的效果啊?失败的效果的话就是示例代码的运行效果,期望的效果就是【关键帧动画每个步骤对应不同的motionPath】,我想确认一下示例代码+之前的描述是不是不太清楚,我的理解是从代码应该足够表达,不行的话我再运行然后录个屏吧,
试了不行,
回答来自ai,
// @Entry 表示这是程序的入口组件
@Component
struct KeyframeAnimateTo02 {
// 定义状态变量 myScale,初始值为 1.0,用于控制缩放比例
@State myScale: number = 1.0;
// 声明一个可选的 UI 上下文对象,默认为 undefined
uiCtx?: UIContext = undefined;
// 定义状态变量 kTranslateOpt,类型为 TranslateOptions,初始值为 { x: 0, y: 0, z: 0 },表示平移选项
@State kTranslateOpt: TranslateOptions = { x: 0, y: 0, z: 0 }
// 起点坐标的状态变量
@State x: number = 0
@State y: number = 0
// 重置函数,将各状态变量恢复到初始值
reset() {
this.x = 0 // 将 x 坐标重置为 0
this.y = 0 // 将 y 坐标重置为 0
this.myScale = 1 // 将缩放比例重置为 1
this.kTranslateOpt = { x: 0, y: 0, z: 0 } // 将平移选项重置为初始值
}
// 关键帧动画函数
keyFrameAnimation() {
// 安全校验,如果不存在 UI 上下文则输出提示信息并返回
if (!this.uiCtx) {
console.info("no uiContext, keyframe failed"); // 打印日志提示没有获取到 UI 上下文,关键帧动画失败
return;
}
// 使用 UI 上下文执行关键帧动画操作
this.uiCtx.keyframeAnimateTo({
iterations: 1, // 整体播放次数设置为 1 次
expectedFrameRateRange: { min: 10, max: 1,
在HarmonyOS Next的关键帧动画中,不同步骤使用不同motionPath的正确方式是通过AttributeModifier动态修改路径属性。
从你的代码分析,问题在于:
-
关键帧事件执行时机:
keyframeAnimateTo中的event回调是立即执行的,不是动画过程中逐步执行的。这导致两个motionPath设置几乎同时发生。 -
路径起点问题:第二个motionPath的起点应该是第一个路径的终点,而不是重新从(0,0)开始。
修正方案:
class MotionPathModifier implements AttributeModifier<CommonAttribute> {
private currentPath: number = 0;
setCurrentPath(pathIndex: number) {
this.currentPath = pathIndex;
}
applyNormalAttribute(instance: CommonAttribute): void {
switch(this.currentPath) {
case 0:
instance.motionPath({
path: 'M0 0 Q150 0 75 75', // 第一段贝塞尔曲线
from: 0,
to: 1,
rotatable: true
});
break;
case 1:
instance.motionPath({
path: 'M75 75 Q225 75 150 150', // 从第一段终点开始
from: 0,
to: 1,
rotatable: true
});
break;
}
}
}
在关键帧动画中:
const modifier = new MotionPathModifier();
// 第一帧设置第一段路径
modifier.setCurrentPath(0);
// 触发UI更新
// 第二帧设置第二段路径
modifier.setCurrentPath(1);
// 触发UI更新
这样确保每段动画使用独立的运动路径,且路径连接自然过渡。


