μ΅κ·Ό μ§νν νλ‘μ νΈμμ λͺ¨λ°μΌμμ μμΉ μ 보λΏλ§ μλλΌ μ¬μ©μμ λ°©ν₯(heading) μ 보λ₯Ό μ€μκ°μΌλ‘ κ°μ Έμ€λ κΈ°λ₯μ ꡬννμ΅λλ€.
νμ§λ§ μ¬μ©μμ μμΉμ λ°©ν₯ μ 보λ₯Ό κ°μ Έμ€λ κΈ°λ₯μ ꡬννλ©΄μ μμμΉ λͺ»ν λ¬Έμ λ₯Ό λ§μ£Όνμ΅λλ€.
λ°μ€ν¬νμμλ κ°μ λ‘ μν κ°μ λ³κ²½νλ©° ν
μ€νΈν λ μ λμνμ§λ§, λͺ¨λ°μΌμμλ λ°©ν₯ λ°μ΄ν°(alpha
)λ₯Ό λ°μμ€μ§ λͺ»νμ΅λλ€.
λ§μ μ‘°μ¬ λμ iOSμμλ Device Orientation API μ¬μ© μ κΆν νμ© μ μ°¨κ° νμνλ€λ μ¬μ€μ μκ² λμκ³ , μ΄λ₯Ό ν΄κ²°νκΈ° μν΄ κΆνμ μμ²νλ λ‘μ§μ μΆκ°ν΄μ£Όμμ΅λλ€.
μ μ νλ‘μ νΈλ₯Ό ν λμλ λ Ήμκ³Ό κ΄λ ¨ν΄μ iosμμ κΆν λ¬Έμ κ° λ°μνλ μ μ΄ μμ΄μ, μ΄λ²μλ λΉμ·ν λ¬Έμ κ² κ±°λ μΆμ΄ λΉκ΅μ κΈλ°© ν΄κ²°ν΄ λΌ μ μμλ κ² κ°μ΅λλ€.
μ΄λ² ν¬μ€ν μμλ iosμμ νμ λ°©ν₯μ κ°μ Έμ€λ κΆνμ μμ²λ°λ λ‘μ§μ μΆκ°νκΈ° μν κ³Όμ μ μμ±ν΄λ³΄λ € ν©λλ€.
νλ‘μ νΈλ₯Ό μ§ννλ©° μμΉ(μλ/κ²½λ)μ λ°©ν₯(heading) λ°μ΄ν°λ₯Ό λμμ κ°μ Έμ€λ €κ³ νμ΅λλ€. Geolocation API
λ₯Ό ν΅ν΄ heading
κ°μ μ»μ μ μμ§λ§, μ΄ κ°μ μ¬μ©μκ° μμ§μ΄κ³ μμ λλ§ μ ν¨ν©λλ€.
κ·Έλ¬λκΉ heading
κ°μ μ¬μ©νκ² λλ©΄, μ μ§ μνμμλ heading
κ°μ΄ nullλ‘ λ°νλλ€λ λ¬Έμ κ° λ°μν©λλ€.
μ΄λ₯Ό 보μνκΈ° μν΄ Device Orientation API
λ₯Ό μ¬μ©νμ¬ alpha(κΈ°κΈ° λ°©ν₯) κ°μ νμ©νκΈ°λ‘ νμ΅λλ€.
heading
κ° νκ³μΌλΆ κ°λ° λ¬Έμλ₯Ό μ°Έκ³ νμ λ, μμΉ μ 보(GeoLocation)μμ heading
κ°μ νμ©ν μλ μμμ΅λλ€.
μ΄λ―Έ μ΄λ μμΉλ₯Ό λ°μμ€κΈ° μν΄ GeoLocation
μ μ¬μ©νκ³ μμκΈ° λλ¬Έμ, μ΅λν GeoLocation
μ κ°μ μ¬μ©νλ κ²μ΄ μ’λ€κ³ νλ¨νμμ§λ§, μμμ μμ±ν λλ‘ GeoLocation
μμ λ°©ν₯μ λ°μμ€λ©΄ μ ν¬ νλ‘μ νΈμ λ§μ§ μλ λ¬Έμ κ° μμμ΅λλ€.
heading
κ°μ μ¬μ©μκ° μ΄λ μ€μΌ λμλ§ κ³μ°λλ©°, μ μ§ μνμμλ μ ν¨νμ§ μμ κ°μ΄κ±°λ null
μ λ°ννλ λ¬Έμ κ° μμκΈ° λλ¬Έμ,
μ μ§ μνμμλ μ¬μ©μμ λ°©ν₯ λ°μ΄ν°λ₯Ό μμ μ μΌλ‘ κ°μ Έμ€κΈ° μν΄ Device Orientation APIμ alpha
κ°μ μ¬μ©νκΈ°λ‘ κ²°μ νμ΅λλ€.
μΉμμ μ¬μ©μμ λ°©ν₯ λ°μ΄ν°λ₯Ό μ»κΈ° μν΄ DeviceOrientationEventλ₯Ό μ¬μ©νμ΅λλ€. μ΄ μ΄λ²€νΈλ alpha
(κΈ°λ³Έ λ°©ν₯), beta
(μμλ κΈ°μΈκΈ°), gamma
(μ’μ° κΈ°μΈκΈ°) κ°μ μ 곡ν©λλ€.
κ·Έλ°λ° λ°μ€ν¬νμμλ μ λμνλ μ½λκ° λͺ¨λ°μΌ(νΉν iOS)μμλ alpha
κ°μ΄ nullλ‘ λ°νλλ λ¬Έμ κ° λ°μνμ΅λλ€.
μλμ κ°μ΄, κ°λ°μ λꡬμ μΌμλ₯Ό νμ©νμ¬ alpha κ°μ λ°κΏμ£Όλ©΄, κ·Έμ λ§κ² μ΄λ―Έμ§κ° μ νμ νλ κ²μ νμΈν μ μμμ§λ§,
ios νκ²½μμλ μ΄ νμ μ μ λλ‘ λ°μμ€μ§ λͺ»νλ λ¬Έμ κ° μμκ³ , κ°€λμμμλ λ³λμ μ€μ μμ΄λ μ λμνλ κ²μ νμΈν μ μμμ΅λλ€.
κ°€λμμμλ λλλ° iosμμ λμ§ μλ κ²½μ°λ₯Ό μ΄μ μΈν΄ νλ‘μ νΈμμ κ²ͺμ΄λ΄€μκ³ , λ Ήμκ³Ό κ΄λ ¨ν κΆν λ¬Έμ μμ΄μ μ΄λ²μλ iosμ κΆν λ¬Έμ μΌ κ²μ΄λΌκ³ μ½κ² μΆμΈ‘μ΄ κ°λ₯νκ³ ,
μ€μ λ‘ iOS νκ²½μμλ Device Orientation APIλ₯Ό μ¬μ©νλ λ° κΆν μμ²μ΄ νμνλ©°, κΆνμ΄ μμΌλ©΄ λ°μ΄ν°(alpha
, beta
, gamma
)κ° null
λ‘ λ°νλλ€λ κ²μ νμΈν μ μμμ΅λλ€.
κ·Έλμ iosμμ κΆνμ νμ©ν΄μ£ΌκΈ° μν λ‘μ§μ μΆκ°ν΄μ£Όμμ΅λλ€.
DeviceOrientationEvent.requestPermission()
λ©μλλ₯Ό μ¬μ©νμ¬ κΆνμ μμ²ν©λλ€. μ΄ λ©μλλ νλ‘λ―Έμ€λ₯Ό λ°ννλ©°, μ±κ³΅μ μΌλ‘ κΆνμ΄ λΆμ¬λλ©΄ μ΄λ²€νΈ 리μ€λλ₯Ό μΆκ°ν©λλ€.
const requestOrientationPermission = async () => {
const DeviceOrientationEventTyped =
DeviceOrientationEvent as unknown as IDeviceOrientationEventWithPermission;
if (
typeof DeviceOrientationEventTyped !== 'undefined' &&
typeof DeviceOrientationEventTyped.requestPermission === 'function'
) {
try {
const permission = await DeviceOrientationEventTyped.requestPermission();
if (permission === 'granted') {
window.addEventListener('deviceorientation', handleOrientation);
} else {
console.error('Device Orientation permission denied.');
}
} catch (error) {
console.error('Failed to request Device Orientation permission:', error);
}
} else {
console.warn('DeviceOrientationEvent.requestPermission is not supported on this browser.');
window.addEventListener('deviceorientation', handleOrientation);
}
};
κΆνμ μ»μ λ€ deviceorientation
μ΄λ²€νΈλ₯Ό ν΅ν΄ λ°©ν₯ λ°μ΄ν°λ₯Ό κ°μ Έμ΅λλ€.
const handleOrientation = (event: DeviceOrientationEvent) => {
if (event.alpha !== null) {
setLocation(prev => ({ ...prev, alpha: event.alpha }));
}
};
useState
λ₯Ό ν΅ν΄ μ¬μ©μμ μμΉ(μλ, κ²½λ)μ λ°©ν₯(alpha) λ°μ΄ν°λ₯Ό μ μ₯ν©λλ€.
λ§μ½ λ°©ν₯ λ°μ΄ν°λ₯Ό κ°μ Έμ€μ§ λͺ»νλ κ²½μ°, λν΄νΈ κ°μΌλ‘ μ€μ ν©λλ€.
const [location, setLocation] = useState<IGetUserLocation>({
lat: null,
lng: null,
alpha: null,
error: null,
});
useEffect(() => {
let watchId: number;
const handlePosition = (position: GeolocationPosition) => {
setLocation(prev => ({
...prev,
lat: position.coords.latitude,
lng: position.coords.longitude,
error: null,
}));
};
const handleError = (error: GeolocationPositionError) => {
setLocation({
lat: 37.3595704,
lng: 127.105399,
alpha: 0,
error: error.message,
});
};
if (navigator.geolocation) {
watchId = navigator.geolocation.watchPosition(handlePosition, handleError, {
enableHighAccuracy: true,
maximumAge: 5000,
timeout: 10000,
});
} else {
setLocation({
lat: 37.3595704,
lng: 127.105399,
alpha: 0,
error: 'νμ¬ μμΉλ₯Ό λΆλ¬μ€μ§ λͺ»νμ΅λλ€',
});
}
const handleOrientation = (event: DeviceOrientationEvent) => {
if (event.alpha !== null) {
setLocation(prev => ({ ...prev, alpha: event.alpha }));
}
};
const requestOrientationPermission = async () => {
const DeviceOrientationEventTyped =
DeviceOrientationEvent as unknown as IDeviceOrientationEventWithPermission;
if (
typeof DeviceOrientationEventTyped !== 'undefined' &&
typeof DeviceOrientationEventTyped.requestPermission === 'function'
) {
try {
const permission = await DeviceOrientationEventTyped.requestPermission();
if (permission === 'granted') {
window.addEventListener('deviceorientation', handleOrientation);
} else {
console.error('Device Orientation permission denied.');
}
} catch (error) {
console.error('Failed to request Device Orientation permission:', error);
}
} else {
console.warn('DeviceOrientationEvent.requestPermission is not supported on this browser.');
window.addEventListener('deviceorientation', handleOrientation);
}
};
requestOrientationPermission().then(() => {
window.addEventListener('deviceorientation', handleOrientation);
});
return () => {
if (watchId) navigator.geolocation.clearWatch(watchId);
window.removeEventListener('deviceorientation', handleOrientation);
};
}, []);
κ²°λ‘ μ μΌλ‘ iOSμμ λ°©ν₯ λ°μ΄ν°λ₯Ό λ°μμ€κΈ° μν΄ κΆν μμ² λ‘μ§μ μΆκ°νκ³ λͺ¨λ°μΌμμλ μ μμ μΌλ‘ λ°μ΄ν°λ₯Ό μ²λ¦¬ν μ μμμ΅λλ€.
μ΄λ²μλ iosμ κΆν λ¬Έμ μΈ κ²μ νμΈνκ³ β¦.. μμλ λλ°μ΄μ€ λ³λ‘ μΈμΈν ν μ€νΈκ° κΌ νμνκ³ μ€μνλ€λ κ²μ ν λ² λ κΉ¨λ«κ² λμμ΅λλ€.