[React] Openlayers (2)

1

리액트

목록 보기
7/14
post-thumbnail

🙆🏻‍♀️ 맵에 객체 그리기 + 수정 🙆🏻‍♀️


객체 그리기

🙆🏻‍♀️ 함수형 컴포넌트 맵 그리기 🙆🏻‍♀️

지난 게시물에서 함수 컴포넌트를 이용해 맵을 표출했다.
이제 표출된 맵에 원하는 객체를 그려보자. (점, 선, 다각형, 원)

객체를 그리고 수정할 때 필요한 모듈(Draw, Snap, Modify)과 객체의 스타일을 지정할 모듈(Style, Circle, Fill, Stroke)을 import한다.

// MapTest.jsx
import React, { useEffect, useRef } from "react";

import { Map as OlMap, View } from "ol";
import { defaults as defaultControls } from "ol/control";
import { fromLonLat, get as getProjection } from "ol/proj";
import { Tile as TileLayer, Vector as VectorLayer } from "ol/layer";
import { XYZ, Vector as VectorSource } from "ol/source";
// +++
import { Style, Circle as CircleStyle, Fill, Stroke } from "ol/style";
import { Draw, Snap, Modify } from "ol/interaction";
// +++
import "ol/ol.css";

객체의 타입을 선택할 select를 추가하고 객체를 그리는 함수 등을 추가했다.

// 객체가 그려질 레이어(점, 선, 도형)
// +++ 기존에 컴포넌트 안에 선언했던 initVectorLayer을 밖으로 꺼냄
const initVectorLayer = new VectorLayer({
  source: new VectorSource(),
  style: new Style({
    fill: new Fill({
      color: "rgba(0, 0, 0, 0.2)",
    }),
    stroke: new Stroke({
      color: "red",
      width: 2,
    }),
    image: new CircleStyle({
      radius: 7,
      fill: new Fill({
        color: "red",
      }),
    }),
  }),
});
// +++

export default function MapTest() {
  // +++
  const [gisMap, setGisMap] = useState({});
  const [featuresLayer, setFeaturesLayer] = useState(null);
  // interaction을 해제하기 위해
  const [drawSnapObj, setDrawSnapObj] = useState<any>({});
  // +++
  
  const mapContent = useRef(null);
  
  // +++
  const typeSelect = useRef(null);
  
  // select 값이 바뀌면 interaction 해제 뒤 addDrawSnap 호출.
  const onChangeHandler = () => {
    gisMap.removeInteraction(drawSnapObj.draw);
    gisMap.removeInteraction(drawSnapObj.snap);
    addDrawSnap();
  };
  
  // 객체 그리기 함수
  const addDrawSnap = () => {
    // select 값이 None일 때는 리턴
    if (typeSelect.current.value === "None") {
      return false;
    }
    
    const draw = new Draw({
      source: featuresLayer.getSource(),
      type: typeSelect.current.value,
    });
    gisMap.addInteraction(draw);
    
    const snap = new Snap({ source: featuresLayer.getSource() });
    gisMap.addInteraction(snap);
    
    // interaction을 해제하기 위해 담아 놓기.
    setDrawSnapObj({ draw, snap });
  }; 
  // +++

  useEffect(() => {
    if (!mapContent.current) {
      return;
    }

    const map = new OlMap({
      controls: defaultControls({ zoom: false, rotate: false }).extend([]),
      layers: [
        new TileLayer({
          source: new XYZ({ url: "http://xdworld.vworld.kr:8080/2d/Base/202002/{z}/{x}/{y}.png" }),
        }),
        initVectorLayer,
      ],
      view: new View({
        projection: getProjection("EPSG:3857"),
        center: fromLonLat([127.296364, 37.503429]),
        zoom: 15,
        minZoom: 7,
        maxZoom: 20,
      }),
      target: mapContent.current,
    });
    
    // +++ map과 initVectorLayer를 set한다. 추후 다른 함수에 이용. (추가, 수정 등)
    setGisMap(map);
    setFeaturesLayer(initVectorLayer);
    // +++

    return () => map.setTarget(undefined);
  }, []);
  
  // +++ gisMap이 있으면 addDrawSnap 호출.
  useEffect(() => {
    // gisMap에 map 존재 여부를 객체의 키의 길이로 판단.
    if (Object.keys(gisMap).length > 0) {
      addDrawSnap();
      
      // 그려진 객체 수정.
      const modify = new Modify({ source: initVectorLayer.getSource() });
      gisMap.addInteraction(modify);
    }

    return () => {};
  }, [addDrawSnap, gisMap, featuresLayer]);
  // +++


  return (
    <div className="gis-map-wrap">
      {/* +++ 객체 타입 선택 */}
      <select ref={typeSelect} defaultValue="None" onChange={() => onChangeHandler(e)}>
        <option value="None">선택</option>
        <option value="Point"></option>
        <option value="LineString"></option>
        <option value="Polygon">다각형</option>
        <option value="Circle">원형</option>
      </select>
      {/* +++ */}
      <div ref={mapContent}></div>
    </div>
  );
 }

오픈레이어스-객체그리기
쨔쟌 타입을 지정해 객체를 그리고 수정도 가능하다.



다음은...🤔

그려진 객체를 GeoJSON 형태로 변환하자.

Openlayers 공식 사이트

profile
당당하게 외치고 싶어요. "나, 「프런트엔드 개발자」야" 라고...😏

0개의 댓글