- 시설 검색, 다중 시설 검색 시 이전 검색 시설 레이어 삭제 기능 추가 - 시설 위치 정보 없을 때 alert 추가 - 시설 검색 시 해당 시설 아이콘 이미지 표출
449 lines
11 KiB
JavaScript
449 lines
11 KiB
JavaScript
import GisApp from './gis.core';
|
|
import Style from 'ol/style/Style.js';
|
|
import { click, mouseOnly, never } from 'ol/events/condition';
|
|
import DragBox from 'ol/interaction/DragBox.js';
|
|
import Draw from 'ol/interaction/Draw.js';
|
|
import Select from 'ol/interaction/Select.js';
|
|
import VectorLayer from 'ol/layer/Vector.js';
|
|
import Overlay from 'ol/Overlay.js';
|
|
import VectorSource from 'ol/source/Vector.js';
|
|
import CircleStyle from 'ol/style/Circle.js';
|
|
import Fill from 'ol/style/Fill.js';
|
|
import Stroke from 'ol/style/Stroke.js';
|
|
|
|
const GisOlSelect = function (map, options) {
|
|
GisApp.select = {};
|
|
GisApp.select.helpTooltipElement = null;
|
|
GisApp.select.helpTooltip = null;
|
|
GisApp.select.helpMsg = null;
|
|
this.initialize(map, options);
|
|
};
|
|
|
|
GisOlSelect.prototype = {
|
|
map: null,
|
|
defaults: {
|
|
hitTolerance: 10,
|
|
useAreaControl: false,
|
|
},
|
|
selectInteraction: null,
|
|
dragBox: null,
|
|
dragPolygon: null,
|
|
selectedFeatures: [],
|
|
selectFeatureFlag: false,
|
|
initialize: function (map, options) {
|
|
this.map = map;
|
|
Object.assign(this.defaults, options);
|
|
this.setInteraction();
|
|
this.pointerMoveEventHandler();
|
|
},
|
|
/**
|
|
* SELECT 이벤트 등록
|
|
*/
|
|
setInteraction: function () {
|
|
let me = this;
|
|
let map = this.map;
|
|
if (this.selectInteraction) {
|
|
this.removeInteration();
|
|
}
|
|
let baseStyle = new Style({
|
|
image : new CircleStyle({
|
|
fill : new Fill({
|
|
color : 'rgba(135, 116, 243, 0.4)',
|
|
}),
|
|
radius : 30
|
|
}),
|
|
stroke : new Stroke({
|
|
color : 'rgba(135, 116, 243, 0.4)',
|
|
width : 10,
|
|
})
|
|
});
|
|
|
|
this.selectInteraction = new Select({
|
|
style: function (feature, resolution) {
|
|
let styles = [];
|
|
let layer = feature.getLayer();
|
|
let styleFn = GisApp.Module.style.getLayerStyleFunction(layer, null);
|
|
|
|
if (styleFn) {
|
|
const style = styleFn(feature, resolution);
|
|
if (Array.isArray(style)) {
|
|
styles.push(...style);
|
|
} else {
|
|
styles.push(style);
|
|
}
|
|
}
|
|
styles.push(baseStyle);
|
|
return styles;
|
|
},
|
|
layers: function (layer) {
|
|
let clickPsblYn = layer?.get('clickPsblYn');
|
|
return clickPsblYn === 'Y';
|
|
},
|
|
condition: click,
|
|
hitTolerance: me.defaults.hitTolerance,
|
|
});
|
|
|
|
map.addInteraction(this.selectInteraction);
|
|
this.selectedFeatures = this.selectInteraction.getFeatures();
|
|
|
|
// 선택된 피처 중심으로 지도 이동
|
|
this.selectInteraction.on('select', function (e) {
|
|
const feature = e.selected[0];
|
|
if (feature) {
|
|
const geometry = feature.getGeometry();
|
|
if (geometry) {
|
|
const extent = geometry.getExtent();
|
|
map.getView().fit(extent, {
|
|
duration: 300,
|
|
padding: [50, 50, 50, 50],
|
|
maxZoom: 16
|
|
});
|
|
}
|
|
}
|
|
});
|
|
},
|
|
/**
|
|
* SELECT 피처 초기화
|
|
*/
|
|
reset: function () {
|
|
let me = this;
|
|
if (GisApp.Module.edit) {
|
|
GisApp.Module.edit.setDrawActive(false);
|
|
}
|
|
if (GisApp.Module.draw) {
|
|
GisApp.Module.draw.setDrawActive(false);
|
|
}
|
|
me.setActive(true);
|
|
me.removeHelpTooltip();
|
|
|
|
let map = this.map;
|
|
map.removeInteraction(me.dragBox);
|
|
map.removeInteraction(me.dragPolygon);
|
|
|
|
this.selectInteraction.addCondition_ = never;
|
|
this.selectFeatureFlag = false;
|
|
|
|
if (GisApp.Module.measure) {
|
|
GisApp.Module.measure.removeFeature();
|
|
GisApp.Module.core.deleteOverlay('measure');
|
|
}
|
|
|
|
GisApp.Module.core.deleteLayer(GisApp.hLayerId);
|
|
GisApp.Module.core.deleteLayer(GisApp.hlLayerId);
|
|
|
|
this.resetSelectedFeature();
|
|
},
|
|
/**
|
|
* 단일 SELECT 이벤트 등록
|
|
*/
|
|
setSingleInteration: function () {
|
|
this.reset();
|
|
this.selectInteraction.addCondition_ = click;
|
|
this.selectFeatureFlag = true;
|
|
},
|
|
/**
|
|
* 박스 SELECT 이벤트 등록
|
|
*/
|
|
setBoxInteration: function () {
|
|
//초기화
|
|
this.reset();
|
|
this.selectFeatureFlag = true;
|
|
|
|
let me = this;
|
|
let map = this.map;
|
|
me.dragBox = new DragBox({
|
|
condition: mouseOnly,
|
|
});
|
|
map.addInteraction(this.dragBox);
|
|
GisApp.select.helpMsg = '직사각형 시작점을 클릭하고 드래그하세요.';
|
|
me.createHelpTooltip();
|
|
me.dragBox.on('boxend', function () {
|
|
let rotation = map.getView().getRotation();
|
|
let oblique = rotation % (Math.PI / 2) !== 0;
|
|
let candidateFeatures = oblique ? [] : me.selectedFeatures;
|
|
let extent = me.dragBox.getGeometry().getExtent();
|
|
let layers = map.getLayers();
|
|
for (let i in layers.array_) {
|
|
let layer = layers.array_[i];
|
|
if (layer?.get('clickPsblYn') == 'Y' && me.getVisible(layer)) {
|
|
layer.getSource().forEachFeatureIntersectingExtent(extent, function (feature) {
|
|
candidateFeatures.push(feature);
|
|
});
|
|
}
|
|
}
|
|
|
|
if (oblique) {
|
|
let anchor = [0, 0];
|
|
let geometry = me.dragBox.getGeometry().clone();
|
|
geometry.rotate(-rotation, anchor);
|
|
let extent$1 = geometry.getExtent();
|
|
candidateFeatures.forEach(function (feature) {
|
|
let geometry = feature.getGeometry().clone();
|
|
geometry.rotate(-rotation, anchor);
|
|
if (geometry.intersectsExtent(extent$1)) {
|
|
me.selectedFeatures.push(feature);
|
|
}
|
|
});
|
|
}
|
|
me.selectInteraction.dispatchEvent({
|
|
type: 'select',
|
|
selected: me.selectedFeatures,
|
|
deselected: [],
|
|
});
|
|
map.removeInteraction(me.dragBox);
|
|
});
|
|
|
|
me.dragBox.on('boxstart', function () {
|
|
me.removeHelpTooltip();
|
|
me.selectedFeatures.clear();
|
|
});
|
|
},
|
|
/**
|
|
* 폴리곤 SELECT 이벤트 등록
|
|
*/
|
|
setPolygonInteration: function () {
|
|
this.reset();
|
|
this.selectFeatureFlag = true;
|
|
|
|
let me = this;
|
|
let map = this.map;
|
|
|
|
//폴리곤 레이어 생성
|
|
let polygonSource = new VectorSource({
|
|
useSpatialIndex: false,
|
|
});
|
|
let polygonLayer = new VectorLayer({
|
|
source: polygonSource,
|
|
});
|
|
map.addLayer(polygonLayer);
|
|
|
|
//폴리곤 draw 객체 생성
|
|
me.dragPolygon = new Draw({
|
|
source: polygonSource,
|
|
type: 'Polygon',
|
|
condition: mouseOnly,
|
|
});
|
|
map.addInteraction(me.dragPolygon);
|
|
|
|
//툴팁 추가
|
|
GisApp.select.helpMsg = '시작점을 클릭하세요.';
|
|
me.createHelpTooltip();
|
|
|
|
me.dragPolygon.on('drawstart', function () {
|
|
me.removeHelpTooltip();
|
|
me.selectedFeatures.clear();
|
|
});
|
|
|
|
me.dragPolygon.on('drawend', function (evt) {
|
|
setTimeout(function () {
|
|
let polygon = evt.feature.getGeometry();
|
|
let layers = map.getLayers();
|
|
for (let i in layers.array_) {
|
|
let layer = layers.array_[i];
|
|
if (layer?.get('clickPsblYn') == 'Y' && me.getVisible(layer)) {
|
|
let features = layer.getSource().getFeatures();
|
|
for (let j = 0; j < features.length; j++) {
|
|
if (polygon.intersectsExtent(features[j].getGeometry().getExtent())) {
|
|
me.selectedFeatures.push(features[j]);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
me.selectInteraction.dispatchEvent({
|
|
type: 'select',
|
|
selected: me.selectedFeatures,
|
|
deselected: [],
|
|
});
|
|
map.removeInteraction(me.dragPolygon);
|
|
map.removeLayer(polygonLayer);
|
|
}, 300);
|
|
});
|
|
return me.dragPolygon;
|
|
},
|
|
/**
|
|
* 레이어 추가
|
|
*/
|
|
addLayer: function (layer) {
|
|
if (layer) {
|
|
layer.set('clickPsblYn', 'Y');
|
|
}
|
|
},
|
|
/**
|
|
* 레이어 삭제
|
|
*/
|
|
removeLayer: function (layer) {
|
|
if (layer) {
|
|
layer.set('clickPsblYn', 'N');
|
|
}
|
|
},
|
|
/**
|
|
* 선택된 객체 초기화
|
|
*/
|
|
resetSelectedFeature: function () {
|
|
const selectedFeatures = this.selectedFeatures;
|
|
selectedFeatures.forEach(feature => {
|
|
selectedFeatures.remove(feature);
|
|
});
|
|
selectedFeatures.clear();
|
|
},
|
|
/**
|
|
* SELECT 이벤트 활성화
|
|
*/
|
|
setActive: function (active) {
|
|
this.selectInteraction.setActive(active);
|
|
},
|
|
/**
|
|
* SELECT 이벤트 삭제
|
|
*/
|
|
removeInteration: function () {
|
|
let map = this.map;
|
|
map.removeInteraction(this.selectInteraction);
|
|
this.selectInteraction = null;
|
|
|
|
//포인터 변경 삭제
|
|
this.removePointerMoveEventHandler('pointerMoveForSelect');
|
|
},
|
|
/**
|
|
* 피처 위에 마우스 오버시 포인터 변경
|
|
*/
|
|
pointerMoveEventHandler: function () {
|
|
let me = this;
|
|
let map = this.map;
|
|
let pointerMoveForSelect = function (evt) {
|
|
let hit = this.forEachFeatureAtPixel(
|
|
evt.pixel,
|
|
function (feature, layer) {
|
|
let returnFlag = true;
|
|
if (layer?.get('clickPsblYn') === 'N') {
|
|
returnFlag = false;
|
|
}
|
|
return returnFlag;
|
|
},
|
|
{ hitTolerance: me.defaults.hitTolerance }
|
|
);
|
|
|
|
if (hit && me.selectInteraction.getActive()) {
|
|
this.getTargetElement().style.cursor = 'pointer';
|
|
} else {
|
|
this.getTargetElement().style.cursor = '';
|
|
}
|
|
};
|
|
map.on('pointermove', pointerMoveForSelect);
|
|
},
|
|
/**
|
|
* 포인터 이벤트 삭제
|
|
*/
|
|
removePointerMoveEventHandler: function (fnNm) {
|
|
GisApp.Module.core.removeMapEventFnNm('pointermove', fnNm);
|
|
},
|
|
/**
|
|
* 선택된 피처 정보 반환(callback)
|
|
*/
|
|
getSelectedInfo: function (callback) {
|
|
let me = this;
|
|
this.selectInteraction.on('select', function (e) {
|
|
if (!e.auto) {
|
|
let features = me.selectInteraction.getFeatures();
|
|
if(features.getArray().length == 0) return;
|
|
let layers = [];
|
|
for (let i in features.array_) {
|
|
let feature = features.array_[0];
|
|
let layer = me.selectInteraction.getLayer(feature);
|
|
layers.push(layer);
|
|
}
|
|
callback(features.array_, layers);
|
|
}
|
|
});
|
|
},
|
|
/**
|
|
* 선택된 피처 정보 반환
|
|
*/
|
|
getSelectedFeatures: function () {
|
|
return this.selectInteraction.getFeatures();
|
|
},
|
|
/**
|
|
* 마지막으로 선택된 피처 정보 반환
|
|
*/
|
|
getLastSelectedFeatures: function () {
|
|
return this.selectInteraction.getFeatures();
|
|
},
|
|
/**
|
|
* 툴팁 생성
|
|
*/
|
|
createHelpTooltip: function () {
|
|
let me = this;
|
|
let map = this.map;
|
|
GisApp.select.helpTooltipElement = document.createElement('div');
|
|
GisApp.select.helpTooltipElement.className = 'ol-tooltip hidden';
|
|
GisApp.select.helpTooltip = new Overlay({
|
|
element: GisApp.select.helpTooltipElement,
|
|
offset: [15, 0],
|
|
positioning: 'center-left',
|
|
});
|
|
map.addOverlay(GisApp.select.helpTooltip);
|
|
map.on('pointermove', me.pointerMoveTooltipHandler);
|
|
},
|
|
/**
|
|
* 툴팁 삭제
|
|
*/
|
|
removeHelpTooltip: function () {
|
|
if (GisApp.select.helpTooltipElement) {
|
|
let map = this.map;
|
|
this.removePointerMoveEventHandler('pointerMoveTooltipHandler');
|
|
map.removeOverlay(GisApp.measure.helpTooltip);
|
|
GisApp.select.helpTooltipElement.remove();
|
|
}
|
|
},
|
|
/**
|
|
* 툴팁용 포인터 move 이벤트
|
|
*/
|
|
pointerMoveTooltipHandler: function (evt) {
|
|
if (evt.dragging) {
|
|
return;
|
|
}
|
|
//GisApp.select.helpTooltipElement.innerHTML = DOMPurify.sanitize(GisApp.select.helpMsg);
|
|
GisApp.select.helpTooltipElement.innerHTML = GisApp.select.helpMsg;
|
|
GisApp.select.helpTooltip.setPosition(evt.coordinate);
|
|
GisApp.select.helpTooltipElement.classList.remove('hidden');
|
|
},
|
|
getVisible: function (layer) {
|
|
let maxZoom = layer.getMaxZoom();
|
|
let minZoom = layer.getMinZoom();
|
|
let map = this.map;
|
|
let curZoom = map.getView().getZoom();
|
|
if (layer.getVisible() && maxZoom > curZoom && minZoom < curZoom) {
|
|
return true;
|
|
}
|
|
return false;
|
|
},
|
|
/**
|
|
* 피처 셀렉트
|
|
*/
|
|
selectFeature: function (feature, auto) {
|
|
let me = this;
|
|
me.selectedFeatures.clear();
|
|
me.selectedFeatures.push(feature);
|
|
me.selectInteraction.dispatchEvent({
|
|
type: 'select',
|
|
selected: me.selectedFeatures,
|
|
deselected: [],
|
|
auto: auto,
|
|
});
|
|
},
|
|
/**
|
|
* 피처 다중 셀렉트
|
|
*/
|
|
selectMultiFeature: function (feature, auto) {
|
|
let me = this;
|
|
me.selectedFeatures.push(feature);
|
|
me.selectInteraction.dispatchEvent({
|
|
type: 'select',
|
|
selected: me.selectedFeatures,
|
|
deselected: [],
|
|
auto: auto,
|
|
});
|
|
},
|
|
};
|
|
|
|
export default GisOlSelect;
|