mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
Kotlinify FrameBasedAnimationDriver (#45764)
Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/45764 # Changelog: [Internal] - As in the title. Reviewed By: cortinico Differential Revision: D60348765 fbshipit-source-id: 1507d802044eb59c7d224ee313ae98c96468f0cd
This commit is contained in:
committed by
Facebook GitHub Bot
parent
df7e0d0fa5
commit
7903dba7ac
-114
@@ -1,114 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
package com.facebook.react.animated;
|
||||
|
||||
import com.facebook.common.logging.FLog;
|
||||
import com.facebook.react.bridge.ReadableArray;
|
||||
import com.facebook.react.bridge.ReadableMap;
|
||||
import com.facebook.react.bridge.ReadableType;
|
||||
import com.facebook.react.common.ReactConstants;
|
||||
import com.facebook.react.common.build.ReactBuildConfig;
|
||||
|
||||
/**
|
||||
* Implementation of {@link AnimationDriver} which provides a support for simple time-based
|
||||
* animations that are pre-calculate on the JS side. For each animation frame JS provides a value
|
||||
* from 0 to 1 that indicates a progress of the animation at that frame.
|
||||
*/
|
||||
class FrameBasedAnimationDriver extends AnimationDriver {
|
||||
|
||||
// 60FPS
|
||||
private static final double FRAME_TIME_MILLIS = 1000d / 60d;
|
||||
|
||||
private long mStartFrameTimeNanos;
|
||||
private double[] mFrames;
|
||||
private double mToValue;
|
||||
private double mFromValue;
|
||||
private int mIterations;
|
||||
private int mCurrentLoop;
|
||||
private int logCount = 0;
|
||||
|
||||
FrameBasedAnimationDriver(ReadableMap config) {
|
||||
resetConfig(config);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resetConfig(ReadableMap config) {
|
||||
ReadableArray frames = config.getArray("frames");
|
||||
int numberOfFrames = frames.size();
|
||||
if (mFrames == null || mFrames.length != numberOfFrames) {
|
||||
mFrames = new double[numberOfFrames];
|
||||
}
|
||||
for (int i = 0; i < numberOfFrames; i++) {
|
||||
mFrames[i] = frames.getDouble(i);
|
||||
}
|
||||
if (config.hasKey("toValue")) {
|
||||
mToValue = config.getType("toValue") == ReadableType.Number ? config.getDouble("toValue") : 0;
|
||||
} else {
|
||||
mToValue = 0;
|
||||
}
|
||||
if (config.hasKey("iterations")) {
|
||||
mIterations =
|
||||
config.getType("iterations") == ReadableType.Number ? config.getInt("iterations") : 1;
|
||||
} else {
|
||||
mIterations = 1;
|
||||
}
|
||||
mCurrentLoop = 1;
|
||||
mHasFinished = mIterations == 0;
|
||||
mStartFrameTimeNanos = -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void runAnimationStep(long frameTimeNanos) {
|
||||
if (mStartFrameTimeNanos < 0) {
|
||||
mStartFrameTimeNanos = frameTimeNanos;
|
||||
if (mCurrentLoop == 1) {
|
||||
// initiate start value when animation runs for the first time
|
||||
mFromValue = mAnimatedValue.nodeValue;
|
||||
}
|
||||
}
|
||||
|
||||
long timeFromStartMillis = (frameTimeNanos - mStartFrameTimeNanos) / 1000000;
|
||||
int frameIndex = (int) Math.round(timeFromStartMillis / FRAME_TIME_MILLIS);
|
||||
if (frameIndex < 0) {
|
||||
String message =
|
||||
"Calculated frame index should never be lower than 0. Called with frameTimeNanos "
|
||||
+ frameTimeNanos
|
||||
+ " and mStartFrameTimeNanos "
|
||||
+ mStartFrameTimeNanos;
|
||||
if (ReactBuildConfig.DEBUG) {
|
||||
throw new IllegalStateException(message);
|
||||
} else {
|
||||
if (logCount < 100) {
|
||||
FLog.w(ReactConstants.TAG, message);
|
||||
logCount++;
|
||||
}
|
||||
return;
|
||||
}
|
||||
} else if (mHasFinished) {
|
||||
// nothing to do here
|
||||
return;
|
||||
}
|
||||
|
||||
double nextValue;
|
||||
if (frameIndex >= mFrames.length - 1) {
|
||||
if (mIterations == -1 || mCurrentLoop < mIterations) {
|
||||
// Use last frame value, just in case it's different from mToValue
|
||||
nextValue = mFromValue + mFrames[mFrames.length - 1] * (mToValue - mFromValue);
|
||||
mStartFrameTimeNanos = -1;
|
||||
mCurrentLoop++;
|
||||
} else {
|
||||
// animation has completed, no more frames left
|
||||
nextValue = mToValue;
|
||||
mHasFinished = true;
|
||||
}
|
||||
} else {
|
||||
nextValue = mFromValue + mFrames[frameIndex] * (mToValue - mFromValue);
|
||||
}
|
||||
mAnimatedValue.nodeValue = nextValue;
|
||||
}
|
||||
}
|
||||
+103
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
package com.facebook.react.animated
|
||||
|
||||
import com.facebook.common.logging.FLog
|
||||
import com.facebook.react.bridge.ReadableMap
|
||||
import com.facebook.react.bridge.ReadableType
|
||||
import com.facebook.react.common.ReactConstants
|
||||
import com.facebook.react.common.build.ReactBuildConfig
|
||||
|
||||
/**
|
||||
* Implementation of [AnimationDriver] which provides a support for simple time-based animations
|
||||
* that are pre-calculate on the JS side. For each animation frame JS provides a value from 0 to 1
|
||||
* that indicates a progress of the animation at that frame.
|
||||
*/
|
||||
internal class FrameBasedAnimationDriver(config: ReadableMap) : AnimationDriver() {
|
||||
private var startFrameTimeNanos: Long = -1
|
||||
private var frames: DoubleArray = DoubleArray(0)
|
||||
private var toValue = 0.0
|
||||
private var fromValue = 0.0
|
||||
private var iterations = 1
|
||||
private var currentLoop = 1
|
||||
private var logCount = 0
|
||||
|
||||
init {
|
||||
resetConfig(config)
|
||||
}
|
||||
|
||||
override fun resetConfig(config: ReadableMap) {
|
||||
val framesConfig = config.getArray("frames")
|
||||
if (framesConfig != null) {
|
||||
val numberOfFrames = framesConfig.size()
|
||||
if (frames.size != numberOfFrames) {
|
||||
frames = DoubleArray(numberOfFrames) { i -> framesConfig.getDouble(i) }
|
||||
}
|
||||
}
|
||||
toValue =
|
||||
if (config.hasKey("toValue") && config.getType("toValue") == ReadableType.Number)
|
||||
config.getDouble("toValue")
|
||||
else 0.0
|
||||
iterations =
|
||||
if (config.hasKey("iterations") && config.getType("iterations") == ReadableType.Number)
|
||||
config.getInt("iterations")
|
||||
else 1
|
||||
currentLoop = 1
|
||||
mHasFinished = iterations == 0
|
||||
startFrameTimeNanos = -1
|
||||
}
|
||||
|
||||
override fun runAnimationStep(frameTimeNanos: Long) {
|
||||
if (startFrameTimeNanos < 0) {
|
||||
startFrameTimeNanos = frameTimeNanos
|
||||
if (currentLoop == 1) {
|
||||
// initiate start value when animation runs for the first time
|
||||
fromValue = mAnimatedValue.nodeValue
|
||||
}
|
||||
}
|
||||
val timeFromStartMillis = (frameTimeNanos - startFrameTimeNanos) / 1000000
|
||||
val frameIndex = Math.round(timeFromStartMillis / FRAME_TIME_MILLIS).toInt()
|
||||
if (frameIndex < 0) {
|
||||
val message =
|
||||
("Calculated frame index should never be lower than 0. Called with frameTimeNanos " +
|
||||
frameTimeNanos +
|
||||
" and mStartFrameTimeNanos " +
|
||||
startFrameTimeNanos)
|
||||
check(!ReactBuildConfig.DEBUG) { message }
|
||||
if (logCount < 100) {
|
||||
FLog.w(ReactConstants.TAG, message)
|
||||
logCount++
|
||||
}
|
||||
return
|
||||
} else if (mHasFinished) {
|
||||
// nothing to do here
|
||||
return
|
||||
}
|
||||
val nextValue: Double
|
||||
if (frameIndex >= frames.size - 1) {
|
||||
if (iterations == -1 || currentLoop < iterations) {
|
||||
// Use last frame value, just in case it's different from mToValue
|
||||
nextValue = fromValue + frames[frames.size - 1] * (toValue - fromValue)
|
||||
startFrameTimeNanos = -1
|
||||
currentLoop++
|
||||
} else {
|
||||
// animation has completed, no more frames left
|
||||
nextValue = toValue
|
||||
mHasFinished = true
|
||||
}
|
||||
} else {
|
||||
nextValue = fromValue + frames[frameIndex] * (toValue - fromValue)
|
||||
}
|
||||
mAnimatedValue.nodeValue = nextValue
|
||||
}
|
||||
|
||||
companion object {
|
||||
// 60FPS
|
||||
private const val FRAME_TIME_MILLIS = 1000.0 / 60.0
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user