UNPKG

@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
'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;