UNPKG

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
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", }, });