react-native-reanimated
Version:
More powerful alternative to Animated library for React Native.
158 lines (140 loc) • 4.14 kB
text/typescript
import { NativeReanimated } from '../NativeReanimated/NativeReanimated';
import {
SensorType,
ShareableRef,
Value3D,
ValueRotation,
} from '../commonTypes';
import { WebSensor } from './WebSensor';
export default class JSReanimated extends NativeReanimated {
nextSensorId = 0;
sensors = new Map<number, WebSensor>();
constructor() {
super(false);
}
makeShareableClone<T>(value: T): ShareableRef<T> {
return { __hostObjectShareableJSRef: value };
}
installCoreFunctions(
_callGuard: <T extends Array<any>, U>(
fn: (...args: T) => U,
...args: T
) => void,
_valueUnpacker: <T>(value: T) => T
): void {
// noop
}
scheduleOnUI<T>(worklet: ShareableRef<T>) {
// @ts-ignore web implementation has still not been updated after the rewrite, this will be addressed once the web implementation updates are ready
requestAnimationFrame(worklet);
}
registerEventHandler<T>(
_eventHash: string,
_eventHandler: ShareableRef<T>
): string {
// noop
return '';
}
unregisterEventHandler(_: string): void {
// noop
}
enableLayoutAnimations() {
console.warn(
'[Reanimated] enableLayoutAnimations is not available for WEB yet'
);
}
registerSensor(
sensorType: SensorType,
interval: number,
iosReferenceFrame: number,
eventHandler: (data: Value3D | ValueRotation) => void
): number {
if (!(this.getSensorName(sensorType) in window)) {
return -1;
}
const sensor: WebSensor = this.initializeSensor(sensorType, interval);
let callback;
if (sensorType === SensorType.ROTATION) {
callback = () => {
const [qw, qx, qy, qz] = sensor.quaternion;
// reference: https://stackoverflow.com/questions/5782658/extracting-yaw-from-a-quaternion
const yaw = Math.atan2(
2.0 * (qy * qz + qw * qx),
qw * qw - qx * qx - qy * qy + qz * qz
);
const pitch = Math.sin(-2.0 * (qx * qz - qw * qy));
const roll = Math.atan2(
2.0 * (qx * qy + qw * qz),
qw * qw + qx * qx - qy * qy - qz * qz
);
eventHandler({
qw,
qx,
qy,
qz,
yaw,
pitch,
roll,
interfaceOrientation: 0,
});
};
} else {
callback = () => {
const { x, y, z } = sensor;
eventHandler({ x, y, z, interfaceOrientation: 0 });
};
}
sensor.addEventListener('reading', callback);
sensor.start();
this.sensors.set(this.nextSensorId, sensor);
return this.nextSensorId++;
}
unregisterSensor(id: number): void {
const sensor: WebSensor | undefined = this.sensors.get(id);
if (sensor !== undefined) {
sensor.stop();
this.sensors.delete(id);
}
}
subscribeForKeyboardEvents(_: ShareableRef<number>): number {
console.warn(
'[Reanimated] useAnimatedKeyboard is not available on web yet.'
);
return -1;
}
unsubscribeFromKeyboardEvents(_: number): void {
// noop
}
initializeSensor(sensorType: SensorType, interval: number): WebSensor {
const config =
interval <= 0
? { referenceFrame: 'device' }
: { frequency: 1000 / interval };
switch (sensorType) {
case SensorType.ACCELEROMETER:
return new window.Accelerometer(config);
case SensorType.GYROSCOPE:
return new window.Gyroscope(config);
case SensorType.GRAVITY:
return new window.GravitySensor(config);
case SensorType.MAGNETIC_FIELD:
return new window.Magnetometer(config);
case SensorType.ROTATION:
return new window.AbsoluteOrientationSensor(config);
}
}
getSensorName(sensorType: SensorType): string {
switch (sensorType) {
case SensorType.ACCELEROMETER:
return 'Accelerometer';
case SensorType.GRAVITY:
return 'GravitySensor';
case SensorType.GYROSCOPE:
return 'Gyroscope';
case SensorType.MAGNETIC_FIELD:
return 'Magnetometer';
case SensorType.ROTATION:
return 'AbsoluteOrientationSensor';
}
}
}