expo-dynamic-image-crop
Version:
Dynamic image cropping component for Expo/React Native with free-form and fixed aspect ratio support
69 lines (68 loc) • 2.85 kB
JavaScript
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import { useEffect, useState } from "react";
import { Image, StyleSheet, View } from "react-native";
import { ImageCropOverlay } from "./ImageCropOverlay";
import { useEditorStore } from "./store";
export function EditingWindow() {
const [imageLayout, setImageLayout] = useState(null);
const imageData = useEditorStore((s) => s.imageData);
const setImageBounds = useEditorStore((s) => s.setImageBounds);
const setImageScaleFactor = useEditorStore((s) => s.setImageScaleFactor);
const editingMode = useEditorStore((s) => s.editingMode);
const isCropping = editingMode === "crop";
const getImageFrame = (layout) => {
onUpdateCropLayout(layout);
};
const onUpdateCropLayout = (layout) => {
if (layout) {
const editingWindowAspectRatio = layout.height / layout.width;
const imageAspectRatio = imageData.height / imageData.width;
const bounds = { x: 0, y: 0, width: 0, height: 0 };
let imageScaleFactor = 1;
if (imageAspectRatio > editingWindowAspectRatio) {
bounds.x =
(((imageAspectRatio - editingWindowAspectRatio) / imageAspectRatio) *
layout.width) /
2;
bounds.width = layout.height / imageAspectRatio;
bounds.height = layout.height;
imageScaleFactor = imageData.height / layout.height;
}
else {
bounds.y =
(((1 / imageAspectRatio - 1 / editingWindowAspectRatio) /
(1 / imageAspectRatio)) *
layout.height) /
2;
bounds.width = layout.width;
bounds.height = layout.width * imageAspectRatio;
imageScaleFactor = imageData.width / layout.width;
}
setImageBounds(bounds);
setImageScaleFactor(imageScaleFactor);
setImageLayout({
height: layout.height,
width: layout.width,
});
}
};
useEffect(() => {
onUpdateCropLayout(imageLayout);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [imageData]);
return (_jsxs(View, { style: styles.container, children: [_jsx(Image, { style: styles.image, source: { uri: imageData.uri }, onLayout: ({ nativeEvent }) => getImageFrame(nativeEvent.layout) }), isCropping && imageLayout != null ? _jsx(ImageCropOverlay, {}) : null] }));
}
const styles = StyleSheet.create({
container: {
flex: 1,
},
image: {
flex: 1,
resizeMode: "contain",
},
glContainer: {
flex: 1,
justifyContent: "center",
alignItems: "center",
},
});