@magnetman103/react-native-zoom-toolkit
Version:
Most complete set of pinch to zoom utilites for React Native
103 lines (100 loc) • 3.39 kB
JavaScript
import { Dimensions } from 'react-native';
import { useDerivedValue, useSharedValue } from 'react-native-reanimated';
import { useVector } from '../commons/hooks/useVector';
import { useSizeVector } from '../commons/hooks/useSizeVector';
const {
width,
height
} = Dimensions.get('window');
const initialPosition = -1 * Math.max(width, height);
export const useTransformationState = param => {
const size = useSizeVector(0, 0);
const translate = useVector(0, 0);
const scale = useSharedValue(1);
const xy = useVector(initialPosition, initialPosition);
const resize = useSizeVector(0, 0);
const rotate = useVector(0, 0);
const rotation = useSharedValue(0);
// Matrices taken from https://stackoverflow.com/questions/77616182/x-rotation-looks-weird
const transform = useDerivedValue(() => {
const r = rotation.value;
const rx = rotate.x.value;
const ry = rotate.y.value;
const sc = scale.value;
// Precalculated matrix for scale, rotate, rotateX and rotateY transformations.
const matrix = [];
matrix[0] = sc * Math.cos(ry) * Math.cos(r);
matrix[1] = sc * Math.sin(ry) * Math.sin(rx) * Math.cos(r) - sc * Math.cos(rx) * Math.sin(r);
matrix[2] = sc * Math.sin(rx) * Math.sin(r) + sc * Math.sin(ry) * Math.cos(rx) * Math.cos(r);
matrix[3] = 0;
matrix[4] = sc * Math.cos(ry) * Math.sin(r);
matrix[5] = sc * Math.cos(rx) * Math.cos(r) + sc * Math.sin(ry) * Math.sin(rx) * Math.sin(r);
matrix[6] = sc * Math.sin(ry) * Math.cos(rx) * Math.sin(r) - sc * Math.sin(rx) * Math.cos(r);
matrix[7] = 0;
matrix[8] = -1 * Math.sin(ry);
matrix[9] = Math.cos(ry) * Math.sin(rx);
matrix[10] = Math.cos(ry) * Math.cos(rx);
matrix[11] = 0;
matrix[12] = 0;
matrix[13] = 0;
matrix[14] = 0;
matrix[15] = 1;
return [{
translateX: translate.x.value
}, {
translateY: translate.y.value
}, {
matrix
}];
}, [translate, scale, rotation, rotate]);
const createSharedState = () => {
// @ts-ignore
const state = {
width: size.width,
height: size.height,
translateX: translate.x,
translateY: translate.y,
scale: scale
};
if (param === 'crop') {
state.rotateX = rotate.x;
state.rotateY = rotate.y;
state.rotate = rotation;
}
if (param === 'snapback') {
state.x = xy.x;
state.y = xy.y;
state.resizedWidth = resize.width;
state.resizedHeight = resize.height;
}
return state;
};
const onUpdate = state => {
'worklet';
size.width.value = state.width;
size.height.value = state.height;
translate.x.value = state.translateX;
translate.y.value = state.translateY;
scale.value = state.scale;
if (param === 'crop') {
const cropState = state;
rotate.x.value = cropState.rotateX;
rotate.y.value = cropState.rotateY;
rotation.value = cropState.rotate;
}
if (param === 'snapback') {
const snapbackState = state;
snapbackState.resizedWidth && (resize.width.value = snapbackState.resizedWidth);
snapbackState.resizedHeight && (resize.height.value = snapbackState.resizedHeight);
xy.x.value = state.x;
xy.y.value = state.y;
}
};
const sharedState = createSharedState();
return {
onUpdate,
transform,
state: sharedState
};
};
//# sourceMappingURL=useTransformationState.js.map