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

344 lines (268 loc) 11 kB
'use strict'; 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;