Atomic Habits

Beginner-Ex-code : 국가명, 국기, 국가경계선 표시하기 본문

IT/Openlayers

Beginner-Ex-code : 국가명, 국기, 국가경계선 표시하기

체계성 2021. 9. 11. 22:05

p.209

<!doctype html>
<html>
  <head>
    <title>Geometry Examples</title>
    <link rel="stylesheet" href="../assets/ol3/css/ol.css" type="text/css" />
    <link rel="stylesheet" href="../assets/css/samples.css" type="text/css" />
  </head>
  <body>
    <div id="map" class="map"></div>
    <script src="../assets/ol3/js/ol-debug.js"></script>
    <script>

      var countries = new ol.layer.Vector({
        source: new ol.source.GeoJSON({
          projection: 'EPSG:3857',
          url: '../assets/data/countries.geojson'
        })
      });

      var center = ol.proj.transform([0, 0], 'EPSG:4326', 'EPSG:3857');

      var view = new ol.View({
        center: center,
        zoom: 1
      });

      var map = new ol.Map({
        target: 'map',
        layers: [countries],
        view: view
      });

      // we want to create text styles based on properties coming from a feature
      // to do this, we need to create a new style for each string that needs to
      // be represented.  All the text styles will share the same properties
      // except for the actual text itself. The properties can be set up ahead
      // of time in an object literal
      var baseTextStyle = {
        font: '20px Calibri,sans-serif',
        textAlign: 'center',
        offsetY: -15,
        fill: new ol.style.Fill({
          color: [0,0,0,1]
        }),
        stroke: new ol.style.Stroke({
          color: [255,255,255,0.5],
          width: 4
        })
      };

      // when we move the mouse over a feature, we can change its style to
      // highlight it temporarily
      var highlightStyle = new ol.style.Style({
        stroke: new ol.style.Stroke({
          color: [255,0,0,0.6],
          width: 2
        }),
        fill: new ol.style.Fill({
          color: [255,0,0,0.2]
        }),
        zIndex: 1
      });

      // the style function for the feature overlay returns
      // a text style for point features and the highlight
      // style for other features (polygons in this case)
      function styleFunction(feature1, resolution) {
        // 1) feature의 가 
        console.log('+++++++++++++++++++++ style');
        var style;
        var geom = feature1.getGeometry();  
        // 1) feature.getGeometry().getType() 는 countries.geojson 에서 key:value이며,
        //    => 'Point', 'MultiPolygon', 'Polygon' 중에 하나의 value 이다.
        // 2) feature.getGeometry().getType()의 type 개수가 2개면, 
        //    2번 연속 styleFunction이 호출되고, 1개면 1번만 styleFunction이 호출된다.
        //    (2번 연속 코드가 수행될 때 map.on(...) 의 코드는 수행되지 않음)
        //         
        console.log('F geom.getType() : '+geom.getType());
        //console.log('A iso_a2 : '+feature.get('iso_a2')); (X) by !layer, Point

        if (geom.getType() == 'Point') {
          var text = feature1.get('text');
          baseTextStyle.text = text;
          // this is inefficient as it could create new style objects for the
          // same text.
          // A good exercise to see if you understand would be to add caching
          // of this text style
          var isoCode = feature1.get('isoCode').toLowerCase();
          console.log('baseTextStyle');
          //console.log('A iso_a2 : '+feature.get('iso_a2')); (X) by !layer, Point
          
          style = new ol.style.Style({
            text: new ol.style.Text(baseTextStyle),
            image: new ol.style.Icon({
              src: '../assets/img/flags/'+isoCode+'.png'
            }),
            zIndex: 2 
            // 1) 0 : 겹쳐져서 반투명한 text, img로 보이며,
            //    2 : style이 상단으로 올라와 선명한 text, img로 보인다.
          });
        } else { // geom.getType() -> MultiPolygon or Polygon
          style = highlightStyle;
          console.log('highlightStyle');
        }
        return [style];
      }

      var featureOverlay = new ol.FeatureOverlay({
        map: map,
        style: styleFunction
        // takes a feature and resolution and returns an array of styles.
      });

      // when the mouse moves over the map, we get an event that we can use
      // to create a new feature overlay from
      map.on('pointermove', function(browserEvent) {
        // first clear any existing features in the overlay
        console.log('----------------------on');
        featureOverlay.getFeatures().clear();
        // 1) 기존 위치의 features 삭제

        var coordinate = browserEvent.coordinate;
        var pixel = browserEvent.pixel;
        console.log('pixel :'+ pixel);

        // then for each feature at the mouse position ...
        map.forEachFeatureAtPixel(pixel, function(feature2, layer) { 
          // 1) .getFeatures().clear()에 의해 이전 위치에서의 feature는 모두 제거되고,
          //    새 위치(pixel)에 feature와 layer를 함께/각각(foreach) 반환한다.
          // 2) 새 위치에 인자 feature가 없으면(ex: 바다 영역) foreach문 실행되지 않는다.
          // 3) forEachFeatureAtPixel의 call-back함수는 기본적으로 1, 2번째 자리에
          //    feature, layer 변수를 받는다.(변수명 달라도 feature, layer 로 인식)

          // check the layer property, if it is not set then it means we
          // are over an OverlayFeature and we can ignore this feature
          console.log("layer : "+layer);
          if (!layer) { // null or object
            console.log('layer X') // (O)
            return; // return -> forEachFeatureAtPixel문 종료
          }
          console.log('layer O') // (O)


          // test the feature's geometry type and compute a reasonable point
          // at which to display the text.
          var geometry = feature2.getGeometry(); 
          var point;
          console.log('M geometry.getType() : '+geometry.getType()+'    M');
          // 1) feature 속성 중에 geometry만 getGeometry()로 호출 가능하고,
          //    나머지는 feature.get('xxx')로 조회한다.
          // 2) feature 속성은 countries.geojosn의 key : value 로 할당된 값이다.

          switch (geometry.getType()) {
            case 'MultiPolygon':
              var poly = geometry.getPolygons().reduce(function(left, right) {
                return left.getArea() > right.getArea() ? left : right;
              });
              point = poly.getInteriorPoint().getCoordinates();
              break;
            case 'Polygon':
              point = geometry.getInteriorPoint().getCoordinates();
              break;
            default: // Point
              point = geometry.getClosestPoint(coordinate);
          }
          

          // create a new feature to display the text
          textFeature = new ol.Feature({
            geometry: new ol.geom.Point(point), 
            
            text: feature2.get('name'),
            isoCode: feature2.get('iso_a2').toLowerCase()
          });
          // 1) geometry는 styleFunction의 feature.getGeometry().getType()로 'Point' 호출됨.
          // 2) new ol.Feature 아래에 literal로 생성된 key 들은 모두 feature로 등록되고
          //    feature.get('xxx')로 조회할 수 있다.

          // and add it to the featureOverlay.  
          // Also add the feature itself so the country gets outlined
          featureOverlay.addFeature(textFeature); // 국기, 나라명
          featureOverlay.addFeature(feature2); // 외곽 경계선
          // 1) featureOverlay.addFeature로 featureOverlay를 호출하게 되고,
          //    styleFunction 함수 실행 후 style을 return 받아 
          //    국기, 나라명, 외곽선 등 스타일이 적용된다.
          // 2) addFeature(feature2) 제외 시 styleFunction 에서 
          //    Point는 호출되고(by textFeature), 
          //    Multi/Polygon은 등록되지 않아 호출되지 않는다. (-> 외곽 경계선 표시X)
          // 3) featureOverlay.getFeatures().clear()에서 feature를 제외했지만, 
          //    forEachFeatureAtPixel에서 새로운 위치(AtPixel) 기준으로
          //    countries.geojosn의 { "type": "MultiPolygon" ... } feature 를 얻는다.
          // 4) addFeature을 통해 feature를 추가하면, styleFunction 에서 
          //    type이 point 아닐 경우 highlightStyle 을 적용한다.

          console.log('on --------- addFeature');
          //console.log('B iso_a2 : '+feature2.get('iso_a2').toLowerCase());
        });
      });

    </script>
  </body>
</html>

<!-- 
move - layer O -> addFeature -> STYLE func -> move
move - layer O -> addFeature -> STYLE func -> Point -> STYLE func -> Polygon -> move
move - layer X -> move
-->

 

 

 

 

'IT > Openlayers' 카테고리의 다른 글

[Openlayers] 기능정리  (0) 2021.09.11
Comments