@mint-ui/map
Version:
- React map library - Control various map with one interface - Google, Naver, Kakao map supported now - Typescript supported - Canvas marker supported
793 lines (655 loc) • 27.6 kB
JavaScript
'use strict';
Object.defineProperty(exports, '__esModule', { value: true });
var tslib = require('tslib');
var MintMapController = require('../core/MintMapController.js');
var waiting = require('../core/util/waiting.js');
var tools = require('@mint-ui/tools');
var MapTypes = require('../types/MapTypes.js');
var MapEventTypes = require('../types/MapEventTypes.js');
var log = require('../core/util/log.js');
var status = require('../core/util/status.js');
require('../core/MintMapCore.js');
require('react');
require('../types/MapDrawables.js');
require('../core/provider/MintMapProvider.js');
require('react-dom');
require('../core/util/animation.js');
require('../core/util/geo.js');
var polygon = require('../core/util/polygon.js');
require('../core/advanced/MapLoadingComponents.js');
require('../core/wrapper/MapControlWrapper.js');
var NaverMintMapController =
/** @class */
function (_super) {
tslib.__extends(NaverMintMapController, _super);
function NaverMintMapController(props) {
var _a;
var _this = _super.call(this, props) || this;
_this.type = 'naver';
_this.map = null;
_this.scriptUrl = 'https://oapi.map.naver.com/openapi/v3/maps.js';
_this.scriptModules = ['drawing']; // , 'geocoder' , 'panorama' , 'visualization']
_this.mapEvent = new MapEventTypes.MapEvent();
_this.mapUIEvent = new MapEventTypes.MapUIEvent();
_this.polylineEvents = ['mouseover', 'mouseout'];
_this.polygonEvents = ['mouseover', 'mouseout'];
_this.markerEvents = ['click', 'mouseover', 'mouseout'];
_this.dragged = false;
_this.eventMap = new Map(); //scriptModules 병합
if (props.scriptModules) {
(_a = _this.scriptModules).push.apply(_a, props.scriptModules);
} //contextmenu 는 지원하지 않지만 호환성을 위해 rightclick 으로 대체
_this.mapUIEvent.CONTEXTMENU = 'rightclick';
Object.freeze(_this.mapEvent);
Object.freeze(_this.mapUIEvent);
return _this; // console.log(`${this.type} controller loadded`);
}
NaverMintMapController.prototype.initMarkerPool = function () {
var _this = this;
if (!this.mapProps.markerCache) return; //marker pool setting
this.markerPool = new tools.ObjectPool() //logging on
//.setLog(true)
//factory 셋팅
.setFactory(function () {
//console.log('pool item created');
return new naver.maps.Marker({
position: new MapTypes.Position(0, 0),
map: _this.map || undefined
});
}) //clear function 셋팅
.setClear(function (item) {
//console.log('pool item cleared');
item.setMap(null);
}) //초기 pool 사이즈
.createPool(this.mapProps.markerCachePoolSize && this.mapProps.markerCachePoolSize > 0 ? this.mapProps.markerCachePoolSize : 1000) //TTL 체크 간격 (기본 5초)
.setCheckLiveTimeInterval(1000);
};
NaverMintMapController.prototype.createPolyline = function (polyline) {
var _this = this;
var _a = polyline.options,
position = _a.position,
_b = _a.lineColor,
lineColor = _b === void 0 ? 'blue' : _b,
_c = _a.lineSize,
lineSize = _c === void 0 ? 1 : _c,
_d = _a.lineOpacity,
lineOpacity = _d === void 0 ? 1 : _d,
_e = _a.visible,
visible = _e === void 0 ? true : _e,
_f = _a.editable,
editable = _f === void 0 ? false : _f,
event = _a.event; //console.log('controller createPolyline start', polyline);
if (this.map && Array.isArray(position)) {
var path = position.map(function (elem) {
return Array.isArray(elem) ? new MapTypes.Position(elem[1], elem[0]) : elem;
});
var pol_1 = new naver.maps.Polyline({
map: this.map,
path: path,
strokeColor: lineColor,
strokeWeight: lineSize,
strokeOpacity: lineOpacity,
clickable: true,
visible: visible
}); //@ts-ignore
editable && pol_1.setEditable(editable); // if(editable){
// //@ts-ignore
// this.drawingManager.addDrawing(pol, naver.maps.drawing.DrawingMode.POLYLINE)
// }
polyline.native = pol_1;
event && event.forEach(function (handler, key) {
if (_this.polylineEvents.includes(key)) {
naver.maps.Event.addListener(pol_1, key, handler);
}
});
}
};
NaverMintMapController.prototype.updatePolyline = function (polyline, options) {
//console.log('controller updatePolyline', options);
if (polyline && polyline.native && polyline.native instanceof naver.maps.Polyline) {
//console.log('controller updatePolyline start');
var path = void 0;
if (Array.isArray(options.position)) {
path = options.position.map(function (elem) {
return Array.isArray(elem) ? new MapTypes.Position(elem[1], elem[0]) : elem;
});
}
polyline.native.setOptions({
path: path || polyline.native.getPath(),
visible: options.visible === undefined || options.visible,
strokeColor: options.lineColor,
strokeWeight: options.lineSize,
strokeOpacity: options.lineOpacity
}); //@ts-ignore
options.editable !== undefined && polyline.native.setEditable(options.editable);
}
};
NaverMintMapController.prototype.createPolygon = function (polygon) {
var _this = this;
var _a = polygon.options,
position = _a.position,
innerPositions = _a.innerPositions,
_b = _a.lineColor,
lineColor = _b === void 0 ? 'green' : _b,
_c = _a.lineSize,
lineSize = _c === void 0 ? 1 : _c,
_d = _a.lineOpacity,
lineOpacity = _d === void 0 ? 1 : _d,
_e = _a.fillColor,
fillColor = _e === void 0 ? 'lightgreen' : _e,
_f = _a.fillOpacity,
fillOpacity = _f === void 0 ? 0.5 : _f,
_g = _a.visible,
visible = _g === void 0 ? true : _g;
_a.editable;
var event = _a.event; //console.log('polygon', polygon);
if (this.map && Array.isArray(position)) {
var outLine = position.map(function (elem) {
return Array.isArray(elem) ? new MapTypes.Position(elem[1], elem[0]) : elem;
});
var paths = [outLine];
innerPositions && paths.push.apply(paths, innerPositions);
var pol_2 = new naver.maps.Polygon({
map: this.map,
paths: paths,
strokeColor: lineColor,
strokeWeight: lineSize,
strokeOpacity: lineOpacity,
fillColor: fillColor,
fillOpacity: fillOpacity,
clickable: true,
visible: visible
}); //@ts-ignore
//pol.setEditable(editable)
polygon.native = pol_2;
event && event.forEach(function (handler, key) {
if (_this.polygonEvents.includes(key)) {
naver.maps.Event.addListener(pol_2, key, handler);
}
});
}
};
NaverMintMapController.prototype.updatePolygon = function (polygon, options) {
//console.log('controller updatePolygon', options);
if (polygon && polygon.native && polygon.native instanceof naver.maps.Polygon) {
//console.log('controller updatePolygon start');
var paths = void 0;
if (Array.isArray(options.position)) {
var outLine = options.position.map(function (elem) {
return Array.isArray(elem) ? new MapTypes.Position(elem[1], elem[0]) : elem;
});
paths = [outLine];
options.innerPositions && paths.push.apply(paths, options.innerPositions);
}
polygon.native.setOptions({
paths: paths || polygon.native.getPaths(),
visible: options.visible === undefined || options.visible,
strokeColor: options.lineColor,
strokeWeight: options.lineSize,
strokeOpacity: options.lineOpacity,
fillColor: options.fillColor,
fillOpacity: options.fillOpacity
}); //@ts-ignore
options.editable !== undefined && polygon.native.setEditable(options.editable);
}
};
NaverMintMapController.prototype.createMarker = function (marker) {
var _this = this;
var _a;
if (this.map) {
var options = {
map: this.map,
position: marker.options.position,
visible: marker.options.visible === undefined || marker.options.visible
};
marker.element && (options.icon = {
content: marker.element,
anchor: marker.options.anchor
});
var naverMarker_1;
if (this.mapProps.markerCache && this.markerPool) {
naverMarker_1 = this.markerPool.getPoolItem();
naverMarker_1.setVisible(true);
options.icon && naverMarker_1.setIcon(options.icon);
marker.native = naverMarker_1;
this.updateMarker(marker, marker.options);
} else {
naverMarker_1 = new naver.maps.Marker(options);
marker.native = naverMarker_1;
}
log.log(this.mapProps.debug || marker.options.debug, marker.options.debugLabel, this.type + ' marker created');
status.Status.setMarker(1, marker.options.debugLabel);
((_a = marker.options) === null || _a === void 0 ? void 0 : _a.event) && marker.options.event.forEach(function (handler, key) {
if (_this.markerEvents.includes(key)) {
naver.maps.Event.addListener(naverMarker_1, key, handler);
}
});
}
};
NaverMintMapController.prototype.updateMarker = function (marker, options) {
//console.log('controller updateMarker', options);
if (marker && marker.native && marker.native instanceof naver.maps.Marker) {
var map = marker.native.getMap();
if (map) {
/** 중요!!!!
* naver 마커의 setOption(MarkerOptions) 은 내부적으로 setMap 을 무조건 강제 처리한다!!!
* setMap 을 처리하면 맵의 이벤트리스너 등등이 모두 초기화 되고 다시 맵을 add 하면서 마커관련된 모든 초기화가 다시 일어난다.
* (심지어 map 이 기존과 같은 객체인데도 초기화 처리함)
* 그래서 민트맵에서는 update 를 지원하는 항목별로 명시적으로 각각 처리한다.
*/
//Position
if (options.position && options.position instanceof MapTypes.Position) {
marker.native.setPosition(options.position);
}
if (options.visible !== undefined) {
marker.native.setVisible(options.visible);
}
if (options.anchor) {
marker.native.setIcon(tslib.__assign(tslib.__assign({}, marker.native.getIcon()), {
anchor: options.anchor
}));
}
log.log(this.mapProps.debug || options.debug, marker.options.debugLabel, this.type + ' marker updated'); // const newOption = {
// map:map,
// position:options.position instanceof Position?options.position:marker.native.getPosition(),
// visible:options.visible === undefined || options.visible,
// } as naver.maps.MarkerOptions
// if(options.anchor){
// newOption.icon = {...marker.native.getIcon(), anchor:options.anchor}
// }
// marker.native.setOptions({
// map:map,
// position:options.position instanceof Position?options.position:marker.native.getPosition(),
// visible:options.visible === undefined || options.visible,
// icon:{...marker.native.getIcon(), anchor:options.anchor}
// })
}
}
};
NaverMintMapController.prototype.getMaxZIndex = function (increment) {
if (increment === void 0) {
increment = 0;
}
if (this.map) {
var targetPane = this.map.getPanes().overlayImage;
var max = 0;
for (var i = 0; i < targetPane.childElementCount; i++) {
var elem = targetPane.children[i];
if (elem instanceof HTMLElement) {
var index = Number(elem.style.zIndex);
if (!isNaN(index) && index > max) {
max = index;
}
}
}
this.markerMaxZIndex = max + increment;
return this.markerMaxZIndex;
} else {
return this.markerMaxZIndex || 1;
}
};
NaverMintMapController.prototype.setMarkerZIndex = function (marker, zIndex) {
if (this.map && marker.element && marker.element instanceof HTMLElement) {
var parent_1 = marker.element.parentElement;
if (parent_1) {
parent_1.style.zIndex = String(zIndex);
}
}
};
NaverMintMapController.prototype.markerToTheTop = function (marker) {
this.setMarkerZIndex(marker, this.getMaxZIndex(1));
};
NaverMintMapController.prototype.clearDrawable = function (drawable) {
var _a;
if (drawable && drawable.native && drawable.native instanceof naver.maps.OverlayView) {
if (drawable.native instanceof naver.maps.Marker) {
if (this.mapProps.markerCache && this.markerPool) {
drawable.native.setVisible(false);
(_a = this.markerPool) === null || _a === void 0 ? void 0 : _a.releasePoolItem(drawable.native);
} else {
drawable.native.setMap(null);
}
log.log(this.mapProps.debug || drawable.options.debug, drawable.options.debugLabel, this.type + ' marker cleared');
status.Status.setMarker(-1, drawable.options.debugLabel);
} else {
drawable.native.setMap(null);
}
naver.maps.Event.clearInstanceListeners(drawable.native);
return true;
}
return false;
};
NaverMintMapController.prototype.isMapDragged = function () {
return this.dragged;
};
NaverMintMapController.prototype.setMapDragged = function (value) {
this.dragged = value;
};
NaverMintMapController.prototype.checkLoaded = function () {
var _a, _b;
return ((_b = (_a = window.naver) === null || _a === void 0 ? void 0 : _a.maps) === null || _b === void 0 ? void 0 : _b.Map) ? true : false;
};
NaverMintMapController.prototype.loadMapApi = function () {
return tslib.__awaiter(this, void 0, void 0, function () {
var _this = this;
return tslib.__generator(this, function (_a) {
return [2
/*return*/
, new Promise(function (resolve, error) {
return tslib.__awaiter(_this, void 0, void 0, function () {
var callbackName, loaded, params, callbackExecFlag, ok;
return tslib.__generator(this, function (_a) {
switch (_a.label) {
case 0:
callbackName = this.getRandomFunctionName('load_naver');
loaded = false; //@ts-ignore
window[callbackName] = function () {
// console.log('naver api loaded');
loaded = true; //@ts-ignore
delete window[callbackName];
};
params = tslib.__assign({
ncpKeyId: this.mapProps.mapKey,
submodules: this.scriptModules.join(','),
callback: callbackName
}, this.mapProps.scriptParams);
return [4
/*yield*/
, this.loadScript(this.buildUrl(this.scriptUrl, params), 'naver_map_script', this.checkLoaded)];
case 1:
callbackExecFlag = _a.sent();
if (!callbackExecFlag) {
loaded = true; //@ts-ignore
delete window[callbackName];
}
return [4
/*yield*/
, waiting.waiting(function () {
return loaded;
})];
case 2:
ok = _a.sent();
if (!ok) {
error('naver script api load failed!!');
}
this.mapApiLoaded = true;
resolve(true);
return [2
/*return*/
];
}
});
});
})];
});
});
};
NaverMintMapController.prototype.initializingMap = function (divElement) {
return tslib.__awaiter(this, void 0, void 0, function () {
var _this = this;
return tslib.__generator(this, function (_a) {
//div element
this.mapDivElement = divElement;
return [2
/*return*/
, new Promise(function (resolve) {
return tslib.__awaiter(_this, void 0, void 0, function () {
var options, maxZoom, minZoom, map;
var _this = this;
var _a, _b, _c, _d, _e, _f;
return tslib.__generator(this, function (_g) {
switch (_g.label) {
case 0:
//이미 생성했으면
//1. divElement 가 그대로인 경우 기존 map 객체 리턴
//2. divElement 가 바뀐경우 기존 map 객체 destroy 하고 새로 생성
if (this.mapInitialized && this.map) {
if (this.map.getElement() === divElement) {
resolve(this.map);
return [2
/*return*/
];
} else {
this.map.destroy();
}
}
if (!!this.mapApiLoaded) return [3
/*break*/
, 2];
return [4
/*yield*/
, this.loadMapApi()];
case 1:
_g.sent();
_g.label = 2;
case 2:
options = {
center: (_a = this.mapProps.base) === null || _a === void 0 ? void 0 : _a.center,
zoom: ((_b = this.mapProps.base) === null || _b === void 0 ? void 0 : _b.zoomLevel) || this.getBaseToMapZoom(15),
draggable: this.mapProps.draggable === false ? false : true,
scrollWheel: this.mapProps.draggable === false ? false : true,
keyboardShortcuts: this.mapProps.keyboardShortcuts === false ? false : true,
logoControl: false,
mapDataControl: false,
mapTypeControl: false,
scaleControl: false
};
maxZoom = 21;
minZoom = 6;
if ((_c = this.mapProps.base) === null || _c === void 0 ? void 0 : _c.maxZoomLevel) {
maxZoom = this.getSafeZoomValue(this.mapProps.base.maxZoomLevel);
}
if ((_d = this.mapProps.base) === null || _d === void 0 ? void 0 : _d.minZoomLevel) {
minZoom = this.getSafeZoomValue(this.mapProps.base.minZoomLevel);
}
if (minZoom > maxZoom) {
minZoom = 6;
}
options.minZoom = minZoom;
options.maxZoom = maxZoom;
divElement.innerHTML = '';
map = new naver.maps.Map(divElement, options);
this.map = map; //맵 커서 초기화
((_e = this.mapProps.base) === null || _e === void 0 ? void 0 : _e.mapCursor) && this.setMapCursor((_f = this.mapProps.base) === null || _f === void 0 ? void 0 : _f.mapCursor); //@ts-ignore
map.addListener('mousedown', function () {
_this.dragged = false; // console.log('map mousedown / dragged => ', this.dragged);
}); //@ts-ignore
map.addListener('dragstart', function () {
_this.dragged = true; // console.log('map dragstart / dragged => ', this.dragged);
}); //@ts-ignore
map.addListener('idle', function (e) {
//onBoundsChanged event
_this.map && _this.checkBoundsChangeThrottleTime() && _this.mapProps.onBoundsChanged && _this.mapProps.onBoundsChanged(_this.getCurrBounds());
});
map.addListener('zoom_changed', function () {
//onZoomChanged event
//console.log('zoom_changed');
_this.map && _this.mapProps.onZoomChanged && _this.mapProps.onZoomChanged(_this.map.getZoom());
}); //@ts-ignore
map.addListener('click', function (e) {
// console.log('map click', e);
if (!_this.mapProps.onClick) return;
var pos = new MapTypes.Position(e.coord.y, e.coord.x);
pos.offset = new MapTypes.Offset(e.offset.x, e.offset.y);
_this.mapProps.onClick(pos);
}); //@ts-ignore
map.addListener('mousemove', function (e) {
if (!_this.mapProps.onMouseMove) return;
var pos = new MapTypes.Position(e.coord.y, e.coord.x);
pos.offset = new MapTypes.Offset(e.offset.x, e.offset.y); // console.log('mousemove', pos)
_this.mapProps.onMouseMove(pos);
});
this.mapInitialized = true;
this.initMarkerPool(); // console.log(`${this.type} map script initialized`, divElement);
resolve(map); //네이버는 로드 후에 idle 이 발생 안해서 직접 일으켜준다
map.trigger('idle');
return [2
/*return*/
];
}
});
});
})];
});
});
};
NaverMintMapController.prototype.getSafeZoomValue = function (value) {
if (value > 21) {
return 21;
} else if (value < 6) {
return 6;
}
return value;
};
NaverMintMapController.prototype.destroyMap = function () {
var _a;
try {
this.removeAllEventListener();
this.map && this.map.destroy();
(_a = this.markerPool) === null || _a === void 0 ? void 0 : _a.destroy();
} catch (e) {
console.log('naver map destroy error', e);
} // console.log(`${this.type} map destroyed`);
};
NaverMintMapController.prototype.getCurrBounds = function () {
if (!this.map) {
throw new Error('Map is not initialized!!');
}
var bounds = this.map.getBounds();
return MapTypes.Bounds.fromNWSE(new MapTypes.Position(bounds.getMax().y, bounds.getMin().x), new MapTypes.Position(bounds.getMin().y, bounds.getMax().x));
};
NaverMintMapController.prototype.panningTo = function (targetCenter) {
var _a;
(_a = this.map) === null || _a === void 0 ? void 0 : _a.panTo(targetCenter, {
duration: 1000
});
};
NaverMintMapController.prototype.getZoomLevel = function () {
var _a;
return ((_a = this.map) === null || _a === void 0 ? void 0 : _a.getZoom()) || 13;
};
NaverMintMapController.prototype.setZoomLevel = function (zoom) {
var _a;
(_a = this.map) === null || _a === void 0 ? void 0 : _a.setZoom(zoom, true);
};
NaverMintMapController.prototype.getCenter = function () {
return this.getCurrBounds().getCenter();
};
NaverMintMapController.prototype.setCenter = function (position) {
var _a;
(_a = this.map) === null || _a === void 0 ? void 0 : _a.setCenter(position);
};
NaverMintMapController.prototype.setMapCursor = function (cursor) {
var _a;
var target = (_a = this.mapDivElement.firstElementChild) === null || _a === void 0 ? void 0 : _a.firstElementChild;
target && (target.style.cursor = cursor);
};
NaverMintMapController.prototype.focusPositionsToFitViewport = function (positions, spacing) {
var _a;
var markerBounds = polygon.PolygonCalculator.getRegionInfo(positions);
if (!markerBounds.maxLat || !markerBounds.minLat || !markerBounds.maxLng || !markerBounds.minLng) {
throw new Error('markerBounds is invalid! in focusPositionsToFitViewport');
}
var pointBounds = naver.maps.PointBounds.bounds(new naver.maps.LatLng(markerBounds.minLat, markerBounds.minLng), new naver.maps.LatLng(markerBounds.maxLat, markerBounds.maxLng));
var marginOptions;
if (typeof spacing === 'number') {
marginOptions = {
top: spacing,
right: spacing,
bottom: spacing,
left: spacing
};
} else if (spacing instanceof MapTypes.Spacing) {
marginOptions = spacing;
}
(_a = this.map) === null || _a === void 0 ? void 0 : _a.panToBounds(pointBounds, {
duration: 500
}, marginOptions);
};
NaverMintMapController.prototype.naverPositionToOffset = function (position) {
if (!this.map) {
return new MapTypes.Offset(0, 0);
}
var offset = this.map.getProjection().fromCoordToOffset(new naver.maps.LatLng(position.lat, position.lng));
return new MapTypes.Offset(offset.x, offset.y);
};
NaverMintMapController.prototype.addEventListener = function (eventName, callback) {
var _this = this;
var naverEventName = this.mapEvent.get(eventName) || this.mapUIEvent.get(eventName);
if (!naverEventName) {
console.warn("MapEventName ".concat(eventName, " is not supported"));
return;
} // console.log(`${eventName} add`);
var map = this.eventMap.get(eventName);
if (!map) {
map = new Map();
this.eventMap.set(eventName, map);
}
var wrappingCallback = function (e) {
if (eventName in _this.mapEvent) {
var bounds = _this.getCurrBounds();
var param = {
name: eventName,
mapType: 'naver',
vendorEventName: naverEventName,
param: {
bounds: bounds,
center: bounds.getCenter(),
zoomLevel: _this.getZoomLevel()
}
};
callback(param);
} else if (eventName in _this.mapUIEvent) {
var position = new MapTypes.Position(e.coord.y, e.coord.x);
position.offset = new MapTypes.Offset(e.offset.x, e.offset.y);
var param = {
name: eventName,
mapType: 'naver',
vendorEventName: naverEventName,
param: {
position: position,
offset: position.offset,
pointerEvent: e.pointerEvent
}
};
callback(param);
}
};
var naverEventListener = naver.maps.Event.addListener(this.map, naverEventName, wrappingCallback);
map.set(callback, naverEventListener);
};
NaverMintMapController.prototype.removeEventListener = function (eventName, callback) {
var map = this.eventMap.get(eventName);
if (map) {
var naverEventListener = map.get(callback);
if (naverEventListener) {
// console.log(`${naverEventListener.eventName} remove`);
naver.maps.Event.removeListener(naverEventListener);
map.delete(callback);
}
}
};
NaverMintMapController.prototype.removeAllEventListener = function (eventName) {
var _this = this;
if (eventName) {
this.clearEventListener(eventName);
} else {
this.eventMap.forEach(function (_map, eventName) {
_this.clearEventListener(eventName);
});
this.eventMap.clear();
}
};
NaverMintMapController.prototype.clearEventListener = function (eventName) {
var map = this.eventMap.get(eventName);
if (map) {
map.forEach(function (naverEventListener) {
// console.log(`${naverEventListener.eventName} remove`);
naver.maps.Event.removeListener(naverEventListener);
});
this.eventMap.delete(eventName);
}
};
return NaverMintMapController;
}(MintMapController.MintMapController);
exports.NaverMintMapController = NaverMintMapController;