@mint-ui/map
Version:
- React map library - Control various map with one interface - Google, Naver, Kakao map supported now - Typescript supported - Canvas marker supported
344 lines (268 loc) • 11 kB
JavaScript
;
Object.defineProperty(exports, '__esModule', { value: true });
var tslib = require('tslib');
var React = require('react');
var MintMapProvider = require('../provider/MintMapProvider.js');
var MintMapCanvasRenderer = require('../MintMapCanvasRenderer.js');
var MapTypes = require('../../types/MapTypes.js');
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
var React__default = /*#__PURE__*/_interopDefaultLegacy(React);
var console = {
log: function () {
}
};
/**
* Mint Map 컴포넌트
*
* @param {MapControlWrapperProps} MapControlWrapperProps
*
* @returns {JSX.Element} JSX
*/
function MapCanvasWrapper(_a) {
var children = _a.children;
tslib.__rest(_a, ["children"]);
var controller = MintMapProvider.useMintMapController(); //render switch
var _b = React.useState(false),
renderFlag = _b[0],
setRenderFlag = _b[1];
var invokeRender = React.useCallback(function () {
setRenderFlag(!renderFlag);
}, []); //canvas renderer
var renderer = React.useRef(); //canvas container ref
var containerRef = React.useRef(null); //canvas ref
var canvasRef = React.useRef(null); //canvas context
var contextRef = React.useRef(); //clear rect
var clearRect = React.useCallback(function () {
if (contextRef.current && canvasRef.current) {
contextRef.current.clearRect(canvasRef.current.width * -1, canvasRef.current.height * -1, canvasRef.current.width * 3, canvasRef.current.height * 3);
}
return true;
}, []); //offset values
// const offsetProvider = useRef(new Offset(0, 0))
// const prevX = useRef(0)
// const prevY = useRef(0)
//scaling
var scaleCanvas = React.useCallback(function (containerRef, canvasElement, canvasContext) {
var devicePixelRatio = window.devicePixelRatio;
var width = containerRef.offsetWidth;
var height = containerRef.offsetHeight;
canvasElement.width = width * devicePixelRatio;
canvasElement.height = height * devicePixelRatio;
canvasElement.style.width = "".concat(width, "px");
canvasElement.style.height = "".concat(height, "px");
canvasContext.scale(devicePixelRatio, devicePixelRatio);
}, []); //init transform
// const initTransform = useCallback(()=>{
// offsetProvider.current.x = 0
// offsetProvider.current.y = 0
// containerRef.current && (containerRef.current.style.transform = `translate(0px, 0px)`)
// console.log('initTransform');
// return true
// }, [])
//parse click param
var parseClickParamToPosition = React.useCallback(function (mapType, e) {
var latlng = e.latlng || e.latLng;
if (!latlng) {
throw new Error("Map Type ".concat(mapType, " canvas marker click not supported (latlng not found)"));
}
var clickPosition = new MapTypes.Position(0, 0);
if (mapType === 'naver') {
clickPosition.lat = latlng._lat;
clickPosition.lng = latlng._lng;
} else if (mapType === 'google') {
clickPosition.lat = latlng.lat();
clickPosition.lng = latlng.lng();
} else if (mapType === 'kakao') {
clickPosition.lat = latlng.Ma;
clickPosition.lng = latlng.La;
} else {
throw new Error("Map Type ".concat(mapType, " canvas marker click not supported"));
}
return clickPosition;
}, []); //box includes
var includes = function (point, targetPoint, width, height) {
// console.log('includes', point, targetPoint, width, height);
if (point.x >= targetPoint.x && point.x <= targetPoint.x + width && point.y >= targetPoint.y && point.y <= targetPoint.y + height) {
return true;
}
return false;
}; //process mouse event
var processMouseEvent = React.useCallback(function (clickedOffset, eventName) {
var items = renderItemsOnView.current;
var hitSet = new Set();
for (var i = items.length - 1; i >= 0; i--) {
var item = items[i];
if (item.visible === undefined || item.visible) {
var event_1 = item[eventName];
if (!event_1) {
continue;
} //includes check
var pos = item.position; // console.log('canvas mouseevent check', pos.offset);
if (pos && !pos.offset) {
pos.offset = controller.positionToOffset(pos);
}
if (!pos || !pos.offset || !includes(clickedOffset, pos.offset, item.boxWidth, item.boxHeight)) {
continue;
} // const propagation =
event_1(clickedOffset);
hitSet.add(item); // if(eventName === 'onMouseOver' || propagation === false){
break; // }
}
}
return hitSet;
}, []); //initialize
React.useEffect(function () {
var resizeObserver;
if (canvasRef.current && containerRef.current) {
resizeObserver = new ResizeObserver(function (entries) {
var elem = entries[0];
canvasRef.current && contextRef.current && scaleCanvas(elem.target, canvasRef.current, contextRef.current); // initTransform()
renderMain();
});
resizeObserver.observe(containerRef.current);
var map = controller.getMap();
if (map) {
// const center = controller.getCenter()
// center.offset = positionToOffset(center)
// if(center.offset){
// prevX.current = center.offset.x
// prevY.current = center.offset.y
// }
//naver 전용 이벤트 'zooming' 일때 캔버스 클리어처리
//@ts-ignore
map.addListener('zooming', function () {
clearRect();
}); //kakao 전용 이벤트 'zoom_start' 일때 캔버스 클리어처리
//@ts-ignore
map.addListener('zoom_start', function () {
clearRect();
}); //@ts-ignore
map.addListener('center_changed', function () {
if (containerRef.current) {
// const pos = controller.getCenter()
// pos.offset = positionToOffset(pos)
// const deltaX = prevX.current - pos.offset.x
// const deltaY = prevY.current - pos.offset.y
// offsetProvider.current.x += deltaX
// offsetProvider.current.y += deltaY
// prevX.current = pos.offset.x
// prevY.current = pos.offset.y
// containerRef.current.style.transform = `translate(${offsetProvider.current.x}px, ${offsetProvider.current.y}px)`
containerRef.current.style.visibility = 'hidden';
}
}); //@ts-ignore
map.addListener('idle', function () {
if (containerRef.current) {
containerRef.current.style.visibility = '';
}
clearRect(); // contextRef.current?.translate(offsetProvider.current.x, offsetProvider.current.y)
// initTransform()
invokeRender();
}); //@ts-ignore
map.addListener('mousemove', function (e) {
var clickPosition = parseClickParamToPosition(controller.getMapType(), e);
var clickedOffset = controller.positionToOffset(clickPosition); // console.log('canvas mousemove', clickedOffset);
var hitSet = processMouseEvent(clickedOffset, 'onMouseOver'); //mouse out 처리
renderItemsMouseOverStatus.current.forEach(function (item) {
if (!hitSet.has(item)) {
item.onMouseOut && item.onMouseOut(clickedOffset);
}
});
renderItemsMouseOverStatus.current = hitSet;
}); //@ts-ignore
map.addListener('click', function (e) {
var clickPosition = parseClickParamToPosition(controller.getMapType(), e);
var clickedOffset = controller.positionToOffset(clickPosition);
processMouseEvent(clickedOffset, 'onClick');
});
}
contextRef.current = canvasRef.current.getContext('2d');
if (contextRef.current) {
scaleCanvas(containerRef.current, canvasRef.current, contextRef.current);
renderer.current = new MintMapCanvasRenderer.MintMapCanvasRenderer(contextRef.current);
}
}
return function () {
resizeObserver && resizeObserver.disconnect();
};
}, []); //items setting
var renderItems = React.useRef([]);
var renderItemsOnView = React.useRef([]);
var renderItemsMouseOverStatus = React.useRef(new Set());
React.useEffect(function () {
renderItems.current = (Array.isArray(children) ? children : children ? [children] : []).map(function (item) {
return item.props;
}); //draw 를 위한 정렬 조건
//1. zIndex 가 있는 것들 끼리 정렬처리
//2. zIndex 가 없는 것들은 원래 배열 순서대로
var zIndexList = [];
var undefinedList = [];
for (var _i = 0, _a = renderItems.current; _i < _a.length; _i++) {
var item = _a[_i];
if (item.zIndex !== undefined) {
zIndexList.push(item);
} else {
undefinedList.push(item);
}
}
renderItems.current = undefinedList;
zIndexList.sort(function (a, b) {
return a > b ? 1 : -1;
}).forEach(function (item) {
renderItems.current.push(item);
});
}, [children]); //rendering main
var renderMain = React.useCallback(function () {
var ctx = contextRef.current;
var container = containerRef.current;
if (!ctx || !container || !renderer.current) {
return;
} //all clear
clearRect(); //draw
var t = new Date().getTime();
var items = renderItems.current;
renderItemsOnView.current.length = 0;
var newSet = new Set();
for (var _i = 0, items_1 = items; _i < items_1.length; _i++) {
var item = items_1[_i];
if (item.visible === undefined || item.visible) {
var pos = item.position; //위치 변환
pos.offset = controller.positionToOffset(pos);
if (item.anchor) {
pos.offset.x += item.anchor.x;
pos.offset.y += item.anchor.y;
}
console.log('canvas marker', pos.offset);
if (pos.offset.x < 0 || pos.offset.x > container.offsetWidth || pos.offset.y < 0 || pos.offset.y > container.offsetHeight) {
continue;
} //그리기
item.renderer(renderer.current, pos.offset, item.payload);
renderItemsOnView.current.push(item);
newSet.add(item);
}
}
renderItemsMouseOverStatus.current.forEach(function (item) {
if (!newSet.has(item)) {
renderItemsMouseOverStatus.current.delete(item);
}
});
console.log("[render ends] ".concat(new Date().getTime() - t, " ms"));
}, []); //render!!!
renderMain();
return React__default["default"].createElement("div", {
ref: containerRef,
style: {
position: 'absolute',
width: '100%',
height: '100%',
zIndex: 2,
pointerEvents: 'none'
}
}, React__default["default"].createElement("canvas", {
ref: canvasRef,
style: {
pointerEvents: 'revert-layer'
}
}), renderFlag && React__default["default"].createElement(React__default["default"].Fragment, null));
}
exports.MapCanvasWrapper = MapCanvasWrapper;