jiuyiUniapp/service/node_modules/react-native/Libraries/Animated/nodes/AnimatedTransform.js

199 lines
5.8 KiB
JavaScript
Raw Normal View History

2025-02-13 09:59:20 +08:00
/**
* 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.
*
* @flow
* @format
*/
'use strict';
import type {PlatformConfig} from '../AnimatedPlatformConfig';
import NativeAnimatedHelper from '../../../src/private/animated/NativeAnimatedHelper';
import {validateTransform} from '../../../src/private/animated/NativeAnimatedValidation';
import AnimatedNode from './AnimatedNode';
import AnimatedWithChildren from './AnimatedWithChildren';
type Transform<T = AnimatedNode> = {
[string]:
| number
| string
| T
| $ReadOnlyArray<number | string | T>
| {[string]: number | string | T},
};
function flatAnimatedNodes(
transforms: $ReadOnlyArray<Transform<>>,
): Array<AnimatedNode> {
const nodes = [];
for (let ii = 0, length = transforms.length; ii < length; ii++) {
const transform = transforms[ii];
// There should be exactly one property in `transform`.
for (const key in transform) {
const value = transform[key];
if (value instanceof AnimatedNode) {
nodes.push(value);
}
}
}
return nodes;
}
export default class AnimatedTransform extends AnimatedWithChildren {
// NOTE: For potentially historical reasons, some operations only operate on
// the first level of AnimatedNode instances. This optimizes that bevavior.
#nodes: $ReadOnlyArray<AnimatedNode>;
_transforms: $ReadOnlyArray<Transform<>>;
/**
* Creates an `AnimatedTransform` if `transforms` contains `AnimatedNode`
* instances. Otherwise, returns `null`.
*/
static from(transforms: $ReadOnlyArray<Transform<>>): ?AnimatedTransform {
const nodes = flatAnimatedNodes(
// NOTE: This check should not be necessary, but the types are not
// enforced as of this writing. This check should be hoisted to
// instantiation sites.
Array.isArray(transforms) ? transforms : [],
);
if (nodes.length === 0) {
return null;
}
return new AnimatedTransform(nodes, transforms);
}
constructor(
nodes: $ReadOnlyArray<AnimatedNode>,
transforms: $ReadOnlyArray<Transform<>>,
) {
super();
this.#nodes = nodes;
this._transforms = transforms;
}
__makeNative(platformConfig: ?PlatformConfig) {
const nodes = this.#nodes;
for (let ii = 0, length = nodes.length; ii < length; ii++) {
const node = nodes[ii];
node.__makeNative(platformConfig);
}
super.__makeNative(platformConfig);
}
__getValue(): $ReadOnlyArray<Transform<any>> {
return mapTransforms(this._transforms, animatedNode =>
animatedNode.__getValue(),
);
}
__getValueWithStaticTransforms(
staticTransforms: $ReadOnlyArray<Object>,
): $ReadOnlyArray<Object> {
const values = [];
mapTransforms(this._transforms, node => {
values.push(node.__getValue());
});
// NOTE: We can depend on `this._transforms` and `staticTransforms` sharing
// a structure because of `useAnimatedPropsMemo`.
return mapTransforms(staticTransforms, () => values.shift());
}
__getAnimatedValue(): $ReadOnlyArray<Transform<any>> {
return mapTransforms(this._transforms, animatedNode =>
animatedNode.__getAnimatedValue(),
);
}
__attach(): void {
const nodes = this.#nodes;
for (let ii = 0, length = nodes.length; ii < length; ii++) {
const node = nodes[ii];
node.__addChild(this);
}
}
__detach(): void {
const nodes = this.#nodes;
for (let ii = 0, length = nodes.length; ii < length; ii++) {
const node = nodes[ii];
node.__removeChild(this);
}
super.__detach();
}
__getNativeConfig(): any {
const transformsConfig: Array<any> = [];
const transforms = this._transforms;
for (let ii = 0, length = transforms.length; ii < length; ii++) {
const transform = transforms[ii];
// There should be exactly one property in `transform`.
for (const key in transform) {
const value = transform[key];
if (value instanceof AnimatedNode) {
transformsConfig.push({
type: 'animated',
property: key,
nodeTag: value.__getNativeTag(),
});
} else {
transformsConfig.push({
type: 'static',
property: key,
/* $FlowFixMe[incompatible-call] - `value` can be an array or an
object. This is not currently handled by `transformDataType`.
Migrating to `TransformObject` might solve this. */
value: NativeAnimatedHelper.transformDataType(value),
});
}
}
}
if (__DEV__) {
validateTransform(transformsConfig);
}
return {
type: 'transform',
transforms: transformsConfig,
};
}
}
function mapTransforms<T>(
transforms: $ReadOnlyArray<Transform<>>,
mapFunction: AnimatedNode => T,
): $ReadOnlyArray<Transform<T>> {
return transforms.map(transform => {
const result: Transform<T> = {};
// There should be exactly one property in `transform`.
for (const key in transform) {
const value = transform[key];
if (value instanceof AnimatedNode) {
result[key] = mapFunction(value);
} else if (Array.isArray(value)) {
result[key] = value.map(element =>
element instanceof AnimatedNode ? mapFunction(element) : element,
);
} else if (typeof value === 'object') {
const object: {[string]: number | string | T} = {};
for (const propertyName in value) {
const propertyValue = value[propertyName];
object[propertyName] =
propertyValue instanceof AnimatedNode
? mapFunction(propertyValue)
: propertyValue;
}
result[key] = object;
} else {
result[key] = value;
}
}
return result;
});
}