2020. 5. 5. 20:27ㆍFrontend
해당 포스트는 https://courses.wesbos.com/account/access/5d760ba285f96c03c1e5725d/view/194128542 를 기반으로 작성되었습니다.
이번 예제는 Geolocation인터페이스를 사용해 웹에서 실시간 위치 정보 수집하기 입니다.
Geolocation.watchPosition() 사용하기
Geolocation.watchPosition()?
장치의 위치가 바뀔 때마다 자동으로 호출할 처리기 함수를 등록할 때 사용합니다. 선택적으로 오류 발생 시 사용할 콜백 함수도 지정할 수 있습니다.
-
매개변수
success
:GeolocationPosition
객체를 입력 매개변수로 사용하는 콜백 함수error
(option) :GeolocationPositionError
객체를 입력 매개변수로 사용하는 콜백 함수options
(option) : 위치 감지 설정 옵션을 제공하는PositionOptions
객체
-
반환 값 : 등록한 처리기를 식별할 때 사용하는 정수 ID. ID를 Geolocation.clearWatch()에 전달해 등록을 해제할 수 있다.
* 자세한 설명은 MDN - Geolocation.watchPosition()에서 확인하실 수 있습니다.
GeolocationPosition 위치정보 수집
성공시 얻을 수 있는 GeolocationPosition
객체에선 어떤 위치 정보를 얻을 수 있을까?
GeolocationPosition 인터페이스?
주어진 시간에 장치가 위치한 지점을 나타냅니다. 지점은 Coordinates 객체로 표현하여, 지구를 나타내는 회전타원체 위의 2D 위치와 더불어 높이와 속도 정보를 담습니다.
Position.coords
: 주어진 시간의 위치를 나타내는Coordinates
객체Position.timestamp
: 위치를 기록한 시간을 나타내는DOMTimeStamp
* 자세한 설명은 MDN - GeolocationPosition에서 확인하실 수 있습니다.
Coordinates 인터페이스
위치 및 고도 지구 장치뿐만 아니라, 이러한 특성이 계산되는 정확도를 나타낸다.
우리가 여기서 얻을 수 있는 정보는 다음과 같다.
latitude
: 위도longitude
: 경도altitude
: 고도accuracy
: 위도, 경도 정확도altitudeAccuracy
: 고도 정확도heading
: 이동 방향speed
: 장치 속도
* 자세한 설명은 MDN - GeolocationCoordinates에서 확인하실 수 있습니다.
만들어 볼 예제
이러한 웹 사이트를 만드는 예제입니다.
실습 결과 확인은 스마트폰에서 npm 외부 링크로 접속해 확인하였습니다.
필요 기능을 분석해보자면,
- 사이트에 접속한 직후부터 동의하에 위치 정보를 수집합니다.
- 실시간 위치 정보를 바탕으로 나침반의 방향이 바뀌고 현재 속도가 표시됩니다.
예제 시작 코드
Wesbos께서 시작 코드를 제공해주시고 계십니다.
https://github.com/wesbos/JavaScript30/tree/master/21%20-%20Geolocation
여기서 index-START.html의 코드를 저희가 원하는 방향으로 수정해가면 됩니다.
코드 실행하고 싶으시면 해당 package.json도 같이 정의하시고npm install
-> npm start
로 실행 후 index-START.html 눌러주세요.
script 코드
우리는 예제에 필요한 정보인 이동 방향, 장치 속도만 활용해 구현합니다.
나침반의 방향 설정은 rotate시켜 구현하였습니다.
id
추출 및 해제가 가능하다고 하여 에러 발생시 해제 까지 구현해보았습니다. (강의 영상엔 없음)
let id = navigator.geolocation.watchPosition(data => {
let {speed, heading} = data.coords;
speedValue.textContent = speed.toString();
arrow.style.transform = `rotate(${heading}deg)`;
}, err => {
console.log(err);
alert('에러가 발생했습니다!');
navigator.geolocation.clearWatch(id);
});
전체 코드 (html)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<meta name="viewport" content="width=device-width">
</head>
<body>
<svg class="arrow" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" x="0px" y="0px" viewBox="0 0 64 64" enable-background="new 0 0 64 64" xml:space="preserve"><g><path fill="#ffffff" d="M32,1.824C15.361,1.824,1.825,15.361,1.825,32c0,16.639,13.537,30.176,30.175,30.176 S62.175,48.639,62.175,32C62.175,15.361,48.639,1.824,32,1.824z M29.715,3.988h1.12l2.333,3.807V3.988h1.069v5.701h-1.155 l-2.298-3.718v3.718h-1.069V3.988z M9.323,33.917H8.102l-1.136-4.262l-1.132,4.262H4.587l-1.361-5.701h1.178l0.859,3.916 l1.042-3.916h1.369l0.999,3.982l0.875-3.982h1.159L9.323,33.917z M33.995,59.828c-0.181,0.285-0.438,0.497-0.77,0.636 c-0.332,0.139-0.745,0.208-1.241,0.208c-0.721,0-1.274-0.167-1.661-0.5c-0.386-0.333-0.617-0.819-0.692-1.456l1.12-0.109 c0.067,0.376,0.204,0.652,0.41,0.828c0.206,0.176,0.484,0.264,0.834,0.264c0.371,0,0.65-0.078,0.838-0.235 c0.188-0.157,0.282-0.34,0.282-0.55c0-0.135-0.04-0.25-0.119-0.344c-0.079-0.095-0.217-0.177-0.414-0.247 c-0.135-0.047-0.442-0.13-0.922-0.249c-0.617-0.153-1.05-0.341-1.299-0.564c-0.35-0.314-0.525-0.696-0.525-1.147 c0-0.29,0.082-0.562,0.247-0.815c0.165-0.253,0.402-0.445,0.712-0.577c0.31-0.132,0.684-0.198,1.122-0.198 c0.716,0,1.254,0.157,1.616,0.471c0.362,0.314,0.552,0.733,0.57,1.256l-1.151,0.051c-0.049-0.293-0.155-0.504-0.317-0.632 c-0.162-0.128-0.405-0.193-0.729-0.193c-0.334,0-0.596,0.069-0.786,0.206c-0.122,0.088-0.183,0.206-0.183,0.354 c0,0.135,0.057,0.25,0.171,0.346c0.145,0.122,0.498,0.249,1.058,0.381c0.56,0.132,0.974,0.269,1.243,0.41 c0.268,0.141,0.478,0.334,0.63,0.58c0.152,0.245,0.227,0.548,0.227,0.908C34.267,59.237,34.176,59.543,33.995,59.828z M32,52.795 c-11.466,0-20.795-9.329-20.795-20.795c0-11.466,9.329-20.795,20.795-20.795S52.795,20.534,52.795,32 C52.795,43.466,43.466,52.795,32,52.795z M55.014,33.917v-5.701h4.227v0.965h-3.076v1.264h2.862v0.96h-2.862v1.552h3.185v0.961 H55.014z"/><g><path fill="#000000" d="M48.904,31.863c-4.074-1.358-8.148-2.717-12.226-4.066c-0.265-0.087-0.399-0.223-0.486-0.486 c-1.349-4.077-2.708-8.151-4.066-12.226c-0.029-0.087-0.074-0.169-0.132-0.3c-0.054,0.152-0.09,0.245-0.122,0.34 c-1.352,4.053-2.707,8.104-4.048,12.161c-0.096,0.292-0.246,0.428-0.532,0.522c-4.056,1.342-8.108,2.696-12.16,4.049 c-0.097,0.032-0.189,0.074-0.344,0.137c0.172,0.06,0.267,0.093,0.362,0.125c4.074,1.358,8.148,2.717,12.224,4.072 c0.204,0.068,0.337,0.158,0.412,0.386c1.243,3.757,2.498,7.511,3.75,11.265c0.144,0.432,0.291,0.862,0.463,1.373 c0.068-0.185,0.108-0.285,0.142-0.386c1.349-4.042,2.701-8.083,4.04-12.128c0.094-0.284,0.231-0.438,0.523-0.534 c4.056-1.341,8.108-2.696,12.161-4.048c0.099-0.033,0.195-0.076,0.347-0.137C49.067,31.925,48.987,31.891,48.904,31.863z M37.475,32.038c-1.316,0.439-2.631,0.879-3.947,1.314c-0.095,0.031-0.139,0.081-0.17,0.173c-0.434,1.313-0.873,2.625-1.311,3.937 c-0.012,0.033-0.024,0.066-0.046,0.126c-0.056-0.166-0.104-0.306-0.15-0.446c-0.407-1.219-0.814-2.437-1.218-3.657 c-0.025-0.074-0.068-0.104-0.134-0.125c-1.323-0.44-2.646-0.881-3.968-1.322c-0.031-0.01-0.062-0.022-0.118-0.041 c0.05-0.02,0.081-0.034,0.112-0.045c1.315-0.439,2.631-0.879,3.947-1.314c0.093-0.03,0.142-0.075,0.173-0.17 c0.435-1.316,0.875-2.632,1.314-3.947c0.01-0.031,0.022-0.062,0.039-0.11c0.019,0.042,0.033,0.069,0.043,0.097 c0.441,1.323,0.882,2.645,1.321,3.969c0.028,0.085,0.072,0.129,0.158,0.158c1.324,0.438,2.646,0.879,3.969,1.32 c0.027,0.009,0.053,0.02,0.1,0.038C37.538,32.013,37.507,32.027,37.475,32.038z"/><path fill="#000000" d="M24.436,27.633c-1.069-2.137-2.119-4.237-3.216-6.43c2.189,1.094,4.292,2.145,6.433,3.216 c-0.359,0.713-0.706,1.404-1.057,2.091c-0.023,0.045-0.078,0.082-0.127,0.106C25.807,26.949,25.143,27.28,24.436,27.633z"/><path fill="#000000" d="M39.573,27.632c-0.696-0.348-1.351-0.673-2.002-1.005c-0.076-0.038-0.155-0.104-0.193-0.177 c-0.338-0.661-0.666-1.326-1.019-2.033c2.121-1.061,4.228-2.115,6.43-3.217C41.69,23.399,40.635,25.509,39.573,27.632z"/><path fill="#000000" d="M24.436,36.339c0.712,0.357,1.394,0.698,2.074,1.043c0.046,0.024,0.088,0.073,0.113,0.121 c0.339,0.671,0.674,1.345,1.028,2.051c-2.126,1.063-4.232,2.117-6.43,3.216C22.317,40.577,23.37,38.472,24.436,36.339z"/><path fill="#000000" d="M36.358,39.555c0.354-0.707,0.688-1.38,1.028-2.05c0.028-0.056,0.084-0.111,0.14-0.139 c0.67-0.339,1.343-0.674,2.047-1.026c1.066,2.131,2.118,4.235,3.215,6.43C40.601,41.676,38.503,40.628,36.358,39.555z"/></g></g></svg>
<h1 class="speed">
<span class="speed-value">0</span>
<span class="units">KM/H</span>
</h1>
<style>
html {
font-size: 100px;
}
body {
margin: 0;
font-family: sans-serif;
min-height: 100vh;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
background:
radial-gradient(black 15%, transparent 16%) 0 0,
radial-gradient(black 15%, transparent 16%) 8px 8px,
radial-gradient(rgba(255,255,255,.1) 15%, transparent 20%) 0 1px,
radial-gradient(rgba(255,255,255,.1) 15%, transparent 20%) 8px 9px;
background-color: #282828;
background-size: 16px 16px;
background-attachment: fixed;
}
.arrow {
width: 250px;
overflow: hidden;
transition: all 0.2s;
transform: rotate(0deg);
display: inline-block;
}
h1 {
color: white;
font-weight: 100;
font-size: 60px;
display: flex;
align-items: center;
}
.units {
font-size: 15px;
}
/*Compass: https://thenounproject.com/search/?q=compass&i=592352*/
</style>
<script>
const arrow = document.querySelector('.arrow');
const speedValue = document.querySelector('.speed-value');
let id = navigator.geolocation.watchPosition(data => {
let {speed, heading} = data.coords;
speedValue.textContent = speed.toString();
arrow.style.transform = `rotate(${heading}deg)`;
}, err => {
console.log(err);
alert('에러가 발생했습니다!');
navigator.geolocation.clearWatch(id);
});
</script>
</body>
</html>