网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
│ │ ├──ComponentTransition.ets // 移动动画转场页面
│ │ ├──CustomTransition.ets // 放缩动画转场页面
│ │ ├──FullCustomTransition.ets // 旋转动画转场页面
│ │ ├──Index.ets // 应用首页
│ │ ├──ShareItem.ets // 共享元素转场部件
│ │ └──SharePage.ets // 共享元素转场页面
│ ├──view
│ │ ├──BackContainer.ets // 自定义头部返回组件
│ │ └──TransitionElement.ets // 自定义动画元素
│ └──viewmodel
│ └──AnimationModel.ets // 动画封装的model类
└──entry/src/main/resources // 资源文件目录
### 构建主界面
在这个任务中,我们将完成主界面的设计和开发,效果如图所示:

从上面效果图可以看出,主界面主要由5个相同样式的功能菜单组成,我们可以将这些菜单抽取成一个子组件Item。
1. 将所需要的图片添加到resources > base > media目录下。

2. 在Index.ets中引入首页所需要图片和路由信息,声明子组件的UI布局并添加样式,使用ForEach方法循环渲染首页列表常量数据“INDEX\_ANIMATION\_MODE”,其中imgRes是设置按钮的背景图片,url用于设置页面路由的地址。
// Index.ets
import { INDEX_ANIMATION_MODE } from ‘…/common/constants/CommonConstants’;
Column() {
ForEach(INDEX_ANIMATION_MODE, (item: AnimationModel) => {
Row()
.backgroundImage(item.imgRes)
.backgroundImageSize(ImageSize.Cover)
.backgroundColor(
r
(
′
a
p
p
.
c
o
l
o
r
.
t
r
a
n
s
p
a
r
e
n
t
′
)
)
.
h
e
i
g
h
t
(
D
i
m
e
n
s
i
o
n
U
t
i
l
.
g
e
t
V
p
(
r('app.color.trans_parent')) .height(DimensionUtil.getVp(
r(′app.color.transparent′)).height(DimensionUtil.getVp(r(‘app.float.main_page_body_height’)))
.margin({ bottom: DimensionUtil.getVp($r(‘app.float.main_page_body_margin’)) })
.width(FULL_LENGTH)
.borderRadius(BORDER_RADIUS)
.onClick(() => {
router.pushUrl({ url: item.url })
.catch((err: Error) => {
hilog.error(DOMAIN, PREFIX, FORMAT, err);
});
})
}, (item: AnimationModel) => JSON.stringify(item))
}
### 页面间转场
#### 实现“底部滑入”效果
在BottomTransition申明pageTransition方法配置转场参数,其中PageTransitionEnter用于自定义当前页面的入场效果,PageTransitionExit用于自定义当前页面的退场效果。效果如图所示:

通过设置PageTransitionEnter和PageTransitionExit的slide属性为SlideEffect.Bottom,来实现BottomTransition入场时从底部滑入,退场时从底部滑出。
// BottomTransition.ets
@Entry
@Component
struct BottomTransition {
build() {
Column() {
TransitionElement()
}
}
/**
- 页面转场通过全局pageTransition方法进行配置转场参数
- SlideEffect.Bottom 入场时从屏幕下方滑入。
- SlideEffect.Bottom 退场时从屏幕下方滑出。
*/
pageTransition() {
PageTransitionEnter({ duration: TRANSITION_ANIMATION_DURATION, curve: Curve.Smooth }).slide(SlideEffect.Bottom);
PageTransitionExit({ duration: TRANSITION_ANIMATION_DURATION, curve: Curve.Smooth }).slide(SlideEffect.Bottom);
}
}
#### 实现”页面转场:自定义1“效果
本节实现的效果,页面入场时为淡入和放大,退场时从右下角滑出。效果如图所示:

在CustomTransition.ets的Column组件中添加TransitionElement组件,并且定义pageTransition方法。
// CustomTransition.ets
@Entry
@Component
struct CustomTransition {
build() {
Column() {
TransitionElement()
}
}
/**
- 页面转场通过全局pageTransition方法进行配置转场参数
- 进场时透明度设置从0.2到1;x、y轴缩放从0变化到1
- 退场时x、y轴的偏移量为500
*/
pageTransition() {
PageTransitionEnter({ duration: TRANSITION_ANIMATION_DURATION, curve: Curve.Smooth })
.opacity(CUSTOM_TRANSITION_OPACITY)
.scale(CUSTOM_TRANSITION_SCALE)
PageTransitionExit({ duration: TRANSITION_ANIMATION_DURATION, curve: Curve.Smooth })
.translate(CUSTOM_TRANSITION_TRANSLATE)
}
}
>
> **说明:** translate设置页面转场时的平移效果,为入场时起点和退场时终点的值,和slide同时设置时默认生效slide。
>
>
>
#### 实现”页面转场:自定义2“动效
本节实现的效果,页面入场时淡入和放大,同时顺时针旋转;退场时淡出和缩小,同时逆时针旋转。效果如图所示:

在FullCustomTransition.ets的Column组件中添加TransitionElement组件,并且定义pageTransition方法。给Stack组件添加opacity、scale、rotate属性,定义变量animValue用来控制Stack组件的动效,在PageTransitionEnter和PageTransitionExit组件中动态改变myProgress的值。
// FullCustomTransition.ets
@Entry
@Component
struct FullCustomTransition {
@State animValue: number = FULL_CUSTOM_TRANSITION_DEFAULT_ANIM_VALUE;
build() {
Column() {
TransitionElement()
}
.opacity(this.animValue)
.scale({ x: this.animValue, y: this.animValue })
.rotate({
z: FULL_CUSTOM_TRANSITION_ROTATE_Z,
angle: FULL_CUSTOM_TRANSITION_ANGLE * this.animValue
})
}
/**
- 页面转场通过全局pageTransition方法进行配置转场参数
- 进场过程中会逐帧触发onEnter回调,入参为动效的归一化进度(0 - 1)
- 进场过程中会逐帧触发onExit回调,入参为动效的归一化进度(0 - 1)
*/
pageTransition() {
PageTransitionEnter({ duration: TRANSITION_ANIMATION_DURATION, curve: Curve.Smooth })
.onEnter((type?: RouteType, progress?: number) => {
if (!progress) {
return;
}
this.animValue = progress;
});
PageTransitionExit({ duration: TRANSITION_ANIMATION_DURATION, curve: Curve.Smooth })
.onExit((type?: RouteType, progress?: number) => {
if (!progress) {
return;
}
this.animValue = FULL_CUSTOM_TRANSITION_DEFAULT_ANIM_VALUE - progress;
});
}
}
### 组件内转场
本节实现组件内转场动效,通过一个按钮来控制组件的添加和移除,呈现容器组件子组件添加和移除时的动效。效果如图所示:

组件转场主要通过transition属性方法配置转场参数,在组件添加和移除时会执行过渡动效,需要配合animateTo才能生效。动效时长、曲线、延时跟随animateTo中的配置。
1. 在ComponentTransition.ets文件中,新建Image子组件,并添加两个transition属性,分别用于定义组件的添加动效和移除动效。
// ComponentTransition.ets
Image($r(‘app.media.bg_element’))
.TransitionEleStyles()
.transition({
type: TransitionType.Insert,
scale: COMPONENT_TRANSITION_SCALE,
opacity: COMPONENT_TRANSITION_OPACITY
})
.transition({
type: TransitionType.Delete,
rotate: COMPONENT_TRANSITION_ROTATE,
opacity: COMPONENT_TRANSITION_OPACITY
})
2. 在ComponentTransition代码中,定义一个isShow变量,用于控制Image子组件的添加和移除,在Button组件的onClick事件中添加animateTo方法,来使Image子组件子组件动效生效。
// ComponentTransition.ets
@State isShow: boolean = false;
Button(
r
(
′
a
p
p
.
s
t
r
i
n
g
.
C
o
m
p
o
n
e
n
t
t
r
a
n
s
i
t
i
o
n
t
o
g
g
l
e
′
)
)
.
h
e
i
g
h
t
(
D
i
m
e
n
s
i
o
n
U
t
i
l
.
g
e
t
V
p
(
r('app.string.Component_transition_toggle')) .height(DimensionUtil.getVp(
r(′app.string.Componenttransitiontoggle′)).height(DimensionUtil.getVp(r(‘app.float.element_trans_btn_height’)))
.width(DimensionUtil.getVp(
r
(
′
a
p
p
.
f
l
o
a
t
.
e
l
e
m
e
n
t
t
r
a
n
s
b
t
n
w
i
d
t
h
′
)
)
)
.
f
o
n
t
C
o
l
o
r
(
C
o
l
o
r
.
W
h
i
t
e
)
.
b
a
c
k
g
r
o
u
n
d
C
o
l
o
r
(
r('app.float.element_trans_btn_width'))) .fontColor(Color.White) .backgroundColor(
r(′app.float.elementtransbtnwidth′))).fontColor(Color.White).backgroundColor(r(‘app.color.light_blue’))
.onClick(() => {
animateTo({ duration: TRANSITION_ANIMATION_DURATION }, () => {
this.isShow = !this.isShow;
})
})
### 共享元素转场
效果如图所示:

共享元素转场通过给组件设置sharedTransition属性来实现,两个页面的组件配置为同一个id,则转场过程中会执行共享元素转场。sharedTransition可以设置动效的时长、动画曲线和延时,实现步骤如下:
1. 在ShareItem.ets中给Image组件设置sharedTransition属性,组件转场id设置为“SHARE\_TRANSITION\_ID”。
// ShareItem.ets
Image(
r
(
′
a
p
p
.
m
e
d
i
a
.
b
g
t
r
a
n
s
i
t
i
o
n
′
)
)
.
w
i
d
t
h
(
F
U
L
L
L
E
N
G
T
H
)
.
h
e
i
g
h
t
(
D
i
m
e
n
s
i
o
n
U
t
i
l
.
g
e
t
V
p
(
r('app.media.bg_transition')) .width(FULL_LENGTH) .height(DimensionUtil.getVp(
r(′app.media.bgtransition′)).width(FULLLENGTH).height(DimensionUtil.getVp(r(‘app.float.share_item_element_height’)))
.borderRadius(DimensionUtil.getVp(KaTeX parse error: Expected '}', got 'EOF' at end of input: …sionUtil.getVp(r(‘app.float.share_item_element_margin_bottom’)) })
.sharedTransition(SHARE_TRANSITION_ID, {
duration: TRANSITION_ANIMATION_DURATION,
curve: Curve.Smooth,
delay: SHARE_ITEM_ANIMATION_DELAY
})
.onClick(() => {
router.pushUrl({ url: SHARE_PAGE_URL })
.catch((err: Error) => {
hilog.error(DOMAIN, PREFIX, FORMAT, err);
});
})
2. 在SharePage.ets中给Image组件设置sharedTransition属性,组件转场id设置为“SHARE\_TRANSITION\_ID”。
// SharePage.ets
@Entry
@Component
struct SharePage {
build() {
Column() {
TransitionElement({ imgFit: ImageFit.Cover })
.sharedTransition(SHARE_TRANSITION_ID, {
duration: SHARE_ITEM_DURATION,
curve: Curve.Smooth,
delay: SHARE_ITEM_ANIMATION_DELAY
})
}
}
}
>
> **说明:** 两个页面的组件配置为同一个id,则转场过程中会执行共享元素转场,配置为空字符串时不会有共享元素转场效果。
>
>
>
### 最后
有很多小伙伴不知道学习哪些鸿蒙开发技术?不知道需要重点掌握哪些鸿蒙应用开发知识点?而且学习时频繁踩坑,最终浪费大量时间。所以有一份实用的**鸿蒙(HarmonyOS NEXT)资料**用来跟着学习是非常有必要的。
**这份鸿蒙(HarmonyOS NEXT)资料包含了鸿蒙开发必掌握的核心知识要点,内容包含了**(**ArkTS、ArkUI开发组件、Stage模型、多端部署、分布式应用开发、音频、视频、WebGL、OpenHarmony****多媒体技术、Napi组件、OpenHarmony内核、Harmony南向开发、鸿蒙项目实战等等)鸿蒙(HarmonyOS NEXT)**技术知识点。
**深知大多数程序员,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!**



**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上鸿蒙开发知识点,真正体系化!**
**由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新**
**[需要这份系统化的资料的朋友,可以戳这里获取](https://bbs.youkuaiyun.com/topics/618636735)**
csdnimg.cn/direct/743b668910224b259a5ffe804fa6d0db.png)
[外链图片转存中...(img-Lh2MemSv-1715709184911)]
[外链图片转存中...(img-Jr2I2UWC-1715709184911)]
**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上鸿蒙开发知识点,真正体系化!**
**由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新**
**[需要这份系统化的资料的朋友,可以戳这里获取](https://bbs.youkuaiyun.com/topics/618636735)**