깜놀하는 해므찌로

Angular Naver Map Api 컴포넌트 예시 / 앵귤러 네이버 지도 본문

IT

Angular Naver Map Api 컴포넌트 예시 / 앵귤러 네이버 지도

agnusdei1207 2023. 9. 9. 19:35
반응형
SMALL
<div #mapContainer [style]="setStyle()"></div>
import { CommonModule } from '@angular/common';
import { HttpClient } from '@angular/common/http';
import {
  AfterViewInit,
  Component,
  ElementRef,
  Input,
  OnInit,
  ViewChild
} from '@angular/core';
import { LatLng } from '@common/interface';
import { SearchService } from '../../services/search.service';

declare let naver: any; // Naver 지도 API를 사용하기 위해 선언된 변수

@Component({
  selector: 'app-naver-map',
  templateUrl: './naver-map.component.html',
  styleUrls: ['./naver-map.component.scss'],
  standalone: true,
  imports: [CommonModule],
})
export class NaverMapComponent implements OnInit, AfterViewInit {
  @ViewChild('mapContainer') mapContainer: ElementRef<HTMLDivElement>; // HTML 요소에 대한 참조를 얻기 위해 사용되는 ViewChild 데코레이터

  @Input() height: number = 600; // 지도 컴포넌트의 높이를 설정하는 입력 속성
  @Input() latlng: LatLng; // 위도와 경도 정보를 담는 입력 속성
  @Input() isMarkerFix: boolean = true; // 마커를 고정할지 여부를 설정하는 입력 속성
  @Input() address: string; // 주소 정보를 담는 입력 속성

  map: any; // Naver 지도 객체
  marker: any = null; // 마커 객체
  circle: any = null; // 원 객체

  constructor(
    private searchService: SearchService, // 주소 검색 서비스
    private httpClient: HttpClient
  ) { }

  ngAfterViewInit(): void {
    if (this.latlng) {
      // 위도와 경도가 제공된 경우, 해당 위치로 지도 초기화 및 마커, 원 표시
      this.mapInit(this.latlng.lat, this.latlng.lng);
      this.overlayInit(this.latlng.lat, this.latlng.lng);
      this.searchService.setLatLng(this.latlng);
    } else if (!this.latlng && this.address) {
      // 위도와 경도가 없고 주소가 제공된 경우, 주소로 지도 초기화 및 위치 검색
      this.mapInit();
      this.geoCoding(this.address);
    }
  }

  ngOnInit(): void {
    this.searchService.getAddress().subscribe({
      next: (res) => {
        this.latlng.address = res.address; // 검색된 주소 정보를 저장
        if (res.isSearch) {
          this.geoCoding(res.address); // 주소 검색이 이루어진 경우, 해당 주소로 지도 이동 및 마커, 원 표시
        }
      },
    });
  }

  mapInit(lat?: number, lng?: number) {
    this.map = null;
    this.map = new naver.maps.Map(this.mapContainer.nativeElement, {
      center: new naver.maps.LatLng(lat ?? 37.521035, lng ?? 127.029576), // 지도의 중심 좌표 설정
      zoom: 15, // 지도 확대/축소 레벨 설정
    });
    this.centerChange(); // 지도 이벤트 리스너 등록
  }

  centerChange() {
    // 지도의 중심 좌표가 변경되었을 때 실행되는 함수
    naver.maps.Event.addListener(this.map, 'dragend', (ev) => {
      const center = this.map.getCenter(); // 변경된 중심 좌표
      this.reverseGeocoding({ y: center.y, x: center.x }); // 좌표를 주소로 변환하여 검색 서비스에 저장
      this.panToMap(center.y, center.x); // 지도를 변경된 중심 좌표로 이동
      if (this.isMarkerFix) {
        return;
      }
      this.setMarker(center.y, center.x); // 마커 추가
      this.setCircle(center.y, center.x); // 원 추가
      this.searchService.setLatLng({ lat: center.y, lng: center.x }); // 변경된 위도와 경도를 검색 서비스에 저장
    });
  }

  reverseGeocoding(latlng: { x: number, y: number }) {
    // 좌표를 주소로 변환하는 함수
    naver.maps.Service.reverseGeocode({
      coords: latlng,
    }, (status, response) => {
      if (status !== naver.maps.Service.Status.OK) {
        return;
      }
      this.searchService.setAddress(response.v2.address.jibunAddress, false); // 검색된 주소 정보를 검색 서비스에 저장
    });
  }

  overlayInit(lat?: number, lng?: number) {
    // 초기화 시 마커와 원을 추가하는 함수
    this.setMarker(lat, lng);
    this.setCircle(lat, lng);
  }

  geoCoding(address: string) {
    // 주소를 좌표로 변환하는 함수
    naver.maps.Service.geocode(
      {
        address,
      },
      (status, response) => {
        if (status !== naver.maps.Service.Status.OK) {
          return;
        }
        const result = response.result;
        if (result.total === 0 && result.items.length === 0) {
          this.searchService.setValid(true); // 검색된 결과가 없는 경우 유효하지 않은 주소로 표시
          return;
        }
        this.searchService.setValid(false); // 검색된 결과가 있는 경우 유효한 주소로 표시
        if (naver) {
          this.panToMap(result.items[0].point.y, result.items[0].point.x); // 첫 번째 결과의 좌표로 지도 이동
          this.overlayInit(result.items[0].point.y, result.items[0].point.x); // 첫 번째 결과의 좌표로 마커와 원 추가
        }
      }
    );
  }

  panToMap(lat: number, lng: number) {
    // 지도를 주어진 좌표로 이동시키는 함수
    this.map.panTo(new naver.maps.LatLng(lat, lng));
  }

  setMarker(lat: number, lng: number) {
    // 지도에 마커를 추가하는 함수
    if (this.marker) this.marker.setMap(null); // 기존 마커 삭제
    this.marker = new naver.maps.Marker({
      position: new naver.maps.LatLng(lat, lng),
      map: this.map,
      icon: {
        url: 'assets/icons/marker.svg',
        size: new naver.maps.Size(35, 45),
        origin: new naver.maps.Point(0,
반응형
LIST