-
-
Notifications
You must be signed in to change notification settings - Fork 1.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
🐛 Camera Preview orientation does not update when screen orientation locks #3323
Comments
Guten Tag, Hans here 🍻 Thanks for your detailed report! It looks like a valid issue with ze camera preview orientation. Since you provided a clear reproduction path and relevant logs, mrousavy can take a look at it. Please allow some time for mrousavy to review and address this, as he is maintaining ze project in his free time. If you have any further information or updates, feel free to share them!
|
I'm using latest |
We are also using expo-screen-orientation, and we are experiencing abnormal rotation of the preview on iOS devices. What's happening?You can reproduce it by running the example app like so:
Reproduceable CodeWe are using expo-sensors to detect screen tilt and expo-screen-orientation to lock the screen orientation. App.jsimport React, { useEffect, useState } from "react";
import { StyleSheet, Text, View, Platform } from "react-native";
import {
Camera,
useCameraPermission,
useCameraDevice,
} from "react-native-vision-camera";
import {
Orientation,
OrientationLock,
getOrientationLockAsync,
lockAsync,
} from "expo-screen-orientation";
import { Accelerometer } from "expo-sensors";
const getNextOrientationFromAccelerometerEvent = (x, y, z) => {
// when the device is flat, keep the current orientation
if (Math.abs(z) > 0.5) {
return undefined;
}
if (x >= 0.75) {
return Orientation.LANDSCAPE_LEFT;
}
if (x <= -0.75) {
return Orientation.LANDSCAPE_RIGHT;
}
if (y >= 0.75) {
return Orientation.PORTRAIT_UP;
}
if (y <= -0.75) {
return Orientation.PORTRAIT_DOWN;
}
return undefined;
};
// custom hook to get the current orientation of the device
const useCurrentOrientation = () => {
const [orientation, setOrientation] = useState(Orientation.PORTRAIT_UP);
useEffect(() => {
Accelerometer.setUpdateInterval(16);
console.log("register subscription");
const subscription = Accelerometer.addListener((event) => {
const nextOrientation = getNextOrientationFromAccelerometerEvent(
event.x,
event.y,
event.z,
);
if (nextOrientation) {
setOrientation(nextOrientation);
}
});
return () => {
console.log("remove subscription");
Accelerometer.removeSubscription(subscription);
};
}, []);
return orientation;
};
const getLockOrientation = (orientation) => {
switch (orientation) {
case Orientation.PORTRAIT_UP:
return OrientationLock.PORTRAIT_UP;
case Orientation.PORTRAIT_DOWN:
return OrientationLock.PORTRAIT_UP;
case Orientation.LANDSCAPE_RIGHT:
return Platform.OS === "ios"
? OrientationLock.LANDSCAPE_RIGHT
: OrientationLock.LANDSCAPE_LEFT;
case Orientation.LANDSCAPE_LEFT:
return Platform.OS === "ios"
? OrientationLock.LANDSCAPE_LEFT
: OrientationLock.LANDSCAPE_RIGHT;
default:
return undefined;
}
};
const App = () => {
const device = useCameraDevice("back");
const { hasPermission, requestPermission } = useCameraPermission();
const orientation = useCurrentOrientation();
useEffect(() => {
if (!hasPermission) {
requestPermission();
}
}, [hasPermission]);
// lock screen orientation based on the current orientation
useEffect(() => {
const f = async () => {
console.log("orientation changed", orientation);
const lockOrientation = await getOrientationLockAsync();
const nextLockOrientation = getLockOrientation(orientation);
if (nextLockOrientation && lockOrientation !== nextLockOrientation) {
// emulates the behavior of production apps
setTimeout(() => {
lockAsync(nextLockOrientation);
}, 500);
}
};
f();
}, [orientation]);
if (!hasPermission)
return (
<View>
<Text>Camera permission required</Text>
</View>
);
if (device == null)
return (
<View>
<Text>No camera device found</Text>
</View>
);
return (
<Camera style={StyleSheet.absoluteFill} device={device} isActive={true} />
);
};
export default App; package.json{
"name": "vision-camera-poc-2",
"version": "1.0.0",
"main": "index.js",
"scripts": {
"ios": "expo run:ios --device",
"android": "expo run:android"
},
"dependencies": {
"@react-navigation/native": "^7.0.9",
"@react-navigation/native-stack": "^7.1.10",
"expo": "~50.0.17",
"expo-screen-orientation": "~6.4.1",
"expo-sensors": "~12.9.1",
"expo-status-bar": "~1.11.1",
"react": "18.2.0",
"react-native": "0.73.6",
"react-native-orientation-locker": "^1.7.0",
"react-native-safe-area-context": "4.8.2",
"react-native-screens": "4",
"react-native-vision-camera": "^4.6.3"
},
"devDependencies": {
"@babel/core": "^7.20.0"
},
"private": true
} Relevant log output
Camera DeviceiPhone11 (iOS 16.6.1) Device
VisionCamera Version4.6.3 RPReplay_Final1733896819.MP4 |
After several attempts I found a solution that helped me:
Basically, you need to rerender the Camera component after handling the OrientationChangeListener (you can also change the Camera prop "key"). |
What's happening?
I have a following scenario in my application:
You can reproduce it by running the example app like so;
All videos are recorded properly, in landscape mode. I'm having issues only with preview orientation.
Sometimes camera preview flips with screen locking but most of the time it stays in previous orientation.
Also if I'll shake device a little orientation change to the right one.
I'm using expo-screen-orientation for locking orientation
Example app:
https://github.com/dawidzawada/camera-bug
Reproduceable Code
Relevant log output
Camera Device
Device
iPhone 12
VisionCamera Version
4.6.3
Can you reproduce this issue in the VisionCamera Example app?
Yes, I can reproduce the same issue in the Example app here
Additional information
The text was updated successfully, but these errors were encountered: