Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Animation 时支持自定义贝塞尔曲线 timingFunction #785

Merged
merged 2 commits into from
Aug 29, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,11 @@
import android.os.Build;
import android.text.TextUtils;
import android.view.animation.*;

import java.util.ArrayList;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import com.tencent.mtt.hippy.common.HippyArray;
import com.tencent.mtt.hippy.common.HippyMap;
import com.tencent.mtt.hippy.dom.node.NodeProps;
Expand All @@ -37,6 +42,7 @@ public class TimingAnimation extends Animation implements ValueAnimator.Animator
private static final String TIMING_FUNCTION_EASE_OUT = "ease-out";
private static final String TIMING_FUNCTION_EASE_IN_OUT = "ease-in-out";
private static final String TIMING_FUNCTION_EASE_BEZIER = "ease_bezier";
private static final Pattern TIMING_FUNCTION_CUBIC_BEZIER_PATTERN = Pattern.compile("^cubic-bezier\\(([^,]*),([^,]*),([^,]*),([^,]*)\\)$");
protected float mStartValue;
protected float mToValue;
protected int mDuration;
Expand Down Expand Up @@ -182,14 +188,32 @@ public void parseFromData(HippyMap param) {
} else if (TextUtils.equals(TIMING_FUNCTION_EASE_IN_OUT, mTimingFunction)) {
mAnimator.setInterpolator(new AccelerateDecelerateInterpolator());
} else if (TextUtils.equals(TIMING_FUNCTION_EASE_BEZIER, mTimingFunction)) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
mAnimator.setInterpolator(new PathInterpolator(0.42f, 0, 1, 1));
this.setCubicBezierInterpolator(0.42f, 0, 1, 1);
} else {
Matcher matcher = TIMING_FUNCTION_CUBIC_BEZIER_PATTERN.matcher(mTimingFunction.trim());
if (matcher.matches()) {
try {
this.setCubicBezierInterpolator(
Float.parseFloat(matcher.group(1)),
Float.parseFloat(matcher.group(2)),
Float.parseFloat(matcher.group(3)),
Float.parseFloat(matcher.group(4))
);
} catch (Exception e) {
mAnimator.setInterpolator(new LinearInterpolator());
}
} else {
mAnimator.setInterpolator(new BezierInterpolator(0.42f, 0, 1, 1));
mAnimator.setInterpolator(new LinearInterpolator());
}
} else {
mAnimator.setInterpolator(new LinearInterpolator());
}
mAnimator.setStartDelay(mDelay);
}

private void setCubicBezierInterpolator(float p1x, float p1y, float p2x, float p2y) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
mAnimator.setInterpolator(new PathInterpolator(p1x, p1y, p2x, p2y));
} else {
mAnimator.setInterpolator(new BezierInterpolator(p1x, p1y, p2x, p2y));
}
}
}
214 changes: 119 additions & 95 deletions docs/hippy-react/best-practices.md

Large diffs are not rendered by default.

190 changes: 95 additions & 95 deletions docs/hippy-react/modules.md

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions examples/android-demo/res/index.android.js

Large diffs are not rendered by default.

12 changes: 6 additions & 6 deletions examples/android-demo/res/vendor.android.js

Large diffs are not rendered by default.

74 changes: 73 additions & 1 deletion examples/hippy-react-demo/src/modules/Animation/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ export default class AnimationExample extends React.Component {
duration: 1000, // 动画持续时长
delay: 500, // 至动画真正开始的延迟时间
mode: 'timing', // 动画模式
timingFunction: 'ease-in', // 动画缓动函数
timingFunction: 'linear', // 动画缓动函数
repeatCount: 'loop',
});
this.verticalAnimation = new Animation({
Expand Down Expand Up @@ -174,6 +174,34 @@ export default class AnimationExample extends React.Component {
],
repeatCount: 'loop',
});

// timingFunction cubic-bezier 范例
this.cubicBezierScaleAnimationSet = new AnimationSet({
children: [
{
animation: new Animation({
startValue: 0,
toValue: 1,
duration: 1000,
delay: 0,
mode: 'timing',
timingFunction: 'cubic-bezier(.45,2.84,.38,.5)',
}),
follow: false,
},
{
animation: new Animation({
startValue: 1,
toValue: 0,
duration: 1000,
mode: 'timing',
timingFunction: 'cubic-bezier(.17,1.45,.78,.14)',
}),
follow: true,
},
],
repeatCount: 'loop',
});
}

componentDidMount() {
Expand All @@ -184,6 +212,7 @@ export default class AnimationExample extends React.Component {
this.scaleAnimationSet.setRef(this.scaleRef);
this.bgColorAnimationSet.setRef(this.bgColorRef);
this.txtColorAnimationSet.setRef(this.textColorRef);
this.cubicBezierScaleAnimationSet.setRef(this.cubicBezierScaleRef);
}
this.horizonAnimation.onHippyAnimationStart(() => {
/* eslint-disable-next-line no-console */
Expand Down Expand Up @@ -213,6 +242,9 @@ export default class AnimationExample extends React.Component {
if (this.verticalAnimation) {
this.verticalAnimation.destroy();
}
if (this.cubicBezierScaleAnimationSet) {
this.cubicBezierScaleAnimationSet.destroy();
}
}

render() {
Expand Down Expand Up @@ -391,6 +423,46 @@ export default class AnimationExample extends React.Component {
color: Platform.OS === 'android' ? this.txtColorAnimationSet : 'white',
}]}>颜色渐变背景和文字</Text></View>
</View>

<Text style={styles.title}>贝塞尔曲线动画</Text>
<View style={styles.buttonContainer}>
<View
style={styles.button}
onClick={() => {
this.cubicBezierScaleAnimationSet.start();
}}
>
<Text style={styles.buttonText}>开始</Text>
</View>
<View
style={[styles.button]}
onClick={() => {
this.cubicBezierScaleAnimationSet.pause();
}}
>
<Text style={styles.buttonText}>暂停</Text>
</View>
<View
style={styles.button}
onClick={() => {
this.cubicBezierScaleAnimationSet.resume();
}}
>
<Text style={styles.buttonText}>继续</Text>
</View>
</View>
<View style={[styles.showArea, { marginVertical: 20 }]}>
<View
ref={(ref) => {
this.cubicBezierScaleRef = ref;
}}
style={[styles.square, {
transform: [{
scale: this.cubicBezierScaleAnimationSet,
}],
}]}
/>
</View>
</ScrollView>
);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
<template>
<div>
<animation
ref="animationView"
:playing="playing"
:actions="loopActions"
class="loop-green"
>
<div class="loop-white">
<slot />
</div>
</animation>
</div>
</template>

<script>
const horizonAnimation = {
transform: {
translateX: [
{
startValue: 50,
toValue: 150,
duration: 1000,
repeatCount: -1,
timingFunction: 'cubic-bezier( 0.45,2.84, 000.38,.5)',
},
{
startValue: 150,
toValue: 50,
duration: 1000,
repeatCount: -1,
timingFunction: 'cubic-bezier( 0.45,2.84, 000.38,.5)',
},
],
},
};

export default {
props: {
playing: Boolean,
onRef: Function,
},
data() {
return {
loopActions: horizonAnimation,
};
},
mounted() {
if (this.$props.onRef) {
this.$props.onRef(this.$refs.animationView);
}
},
};
</script>

<style scope>
.loop-green {
margin-top: 10px;
justify-content: center;
align-items: center;
background-color: #40b883;
width: 200px;
height: 80px;
}

.loop-white {
justify-content: center;
align-items: center;
background-color: white;
width: 160px;
height: 50px;
}
</style>
Loading