특정 아이콘을 집어넣고 마우스 오버 및 클릭 이벤트를 부여하는 방법 입니다.
해당 기능을 만드는 이유는 원하는 지역에 아이콘을 표시한 뒤에 tooltip같은 효과를 주는데 주로 사용하기 위해서 자주 사용 됩니다.
마치 네이버나 구글지도에서 마커같은거 클릭해서 상세보기기능이 나오는 것 과 같은 기능 입니다.
가장 처음 할 일은 역시나...기본 레이어를 만들어 화면을 구성하여 주는 것 입니다.
그 다음에 할 일은 가장 기초인 아이콘을 넣어 줍니다.
import Map from 'ol/Map.js';
import View from 'ol/View.js';
import OSM from 'ol/source/OSM.js';
import OlTileLayer from 'ol/layer/Tile.js';
import point from 'ol/geom/Point';
var pnt = new point([126,37]).transform('EPSG:4326', 'EPSG:3857');
var center = pnt.getCoordinates();
var layer = new OlTileLayer({
source: new OSM()
});
var myView = new View({
center:center,
zoom: 8
});
var map = new Map({
layers: [layer],
target: 'map',
view: myView
});
import {Icon, Style} from 'ol/style.js';
import Feature from 'ol/Feature.js';
import Vector from 'ol/source/Vector.js';
import VectorLayer from 'ol/layer/Vector.js';
function createStyle(src) {
return new Style({
image: new Icon( ({
anchor: [0.5, 0.5],
crossOrigin: 'anonymous',
src: src,
imgSize: [50,50]
}))
});
}
var vectorSource = new Vector({projection: 'EPSG:4326'}); //새로운 벡터 생성
var iconFeature = new Feature(pnt);
iconFeature.set('style', createStyle('img/icon.png'));
iconFeature.set('index', '001');
vectorSource.addFeature(iconFeature);
var iconLayer = new VectorLayer({
style: function(feature) {
return feature.get('style');
},
source: vectorSource
})
map.addLayer(iconLayer);
저기서...구조체에 뭔가 index라는 값을 주는 것은 나중에 키 값으로 사용하기 위해서 준 데이터 잉ㅂ니다.
이를 완성하고 나면 아이콘이 이쁘게 표출 됩니다.
다음으로 이벤트를 줄 차레인데...SelectFeatures나 Select객체를 활용해서 쓰라는 내용의 글이 많았습니다.
너무 복잡하고 뜯어 고치기 힘들어 그냥 맵 객체에 이벤트 리스너를 붙이고 이벤트 효과에 대해서 처리하는 방식으로 변경 하였습니다.
먼저 hover효과를 주는 부분 입니다.
// hover 효과 ------------------- -------------------
let hover = null;
map.on('pointermove', function(evt) {
map.getTargetElement().style.cursor = map.hasFeatureAtPixel(evt.pixel) ? 'pointer' : '';
if (hover !== null) {
if(hover.get('index') == '001'){
hover.setStyle(createStyle('img/icon.png'));
console.log('Hover 효과 해제');
}
hover = null;
}
map.forEachFeatureAtPixel(evt.pixel, function(f) {
hover = f;
return true;
});
if(hover){
if(hover.get('index') == '001'){
console.log('Hover 효과');
hover.setStyle(createStyle('img/icon2.png'));
}
}
});
pointermove라는 이벤트는 마우스가 hover될 때를 의미 합니다.
또한 map에서 forEachFeatureAtPixel이라는 함수에서 생성한 구조체를 가져 올 수 있습니다.
정말 편리하게도 저 함수 한번에 데이터를 받아 볼 수 있습니다.
index라는 고유 값을 준 이유는, 해당 아이콘인지 아닌지를 판별하기 위해서이며,
나중에 여러개의 아이콘 형식의 이미지를 넣은 경우에는 해당 인덱스 값을 서로 다르게 주면 될 것 입니다.
이를 적용 한 모습 입니다.
조금만 응용하면 클릭효과도 쉽게 구현 가능 합니다.
해당 속성을 click 이벤트 리스너를 부여하여 가져오면 됩니다.
// click 효과 ------------------- -------------------
let clicker = null;
map.on('click', function(evt) {
map.forEachFeatureAtPixel(evt.pixel, function(f) {
clicker = f;
return true;
});
if(clicker != null){
console.log(clicker.get('index'));
if(clicker.get('index') == '001'){
console.log('click 효과');
clicker.setStyle(createStyle('img/icon3.png'));
}
clicker = null;
}
});
아래 소스코드가 최종 완성 본 입니다.
import Map from 'ol/Map.js';
import View from 'ol/View.js';
import OSM from 'ol/source/OSM.js';
import OlTileLayer from 'ol/layer/Tile.js';
import point from 'ol/geom/Point';
var pnt = new point([126,37]).transform('EPSG:4326', 'EPSG:3857');
var center = pnt.getCoordinates();
var layer = new OlTileLayer({
source: new OSM()
});
var myView = new View({
center:center,
zoom: 8
});
var map = new Map({
layers: [layer],
target: 'map',
view: myView
});
import {Icon, Style} from 'ol/style.js';
import Feature from 'ol/Feature.js';
import Vector from 'ol/source/Vector.js';
import VectorLayer from 'ol/layer/Vector.js';
function createStyle(src) {
return new Style({
image: new Icon( ({
anchor: [0.5, 0.5],
crossOrigin: 'anonymous',
src: src,
imgSize: [50,50]
}))
});
}
var vectorSource = new Vector({projection: 'EPSG:4326'}); //새로운 벡터 생성
var iconFeature = new Feature(pnt);
iconFeature.set('style', createStyle('img/icon.png'));
iconFeature.set('index', '001');
vectorSource.addFeature(iconFeature);
var iconLayer = new VectorLayer({
style: function(feature) {
return feature.get('style');
},
source: vectorSource
})
map.addLayer(iconLayer);
// hover 효과 ------------------- -------------------
let hover = null;
map.on('pointermove', function(evt) {
map.getTargetElement().style.cursor = map.hasFeatureAtPixel(evt.pixel) ? 'pointer' : '';
if (hover !== null) {
if(hover.get('index') == '001'){
hover.setStyle(createStyle('img/icon.png'));
console.log('Hover 효과 해제');
}
hover = null;
}
map.forEachFeatureAtPixel(evt.pixel, function(f) {
hover = f;
return true;
});
if(hover){
if(hover.get('index') == '001'){
console.log('Hover 효과');
hover.setStyle(createStyle('img/icon2.png'));
}
}
});
// click 효과 ------------------- -------------------
let clicker = null;
map.on('click', function(evt) {
map.forEachFeatureAtPixel(evt.pixel, function(f) {
clicker = f;
return true;
});
if(clicker != null){
console.log(clicker.get('index'));
if(clicker.get('index') == '001'){
console.log('click 효과');
clicker.setStyle(createStyle('img/icon3.png'));
}
clicker = null;
}
});
이를 동작 시켜본 모습 입니다.
맵 객체에 이벤트를 부여하는 방법이 이벤트를 만들어내는 데 쉬웠던 것 같습니다.
아래 소스코드를 첨부합니다!
* 해당 내용은 npm과 parcel 환경으로 구성되어 있습니다.
* 아래 주소를 통해 환경구성을 하면 이해하기 쉽습니다.
https://lts0606.tistory.com/194?category=726697
댓글