https://generalcoder.tistory.com/4
지난 시간에는 위도와 경도로 두 점사이의 거리를 구하는 방법을 살펴보았다. 이번에는 내가 설정한 거리안에 있는 게시물만 출력해주는 기능을 구현해보려 한다.
지난포스팅과 연속성을 갖기 때문에 이해를 위해서 이전 포스팅부터 보는 것을 추천한다.
1. 게시물 리스트 만들기
1.1 HTML 정적페이지 생성
일단 동적으로 게시글을 받아와 화면에 출력해 줄 수 있는 코드를 작성해보자.
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link rel="stylesheet" href="distance.css">
</head>
<body>
<div class="list">
<!--게시물 들어갈곳-->
</div>
</body>
</html>
기본적인 HTML 템플릿에 list라는 클래스명을 갖는 <div> 태그를 하나 생성해준다. 동적으로 자료를 받아와서 출력해줄 수 있도록 하기 위해 일단 내용물은 비어있다.
1.2 위치정보 변수 선언
원래는 DB에서 동적으로 받아와야하지만 아직 DB연동을 하지 않았기 때문에 4개의 게시글을 만들기위한 변수들을 선언해준다. 현재 내 위치와 거리를 비교해야 하기 때문에 currentLat, currentLng라는 변수를 먼저 선언해주고 각각 다른 위치를 갖는 네개의 지역정보를 변수로 선언해준다.
//교대역(현재 내 위치)
const currentLat = 37.49280804864656
const currentLng = 127.01379561074029
//강남역
const name1 = "강남역" //위치명
const lat1 = 37.49813943152925//위도
const lng1 = 127.02827170358093//경도
let result1 = getDistance(currentLat, currentLng, lat1, lng1)//현재위치에서의 거리
let distance1 = Math.round(result1*1000)/1000;//반올림처리로 m단위까지 표현
//양재역
const name2 = "양재역"
const lat2 = 37.48390185679575
const lng2 = 127.03450754512691
let result2 = getDistance(currentLat, currentLng, lat2, lng2)
let distance2 = Math.round(result2*1000)/1000;
//신논현역
const name3 = "신논현역"
const lat3 = 37.50462740802899
const lng3 = 127.02501696793027
let result3 = getDistance(currentLat, currentLng, lat3, lng3)
let distance3 = Math.round(result3*1000)/1000;
//신중동역
const name4 = "신중동역"
const lat4 = 37.50294094152464
const lng4 = 126.77648105378721
let result4 = getDistance(currentLat, currentLng, lat4, lng4)
let distance4 = Math.round(result4*1000)/1000;
현재 위치(교대역)로부터 거리인 distance를 구하기 위해 getDistance라는 함수를 사용했는데 그 내용은 아래와 같다. 지난 포스팅에 함수에 대해서 설명한 내용이 있으니 자세히 설명하지는 않겠다.
function getDistance(lat1,lng1,lat2,lng2) {
function deg2rad(deg) {
return deg * (Math.PI/180)
}
var R = 6371; // Radius of the earth in km
var dLat = deg2rad(lat2-lat1); // deg2rad below
var dLon = deg2rad(lng2-lng1);
var a = Math.sin(dLat/2) * Math.sin(dLat/2) + Math.cos(deg2rad(lat1)) * Math.cos(deg2rad(lat2)) * Math.sin(dLon/2) * Math.sin(dLon/2);
var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
var d = R * c; // Distance in km
return d;
}
1.3 각각의 정보를 담는 리스트 생성
array라는 이름의 배열을 생성하고 아까 생성해놓은 값을 object에 먼저 담고 list에 담아주었다.
let array = [];
let loc1 ={name:name1, lat:lat1, lng:lng1, distance:distance1};
let loc2 ={name:name2, lat:lat2, lng:lng2, distance:distance2};
let loc3 ={name:name3, lat:lat3, lng:lng3, distance:distance3};
let loc4 ={name:name4, lat:lat4, lng:lng4, distance:distance4};
array.push(loc1);
array.push(loc2);
array.push(loc3);
array.push(loc4);
console.log(array);
값이 잘 들어갔는지 확인하기 위해 단위테스트를 해보았다. 이전에 넣었던 값이 배열의 형태로 잘 출력되는 것을 볼 수 있다.
1.4 리스트를 브라우저 화면에 출력해보기
이제 정보를 가지고 있는 배열(array)을 가지고 브라우저 화면에 게시글의 형태로 뿌려보자. 일단 게시물이 삽입될 태그의 정보를 받아온다. querySelector로 태그정보를 받아서 list라는 변수에 담아준다. 그 다음은 리스트에 담긴 갯수만큼 순회하며 화면에 게시물을 출력해줄 반복문을 작성해준다. forEach문을 사용했다.
이 구문에서 가장 중요한 포인트는 if문이다. 내가 설정한 거리(아래 코드에서는 100km)이내에 있는 게시물만 출력해주도록 조건을 설정했다.
const list = document.querySelector(".list");//게시글을 삽입해줄 태그를 받아온다.
array.forEach((loc)=>{//리스트를 순회하며
const container = document.createElement("div")
if(loc.distance < 100){ //설정한 거리보다 적은 게시물만 출력하는 if문 작성
container.innerHTML =`
<div>
<div>위치: ${loc.name}</div>//장소이름
<div>위도: ${loc.lat}</div>//위도
<div>경도: ${loc.lng}</div>//경도
<div>거리: ${loc.distance}km</div>//현재위치에서 거리
</div>
`
}
list.append(container);//게시물을 <div class="list"> 에 삽입
})
2. 게시물 출력, 거리 테스트
이제 브라우저에 잘 출력되는지 확인해보자.
현재 위치부터 거리가 전부 100km내에 존재하기 때문에 4개의 게시물이 전부 출력되는 것을 볼 수 있다. 좀 더 세밀한 테스트를 위해 1km와 4km로 설정후 출력이 되는지 확인해 보았다. 게시물 중에 1km 이내의 거리를 가진 게시물이 없기 때문에 1km 범위는 출력이 되지 않는다. 4km이내에는 3개가 있기 때문에 출력이 잘 되는 것을 확인할 수 있다.
간단한 시연을 위해 이번 포스팅에서는 위도와 경도값을 임의로 지정해주었으나 DB에 저장된 위치값을 실시간으로 받아와서 화면에 뿌려준다면 당근마켓의 동네검색 기능과 비슷한 기능을 구현할 수 있을 것이다.
'만들자' 카테고리의 다른 글
[Javascript]위도 경도로 두 점 사이의 거리 구하기 - 카카오 지도api (1) | 2023.11.21 |
---|---|
[Javascript]카카오 지도, 주소api 사용해보기 (0) | 2023.11.16 |
[Firebase] 파이어베이스로 마켓어플 만들어본 후기(Firestore, Storage연동, 인증) (2) | 2023.11.12 |