각도 응용 프로그램의 Openlayers - 기초

새로운 웹 지도 프로그램을 개발하기 시작하는 것은 항상 사람을 흥분시킨다.아름다운 지도, 제공하고자 하는 데이터, 그리고 지도의 상호작용을 위한 유일무이한 모든 도구가 생각났다.
이 완벽한 상태에 도달하기 전에, 너는 반드시 구조와 기술 방면에서 중요한 선택을 해야 한다.
맵 라이브러리에 대해 Openlayers은 매우 유연하고 기능이 풍부하기 때문에 좋은 후보가 될 것이다.그리고 프레임을 사용할지, 아니면 어떤 프레임을 사용할지 고려해야 한다.Openlayers와의 짝짓기에 관해서는 좋은 선택이나 나쁜 선택이 없으면 어떤 방식으로든 좋습니다.
본고는 Angular와 Openlayers를 기반으로 한 웹 맵 프로그램을 만드는 방법에 대한 차근차근 안내서를 제공합니다.이것은 갈수록 복잡해지는 용례를 포함하는 일련의 문장의 첫걸음이다.
두 라이브러리를 동시에 실행하는 데 필요한 모든 설정을 먼저 볼 수 있습니다.그리고 첫 번째 지도를 추가하고 다음과 같은 유용한 지리적 공간 각도 구성 요소 구조를 설계하는 정확한 방법을 소개합니다.
지도
  • 마우스 위치
  • 눈금선
  • 설치 프로그램


    먼저 Angular cli 를 설치해야 합니다.
    npm install -g @angular/cli
    
    그런 다음 각도 응용 프로그램을 생성합니다(엄격한 유형 검사 없음, 라우팅 없음, CSS).
    ng new openlayers-angular
    cd openlayers-angular
    
    Openlayers 설치
    npm install --save ol
    
    구축 프로세스에 Openlayers CSS 추가: angular.json을 열고 /projects/openlayers-angular/architect/build/options/styles 속성으로 이동하여 CSS 링크
    "styles": [
      "src/styles.css",
      "node_modules/ol/ol.css"
    ],
    

    맵 추가


    각도 응용 프로그램의 루트 구성 요소는 app.component입니다.눈썹, 꼬리, 사이드바, 지도를 렌더링하는 패널을 포함한 프로그램의 전역 레이아웃을 설계합시다.
    우선 루트 styles.css을 편집합니다. 이 CSS 파일은 구성 요소에 추가되지 않았고, 스타일 봉인도 없습니다. 여기에 정의된 모든 규칙은 프로그램 전체에 적용됩니다.CSS 변수를 선언하고, 글꼴을 가져오고, 루트 요소(예: body 또는 html)를 추가하는 규칙의 올바른 위치입니다.
    @import url('https://fonts.googleapis.com/css?family=Roboto');
    body {
        font-family: 'Roboto';
        color: var(--text-color);
        margin: 0;
        --header-color: #D1DFB7;
        --sidebar-color: #FAE6BE;
        --text-color: black;
    }
    
    app.component.html에서 레이아웃 생성
    <header>
      <div class="title">Map Viewer - Openlayers & Angular</div>
    </header>
    <main>
      <div class="left-bar"></div>
      <div id="ol-map" class="map-container"></div>
    </main>
    <footer>
      Footer
    </footer>
    
    
    관련 app.component.css
    :host {
        display: flex;
        flex-direction: column;
        height: 100vh;
    }
    header {
        background-color: var(--header-color);
        padding: 2em;
    }
    header .title {
        font-size: 28px;
    }
    main {
        display: flex;
        flex-grow: 1;
    }
    .left-bar {
        width: 20em;
        background-color: var(--sidebar-color);
    }
    .map-container {
        flex-grow: 1;
    }
    footer {
        background-color: var(--header-color);
        padding: 1em;
    }
    
    
    현재 루트 구성 요소에 간단한 Openlayers 맵을 만들고 맵 용기에 추가합니다.일반적으로, ngOnInit() 방법에서 Openlayers 맵을 정의할 수 있으며, 구성 요소는 준비가 되어 있고, Openlayers는 맵을 DOM에 정확하게 추가할 수 있습니다.더 많은 정보는 component lifecycle documentationngAfterViewInit()을 참고하셔도 좋은 후보가 될 수 있습니다.
    import { Component, OnInit } from '@angular/core';
    import Map from 'ol/Map';
    import View from 'ol/View';
    import TileLayer from 'ol/layer/Tile';
    import OSM from 'ol/source/OSM';
    
    @Component({
      selector: 'app-root',
      templateUrl: './app.component.html',
      styleUrls: ['./app.component.css'],
    })
    export class AppComponent implements OnInit {
    
      map: Map;
    
      ngOnInit(): void {
        this.map = new Map({
          view: new View({
            center: [0, 0],
            zoom: 1,
          }),
          layers: [
            new TileLayer({
              source: new OSM(),
            }),
          ],
          target: 'ol-map'
        });
      }
    }
    
    공평하다. 우리는 지금 당신의 응용 프로그램을 구축하기 위해 지도와 그럴듯한 배치를 가지고 있다.좀 더 파서 각도로 합시다.

    맵 구성 요소 만들기


    지도가 페이지에 나타나는 이유는 두 가지입니다: 지도 생성 중인 target: 'ol-map' 옵션은 해당하는 id를 가진 요소를 인용합니다: <div id="ol-map" class="map-container"></div>.
    지도 구성 요소를 만들어서 그것을 관리하는 방법을 보여 줍니다.
    맵 구성 요소 만들기
    ng generate component components/Map --changeDetection=OnPush --style=css --inlineTemplate=true --inlineStyle=true
    
    이 구성 요소는 지도를 만드는 것이 아니라 지도를 그리는 데 사용됩니다. 이것은 벙어리 구성 요소이기 때문에 우리는 지도를 Input()으로 전달합니다.나는 명령식 방법을 더 좋아한다. 너는 하나의 구성 요소가 있다. (여기는 루트 구성 요소) 지도를 만들어서 그것을 입력으로 필요한 모든 하위 구성 요소에 전달할 수 있다.반대 방법 (성명식) 은 지도 설정 (범위, 축소, 도면층) 을 입력으로 하고 지도를 만들어서 출력으로 되돌려주는 구성 요소를 제공합니다.나는 명령식 방법이 두 가지 장점이 있다고 생각한다.
  • 당신은 맵
  • 의 창설을 완전히 제어합니다
  • 은 서브어셈블리를 초기화하기 전에 매핑을 동기화 방식으로 생성하고 준비합니다.
  • 구성 요소에 비추기 위해 구조 함수에 ElementRef을 주입했습니다. 이것은 구성 요소 자체의 뿌리 요소에 대한 인용입니다.그리고 우리는 setTarget(this.elementRef.nativeElement) 함수를 사용하여 HTML 원생 요소를 지도를 렌더링할 위치로 전달할 수 있다.map.component.ts
    import { Component, OnInit, ChangeDetectionStrategy, Input, ElementRef } from '@angular/core';
    import Map from 'ol/Map';
    
    @Component({
      selector: 'app-map',
      template: '',
      styles: [':host { width: 100%; height: 100%; display: block; }',
      ],
      changeDetection: ChangeDetectionStrategy.OnPush,
    })
    export class MapComponent implements OnInit {
      @Input() map: Map;
      constructor(private elementRef: ElementRef) {
      }
      ngOnInit() {
        this.map.setTarget(this.elementRef.nativeElement);
      }
    }
    
    어셈블리에는 전체 컨테이너에 맵을 렌더링할 수 있도록 전체 너비/전체 높이가 있어야 합니다.각도 분량은 <div>이 아니기 때문에 display:block으로 표시하려면 지정해야 합니다.
    이제 루트 구성 요소에서 맵 구성 요소를 가져옵니다.app.component.ts
      <div class="map-container">
        <app-map [map]="map"></app-map>
      </div>
    
    결과는 비주얼적으로 이전과 동일하지만 맵 렌더링을 전용 어셈블리에 위임할 수 있습니다.응용 프로그램에서 이 구성 요소를 여러 번 사용할 수 있으며, 맵 대상 요소에 충돌이 발생하지 않습니다.
    다른 일반적인 Openlayers 인공 제품에 구성 요소를 만들기 위해 지도를 만들었습니다. 마우스 위치와 비례선을 추가해서 Openlayers 컨트롤을 처리하는 각도가 무엇인지 봅시다.

    축척 선 어셈블리


    이렇게 하는 목적은 관심사를 분류하는 것이지 루트 구성 요소에 너무 많은 책임을 두는 것이 아니다.우리는 같은 위치에서 지도 보기와 관련된 모든 내용을 관리하기를 원하지 않지만, 이 작업을 구성 요소에 위임하기를 희망합니다.
    배율 선 어셈블리 생성하기
    ng generate component components/Scaleline --changeDetection=OnPush --style=css --inlineTemplate=true --inlineStyle=true
    
    이 방법은 지도 구성 요소의 전체적인 방법과 같으며, 이 구성 요소는 Openlayers 인공 제품의 숙주일 뿐이다.컨트롤은 구성 요소 내부에서 만들어진 것이지 다른 곳에서 만들어진 것이 아니기 때문에 프로그램 템플릿에 구성 요소가 존재할 때만 맵에 추가됩니다.
    import { Component, OnInit, ChangeDetectionStrategy, Input, ElementRef } from '@angular/core';
    import Map from 'ol/Map';
    import ControlScaleLine from 'ol/control/ScaleLine';
    
    @Component({
      selector: 'app-scaleline',
      template: ``,
      styles: [],
      changeDetection: ChangeDetectionStrategy.OnPush,
    })
    export class ScalelineComponent implements OnInit {
      @Input() map: Map;
      control: ControlScaleLine;
    
      constructor(private elementRef: ElementRef) {}
    
      ngOnInit() {
        this.control = new ControlScaleLine({
          target: this.elementRef.nativeElement,
        });
        this.map.addControl(this.control);
      }
    }
    
    구성 요소의 유일한 직책은 컨트롤을 만들고 호스트에 내용을 보여주며 맵에 컨트롤을 추가하는 것입니다.이 방법을 Openlayers 컨트롤에 사용하고 책임 격리 문제를 존중할 수 있습니다.

    마우스 위치


    마우스 위치 컨트롤은 좌표 형식 함수에 의존하기 때문에 좀 복잡합니다.이것은 Angular 서비스를 도입할 수 있는 절호의 기회로 논리가 구성 요소에 봉인되지 않고 서비스로 공유되어야 한다.좌표를 포맷하고 포맷 옵션을 제공하는 것이 이 서비스의 역할입니다.
    ng generate service services/CoordinateFormatter
    
    이 서비스는 템플릿과 예상 숫자의 수량에 따라 좌표를 포맷하는 방법을 공개할 것이다.coordinate-formatter.service.ts
    import { Injectable } from '@angular/core';
    import { DecimalPipe } from '@angular/common';
    
    @Injectable({
      providedIn: 'root',
    })
    export class CoordinateFormatterService {
      constructor(private decimalPipe: DecimalPipe) {
      }
    
      numberCoordinates(
        coordinates: number[],
        fractionDigits: number = 0,
        template?: string,
      ) {
        template = template || '{x} {y}';
    
        const x = coordinates[0];
        const y = coordinates[1];
        const digitsInfo = `1.${fractionDigits}-${fractionDigits}`;
        const sX = this.decimalPipe.transform(x, digitsInfo);
        const sY = this.decimalPipe.transform(y, digitsInfo);
        return template.replace('{x}', sX).replace('{y}', sY);
      }
    }
    
    마우스 위치 컨트롤을 위한 각도 구성 요소를 만듭니다.논리는 ScaleLineComponent과 같습니다. 여기에 추가된 것은 우리의 새로운 서비스의 사용입니다.
    어셈블리 생성
    ng generate component components/MousePosition --changeDetection=OnPush --style=css --inlineTemplate=true --inlineStyle=true
    
    마우스 위치 컨트롤을 추가하여 이전처럼 목표를 설정하고 좌표지도 서비스에 연결합니다.
    import {
      Component,
      OnInit,
      ChangeDetectionStrategy,
      Input,
      ElementRef,
    } from '@angular/core';
    import Map from 'ol/Map';
    import ControlMousePosition from 'ol/control/MousePosition';
    import { CoordinateFormatterService } from '../../services/coordinate-formatter.service';
    
    @Component({
      selector: 'app-mouse-position',
      template: ``,
      styles: [],
      changeDetection: ChangeDetectionStrategy.OnPush,
    })
    export class MousePositionComponent implements OnInit {
    
      @Input() map: Map;
      @Input() positionTemplate: string;
      control: ControlMousePosition;
    
      constructor(
        private element: ElementRef,
        private coordinateFormatter: CoordinateFormatterService,
      ) {
      }
    
      ngOnInit() {
        this.control = new ControlMousePosition({
          className: 'mouseposition-control',
          coordinateFormat: (coordinates: number[]) => this.coordinateFormatter
            .numberCoordinates(coordinates, 4, this.positionTemplate),
          target: this.element.nativeElement,
          undefinedHTML: undefined,
        });
        this.map.addControl(this.control);
      }
    }
    
    구성 요소의 논리는 매우 간단하다. 우리는 좌표 템플릿을 입력 전달으로 삼기만 하면 된다.현실 생활에서 우리는 이 구성 요소를 확장해서 더 많은 옵션을 처리할 수 있다. 예를 들어 우리는 마우스 위치에 나타난 투영, DMS 형식 등이다.

    스타일 Openlayers 내부 HTML


    각도 구성 요소 view encapsulation은 구성 요소 CSS만 구성 요소 HTML에 첨부하는 메커니즘입니다.기본적으로 구성 요소의 모든 HTML 요소에 임의 속성을 추가하고 해당 속성을 구성 요소 CSS 규칙에 바인딩합니다.
    <header _ngcontent-cwb-c14="">
       <div _ngcontent-cwb-c14="" class="title">
          Map Viewer - Openlayers Angular
       </div>
    </header>
    
    header[_ngcontent-cwb-c14] {
        background-color: var(--header-color);
        padding: 2em;
    }
    
    문제는 Openlayers가 컨트롤에 HTML을 표시할 때 이 속성을 추가하지 않기 때문에 구성 요소에서 컨트롤에 대해 정의한 모든 CSS 규칙이 적용되지 않는다는 것입니다.Openlayers HTML 요소를 올바르게 지정하려면 키워드 ng-deep을 추가해야 합니다. 이는 규칙이 어셈블리 중첩 요소 중 어느 곳에나 적용됨을 의미합니다.mouse-position.component.ts에서 다음 CSS 규칙을 추가하여 배율선의 렌더링을 변경합니다.
    ::ng-deep .ol-scale-line {
          position: relative;
      }
    ::ng-deep .ol-scale-line, ::ng-deep .ol-scale-line-inner {
          background-color: transparent;
          border-color: var(--text-color);
          color: var(--text-color);
          font-size: inherit;
          bottom: auto;
      }
    

    최종 렌더링


    프로그램의 꼬릿말에 마지막 두 개의 구성 요소를 포함하고 정확하게 정렬합니다.이 두 구성 요소는 모두 지도를 입력으로 하고 비례선 구성 요소도 좌표 템플릿 형식을 사용한다. 이것은 우리가 numberCoordinates 방법을 사용해서 숫자를 표시하지 않고 주어진 템플릿을 적용하기를 원한다는 것을 나타낸다.
    <footer>
      <app-scaleline [map]="map"></app-scaleline>
      <app-mouse-position [map]="map" positionTemplate="{x}, {y} m"></app-mouse-position>
    </footer>
    
    페이지의 꼬릿말을 정확하게 맞추기 위해 app.component.css을 업데이트합니다
    footer {
        display: flex;
        background-color: var(--header-color);
        padding: 1em;
        justify-content: space-between;
    }
    
    이것은 스크립트의 컨트롤과 사용자 정의 스타일의 비례자의 최종 결과입니다.

    결론


    본고를 통해 우리는 Angular 응용 프로그램에서 Openlayers를 어떻게 설정하는지 이해했고 웹 맵에 대한 간단하지만 구체적인 용례를 소개했다.다음 글은 이 라이브러리의 통합을 깊이 있게 이해하고 지도에 더 많은 상호작용(도층, 기능, 양식, 상호작용...)을 가져다 줄 것입니다.
    너는 https://github.com/fgravin/angular-openlayers-tutorial/tree/1-basics에서 본문의 코드를 찾을 수 있다

    좋은 웹페이지 즐겨찾기