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