前言
Flutter
提供了丰富的动画支持,使开发者能够轻松创建各种类型的动画效果,从简单的渐变和旋转到复杂的交互式动画都可以实现。而 ArkUI
从 api
上面看起来更简单,更容易编写代码。我们今天迁移的是 Flutter
上面的 like_button , 它使我们的点赞效果更简单酷炫和简单。
点赞按钮
Like Button
支持推特点赞效果和喜欢数量动画的 ArkUI
库.
安装
ohpm install @candies/like_button
参数
配置参数
参数 | 类型 | 描述 |
---|---|---|
likeWidgetSize | number | LikeWidget 的大小(默认 30) |
bubblesSize | number | 动画时候的泡泡的大小(默认为 likeWidgetSize 的 2 倍) |
bubblesColor | BubblesColor | 动画时候的泡泡的颜色,可以分别设置 4 种(默认为 dotPrimaryColor: '#FFFFC107',dotSecondaryColor: '#FFFF9800',dotThirdColor: '#FFFF5722',dotLastColor: '#FFF44336' |
circleSize | number | 动画时候的圈的最大大小(默认为 likeWidgetSize 的 0.8 倍) |
circleColor | BubblesColor | 动画时候的圈的颜色,需要设置 2 种 (默认为 start: '#FFFF5722', end: '#FFFFC107') |
isLiked | boolean | 是否喜欢。(默认 false ) |
animationDuration | number | LikeWidget 动画时长(默认 1000 毫秒) |
likeCount | number | 喜欢数量。如果不设置(undefined),不显示 LikeCountWidget |
flexOptions | FlexOptions | LikeWidget 和 LikeCountWidget 2 个组件位置的配置(默认为 direction: FlexDirection.Row, justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center) |
likeCountAnimationType | LikeCountAnimationType | 喜欢数量动画的类型(none,part,all)。没有动画;只动画改变的部分;全部部分 |
widgetsMargin | number | LikeWidget and LikeCountWidget 的距离 |
likeCountAnimationDuration | number | LikeCountWidget 动画时长(默认 1000 毫秒) |
controller | Controller | 可以通过调用 Controller 的 Tap 的方法,执行动画 |
回调
这是一个异步回调,你可以等待服务返回之后再改变状态。也可以先改变状态,请求失败之后重置回状态
onTap: (isLike: boolean) => Promise<boolean> = async (isLike: boolean) => {
return !isLike;
};
组件创建回调
回调 | 参数 | 描述 |
---|---|---|
likeWidgetBuilder | isLiked: boolean | 用于自定义 LikeWidget |
likeCountWidgetBuilder | isLiked: boolean,likeCount: number,showText: string | 用于自定义 LikeCountWidget |
@BuilderParam
likeWidgetBuilder?: ($$: { isLiked: boolean }) => void = this.buildLikeWidget.bind(this);
@BuilderParam
likeCountWidgetBuilder?: ($$: {
isLiked: boolean,
likeCount: number,
showText: string
}) => void = this.buildLikeCountWidget.bind(this);
例子
无限点赞
将 onTap
固定返回 true
,可以实现无限点赞的效果。
LikeButton(
{
likeCount: 666,
onTap: async (isLike: boolean): Promise<true> => {
return true;
},
}
)
LikeCountWidget 特殊处理逻辑
你可以根据 likeCount
的值的不同,做一些特殊的处理。
LikeButton(
{
likeCount: 999,
likeWidgetBuilder: this.buildLikeWidget8,
bubblesColor: new BubblesColor({
dotPrimaryColor: '#FF00796B',
dotSecondaryColor: '#FF004D40',
},),
circleColor: new CircleColor({
start: '#FF26A69A',
end: '#FFB2DFDB',
}),
likeCountWidgetBuilder: this.buildLikeCountWidget2,
}
)
@Builder
buildLikeCountWidget2($$: {
isLiked: boolean,
likeCount: number,
showText: string
}) {
if ($$.likeCount >= 1000)
Text(`${($$.likeCount / 1000).toFixed(1)}k`).fontColor($$.isLiked ? '#FF004D40' : Color.Gray)
else
Text(`${$$.showText}`).fontColor($$.isLiked ? '#FF004D40' : Color.Gray)
}
@Builder
buildLikeWidget8($$: { isLiked: boolean }) {
Image($r('app.media.save'))
.fillColor($$.isLiked ? '#FF004D40' : Color.Gray)
}
设置 LikeWidget 和 LikeCountWidget 的位置
LikeButton(
{
likeCount: 888,
flexOptions: {
direction: FlexDirection.Column,
justifyContent: FlexAlign.Center,
alignItems: ItemAlign.Center,
},
}
)
学废了
动画
ArkUI
里面使用动画蛮简单的。
@Entry
@Component
struct LayoutChange2 {
@State myWidth: number = 100;
@State myHeight: number = 50;
// 标志位,true和false分别对应一组myWidth、myHeight值
@State flag: boolean = false;
build() {
Column({ space: 10 }) {
Button("text")
.type(ButtonType.Normal)
.width(this.myWidth)
.height(this.myHeight)
.margin(20)
Button("area: click me")
.fontSize(12)
.margin(20)
.onClick(() => {
animateTo({ duration: 1000, curve: Curve.Ease }, () => {
// 动画闭包中根据标志位改变控制第一个Button宽高的状态变量,使第一个Button做宽高动画
if (this.flag) {
this.myWidth = 100;
this.myHeight = 50;
} else {
this.myWidth = 200;
this.myHeight = 100;
}
this.flag = !this.flag;
});
})
}
.width("100%")
.height("100%")
}
}
但是你没法获取到每一帧的动画值。我们需要另外一个 api
来实现。
let options: AnimatorOptions = {
duration: 1000,
easing: "ease",
delay: 0,
fill: "forwards",
direction: "normal",
iterations: 1,
begin: 0.0,
end: 1.0
};
let animatorResult = animator.create(options);
animatorResult.onframe=(progress: number)=>{
};
animatorResult.onfinish=()=>{
};
animatorResult.play();
animatorResult.pause();
animatorResult.cancel();
animatorResult.reverse();
animatorResult.reset(options);
onframe
方法中的 progress
在 begin
和 end
之间的值。你可以在这个方法里面对某个属性做改变,达到动画的效果。
不过这个 api
没法像 Flutter
中一样, 使用同一个 Controller
对不同的属性,在不同时间段做不同的动画效果。比如下面的 Controller
的动画总时间为 1000
秒,那么就 _innerCircleAnimation
就是一个值从 0.2
开始 1.0
结束,并且是从 200
秒开始 500
秒结束的 Curves.ease
动画。虽然
ArkUI
中 AnimatorOptions
中可以设置 delay
来控制开始的时间,但是这也会影响整个动画的曲线。
_innerCircleAnimation = Tween<double>(
begin: 0.2,
end: 1.0,
).animate(
CurvedAnimation(
parent: _controller!,
curve: const Interval(
0.2,
0.5,
curve: Curves.ease,
),
),
);
最终我的实现方案是将 Flutter
中的动画曲线迁移到 ArkUI
中,使用固定的 0.0
到 1.0
的 AnimatorOptions
来作为 Flutter
中的
AnimationController
来驱动动画。
let options: AnimatorOptions = {
duration: this.animationDuration,
easing: "ease",
delay: 0,
fill: "forwards",
direction: "normal",
iterations: 1,
begin: 0.0,
end: 1.0
};
_outerCircleCurve = new Interval({
begin: 0.0,
end: 0.3,
curve: Cubic.ease,
beginValue: 0.1,
endValue: 1.0,
});
_innerCircleCurve = new Interval({
begin: 0.2,
end: 0.5,
curve: Cubic.ease,
beginValue: 0.2,
endValue: 1.0,
});
_bubblesCurve = new Interval({
begin: 0.1,
end: 1.0,
curve: new DecelerateCurve(),
beginValue: 0.0,
endValue: 1.0,
});
_iconScaleCurve = new Interval({
begin: 0.35,
end: 0.7,
curve: new OvershootCurve(),
beginValue: 0.1,
endValue: 1.0
});
this._animatorResult.onframe = (value: number) => {
this._outerCircleRadiusProgress = this._outerCircleCurve.transform(value);
this._innerCircleRadiusProgress = this._innerCircleCurve.transform(value);
this._bubblesProgress = this._bubblesCurve.transform(value);
this._iconScale = this._iconScaleCurve.transform(value);
};
这样子就能实现跟 Flutter
一模一样的动画曲线了。
结语
从 Flutter
迁移到 ArkUI
过程蛮简单的,只需要去找准对应的 api
即可,关于 Canvas
的 api
各种平台的都大差不差的。
写在最后
如果你觉得这篇内容对你还蛮有帮助,我想邀请你帮我三个小忙:
- 点赞,转发,有你们的 『点赞和评论』,才是我创造的动力。
- 关注小编,同时可以期待后续文章ing🚀,不定期分享原创知识。
- 想要获取更多完整鸿蒙最新学习知识点,请移步前往小编:
https://gitee.com/MNxiaona/733GH/blob/master/jianshu
网友评论