Skip to content

Commit

Permalink
add Animation
Browse files Browse the repository at this point in the history
  • Loading branch information
zmtzawqlp committed Dec 6, 2023
1 parent 180665b commit 023c86b
Show file tree
Hide file tree
Showing 9 changed files with 295 additions and 219 deletions.
6 changes: 3 additions & 3 deletions build-profile.json5
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,17 @@
"products": [
{
"name": "default",
"signingConfig": "default",
"signingConfig": "default"
}
],
"buildModeSet": [
{
"name": "debug",
"name": "debug"
},
{
"name": "release"
}
]
],
},
"modules": [
{
Expand Down
33 changes: 21 additions & 12 deletions entry/src/main/ets/pages/Index.ets
Original file line number Diff line number Diff line change
@@ -1,23 +1,32 @@
import { LikeButton } from '@candies/like_button';
import { LikeButton, like_button } from '@candies/like_button';

@Entry
@Component
struct Index {
@State message: string = 'Hello World';
@State controller: like_button.Controller = new like_button.Controller();

aboutToAppear() {
// this.controller.likeComponentSize = 150;
// this.controller.animationDuration=1000;
}

build() {
Row() {
Column() {
Text(this.message)
.fontSize(50)
.fontWeight(FontWeight.Bold)
LikeButton(
{ animationDuration: 5000, isLiked: false, }
)
.backgroundColor('#FFFF5722')
Navigation(){
Grid() {
GridItem() {
LikeButton(
{
controller: this.controller
}
)
}
}
.columnsTemplate('1fr 1fr 1fr')
.columnsGap(10)
.rowsGap(10)
.width('100%')
}
.height('100%')
.height('100%')
}.title('LikeButtonDemo').titleMode(NavigationTitleMode.Mini)
}
}
4 changes: 3 additions & 1 deletion like_button/Index.ets
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@

export { LikeButton } from './src/main/ets/components/LikeButton'
export { LikeButton } from './src/main/ets/components/LikeButton'

export { default as like_button } from './src/main/ets/common/Controller'
130 changes: 127 additions & 3 deletions like_button/src/main/ets/common/Controller.ets
Original file line number Diff line number Diff line change
@@ -1,9 +1,133 @@
export default like_button;
import { BubblesColor, CircleColor } from './Model';
import animator, { AnimatorOptions, AnimatorResult } from '@ohos.animator';
import { Cubic, DecelerateCurve, Interval, OvershootCurve } from './Curve';


namespace like_button {
export class Controller {
onTap() {
/// size of like widget
likeComponentSize: number = 30;
/// animation duration to change isLiked state
// final Duration animationDuration;

/// total size of bubbles
bubblesSize: number;
/// colors of bubbles
bubblesColor: BubblesColor = new BubblesColor(
{ dotPrimaryColor: '#FFFFC107',
dotSecondaryColor: '#FFFF9800',
dotThirdColor: '#FFFF5722',
dotLastColor: '#FFF44336', }
);
/// size of circle
circleSize: number;
/// colors of circle
circleColor: CircleColor = new CircleColor({ start: '#FFFF5722', end: '#FFFFC107', });
/// tap call back of like button
// final LikeButtonTapCallback? onTap;
/// whether it is liked
/// it's initial value
/// you can get current value from onTap/countBuilder
isLiked: boolean | null = false;
/// animation duration to change isLiked state
animationDuration: number = 1000;
outerCircleRadiusProgress: number = 0;
innerCircleRadiusProgress: number = 0;
bubblesProgress: number = 0;
iconScale: number = 0;
_animatorResult: AnimatorResult | undefined = undefined;
onTap: (isLike: boolean) => Promise<boolean>;
private outerCircleCurve = new Interval({
begin: 0.0,
end: 0.3,
curve: Cubic.ease,
beginValue: 0.1,
endValue: 1.0,
});
private innerCircleCurve = new Interval({
begin: 0.2,
end: 0.5,
curve: Cubic.ease,
beginValue: 0.2,
endValue: 1.0,
});
private bubblesCurve = new Interval({
begin: 0.1,
end: 1.0,
curve: new DecelerateCurve(),
beginValue: 0.0,
endValue: 1.0,
});
private iconScaleCurve = new Interval({
begin: 0.35,
end: 0.7,
curve: new OvershootCurve(),
beginValue: 0.1,
endValue: 1.0
});

initAnimation() {

let options: AnimatorOptions = {
duration: this.animationDuration,
easing: "ease",
delay: 0,
fill: "forwards",
direction: "normal",
iterations: 1,
begin: 0.0,
end: 1.0
};
// curve: const Interval(
// 0.0,
// 0.3,
// curve: Curves.ease,
// ),

this._animatorResult = animator.create(options);
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);
};
this._animatorResult.onfinish = () => {
this._animatorResult = undefined;
}
}

public isAnimating(): boolean {
return this._animatorResult != undefined;

}

play() {
if (this.isAnimating()) {
return;
}
this.initAnimation();
this._animatorResult.play();
}

dispose() {
if (this._animatorResult != undefined) {
this._animatorResult.cancel();
this._animatorResult = undefined;
}
}

Tap() {
if (this.isAnimating()) {
return;
}
this.onTap(this.isLiked).then((value) => {
this.isLiked = value;
if (this.isLiked) {
this.play();
}
});
}
}
}
}

export default like_button;
91 changes: 87 additions & 4 deletions like_button/src/main/ets/common/Curve.ets
Original file line number Diff line number Diff line change
Expand Up @@ -8,23 +8,35 @@ export class Interval extends Curve {
constructor(value: {
begin: number,
end: number,
curve: Curve
curve: Curve,
beginValue: number,
endValue: number,
}) {
super();
this.begin = value.begin;
this.end = value.end;
this.curve = value.curve;
this.beginValue = value.beginValue;
this.endValue = value.endValue;
}

begin: number;
end: number;
curve: Curve;
beginValue: number;
endValue: number;

transform(t: number): number {
t = clamp(((t - this.begin) / (this.end - this.begin)), 0.0, 1.0);
if (t == 0.0 || t == 1.0)
return t;
return this.curve.transform(t);
if (t == 0) {
return this.beginValue;
}
else if (t == 1.0) {
return this.endValue;
}
// if (t == 0.0 || t == 1.0)
// return t;
return this.beginValue + this.curve.transform(t) * (this.endValue - this.beginValue);
}
}

Expand All @@ -42,4 +54,75 @@ export class DecelerateCurve extends Curve {
t = 1.0 - t;
return 1.0 - t * t;
}
}


export class Cubic extends Curve {
constructor(a: number,
b: number,
c: number,
d: number,) {
super();
this.a = a;
this.b = b;
this.c = c;
this.d = d;
}

transform(t: number): number {
return this.transformInternal(t);
}

/// Creates a cubic curve.
///
/// Rather than creating a new instance, consider using one of the common
/// cubic curves in [Curves].
///
/// The [a] (x1), [b](x2), [c](y1), and [d](y2) arguments must not be null.

/// The x coordinate of the first control point.
///
/// The line through the point (0, 0) and the first control point is tangent
/// to the curve at the point (0, 0).
a: number;
/// The y coordinate of the first control point.
///
/// The line through the point (0, 0) and the first control point is tangent
/// to the curve at the point (0, 0).
b: number;
/// The x coordinate of the second control point.
///
/// The line through the point (1, 1) and the second control point is tangent
/// to the curve at the point (1, 1).
c: number;
/// The y coordinate of the second control point.
///
/// The line through the point (1, 1) and the second control point is tangent
/// to the curve at the point (1, 1).
d: number;
static _cubicErrorBound: number = 0.001;
static ease: Cubic = new Cubic(0.25, 0.1, 0.25, 1.0);

_evaluateCubic(a: number, b: number, m: number): number {
return 3 * a * (1 - m) * (1 - m) * m +
3 * b * (1 - m) * m * m +
m * m * m;
}


transformInternal(t: number): number {
let start: number = 0.0;
let end: number = 1.0;

while (true) {
let midpoint: number = (start + end) / 2;
let estimate: number = this._evaluateCubic(this.a, this.c, midpoint);
if (Math.abs((t - estimate)) < Cubic._cubicErrorBound)
return this._evaluateCubic(this.b, this.d, midpoint);
if (estimate < t)
start = midpoint;
else
end = midpoint;
}
}
}
Loading

0 comments on commit 023c86b

Please sign in to comment.