Skip to content

Instantly share code, notes, and snippets.

@manduks
Created May 12, 2022 00:43
Show Gist options
  • Save manduks/8344e96634c379af45a4ab5a0e6d2db4 to your computer and use it in GitHub Desktop.
Save manduks/8344e96634c379af45a4ab5a0e6d2db4 to your computer and use it in GitHub Desktop.
import { useState, useEffect, useRef } from "react";
import {
PinchGestureHandler,
PinchGestureHandlerGestureEvent,
State,
} from "react-native-gesture-handler";
import {
StyleSheet,
Text,
View,
TouchableOpacity,
Animated,
} from "react-native";
import { Camera } from "expo-camera";
import { MaterialIcons } from "@expo/vector-icons";
import { RootTabParamList } from "../types";
import type { NativeStackScreenProps } from "@react-navigation/native-stack";
type CameraScreenProps = NativeStackScreenProps<RootTabParamList, "TabOne">;
const PITCH_SCALE = new Animated.Value(1);
type ImageType = {
height: number;
width: number;
uri: string;
} | null;
export enum CameraType {
front = "front",
back = "back",
}
export default function CameraScreen({ navigation }: CameraScreenProps) {
const [hasPermission, setHasPermission] = useState(false);
const [type, setType] = useState(CameraType.back);
const [zoomValue, setZoomValue] = useState(0);
const [image, setImage] = useState<ImageType>(null);
const cameraRef = useRef<any>();
useEffect(() => {
(async () => {
const { status } = await Camera.requestCameraPermissionsAsync();
setHasPermission(status === "granted");
})();
}, []);
if (hasPermission === null) {
return <View />;
}
if (hasPermission === false) {
return <Text>No access to camera</Text>;
}
const onPinchGestureEvent = (event: PinchGestureHandlerGestureEvent) => {
let scale = event.nativeEvent.scale;
scale = scale < 0.5 ? 0 : scale > 3 ? 3 : scale;
setZoomValue((scale * 20) / 3000);
};
return image ? (
<View style={styles.imageContainer}>
<Animated.Image style={[styles.pinchableImage]} source={image} />
<View style={styles.imageActionsContent}>
<TouchableOpacity
onPress={() => {
setImage(null);
}}
>
<Text style={styles.cancelText}> Cancel </Text>
</TouchableOpacity>
<TouchableOpacity onPress={() => {}}>
<Text style={styles.cancelText}> Use </Text>
</TouchableOpacity>
</View>
</View>
) : (
<View style={styles.container}>
<Camera
style={styles.camera}
type={type}
ref={cameraRef}
zoom={zoomValue}
>
<PinchGestureHandler onGestureEvent={onPinchGestureEvent}>
<Animated.View style={styles.photoContainer}></Animated.View>
</PinchGestureHandler>
<View style={styles.actionsContainer}>
<View style={styles.actionsHeader}>
<Text style={styles.headerTitle}> PHOTO </Text>
</View>
<View style={styles.actionsContent}>
<TouchableOpacity
onPress={() => {
navigation.navigate("TabOne");
}}
>
<Text style={styles.cancelText}> Cancel </Text>
</TouchableOpacity>
<View style={styles.takePhoto}>
<TouchableOpacity
style={styles.takePhotoInner}
onPress={async () => {
let photo = await cameraRef?.current.takePictureAsync();
console.log(photo);
setImage(photo);
}}
></TouchableOpacity>
</View>
<TouchableOpacity
onPress={() => {
setType(
type === CameraType.back ? CameraType.front : CameraType.back
);
}}
>
<MaterialIcons
size={30}
style={{ marginBottom: -3 }}
color="white"
name="flip-camera-android"
/>
</TouchableOpacity>
</View>
</View>
</Camera>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: "center",
justifyContent: "center",
},
photoContainer: {
flex: 1,
},
camera: {
flex: 1,
width: "100%",
justifyContent: "flex-end",
},
actionsContainer: {
height: 120,
backgroundColor: "black",
},
actionsHeader: {
width: "100%",
alignItems: "center",
justifyContent: "center",
paddingTop: 4,
paddingLeft: 0,
},
headerTitle: {
fontSize: 14,
color: "yellow",
},
actionsContent: {
display: "flex",
flexDirection: "row",
alignItems: "center",
paddingHorizontal: 16,
paddingVertical: 8,
justifyContent: "space-between",
flex: 1,
},
cancelText: {
color: "white",
fontSize: 16,
fontWeight: "600",
},
takePhoto: {
height: 60,
width: 60,
borderRadius: 60,
backgroundColor: "white",
alignItems: "center",
justifyContent: "center",
marginRight: 28,
},
takePhotoInner: {
height: 50,
width: 50,
borderRadius: 50,
backgroundColor: "white",
borderWidth: 2,
borderColor: "black",
},
// image
imageContainer: {
flex: 1,
alignItems: "center",
justifyContent: "center",
},
pinchableImage: {
flex: 6,
justifyContent: "center",
alignItems: "center",
resizeMode: "contain",
},
imageActionsContent: {
display: "flex",
flexDirection: "row",
alignItems: "center",
paddingHorizontal: 16,
paddingVertical: 8,
justifyContent: "space-around",
flex: 1,
width: "100%",
},
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment