본문 바로가기
IT 개발/OpenLayers

OpenLayers (Mask Layer)

by Love of fate 2020. 1. 17.
728x90
반응형

Mask  - 반투명의 검은 막의 바탕 

ex) 팝업 마스크 : 팝업을 사용할때 배경을 흐리게 만들어 팝업에 집중할 수 있게 효과를 주는 방법


Mask 작업 방법

1. JSTS라는 라이브러리를 사용

2. DB에서 쿼리를 사용하여 위 모양의 형태의 GEOMETRY를 가져오는 방법

 

* 필자는 두번째 방법을 통해 작업


1) DB에서 쿼리를 사용하여 mask 형태의 GEOMETRY를 가져온다. (ST_DIFFERENCE 사용)

   - 아래 쿼리로 만들어진 GEOMETRY를 js에 Map형식으로 미리 만들어 둠

ex)
SELECT 
	ST_DIFFERENCE (
 ⓐ --  	ST_GEOFORMTEXT('POLYGON((좌표들))', '4326'), -- ST_GEOMFROMTEXT : 4326 좌표계로 변환
 ⓑ --   ST_GEOFORMTEXT('POLYGON((좌표들))', '4326')  
    );
  
 -- ST_DIFFERENCE : ⓑ-ⓐ를 반환 (B의 일부) 
 -- 지오메트리 B와 교차하지 않는 A의 해당 부분을 나타내는 지오메트리를 반환  

 

2) 시군 이동 select box에서 클릭시 'change' 이벤트 동작

   - sggCode가 ""이면 '선택'을 클릭한 것이며, 어떠한 시/군도 선택하지 않았기 때문에 mapMaskOff() 메소드를 실행

   - sggCode가 있으면 mapMaskOn()을 실행 (_SIG_MASK_WKT,  _SIG_EXTENT_WKT)

jQuery('.sigCodeSelect').on('change', function() {

	var sggCode = jQuery(this).val();

	if (sggCode == "" || sggCode == null || typeof (sggCode) == undefined) {
		mapMaskOff();
	} else {
			
		var sigCode = sggCode.substring(0, 4);
		var maskGeom = _SIG_MASK_WKT[sigCode];
		var maskGeomExtent = _SIG_EXTENT_WKT[sigCode];
			
		mapMaskOn(maskGeom, maskGeomExtent);
		
		// view.fit 주어진지도 크기와 경계를 기준으로 주어진 지오메트리 또는 범위를 맞 춥니다.
	        // 크기는 범위에 맞는 상자의 픽셀 크기입니다.
		// 대부분의 경우지도 크기, 즉을 사용하려고합니다 map.getSize(). 지도 각도를 관리합니다.
		// view.fit(geometry, map.getSize());
		
		//map.getView().fit(sggGeom, map.getSize());
	}
});

 

3) mapMaskOn() 실행 

   - mapMaskOn(maskGeom, maskGeomExtent); : maskGeom과 maskGeomExtent를 넘김

   - maskLayer를 for문을 통해 찾아서 제거. 

      - maskLayer를 지우지 않으면 또 실행했을때 vectorLayer가 겹겹이 계속 쌓인다. 

   - vectorLayer를 생성하여 map에 addLayer()메소드를 통해 추가한다.

function mapMaskOn(geom, extent) {
	
	var layers = map.getLayers();
	layers = layers.getArray();
		
	for(var i=0; i < layers.length; i++){
		var name = layers[i].get('name');
		if(name === "maskVectorLayer"){
			map.removeLayer(layers[i]);
		}
	}

	var style = new ol.style.Style({
		fill : new ol.style.Fill({
			color : 'rgba(0, 0, 0, 0.7)' //black / 0.7 : opacity
		}),
		stroke : new ol.style.Stroke({
			color : '#000000'
		})
	});
	//dataProjection : EPSG:4326
 	//mapProjection : EPSG:3857
	//vworld는 3857좌표계로 되어있기 때문에 transform을 통해 4326좌표계를 3857로 변환한다.
	geom = wktFormat.readGeometry(geom);
	geom.transform(dataProjection, mapProjection); 
	
	var feature = new ol.Feature({
		geometry : geom
	});

	if (extent) {

		var geometry = wktFormat.readGeometry(extent);
		
		geometry.transform(dataProjection, mapProjection);
		view.fit(geometry, map.getSize());
	}

	var vectorSource = new ol.source.Vector({
		features : [feature]
	});
	
	var maskVactorLayer = new ol.layer.Vector({
		name : "maskVectorLayer",
		source : vectorSource,
		style : style
	});
	
	map.addLayer(maskVactorLayer);
	
}

 

4) mapMaskOff() 실행

function mapMaskOff() {
	var layers = map.getLayers();
	layers = layers.getArray();
		
	for(var i=0; i < layers.length; i++){
		var name = layers[i].get('name');
		if(name === "maskVectorLayer"){
			map.removeLayer(layers[i]);
		}
	}
}

* 실행결과

시군 이동 selectBox 클릭
mapMaskOn() 실행 및 적용
선택으로 변경했을 시 mapMaskOff() 실행

 

728x90
반응형