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

265 lines (212 loc) 10.1 kB
'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var tslib = require('tslib'); var React = require('react'); var reactDom = require('react-dom'); var MintMapProvider = require('../provider/MintMapProvider.js'); var MarkerMovingHook = require('../hooks/MarkerMovingHook.js'); var MapDrawables = require('../../types/MapDrawables.js'); var offsetCalibration = function (mapType, divElement, options, autoFitToViewport, autoAdjustAnchor, autoAdjustAnchorConfig, mapDivElement) { //google 맵의 anchor 보정 (네이버와 같이 왼쪽/위 기준으로 처리) var baseTransform = ''; if (mapType === 'google') { baseTransform = "translate(50%, 100%) translate(".concat(options.anchor ? options.anchor.x * -1 : '0', "px, ").concat(options.anchor ? options.anchor.y * -1 : '0', "px)"); } else if (mapType === 'kakao') { baseTransform = "translate(".concat(options.anchor ? options.anchor.x * -1 : '0', "px, ").concat(options.anchor ? options.anchor.y * -1 : '0', "px)"); } divElement.style.transform = baseTransform; if (autoFitToViewport || autoAdjustAnchor) { // google 은 마커의 getBoundingClientRect 값을 바로 얻을 수 없어서 next tick 에 처리 (50회 트라이) if (mapType === 'google') { divElement.style.visibility = 'hidden'; transformToFitWithNextTick(divElement, mapDivElement, baseTransform, autoAdjustAnchor, autoAdjustAnchorConfig, 50); } else { transformToFit(divElement, mapDivElement, baseTransform, autoAdjustAnchor, autoAdjustAnchorConfig); } } }; var transformToFitWithNextTick = function (divElement, mapDivElement, baseTransform, anchorAdjust, autoAdjustAnchorConfig, maxTryCount, nextCount) { var tryCount = nextCount || 0; setTimeout(function () { tryCount += 1; if (tryCount > maxTryCount) { return; } var rect = divElement.getBoundingClientRect(); if (rect.x === 0 && rect.y === 0 && rect.width === 0 && rect.height === 0) { transformToFitWithNextTick(divElement, mapDivElement, baseTransform, anchorAdjust, autoAdjustAnchorConfig, maxTryCount, tryCount); } else { transformToFit(divElement, mapDivElement, baseTransform, anchorAdjust, autoAdjustAnchorConfig); divElement.style.visibility = 'visible'; } }, 20); }; var transformToFit = function (divElement, mapDivElement, baseTransform, anchorAdjust, autoAdjustAnchorConfig) { var mapRect = mapDivElement.getBoundingClientRect(); var rect = divElement.getBoundingClientRect(); // 보정 값 계산 var xValue = getMarkersFitPosition(mapRect.x, mapRect.width, rect.x, rect.width); var yValue = getMarkersFitPosition(mapRect.y, mapRect.height, rect.y, rect.height); if (anchorAdjust) { var toLeft = xValue < 0; var toRight = xValue > 0; var toTop = yValue < 0; var toBottom = yValue > 0; var transX = toLeft ? (rect.width + (autoAdjustAnchorConfig.marginLeft || 0)) * -1 : toRight ? rect.width + (autoAdjustAnchorConfig.marginRight || 0) : 0; var transY = toTop ? (rect.height + (autoAdjustAnchorConfig.marginTop || 0)) * -1 : toBottom ? rect.height + (autoAdjustAnchorConfig.marginBottom || 0) : 0; divElement.style.transform = baseTransform + " translate(".concat(transX, "px, ").concat(transY, "px)"); } else { divElement.style.transform = baseTransform + " translate(".concat(xValue, "px, ").concat(yValue, "px)"); } }; var getMarkersFitPosition = function (containerPosition, containerSize, markerPosition, markerSize) { var delta = markerPosition - containerPosition; var mapSize = containerSize; var overflowMin = delta < 0; var overflowMax = delta + markerSize > mapSize; // 한쪽만 넘어간 경우 처리 if (overflowMin && !overflowMax) { return delta * -1; } else if (!overflowMin && overflowMax) { return mapSize - delta - markerSize; } return 0; }; /** * Mint Map 컴포넌트 * * @param {MapControlWrapperProps} MapControlWrapperProps * * @returns {JSX.Element} JSX */ function MapMarkerWrapper(_a) { _a.startAnimationClassName; _a.endAnimationClassName; var _b = _a.autoFitToViewport, autoFitToViewport = _b === void 0 ? false : _b, _c = _a.autoAdjustAnchor, autoAdjustAnchor = _c === void 0 ? false : _c, _d = _a.autoAdjustAnchorConfig, autoAdjustAnchorConfig = _d === void 0 ? {} : _d, _e = _a.topOnClick, topOnClick = _e === void 0 ? false : _e, _f = _a.topOnHover, topOnHover = _f === void 0 ? false : _f, movingAnimation = _a.movingAnimation, _g = _a.disablePointerEvent, disablePointerEvent = _g === void 0 ? false : _g, children = _a.children, options = tslib.__rest(_a, ["startAnimationClassName", "endAnimationClassName", "autoFitToViewport", "autoAdjustAnchor", "autoAdjustAnchorConfig", "topOnClick", "topOnHover", "movingAnimation", "disablePointerEvent", "children"]); //controller var controller = MintMapProvider.useMintMapController(); //element var divRef = React.useRef(document.createElement('div')); var divElement = divRef.current; //marker var markerRef = React.useRef(); //moving animation var _h = React.useState({}), movingState = _h[0], setMovingState = _h[1]; React.useEffect(function () { // console.log('movingState', movingState); if (movingState.autoStart) { setTimeout(function () { start(); }, movingState.delay); } }, [movingState]); React.useEffect(function () { // console.log('movingAnimation changed', movingAnimation); if (movingAnimation) { setMovingState(tslib.__assign(tslib.__assign({}, movingAnimation), { marker: markerRef.current })); } }, [movingAnimation]); //marker moving hook var start = MarkerMovingHook.useMarkerMoving(movingState)[0]; //event handlers var onMousedownHandler = function (e) { // console.log('onMousedownHandler setMapDragged', false); // 맵 드래그 여부 초기화 controller.setMapDragged(false); }; var onClickHandler = function (e) { var _a; var marker = markerRef.current; if (marker) { var clickHandler = (_a = options === null || options === void 0 ? void 0 : options.event) === null || _a === void 0 ? void 0 : _a.get('click'); var next = true; if (clickHandler) { var hasNext = clickHandler(e); hasNext !== undefined && (next = hasNext); } next && !topOnHover && topOnClick && controller.markerToTheTop(marker); } }; var onMouseOverHandler = function (e) { var _a; var marker = markerRef.current; //console.log('onMouseOverHandler', marker); if (marker) { var mouseOverHandler = (_a = options === null || options === void 0 ? void 0 : options.event) === null || _a === void 0 ? void 0 : _a.get('mouseover'); var next = true; if (mouseOverHandler) { var hasNext = mouseOverHandler(e); hasNext !== undefined && (next = hasNext); } next && topOnHover && controller.markerToTheTop(marker); } }; //create object React.useEffect(function () { // console.log('drawable created') // divElement.style.display = 'flex' // divElement.style.justifyContent = 'flex-start' // divElement.style.alignItems = 'flex-start' // divElement.style.flexDirection = 'column' divElement.style.width = 'fit-content'; divElement.style.pointerEvents = disablePointerEvent ? 'none' : ''; divElement.addEventListener('click', onClickHandler); divElement.addEventListener('mousedown', onMousedownHandler, { capture: true }); //드래그 여부 초기화를 먼저 수행하기 위해 capture : true 처리 divElement.addEventListener('mouseover', onMouseOverHandler); return function () { divElement.removeEventListener('click', onClickHandler); divElement.removeEventListener('mousedown', onMousedownHandler); divElement.removeEventListener('mouseover', onMouseOverHandler); if (markerRef.current) { controller.clearDrawable(markerRef.current); markerRef.current = undefined; // console.log('drawable cleared') } }; }, []); //create / update object React.useEffect(function () { if (options) { if (markerRef.current) { //console.log('update Marker') controller.updateMarker(markerRef.current, options); //disablePointerEvent 처리 if (divElement.parentElement) { divElement.style.pointerEvents = disablePointerEvent ? 'none' : ''; divElement.parentElement.style.pointerEvents = disablePointerEvent ? 'none' : ''; } //marker offset 보정 offsetCalibration(controller.getMapType(), divElement, options, autoFitToViewport, autoAdjustAnchor, autoAdjustAnchorConfig, controller.mapDivElement); //z-index 처리 if (options.zIndex !== undefined) { controller.setMarkerZIndex(markerRef.current, options.zIndex); } } else { //console.log('create Marker') markerRef.current = new MapDrawables.Marker(options); markerRef.current.element = divElement; controller.createMarker(markerRef.current); //disablePointerEvent 처리 if (divElement.parentElement) { divElement.style.pointerEvents = disablePointerEvent ? 'none' : ''; divElement.parentElement.style.pointerEvents = disablePointerEvent ? 'none' : ''; } //marker offset 보정 offsetCalibration(controller.getMapType(), divElement, options, autoFitToViewport, autoAdjustAnchor, autoAdjustAnchorConfig, controller.mapDivElement); //z-index 처리 if (options.zIndex !== undefined) { controller.setMarkerZIndex(markerRef.current, options.zIndex); } //moving 애니메이션 시작 if (movingAnimation) { setMovingState(tslib.__assign(tslib.__assign({}, movingAnimation), { marker: markerRef.current })); } } } }, [options]); return reactDom.createPortal(children, divElement); } exports.MapMarkerWrapper = MapMarkerWrapper;