feat(zhst/meta,zhst/map): zhst/map:拓展地图api,加入tools组件、cluster组价、marker组件
、draw组件、popup组件;zhst/mata:添加floatButton组件
This commit is contained in:
parent
dd6ff1d2be
commit
f778ec1b72
3
.vscode/settings.json
vendored
3
.vscode/settings.json
vendored
@ -10,6 +10,9 @@
|
|||||||
"flvjs",
|
"flvjs",
|
||||||
"indicatorsize",
|
"indicatorsize",
|
||||||
"lambo",
|
"lambo",
|
||||||
|
"mapbox",
|
||||||
|
"maxzoom",
|
||||||
|
"minzoom",
|
||||||
"remuxer",
|
"remuxer",
|
||||||
"stylelint",
|
"stylelint",
|
||||||
"transmuxer",
|
"transmuxer",
|
||||||
|
@ -1,5 +1,12 @@
|
|||||||
# @zhst/biz
|
# @zhst/biz
|
||||||
|
|
||||||
|
## 0.22.3
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies
|
||||||
|
- @zhst/meta@0.22.0
|
||||||
|
|
||||||
## 0.22.2
|
## 0.22.2
|
||||||
|
|
||||||
### Patch Changes
|
### Patch Changes
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@zhst/biz",
|
"name": "@zhst/biz",
|
||||||
"version": "0.22.2",
|
"version": "0.22.3",
|
||||||
"description": "业务库",
|
"description": "业务库",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"business",
|
"business",
|
||||||
|
@ -1,5 +1,16 @@
|
|||||||
# @zhst/map
|
# @zhst/map
|
||||||
|
|
||||||
|
## 0.3.0
|
||||||
|
|
||||||
|
### Minor Changes
|
||||||
|
|
||||||
|
- zhst/map:拓展地图 api,加入 tools 组件、cluster 组价、marker 组件、draw 组件、popup 组件;zhst/mata:添加 floatButton 组件
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies
|
||||||
|
- @zhst/meta@0.22.0
|
||||||
|
|
||||||
## 0.2.1
|
## 0.2.1
|
||||||
|
|
||||||
### Patch Changes
|
### Patch Changes
|
||||||
|
@ -2,7 +2,9 @@
|
|||||||
|
|
||||||
## 介绍
|
## 介绍
|
||||||
|
|
||||||
地图库,基于map-box开发
|
地图库,基于map-box开发,配合 @turf/turf 工具能达到地图交互体验感最大化。
|
||||||
|
|
||||||
|
设计的初衷是将业务中常见的一些模块抽离成组件的形式。在不影响地图原有的api的情况下,进行增量定制化开发。
|
||||||
|
|
||||||
## 安装
|
## 安装
|
||||||
|
|
||||||
|
@ -1,52 +1,195 @@
|
|||||||
function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
|
function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
|
||||||
var _excluded = ["style", "children", "mapRef", "onLoad", "mapCenter", "mapConfig"];
|
var _excluded = ["style", "children", "height", "width", "draw", "markerData", "sluterData", "popUpInfo", "showPopUp", "toolsBarOpen", "showMarker", "showCluster", "clusterProps", "interactiveLayerIds", "buttonList", "onMarkerClick", "onPopUpClose", "customMarkerRender", "onLoad", "onDrawCreate", "onDrawUpdate", "onDrawDelete", "onToolClick"];
|
||||||
function _extends() { _extends = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
|
function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); }
|
||||||
|
function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
|
||||||
|
function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); }
|
||||||
|
function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); }
|
||||||
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
||||||
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
||||||
function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
||||||
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : String(i); }
|
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : String(i); }
|
||||||
function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
|
function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
|
||||||
|
function _extends() { _extends = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
|
||||||
|
function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
|
||||||
|
function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
|
||||||
|
function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
|
||||||
|
function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
|
||||||
|
function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t.return && (u = t.return(), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }
|
||||||
|
function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
|
||||||
function _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }
|
function _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }
|
||||||
function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }
|
function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }
|
||||||
import 'mapbox-gl/dist/mapbox-gl.css';
|
import 'mapbox-gl/dist/mapbox-gl.css';
|
||||||
|
import '@mapbox/mapbox-gl-draw/dist/mapbox-gl-draw.css';
|
||||||
|
import React, { forwardRef, useImperativeHandle, useMemo, useRef, useState } from 'react';
|
||||||
import Map from 'react-map-gl';
|
import Map from 'react-map-gl';
|
||||||
|
import classnames from 'classnames';
|
||||||
|
import { merge } from '@zhst/func';
|
||||||
|
import Tools from "./components/tools";
|
||||||
|
import DrawControl from "./components/drawControl";
|
||||||
|
import { defaultMapConfig } from "./utils/constants";
|
||||||
import "./index.less";
|
import "./index.less";
|
||||||
import React from 'react';
|
import mapboxDrawStyle from "./utils/drawStyle";
|
||||||
import { merge } from "./utils";
|
import Marker from "./components/marker";
|
||||||
import { MAP_CENTER, defaultMapConfig } from "./constants";
|
import PopUp from "./components/popup";
|
||||||
var MapBox = function MapBox(props) {
|
import Cluster from "./components/clusters/Clusters";
|
||||||
|
import { clusterLayer } from "./components/clusters/layers";
|
||||||
|
var componentName = 'zhst-map';
|
||||||
|
var MapBox = /*#__PURE__*/forwardRef(function (props, ref) {
|
||||||
var _ref = props || {},
|
var _ref = props || {},
|
||||||
_ref$style = _ref.style,
|
_ref$style = _ref.style,
|
||||||
style = _ref$style === void 0 ? {} : _ref$style,
|
style = _ref$style === void 0 ? {} : _ref$style,
|
||||||
children = _ref.children,
|
children = _ref.children,
|
||||||
mapRef = _ref.mapRef,
|
_ref$height = _ref.height,
|
||||||
_onLoad = _ref.onLoad,
|
height = _ref$height === void 0 ? 600 : _ref$height,
|
||||||
_ref$mapCenter = _ref.mapCenter,
|
_ref$width = _ref.width,
|
||||||
mapCenter = _ref$mapCenter === void 0 ? MAP_CENTER : _ref$mapCenter,
|
width = _ref$width === void 0 ? '100%' : _ref$width,
|
||||||
_ref$mapConfig = _ref.mapConfig,
|
draw = _ref.draw,
|
||||||
mapConfig = _ref$mapConfig === void 0 ? {} : _ref$mapConfig,
|
_ref$markerData = _ref.markerData,
|
||||||
|
markerData = _ref$markerData === void 0 ? [] : _ref$markerData,
|
||||||
|
_ref$sluterData = _ref.sluterData,
|
||||||
|
sluterData = _ref$sluterData === void 0 ? [] : _ref$sluterData,
|
||||||
|
_ref$popUpInfo = _ref.popUpInfo,
|
||||||
|
popUpInfo = _ref$popUpInfo === void 0 ? {
|
||||||
|
longitude: 0,
|
||||||
|
latitude: 0
|
||||||
|
} : _ref$popUpInfo,
|
||||||
|
showPopUp = _ref.showPopUp,
|
||||||
|
toolsBarOpen = _ref.toolsBarOpen,
|
||||||
|
_ref$showMarker = _ref.showMarker,
|
||||||
|
showMarker = _ref$showMarker === void 0 ? true : _ref$showMarker,
|
||||||
|
_ref$showCluster = _ref.showCluster,
|
||||||
|
showCluster = _ref$showCluster === void 0 ? false : _ref$showCluster,
|
||||||
|
clusterProps = _ref.clusterProps,
|
||||||
|
_ref$interactiveLayer = _ref.interactiveLayerIds,
|
||||||
|
interactiveLayerIds = _ref$interactiveLayer === void 0 ? [] : _ref$interactiveLayer,
|
||||||
|
_ref$buttonList = _ref.buttonList,
|
||||||
|
buttonList = _ref$buttonList === void 0 ? [{
|
||||||
|
label: '圆形框选',
|
||||||
|
key: 'circle',
|
||||||
|
icon: 'icon-yuan',
|
||||||
|
onClick: function onClick() {
|
||||||
|
var _drawControlRef$curre, _drawControlRef$curre2;
|
||||||
|
return (_drawControlRef$curre = drawControlRef.current) === null || _drawControlRef$curre === void 0 || (_drawControlRef$curre = _drawControlRef$curre.drawer) === null || _drawControlRef$curre === void 0 || (_drawControlRef$curre2 = _drawControlRef$curre.changeMode) === null || _drawControlRef$curre2 === void 0 ? void 0 : _drawControlRef$curre2.call(_drawControlRef$curre, 'simple_select');
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
label: '矩形框选',
|
||||||
|
key: 'rect',
|
||||||
|
icon: 'icon-fang',
|
||||||
|
onClick: function onClick() {
|
||||||
|
var _drawControlRef$curre3, _drawControlRef$curre4;
|
||||||
|
return (_drawControlRef$curre3 = drawControlRef.current) === null || _drawControlRef$curre3 === void 0 || (_drawControlRef$curre3 = _drawControlRef$curre3.drawer) === null || _drawControlRef$curre3 === void 0 || (_drawControlRef$curre4 = _drawControlRef$curre3.changeMode) === null || _drawControlRef$curre4 === void 0 ? void 0 : _drawControlRef$curre4.call(_drawControlRef$curre3, 'draw_rect');
|
||||||
|
},
|
||||||
|
popoverProps: {
|
||||||
|
placement: 'bottom',
|
||||||
|
content: '自定义内容'
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
label: '多边形框选',
|
||||||
|
key: 'more',
|
||||||
|
icon: 'icon-duobianxing',
|
||||||
|
onClick: function onClick() {
|
||||||
|
var _drawControlRef$curre5, _drawControlRef$curre6;
|
||||||
|
return (_drawControlRef$curre5 = drawControlRef.current) === null || _drawControlRef$curre5 === void 0 || (_drawControlRef$curre5 = _drawControlRef$curre5.drawer) === null || _drawControlRef$curre5 === void 0 || (_drawControlRef$curre6 = _drawControlRef$curre5.changeMode) === null || _drawControlRef$curre6 === void 0 ? void 0 : _drawControlRef$curre6.call(_drawControlRef$curre5, 'draw_polygon');
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
label: '路径框选',
|
||||||
|
key: 'path',
|
||||||
|
icon: 'icon-lujingkuangxuannor',
|
||||||
|
onClick: function onClick() {
|
||||||
|
var _drawControlRef$curre7, _drawControlRef$curre8;
|
||||||
|
return (_drawControlRef$curre7 = drawControlRef.current) === null || _drawControlRef$curre7 === void 0 || (_drawControlRef$curre7 = _drawControlRef$curre7.drawer) === null || _drawControlRef$curre7 === void 0 || (_drawControlRef$curre8 = _drawControlRef$curre7.changeMode) === null || _drawControlRef$curre8 === void 0 ? void 0 : _drawControlRef$curre8.call(_drawControlRef$curre7, 'draw_line_string');
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
label: '测距',
|
||||||
|
key: 'path',
|
||||||
|
icon: 'icon-ceju',
|
||||||
|
onClick: function onClick() {
|
||||||
|
var _drawControlRef$curre9, _drawControlRef$curre10;
|
||||||
|
return (_drawControlRef$curre9 = drawControlRef.current) === null || _drawControlRef$curre9 === void 0 || (_drawControlRef$curre9 = _drawControlRef$curre9.drawer) === null || _drawControlRef$curre9 === void 0 || (_drawControlRef$curre10 = _drawControlRef$curre9.changeMode) === null || _drawControlRef$curre10 === void 0 ? void 0 : _drawControlRef$curre10.call(_drawControlRef$curre9, 'draw_line_string');
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
label: '清除',
|
||||||
|
key: 'clear',
|
||||||
|
icon: 'icon-gongjuxiangguanbi',
|
||||||
|
onClick: function onClick() {
|
||||||
|
var _drawControlRef$curre11;
|
||||||
|
return (_drawControlRef$curre11 = drawControlRef.current) === null || _drawControlRef$curre11 === void 0 || (_drawControlRef$curre11 = _drawControlRef$curre11.drawer) === null || _drawControlRef$curre11 === void 0 ? void 0 : _drawControlRef$curre11.deleteAll();
|
||||||
|
}
|
||||||
|
}] : _ref$buttonList,
|
||||||
|
onMarkerClick = _ref.onMarkerClick,
|
||||||
|
onPopUpClose = _ref.onPopUpClose,
|
||||||
|
customMarkerRender = _ref.customMarkerRender,
|
||||||
|
onLoad = _ref.onLoad,
|
||||||
|
onDrawCreate = _ref.onDrawCreate,
|
||||||
|
onDrawUpdate = _ref.onDrawUpdate,
|
||||||
|
onDrawDelete = _ref.onDrawDelete,
|
||||||
|
onToolClick = _ref.onToolClick,
|
||||||
others = _objectWithoutProperties(_ref, _excluded);
|
others = _objectWithoutProperties(_ref, _excluded);
|
||||||
|
var mapRef = useRef(null);
|
||||||
|
var drawControlRef = useRef(null);
|
||||||
|
|
||||||
|
// 默认绘制配置
|
||||||
|
var _useState = useState({
|
||||||
|
displayControlsDefault: false,
|
||||||
|
position: 'top-left',
|
||||||
|
styles: mapboxDrawStyle,
|
||||||
|
// Select which mapbox-gl-draw control buttons to add to the map.
|
||||||
|
// @ts-ignore
|
||||||
|
controls: false,
|
||||||
|
// The user does not have to click the polygon control button first.
|
||||||
|
defaultMode: 'draw_polygon'
|
||||||
|
}),
|
||||||
|
_useState2 = _slicedToArray(_useState, 1),
|
||||||
|
drawConfig = _useState2[0];
|
||||||
|
var initMarker = useMemo(function () {
|
||||||
|
return markerData.map(function (_item) {
|
||||||
|
return /*#__PURE__*/React.createElement(Marker, _extends({
|
||||||
|
customMarkerRender: customMarkerRender,
|
||||||
|
onMarkerClick: onMarkerClick
|
||||||
|
}, _item));
|
||||||
|
});
|
||||||
|
}, [markerData]);
|
||||||
|
useImperativeHandle(ref, function () {
|
||||||
|
var _drawControlRef$curre12;
|
||||||
|
return {
|
||||||
|
mapRef: mapRef.current,
|
||||||
|
drawer: (_drawControlRef$curre12 = drawControlRef.current) === null || _drawControlRef$curre12 === void 0 ? void 0 : _drawControlRef$curre12.drawer
|
||||||
|
};
|
||||||
|
});
|
||||||
return (
|
return (
|
||||||
/*#__PURE__*/
|
/*#__PURE__*/
|
||||||
//@ts-ignore
|
//@ts-ignore
|
||||||
React.createElement(Map, _extends({
|
React.createElement("div", {
|
||||||
ref: function ref(e) {
|
className: classnames("".concat(componentName))
|
||||||
if (mapRef) {
|
}, /*#__PURE__*/React.createElement(Tools, {
|
||||||
mapRef.current = e;
|
open: toolsBarOpen,
|
||||||
}
|
buttonList: buttonList,
|
||||||
},
|
onToolClick: onToolClick
|
||||||
onLoad: function onLoad(e) {
|
}), /*#__PURE__*/React.createElement(Map, _extends({
|
||||||
_onLoad && _onLoad(e);
|
ref: mapRef,
|
||||||
},
|
onLoad: onLoad,
|
||||||
style: _objectSpread({
|
style: _objectSpread({
|
||||||
width: '100%',
|
width: width,
|
||||||
height: 600
|
height: height
|
||||||
}, style)
|
}, style),
|
||||||
}, merge(defaultMapConfig, mapConfig), {
|
interactiveLayerIds: [clusterLayer.id].concat(_toConsumableArray(interactiveLayerIds))
|
||||||
initialViewState: _objectSpread(_objectSpread({}, mapCenter), {}, {
|
}, merge(defaultMapConfig, others)), showMarker && initMarker, showPopUp && popUpInfo && /*#__PURE__*/React.createElement(PopUp, _extends({
|
||||||
zoom: 10
|
onClose: onPopUpClose
|
||||||
})
|
}, popUpInfo)), showCluster && !showMarker && /*#__PURE__*/React.createElement(Cluster, _extends({
|
||||||
}, others), children)
|
type: "geojson",
|
||||||
|
cluster: true,
|
||||||
|
clusterMaxZoom: 14,
|
||||||
|
clusterRadius: 50,
|
||||||
|
data: sluterData
|
||||||
|
}, clusterProps)), draw && /*#__PURE__*/React.createElement(DrawControl, _extends({
|
||||||
|
ref: drawControlRef,
|
||||||
|
onCreate: onDrawCreate,
|
||||||
|
onUpdate: onDrawUpdate,
|
||||||
|
onDelete: onDrawDelete,
|
||||||
|
onSelectionChange: function onSelectionChange(e) {
|
||||||
|
return console.log('e', e);
|
||||||
|
}
|
||||||
|
}, drawConfig)), children))
|
||||||
);
|
);
|
||||||
};
|
});
|
||||||
export default MapBox;
|
export default MapBox;
|
@ -1,47 +0,0 @@
|
|||||||
export var mapboxAccessToken = 'pk.eyJ1IjoiZGluZ2xpMTIzIiwiYSI6ImNra204ODhjczBobTgyeHJ6MmJpZHMxNWgifQ.NbKrXh_hb2gvjr5CEMDnyQ';
|
|
||||||
export var MAP_CENTER = {
|
|
||||||
longitude: 120.2667694313269,
|
|
||||||
latitude: 30.180942826533766
|
|
||||||
}; //地图中心
|
|
||||||
var MapUrl = 'http://10.0.0.120:30003/map';
|
|
||||||
export var defaultMapConfig = {
|
|
||||||
mapboxAccessToken: mapboxAccessToken,
|
|
||||||
maxZoom: 18,
|
|
||||||
minZoom: 4,
|
|
||||||
dragRotate: false,
|
|
||||||
mapStyle: {
|
|
||||||
version: 8,
|
|
||||||
name: 'Mapbox Streets',
|
|
||||||
// sprite: `${location.origin}/mapbox/sprite`, // 地图图标
|
|
||||||
glyphs: 'mapbox://fonts/mapbox/{fontstack}/{range}.pbf',
|
|
||||||
// 字体
|
|
||||||
sources: {
|
|
||||||
//数据源
|
|
||||||
'osm-tiles': {
|
|
||||||
type: 'raster',
|
|
||||||
//栅格切片。vector:矢量切片
|
|
||||||
// Z-瓦片层级,一般支持0-18级,越大代表越清晰;
|
|
||||||
// X-瓦片列号,从西向东(0->360),依次0,1,2,……;
|
|
||||||
// Y-瓦片行号,从北向南(有些也可能是从南向北),依次0,1,2,……;
|
|
||||||
tiles: ["".concat(MapUrl, "/api/tilesets/mapfile/{z}/{x}/{y}.png")],
|
|
||||||
//在线地址,先写死120
|
|
||||||
tileSize: 256 //切片的最小展示尺寸(可选,单位:像素,默认值为 512,即 1024/2
|
|
||||||
}
|
|
||||||
},
|
|
||||||
layers: [
|
|
||||||
// 图层。图层指定了如何渲染数据源提供的数据
|
|
||||||
{
|
|
||||||
id: 'zhstLayer',
|
|
||||||
//唯一id
|
|
||||||
type: 'raster',
|
|
||||||
//类型 栅格。circle,symbol,line...
|
|
||||||
source: 'osm-tiles',
|
|
||||||
// 'source-layer': 'osmtiles',//数据源必须是type:vector
|
|
||||||
minZoom: 4,
|
|
||||||
//最小层级
|
|
||||||
maxZoom: 17,
|
|
||||||
//最大层级
|
|
||||||
renderingMode: '2d'
|
|
||||||
}]
|
|
||||||
}
|
|
||||||
};
|
|
@ -1 +1,2 @@
|
|||||||
export { default as MapBox } from "./MapBox";
|
export { default as MapBox } from "./MapBox";
|
||||||
|
export * from 'react-map-gl';
|
@ -1,3 +1,9 @@
|
|||||||
.mapboxgl-ctrl-attrib-button {
|
.zhst-map {
|
||||||
|
position: relative;
|
||||||
|
width: auto;
|
||||||
|
height: auto;
|
||||||
|
|
||||||
|
.mapboxgl-ctrl-logo {
|
||||||
display: none;
|
display: none;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1 +0,0 @@
|
|||||||
export {};
|
|
@ -1,36 +0,0 @@
|
|||||||
var getRawType = function getRawType(val) {
|
|
||||||
return Object.prototype.toString.call(val).slice(8, -1);
|
|
||||||
};
|
|
||||||
var isPlainObjectOrArray = function isPlainObjectOrArray(val) {
|
|
||||||
return isPlainObject(val) || Array.isArray(val);
|
|
||||||
};
|
|
||||||
var isPlainObject = function isPlainObject(val) {
|
|
||||||
return getRawType(val) === 'Object';
|
|
||||||
};
|
|
||||||
export var merge = function merge(object) {
|
|
||||||
for (var _len = arguments.length, sources = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
|
|
||||||
sources[_key - 1] = arguments[_key];
|
|
||||||
}
|
|
||||||
for (var _i = 0, _sources = sources; _i < _sources.length; _i++) {
|
|
||||||
var source = _sources[_i];
|
|
||||||
for (var key in source) {
|
|
||||||
if (source[key] === undefined && key in object) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (isPlainObjectOrArray(source[key])) {
|
|
||||||
if (getRawType(object[key] === getRawType(source[key]))) {
|
|
||||||
if (isPlainObject(object[key])) {
|
|
||||||
merge(object[key], source[key]);
|
|
||||||
} else {
|
|
||||||
object[key] = object[key].concat(source[key]);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
object[key] = source[key];
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
object[key] = source[key];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return object;
|
|
||||||
};
|
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@zhst/map",
|
"name": "@zhst/map",
|
||||||
"version": "0.2.1",
|
"version": "0.3.0",
|
||||||
"description": "地图库",
|
"description": "地图库",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"map",
|
"map",
|
||||||
@ -40,7 +40,6 @@
|
|||||||
"@mapbox/mapbox-gl-draw": "^1.4.3",
|
"@mapbox/mapbox-gl-draw": "^1.4.3",
|
||||||
"@mapbox/mapbox-gl-draw-static-mode": "^1.0.1",
|
"@mapbox/mapbox-gl-draw-static-mode": "^1.0.1",
|
||||||
"@turf/turf": "^6.5.0",
|
"@turf/turf": "^6.5.0",
|
||||||
"@turf/union": "^6.5.0",
|
|
||||||
"@zhst/hooks": "workspace:^0.13.1",
|
"@zhst/hooks": "workspace:^0.13.1",
|
||||||
"@zhst/icon": "workspace:^0.5.0",
|
"@zhst/icon": "workspace:^0.5.0",
|
||||||
"@zhst/meta": "workspace:^",
|
"@zhst/meta": "workspace:^",
|
||||||
|
@ -5,17 +5,19 @@ import Map, { PopupEvent } from 'react-map-gl';
|
|||||||
import { CSSProperties } from "react";
|
import { CSSProperties } from "react";
|
||||||
import { MapRef, MapStyle, MapProps as MapBoxProps } from "react-map-gl";
|
import { MapRef, MapStyle, MapProps as MapBoxProps } from "react-map-gl";
|
||||||
import classnames from 'classnames'
|
import classnames from 'classnames'
|
||||||
|
import { merge } from '@zhst/func'
|
||||||
import Tools, { ToolsProps } from './components/tools'
|
import Tools, { ToolsProps } from './components/tools'
|
||||||
import DrawControl, { DrawControlProps, DrawControlRefProps } from './components/drawControl';
|
import DrawControl, { DrawControlProps, DrawControlRefProps } from './components/drawControl';
|
||||||
import { MAP_CENTER, defaultMapConfig } from './utils/constants';
|
import { defaultMapConfig } from './utils/constants';
|
||||||
import './index.less';
|
import './index.less';
|
||||||
import mapboxDrawStyle from './utils/drawStyle';
|
import mapboxDrawStyle from './utils/drawStyle';
|
||||||
import Marker, { MarkerProps } from './components/marker';
|
import Marker, { MarkerProps } from './components/marker';
|
||||||
import PopUp, { PopUpProps } from './components/popup';
|
import PopUp, { PopUpProps } from './components/popup';
|
||||||
|
import Cluster, { ClusterProps } from './components/clusters/Clusters';
|
||||||
|
import { clusterLayer } from './components/clusters/layers';
|
||||||
|
|
||||||
const componentName = 'zhst-map'
|
const componentName = 'zhst-map'
|
||||||
|
|
||||||
|
|
||||||
export interface MapProps extends MapBoxProps {
|
export interface MapProps extends MapBoxProps {
|
||||||
mapboxAccessToken?: string //token
|
mapboxAccessToken?: string //token
|
||||||
markerData?: MarkerProps[]
|
markerData?: MarkerProps[]
|
||||||
@ -27,14 +29,15 @@ export interface MapProps extends MapBoxProps {
|
|||||||
mapRef?: MapRef
|
mapRef?: MapRef
|
||||||
style?: CSSProperties
|
style?: CSSProperties
|
||||||
children?: JSX.Element | JSX.Element[] | Array<JSX.Element | undefined>
|
children?: JSX.Element | JSX.Element[] | Array<JSX.Element | undefined>
|
||||||
mapCenter?: {
|
sluterData?: any;
|
||||||
longitude: number, latitude: number
|
|
||||||
}
|
|
||||||
draw?: boolean
|
draw?: boolean
|
||||||
showMarker?: boolean // 显示标记点
|
showMarker?: boolean // 显示标记点
|
||||||
|
showCluster?: boolean // 显示范围统计
|
||||||
buttonList?: ToolsProps['buttonList']
|
buttonList?: ToolsProps['buttonList']
|
||||||
popUpInfo?: PopUpProps
|
popUpInfo?: PopUpProps
|
||||||
showPopUp?: boolean
|
showPopUp?: boolean
|
||||||
|
clusterProps?: ClusterProps
|
||||||
|
toolsBarOpen?: boolean
|
||||||
customMarkerRender?: MarkerProps['customMarkerRender']
|
customMarkerRender?: MarkerProps['customMarkerRender']
|
||||||
onLoad?: (e: mapboxgl.MapboxEvent<undefined>) => void
|
onLoad?: (e: mapboxgl.MapboxEvent<undefined>) => void
|
||||||
onDrawCreate?: (e: { features: object[], [key: string]: any }) => void
|
onDrawCreate?: (e: { features: object[], [key: string]: any }) => void
|
||||||
@ -42,6 +45,7 @@ export interface MapProps extends MapBoxProps {
|
|||||||
onDrawDelete?: (e: { features: object[], [key: string]: any }) => void
|
onDrawDelete?: (e: { features: object[], [key: string]: any }) => void
|
||||||
onMarkerClick?: MarkerProps['onMarkerClick']
|
onMarkerClick?: MarkerProps['onMarkerClick']
|
||||||
onPopUpClose?: (e: PopupEvent) => void;
|
onPopUpClose?: (e: PopupEvent) => void;
|
||||||
|
onToolClick?: ToolsProps['onToolClick']
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface MapRefProps {
|
export interface MapRefProps {
|
||||||
@ -51,31 +55,37 @@ const MapBox = forwardRef<MapRefProps, MapProps>((props, ref) => {
|
|||||||
const {
|
const {
|
||||||
style = {},
|
style = {},
|
||||||
children,
|
children,
|
||||||
mapCenter = MAP_CENTER,
|
|
||||||
height = 600,
|
height = 600,
|
||||||
width = '100%',
|
width = '100%',
|
||||||
draw,
|
draw,
|
||||||
markerData = [],
|
markerData = [],
|
||||||
|
sluterData = [],
|
||||||
popUpInfo = {
|
popUpInfo = {
|
||||||
...MAP_CENTER
|
longitude: 0,
|
||||||
|
latitude: 0
|
||||||
},
|
},
|
||||||
showPopUp,
|
showPopUp,
|
||||||
customMarkerRender,
|
toolsBarOpen,
|
||||||
showMarker,
|
showMarker = true,
|
||||||
onMarkerClick,
|
showCluster = false,
|
||||||
onPopUpClose,
|
clusterProps,
|
||||||
|
interactiveLayerIds = [],
|
||||||
buttonList = [
|
buttonList = [
|
||||||
{
|
{
|
||||||
label: '圆形框选',
|
label: '圆形框选',
|
||||||
key: 'circle',
|
key: 'circle',
|
||||||
icon: 'icon-yuan',
|
icon: 'icon-yuan',
|
||||||
onClick: () => drawControlRef.current?.drawer?.changeMode?.('draw_circle')
|
onClick: () => drawControlRef.current?.drawer?.changeMode?.('simple_select')
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '矩形框选',
|
label: '矩形框选',
|
||||||
key: 'rect',
|
key: 'rect',
|
||||||
icon: 'icon-fang',
|
icon: 'icon-fang',
|
||||||
onClick: () => drawControlRef.current?.drawer?.changeMode?.('draw_rect')
|
onClick: () => drawControlRef.current?.drawer?.changeMode?.('draw_rect'),
|
||||||
|
popoverProps: {
|
||||||
|
placement: 'bottom',
|
||||||
|
content: '自定义内容'
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '多边形框选',
|
label: '多边形框选',
|
||||||
@ -89,6 +99,12 @@ const MapBox = forwardRef<MapRefProps, MapProps>((props, ref) => {
|
|||||||
icon: 'icon-lujingkuangxuannor',
|
icon: 'icon-lujingkuangxuannor',
|
||||||
onClick: () => drawControlRef.current?.drawer?.changeMode?.('draw_line_string')
|
onClick: () => drawControlRef.current?.drawer?.changeMode?.('draw_line_string')
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
label: '测距',
|
||||||
|
key: 'path',
|
||||||
|
icon: 'icon-ceju',
|
||||||
|
onClick: () => drawControlRef.current?.drawer?.changeMode?.('draw_line_string')
|
||||||
|
},
|
||||||
{
|
{
|
||||||
label: '清除',
|
label: '清除',
|
||||||
key: 'clear',
|
key: 'clear',
|
||||||
@ -96,10 +112,14 @@ const MapBox = forwardRef<MapRefProps, MapProps>((props, ref) => {
|
|||||||
onClick: () => drawControlRef.current?.drawer?.deleteAll()
|
onClick: () => drawControlRef.current?.drawer?.deleteAll()
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
onMarkerClick,
|
||||||
|
onPopUpClose,
|
||||||
|
customMarkerRender,
|
||||||
onLoad,
|
onLoad,
|
||||||
onDrawCreate,
|
onDrawCreate,
|
||||||
onDrawUpdate,
|
onDrawUpdate,
|
||||||
onDrawDelete,
|
onDrawDelete,
|
||||||
|
onToolClick,
|
||||||
...others
|
...others
|
||||||
} = props || {};
|
} = props || {};
|
||||||
const mapRef = useRef<MapRef>(null)
|
const mapRef = useRef<MapRef>(null)
|
||||||
@ -112,6 +132,7 @@ const MapBox = forwardRef<MapRefProps, MapProps>((props, ref) => {
|
|||||||
|
|
||||||
styles: mapboxDrawStyle,
|
styles: mapboxDrawStyle,
|
||||||
// Select which mapbox-gl-draw control buttons to add to the map.
|
// Select which mapbox-gl-draw control buttons to add to the map.
|
||||||
|
// @ts-ignore
|
||||||
controls: false,
|
controls: false,
|
||||||
// The user does not have to click the polygon control button first.
|
// The user does not have to click the polygon control button first.
|
||||||
defaultMode: 'draw_polygon',
|
defaultMode: 'draw_polygon',
|
||||||
@ -119,13 +140,11 @@ const MapBox = forwardRef<MapRefProps, MapProps>((props, ref) => {
|
|||||||
|
|
||||||
const initMarker = useMemo(
|
const initMarker = useMemo(
|
||||||
() => {
|
() => {
|
||||||
return markerData.map((_item, index) => (
|
return markerData.map((_item) => (
|
||||||
<Marker
|
<Marker
|
||||||
key={_item.key || String(index)}
|
|
||||||
customMarkerRender={customMarkerRender}
|
customMarkerRender={customMarkerRender}
|
||||||
onMarkerClick={onMarkerClick}
|
onMarkerClick={onMarkerClick}
|
||||||
latitude={_item.latitude}
|
{..._item}
|
||||||
longitude={_item.longitude}
|
|
||||||
/>
|
/>
|
||||||
))
|
))
|
||||||
}, [markerData]
|
}, [markerData]
|
||||||
@ -140,30 +159,45 @@ const MapBox = forwardRef<MapRefProps, MapProps>((props, ref) => {
|
|||||||
//@ts-ignore
|
//@ts-ignore
|
||||||
<div className={classnames(`${componentName}`)}>
|
<div className={classnames(`${componentName}`)}>
|
||||||
<Tools
|
<Tools
|
||||||
|
open={toolsBarOpen}
|
||||||
buttonList={buttonList}
|
buttonList={buttonList}
|
||||||
|
onToolClick={onToolClick}
|
||||||
/>
|
/>
|
||||||
{/* @ts-ignore */}
|
{/* @ts-ignore */}
|
||||||
<Map
|
<Map
|
||||||
ref={mapRef}
|
ref={mapRef}
|
||||||
{...defaultMapConfig}
|
|
||||||
initialViewState={{ ...mapCenter }}
|
|
||||||
onLoad={onLoad}
|
onLoad={onLoad}
|
||||||
style={{ width: width, height: height, ...style }}
|
style={{ width: width, height: height, ...style }}
|
||||||
{...others}
|
interactiveLayerIds={[clusterLayer.id!, ...interactiveLayerIds]}
|
||||||
|
{...merge(defaultMapConfig, others)}
|
||||||
>
|
>
|
||||||
{/* 标记点位 */}
|
{/* 标记点位 */}
|
||||||
{showMarker && initMarker}
|
{showMarker && initMarker}
|
||||||
{/* 点位弹框 */}
|
|
||||||
|
{/* 全局弹框弹框 */}
|
||||||
{showPopUp && popUpInfo && (
|
{showPopUp && popUpInfo && (
|
||||||
<PopUp
|
<PopUp
|
||||||
onClose={onPopUpClose}
|
onClose={onPopUpClose}
|
||||||
{...popUpInfo}
|
{...popUpInfo}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{/* <CustomOverlay
|
{/* <CustomOverlay
|
||||||
>
|
>
|
||||||
<Button>定制图层</Button>
|
<Button>自定义图层</Button>
|
||||||
</CustomOverlay> */}
|
</CustomOverlay> */}
|
||||||
|
|
||||||
|
{/* 范围统计标点 */}
|
||||||
|
{showCluster && !showMarker && (
|
||||||
|
<Cluster
|
||||||
|
type="geojson"
|
||||||
|
cluster={true}
|
||||||
|
clusterMaxZoom={14}
|
||||||
|
clusterRadius={50}
|
||||||
|
data={sluterData}
|
||||||
|
{...clusterProps}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
{/* ---------------绘制图层--------------------- */}
|
{/* ---------------绘制图层--------------------- */}
|
||||||
{draw && (
|
{draw && (
|
||||||
<DrawControl
|
<DrawControl
|
||||||
@ -171,6 +205,7 @@ const MapBox = forwardRef<MapRefProps, MapProps>((props, ref) => {
|
|||||||
onCreate={onDrawCreate}
|
onCreate={onDrawCreate}
|
||||||
onUpdate={onDrawUpdate}
|
onUpdate={onDrawUpdate}
|
||||||
onDelete={onDrawDelete}
|
onDelete={onDrawDelete}
|
||||||
|
onSelectionChange={e => console.log('e', e)}
|
||||||
{...drawConfig}
|
{...drawConfig}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
// @ts-nocheck
|
||||||
//引入地图所所有点图片
|
//引入地图所所有点图片
|
||||||
const file: { [key: string]: string } = {};
|
const file: { [key: string]: string } = {};
|
||||||
|
|
||||||
|
@ -1,62 +1,36 @@
|
|||||||
/**
|
/**
|
||||||
* Created by jiangzhixiong on 2024/05/23
|
* Created by jiangzhixiong on 2024/05/23
|
||||||
*/
|
*/
|
||||||
import React, { forwardRef, useContext, useImperativeHandle } from 'react'
|
import React, { forwardRef, useImperativeHandle } from 'react'
|
||||||
import { Source, Layer, SourceProps } from 'react-map-gl';
|
import { Source, Layer, SourceProps } from 'react-map-gl';
|
||||||
import { ConfigProvider } from '@zhst/meta'
|
import { clusterLayer, clusterCountLayer } from './layers';
|
||||||
import {clusterLayer, clusterCountLayer, unclusteredPointLayer} from './layers';
|
|
||||||
|
|
||||||
const { ConfigContext } = ConfigProvider
|
// const { ConfigContext } = ConfigProvider
|
||||||
|
|
||||||
export interface ClusterProps extends SourceProps {
|
export interface ClusterProps {
|
||||||
prefixCls?: string;
|
prefixCls?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ClusterRefProps {
|
export interface ClusterRefProps {
|
||||||
}
|
}
|
||||||
|
|
||||||
const Cluster = forwardRef<ClusterRefProps, ClusterProps>((props, ref) => {
|
const Cluster = forwardRef<ClusterRefProps, ClusterProps & SourceProps>((props, ref) => {
|
||||||
const {
|
const {
|
||||||
prefixCls: customizePrefixCls,
|
prefixCls: customizePrefixCls,
|
||||||
...rest
|
...rest
|
||||||
} = props
|
} = props
|
||||||
const { getPrefixCls } = useContext(ConfigContext)
|
// const { getPrefixCls } = useContext(ConfigContext)
|
||||||
const componentName = getPrefixCls('map-cluster', customizePrefixCls);
|
// const componentName = getPrefixCls('map-cluster', customizePrefixCls);
|
||||||
|
|
||||||
// const onClick = event => {
|
useImperativeHandle(ref, () => ({}))
|
||||||
// const feature = event.features[0];
|
|
||||||
// const clusterId = feature.properties.cluster_id;
|
|
||||||
|
|
||||||
// const mapboxSource = mapRef.current.getSource('earthquakes') as GeoJSONSource;
|
|
||||||
|
|
||||||
// mapboxSource.getClusterExpansionZoom(clusterId, (err, zoom) => {
|
|
||||||
// if (err) {
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// mapRef.current.easeTo({
|
|
||||||
// center: feature.geometry.coordinates,
|
|
||||||
// zoom,
|
|
||||||
// duration: 500
|
|
||||||
// });
|
|
||||||
// });
|
|
||||||
// };
|
|
||||||
|
|
||||||
useImperativeHandle(ref, () => ({
|
|
||||||
|
|
||||||
}))
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Source
|
<Source
|
||||||
type="geojson"
|
|
||||||
cluster={true}
|
|
||||||
clusterMaxZoom={14}
|
|
||||||
clusterRadius={50}
|
|
||||||
{...rest}
|
{...rest}
|
||||||
>
|
>
|
||||||
<Layer {...clusterLayer} />
|
<Layer {...clusterLayer} />
|
||||||
<Layer {...clusterCountLayer} />
|
<Layer {...clusterCountLayer} />
|
||||||
<Layer {...unclusteredPointLayer} />
|
{/* <Layer {...unclusteredPointLayer} /> */}
|
||||||
</Source>
|
</Source>
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
/**
|
/**
|
||||||
* Created by jiangzhixiong on 2024/05/23
|
* Created by jiangzhixiong on 2024/05/23
|
||||||
*/
|
*/
|
||||||
export { default as Clusters } from './Clusters'
|
import Clusters from './Clusters'
|
||||||
// export type { ClustersProps, ClustersRefProps } from './Clusters'
|
// export type { ClustersProps, ClustersRefProps } from './Clusters'
|
||||||
|
|
||||||
|
export default Clusters
|
||||||
|
@ -1,28 +1,32 @@
|
|||||||
import type {LayerProps} from 'react-map-gl';
|
import type { LayerProps } from 'react-map-gl';
|
||||||
|
|
||||||
|
// 绘制聚合圆形
|
||||||
export const clusterLayer: LayerProps = {
|
export const clusterLayer: LayerProps = {
|
||||||
id: 'clusters',
|
id: 'clusters',
|
||||||
type: 'circle',
|
type: 'circle',
|
||||||
source: 'earthquakes',
|
source: 'earthquakes',
|
||||||
filter: ['has', 'point_count'],
|
// "metadata": { // 元数据(可选,用于为 layer 附加任意的属性。为避免冲突,建议添加前缀,如 mapbox:)
|
||||||
|
// "mapbox:name": "test"
|
||||||
|
// },
|
||||||
|
// "minzoom": 0, // 最小层级(可选,取值范围为 0 ~ 24。当 style 的 zoom 小于此 minzoom 时,layer 将被隐藏)
|
||||||
|
// "maxzoom": 24, // 最大层级(可选,取值范围为 0 ~ 24。当 style 的 zoom 大于此 maxzoom 时,layer 将被隐藏)
|
||||||
|
filter: ['has', 'point_count'], // 过滤(可选,用特定的表达式过滤指定的数据源的要素。具体的表达式详见 expression)
|
||||||
paint: {
|
paint: {
|
||||||
'circle-color': ['step', ['get', 'point_count'], '#51bbd6', 100, '#f1f075', 750, '#f28cb1'],
|
'circle-color': ['step', ['get', 'point_count'], '#2eacff', 200, '#f90', 750, '#f34e52'],
|
||||||
'circle-radius': ['step', ['get', 'point_count'], 20, 100, 30, 750, 40]
|
'circle-radius': ['step', ['get', 'point_count'], 20, 200, 30, 750, 40],
|
||||||
}
|
"circle-stroke-color": "#fff", // 圆点的描边颜色(可选,默认值为 #000000)
|
||||||
};
|
// "circle-opacity": 1, // 圆点的不透明度(可选,取值范围为 0 ~ 1,默认值为 1)
|
||||||
|
// "circle-blur": 0, // 圆点的虚化(可选,默认值为 0。当值为 1 时,表示把圆虚化到只有圆心是不透明的)
|
||||||
export const clusterCountLayer: LayerProps = {
|
// "circle-translate": [0, 0], // 圆点的平移(可选,通过平移 [x, y] 达到一定的偏移量。默认值为 [0, 0],单位:像素。)
|
||||||
id: 'cluster-count',
|
// "circle-translate-anchor": "map", // 圆点的平移锚点,即相对的参考物(可选,可选值为 map、viewport,默认为 map)
|
||||||
type: 'symbol',
|
// "circle-pitch-scale": "map", // 地图倾斜时圆点的缩放(可选,可选值为 map、viewport,默认为 map。值为 viewport 时,圆点不会缩放)
|
||||||
source: 'earthquakes',
|
// "circle-pitch-alignment": "map", // 地图倾斜时圆点的对齐方式(可选,可选值为 map、viewport,默认为 map)
|
||||||
filter: ['has', 'point_count'],
|
"circle-stroke-width": 1, // 圆点的描边宽度(可选,值 >= 0,默认值为 0,单位:像素)
|
||||||
layout: {
|
// "circle-stroke-opacity": 1 // 圆点的描边不透明度(可选,取值范围为 0 ~ 1,默认值为 1)
|
||||||
'text-field': '{point_count_abbreviated}',
|
},
|
||||||
'text-font': ['DIN Offc Pro Medium', 'Arial Unicode MS Bold'],
|
|
||||||
'text-size': 12
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 单个绘制圆形
|
||||||
export const unclusteredPointLayer: LayerProps = {
|
export const unclusteredPointLayer: LayerProps = {
|
||||||
id: 'unclustered-point',
|
id: 'unclustered-point',
|
||||||
type: 'circle',
|
type: 'circle',
|
||||||
@ -35,3 +39,289 @@ export const unclusteredPointLayer: LayerProps = {
|
|||||||
'circle-stroke-color': '#fff'
|
'circle-stroke-color': '#fff'
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// 绘制填充
|
||||||
|
export const FillLayer: LayerProps = {
|
||||||
|
"id": "fill-id", // 唯一 id (必填)
|
||||||
|
"type": "fill", // 类型(必填)
|
||||||
|
"metadata": { // 元数据(可选,用于为 layer 附加任意的属性。为避免冲突,建议添加前缀,如 mapbox:)
|
||||||
|
"mapbox:name": "test"
|
||||||
|
},
|
||||||
|
"source": "source-name", // 数据源的名称(除了 layer 的 type 为 background 外,source 必填)
|
||||||
|
"source-layer": "source-layer-name", // 数据源的图层(只有数据源 source 的 type 为 vector 时,才能设置 source-layer,其他类型的不可以设置)
|
||||||
|
"minzoom": 0, // 最小层级(可选,取值范围为 0 ~ 24。当 style 的 zoom 小于此 minzoom 时,layer 将被隐藏)
|
||||||
|
"maxzoom": 24, // 最大层级(可选,取值范围为 0 ~ 24。当 style 的 zoom 大于此 maxzoom 时,layer 将被隐藏)
|
||||||
|
"filter": [], // 过滤(可选,用特定的表达式过滤指定的数据源的要素。具体的表达式详见 expression)
|
||||||
|
"layout": { // 布局类属性
|
||||||
|
"visibility": "visible", // 可见性(可选,可选值为 none、visible,默认值为 visible)
|
||||||
|
},
|
||||||
|
"paint": { // 绘制类属性
|
||||||
|
"fill-antialias": true, // 填充时是否反锯齿(可选,默认值为 true)
|
||||||
|
"fill-opacity": 1, // 填充的不透明度(可选,取值范围为 0 ~ 1,默认值为 1)
|
||||||
|
"fill-pattern": "", // 填充用的图案(可选,这里填写在 sprite 雪碧图中图标名称。为了图案能无缝填充,图标的高宽需要是 2 的倍数)
|
||||||
|
"fill-color": "#000000", // 填充的颜色(可选,默认值为 #000000。如果设置了 fill-pattern,则 fill-color 将无效)
|
||||||
|
"fill-outline-color": "#000000", // 描边的颜色(可选,默认和 fill-color 一致。如果设置了 fill-pattern,则 fill-outline-color 将无效。为了使用此属性,还需要设置 fill-antialias 为 true)
|
||||||
|
"fill-translate": [0, 0], // 填充的平移(可选,通过平移 [x, y] 达到一定的偏移量。默认值为 [0, 0],单位:像素。)
|
||||||
|
"fill-translate-anchor": "map" // 平移的锚点,即相对的参考物(可选,可选值为 map、viewport,默认为 map)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// --------------------------------- 绘制线 ----------------------------------------
|
||||||
|
export const LineLayer: LayerProps = {
|
||||||
|
"id": "line-id", // 唯一 id (必填)
|
||||||
|
"type": "line", // 类型(必填)
|
||||||
|
"metadata": { // 元数据(可选,用于为 layer 附加任意的属性。为避免冲突,建议添加前缀,如 mapbox:)
|
||||||
|
"mapbox:name": "test"
|
||||||
|
},
|
||||||
|
"source": "source-name", // 数据源的名称(除了 layer 的 type 为 background 外,source 必填)
|
||||||
|
"source-layer": "source-layer-name", // 数据源的图层(只有数据源 source 的 type 为 vector 时,才能设置 source-layer,其他类型的不可以设置)
|
||||||
|
"minzoom": 0, // 最小层级(可选,取值范围为 0 ~ 24。当 style 的 zoom 小于此 minzoom 时,layer 将被隐藏)
|
||||||
|
"maxzoom": 24, // 最大层级(可选,取值范围为 0 ~ 24。当 style 的 zoom 大于此 maxzoom 时,layer 将被隐藏)
|
||||||
|
"filter": [], // 过滤(可选,用特定的表达式过滤指定的数据源的要素。具体的表达式详见 expression)
|
||||||
|
"layout": { // 布局类属性
|
||||||
|
"visibility": "visible", // 可见性(可选,可选值为 none、visible,默认值为 visible)
|
||||||
|
"line-cap": "butt", // 线末端的显示样式(可选,可选值为 butt、round、square,默认值为 butt)
|
||||||
|
// --- butt:方型末端(仅绘制到线的端点)
|
||||||
|
// --- round:圆型末端(以线宽的 1/2 为半径,以线的端点为圆心,绘制圆型端点,会超出线的端点)
|
||||||
|
// --- square:方型末端(以线宽的 1/2 长度超出线的端点)
|
||||||
|
"line-join": "miter", // 线交叉时的显示样式(可选,可选值为 bevel、round、miter,默认值为 miter)
|
||||||
|
// --- bevel:方型交点(以线宽的 1/2 长度超出线的交点)
|
||||||
|
// --- round:圆型交点(以线宽的 1/2 为半径,以线的交点为圆心,绘制圆型交点,会超出线的交点)
|
||||||
|
// --- miter:尖型交点(以两线段的外沿相交,超出交点绘制)
|
||||||
|
"line-miter-limit": 2, // 最大斜接长度(可选,用来将 miter 尖型交点自动转为 bevel 方型交点,默认值为 2。只有 line-join 为 miter 时,才需要设置此属性)
|
||||||
|
"line-round-limit": 1.05, // 最小圆角半径(可选,用来将 round 圆型交点自动转为 miter 尖型交点,默认值为 1.05。只有 line-join 为 round 时,才需要设置此属性)
|
||||||
|
},
|
||||||
|
"paint": { // 绘制类属性
|
||||||
|
"line-opacity": 1, // 线的不透明度(可选,取值范围为 0 ~ 1,默认值为 1)
|
||||||
|
"line-pattern": "", // 线用的图案(可选,这里填写在 sprite 雪碧图中图标名称。为了图案能无缝填充,图标的高宽需要是 2 的倍数)
|
||||||
|
"line-color": "#000000", // 线的颜色(可选,默认值为 #000000。如果设置了 line-pattern,则 line-color 将无效)
|
||||||
|
"line-translate": [0, 0], // 线的平移(可选,通过平移 [x, y] 达到一定的偏移量。默认值为 [0, 0],单位:像素。)
|
||||||
|
"line-translate-anchor": "map", // 线的平移锚点,即相对的参考物(可选,可选值为 map、viewport,默认为 map)
|
||||||
|
"line-width": 1, // 线的宽度(可选,值 >= 0,默认值为 1,单位:像素)
|
||||||
|
"line-gap-width": 0, // 线的外部间距宽度(可选,值 >= 0,默认值为 0,单位:像素。用来在线的外部再绘制一部分,此值表示内间距)
|
||||||
|
"line-offset": 0, // 线的偏移(可选,默认值为 0,单位:像素。对于单线,则是向右的偏移量;对于多边形,正值为内缩 inset,负值为外突 outset)
|
||||||
|
"line-blur": 0, // 线的模糊度(可选,值 >= 0,默认值为 0,单位:像素)
|
||||||
|
"line-dasharray": [0, 0], // 虚线的破折号部分和间隔的长度(可选,默认值为 [0, 0]。如果设置了 line-pattern,则 line-dasharray 将无效)
|
||||||
|
// "line-gradient": "#000000", // 线的渐变色(可选。如果设置了 line-pattern 或 line-dasharray,则 line-gradient 将无效。只有数据源 source 的 type 为 geojson ,且 source 的 lineMetrics 为 true 时,line-gradient 才有效)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 绘制符号
|
||||||
|
export const clusterCountLayer: LayerProps = {
|
||||||
|
id: 'cluster-count',
|
||||||
|
type: 'symbol',
|
||||||
|
source: 'earthquakes',
|
||||||
|
filter: ['has', 'point_count'],
|
||||||
|
layout: {
|
||||||
|
'text-field': '{point_count_abbreviated}',
|
||||||
|
'text-font': ['DIN Offc Pro Medium', 'Arial Unicode MS Bold'],
|
||||||
|
'text-size': 12,
|
||||||
|
// "visibility": "visible", // 可见性(可选,可选值为 none、visible,默认值为 visible)
|
||||||
|
// "symbol-placement": "point", // 符号的位置(可选,可选值为 point、line、line-center,默认值为 point)
|
||||||
|
// // --- point:符号在几何形状的点上
|
||||||
|
// // --- line:符号在几何形状的线上(几何形状只能为 LineString 或 Polygon)
|
||||||
|
// // --- line-center:符号在几何形状的线的中心点上(几何形状只能为 LineString 或 Polygon)
|
||||||
|
// "symbol-spacing": 250, // 符号之间的距离(可选,值 >= 1,默认值为 250,单位:像素。只有 symbol-placement 为 line 时才有效)
|
||||||
|
// "symbol-avoid-edges": false, // 是否避免边缘冲突(可选,默认值为 false。当为 true 时,符号不会超过切片的边缘)
|
||||||
|
// "symbol-sort-key": 1, // 排序的参考值(可选,无默认值。值越大,越在上方)
|
||||||
|
// "symbol-z-order": 'source', // z 轴上的顺序控制(可选,可选值为 viewport-y、source)
|
||||||
|
|
||||||
|
// // 图标类属性(需要设置 icon-image)
|
||||||
|
// "icon-image": "", // 图标的图片(可选,这里填写在 sprite 雪碧图中图标名称)
|
||||||
|
// "icon-size": 1, // 图标的大小(可选,值 >= 0,默认值为 1。这里实际上是图标对应的原始图片的大小的缩放比例。值为 1 表示图标大小为原始图片的大小)
|
||||||
|
// "icon-padding": 2, // 图标的外边距(可选,值 >= 0,默认值为 2。可用于碰撞检测)
|
||||||
|
// "icon-offset": [0, 0], // 图标的偏移量(可选,默认值为 [0, 0])
|
||||||
|
// "icon-anchor": "center", // 图标与锚点的位置关系(可选,可选值为 center、left、right、top、bottom、top-left、top-right、bottom-left、bottom-right,默认值为 center)
|
||||||
|
// "icon-rotate": 0, // 图标的顺时针旋转角度(可选,默认值为 0,单位:角度)
|
||||||
|
// "icon-allow-overlap": false, // 是否允许图标重叠(可选,默认值为 false。当值为 true 时,图标即使和其他符号触碰也会显示)
|
||||||
|
// "icon-ignore-placement": false, // 是否忽略图标位置(可选,默认值为 false。当值为 true 时,其他符号即使与此图标触碰也会显示)
|
||||||
|
// "icon-optional": false, // 图标是否可不显示(可选,默认值为 false。当值为 true 时,如果图标与文本标签碰撞,则显示文本标签)
|
||||||
|
// "icon-text-fit": "none", // 图标与文本的大小适应关系(可选,可选值为 none、width、height、both,默认值为 none)
|
||||||
|
// // --- none:图标按其本身的比例显示
|
||||||
|
// // --- width:图标在 x 轴上缩放以适应文本的宽度
|
||||||
|
// // --- height:图标在 y 轴上缩放以适应文本的高度
|
||||||
|
// // --- both:图标在 x 和 y 轴上缩放以适应文本的宽高
|
||||||
|
// "icon-text-fit-padding": [0, 0, 0, 0], // 图标与文本的内边距(可选,默认值为 [0,0,0,0],单位:像素)
|
||||||
|
// "icon-keep-upright": false, // 当 icon-rotation-alignment 为 map,且 symbol-placement 为 line 或者 line-center 时,设置为 true 的话,可以避免图标上下颠倒
|
||||||
|
// "icon-rotation-alignment": "auto", // 地图旋转时图标的对齐方式(可选,可选值为 map、viewport、auto,默认值为 auto)
|
||||||
|
// // --- map:当 symbol-placement 为 point 时,图标与地图的东西方向对齐;当 symbol-placement 为 line 时,图标的 x 轴和线对齐
|
||||||
|
// // --- viewport:图标的 x 轴和视口的 x 轴对齐
|
||||||
|
// // --- auto:当 symbol-placement 为 point 时,和 viewport 一致;当 symbol-placement 为 line 时,和 map 一致
|
||||||
|
// "icon-pitch-alignment": "auto", // 地图倾斜时图标的对齐方式(可选,可选值为 map、viewport、auto,默认值为 auto)
|
||||||
|
// // --- map:图标的 x 轴与地图平面对齐
|
||||||
|
// // --- viewport:图标的 x 轴和视口的 x 轴对齐
|
||||||
|
// // --- auto:当 symbol-placement 为 point 时,和 viewport 一致;当 symbol-placement 为 line 时,和 map 一致
|
||||||
|
|
||||||
|
// // 文本类属性(需要指定 text-field)
|
||||||
|
// "text-rotation-alignment": "auto", // 与 icon-rotation-alignment 类似
|
||||||
|
// "text-pitch-alignment": "auto", // 与 icon-pitch-alignment 类似
|
||||||
|
// "text-field": "", // 文本所对应的字段(可选,默认值为 "")
|
||||||
|
// "text-font": ["Open Sans Regular","Arial Unicode MS Regular"], // 文本的字体集合(可选,默认值为 ["Open Sans Regular","Arial Unicode MS Regular"])
|
||||||
|
// "text-size": 16, // 文本的大小(可选,默认值为 16,单位:像素)
|
||||||
|
// "text-max-width": 10, // 文本的最大宽度,超过则折行(可选,默认值为 10,单位:ems)
|
||||||
|
// "text-line-height": 1.2, // 文本的行高(可选,默认值为 1.2,单位:ems)
|
||||||
|
// "text-letter-spacing": 0, // 文本的字符间距(可选,默认值为 0,单位:ems)
|
||||||
|
// "text-justify": "center", // 文本的水平对齐方式(可选,可选值为 auto、left、center、right。默认值为 center)
|
||||||
|
// "text-anchor": "center", // 文本与锚点的位置关系(可选,可选值为 center、left、right、top、bottom、top-left、top-right、bottom-left、bottom-right,默认值为 center)
|
||||||
|
// "text-max-angle": 45, // 当 symbol-placement 为 line 或 line-center 时,文本相邻字符的最大夹角,默认 45 度
|
||||||
|
// "text-rotate": 0, // 文本的顺时针旋转角度(可选,默认值为 0,单位:角度)
|
||||||
|
// "text-padding": 2, // 文本的外边距(可选,值 >= 0,默认值为 2。可用于碰撞检测)
|
||||||
|
// "text-keep-upright": false, // 当 icon-rotation-alignment 为 map,且 symbol-placement 为 line 或者 line-center 时,设置为 true 的话,可以避免文本上下颠倒
|
||||||
|
// "text-transform": "none", // 文本大小写转换(可选,可选值为 none、uppercase、lowercase,默认值为 none)
|
||||||
|
// "text-offset": [0, 0], // 图标的偏移量(可选,默认值为 [0, 0])
|
||||||
|
// "text-radial-offset": 0, // 文本的径向偏移量,优先级比 text-offset 高
|
||||||
|
// "text-allow-overlap": false, // 是否允许文本重叠(可选,默认值为 false。当值为 true 时,文本即使和其他符号触碰也会显示)
|
||||||
|
// "text-ignore-placement": false, // 是否忽略文本位置(可选,默认值为 false。当值为 true 时,其他符号即使与此文本触碰也会显示)
|
||||||
|
// "text-optional": false // 文本是否可不显示(可选,默认值为 false。当值为 true 时,如果文本与图标碰撞,则显示图标)
|
||||||
|
},
|
||||||
|
"paint": { // 绘制类属性
|
||||||
|
// // 图标类属性(需要设置 icon-image)
|
||||||
|
// "icon-opacity": 1, // 图标的不透明度(可选,取值范围为 0 ~ 1,默认值为 1)
|
||||||
|
"icon-color": "#fff", // 图标的颜色(可选,默认值为 #000000)
|
||||||
|
// "icon-halo-color": "rgba(0,0,0,0)", // 图标的光晕颜色(可选,默认值为 rgba(0,0,0,0))
|
||||||
|
// "icon-halo-width": 0, // 图标的光晕宽度(可选,值 >= 0,默认值为 0,单位:像素)
|
||||||
|
// "icon-halo-blur": 0, // 图标的光晕模糊宽度(可选,值 >= 0,默认值为 0,单位:像素)
|
||||||
|
// "icon-translate": [0, 0], // 图标的平移(可选,通过平移 [x, y] 达到一定的偏移量。默认值为 [0, 0],单位:像素。)
|
||||||
|
// "icon-translate-anchor": "map", // 图标的平移锚点,即相对的参考物(可选,可选值为 map、viewport,默认为 map)
|
||||||
|
|
||||||
|
// // 文本类属性(需要设置 text-field)
|
||||||
|
// "text-opacity": 1, // 文本的不透明度(可选,取值范围为 0 ~ 1,默认值为 1)
|
||||||
|
"text-color": "#fff", // 文本的颜色(可选,默认值为 #000000)
|
||||||
|
// "text-halo-color": "rgba(0,0,0,0)", // 文本的光晕颜色(可选,默认值为 rgba(0,0,0,0))
|
||||||
|
// "text-halo-width": 0, // 文本的光晕宽度(可选,值 >= 0,默认值为 0,单位:像素)
|
||||||
|
// "text-halo-blur": 0, // 文本的光晕模糊宽度(可选,值 >= 0,默认值为 0,单位:像素)
|
||||||
|
// "text-translate": [0, 0], // 文本的平移(可选,通过平移 [x, y] 达到一定的偏移量。默认值为 [0, 0],单位:像素。)
|
||||||
|
// "text-translate-anchor": "map", // 文本的平移锚点,即相对的参考物(可选,可选值为 map、viewport,默认为 map)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 背景
|
||||||
|
export const backgroundLayer: LayerProps = {
|
||||||
|
"id": "background-id", // 唯一 id (必填)
|
||||||
|
"type": "background", // 类型(必填)
|
||||||
|
"metadata": { // 元数据(可选,用于为 layer 附加任意的属性。为避免冲突,建议添加前缀,如 mapbox:)
|
||||||
|
"mapbox:name": "test"
|
||||||
|
},
|
||||||
|
"minzoom": 0, // 最小层级(可选,取值范围为 0 ~ 24。当 style 的 zoom 小于此 minzoom 时,layer 将被隐藏)
|
||||||
|
"maxzoom": 24, // 最大层级(可选,取值范围为 0 ~ 24。当 style 的 zoom 大于此 maxzoom 时,layer 将被隐藏)
|
||||||
|
"layout": { // 布局类属性
|
||||||
|
"visibility": "visible", // 可见性(可选,可选值为 none、visible,默认值为 visible)
|
||||||
|
},
|
||||||
|
"paint": { // 绘制类属性
|
||||||
|
"background-color": "#000000", // 背景颜色(可选,默认值为 #000000。如果设置了 background-pattern,则 background-color 将无效)
|
||||||
|
"background-pattern": "", // 背景图案(可选,这里填写在 sprite 雪碧图中图标名称。为了背景图案能无缝填充,图标的高宽需要是 2 的倍数)
|
||||||
|
"background-opacity": 1 // 背景不透明度(可选,取值范围为 0 ~ 1,默认值为 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 栅格布局
|
||||||
|
export const rasterLayer: LayerProps = {
|
||||||
|
"id": "raster-id", // 唯一 id (必填)
|
||||||
|
"type": "raster", // 类型(必填)
|
||||||
|
"metadata": { // 元数据(可选,用于为 layer 附加任意的属性。为避免冲突,建议添加前缀,如 mapbox:)
|
||||||
|
"mapbox:name": "test"
|
||||||
|
},
|
||||||
|
"source": "source-name", // 数据源的名称(除了 layer 的 type 为 background 外,source 必填)
|
||||||
|
"source-layer": "source-layer-name", // 数据源的图层(只有数据源 source 的 type 为 vector 时,才能设置 source-layer,其他类型的不可以设置)
|
||||||
|
"minzoom": 0, // 最小层级(可选,取值范围为 0 ~ 24。当 style 的 zoom 小于此 minzoom 时,layer 将被隐藏)
|
||||||
|
"maxzoom": 24, // 最大层级(可选,取值范围为 0 ~ 24。当 style 的 zoom 大于此 maxzoom 时,layer 将被隐藏)
|
||||||
|
"filter": [], // 过滤(可选,用特定的表达式过滤指定的数据源的要素。具体的表达式详见 expression)
|
||||||
|
"layout": { // 布局类属性
|
||||||
|
"visibility": "visible", // 可见性(可选,可选值为 none、visible,默认值为 visible)
|
||||||
|
},
|
||||||
|
"paint": { // 绘制类属性
|
||||||
|
"raster-opacity": 1, // 图片的不透明度(可选,取值范围为 0 ~ 1,默认值为 1)
|
||||||
|
"raster-hue-rotate": 0, // 在色轮上旋转色相的角度(可选,默认值为 0,单位:角度)
|
||||||
|
"raster-brightness-min": 0, // 图片的最小亮度(可选,取值范围为 0 ~ 1,默认值为 0)
|
||||||
|
"raster-brightness-max": 1, // 图片的最大亮度(可选,取值范围为 0 ~ 1,默认值为 1)
|
||||||
|
"raster-saturation": 0, // 图片的饱和度(可选,取值范围为 -1 ~ 1,默认值为 0)
|
||||||
|
"raster-contrast": 0, // 图片的对比度(可选,取值范围为 -1 ~ 1,默认值为 0)
|
||||||
|
"raster-resampling": "linear", // 采样方式(可选,可选值为 linear、nearest,默认值为 linear)
|
||||||
|
"raster-fade-duration": 300 // 切换瓦片时的渐隐时间(可选,默认值为 300,单位:毫秒)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 热力图
|
||||||
|
export const heatmapLayer: LayerProps = {
|
||||||
|
"id": "heatmap-id", // 唯一 id (必填)
|
||||||
|
"type": "heatmap", // 类型(必填)
|
||||||
|
"metadata": { // 元数据(可选,用于为 layer 附加任意的属性。为避免冲突,建议添加前缀,如 mapbox:)
|
||||||
|
"mapbox:name": "test"
|
||||||
|
},
|
||||||
|
"source": "source-name", // 数据源的名称(除了 layer 的 type 为 background 外,source 必填)
|
||||||
|
"source-layer": "source-layer-name", // 数据源的图层(只有数据源 source 的 type 为 vector 时,才能设置 source-layer,其他类型的不可以设置)
|
||||||
|
"minzoom": 0, // 最小层级(可选,取值范围为 0 ~ 24。当 style 的 zoom 小于此 minzoom 时,layer 将被隐藏)
|
||||||
|
"maxzoom": 24, // 最大层级(可选,取值范围为 0 ~ 24。当 style 的 zoom 大于此 maxzoom 时,layer 将被隐藏)
|
||||||
|
"filter": [], // 过滤(可选,用特定的表达式过滤指定的数据源的要素。具体的表达式详见 expression)
|
||||||
|
"layout": { // 布局类属性
|
||||||
|
"visibility": "visible", // 可见性(可选,可选值为 none、visible,默认值为 visible)
|
||||||
|
},
|
||||||
|
"paint": { // 绘制类属性
|
||||||
|
"heatmap-opacity": 1, // 热力图的不透明度(可选,取值范围为 0 ~ 1,默认值为 1)
|
||||||
|
"heatmap-radius": 30, // 一个热力图点的影响半径(可选,值 >= 1,默认值为 30,单位:像素)
|
||||||
|
"heatmap-weight": 1, // 一个热力图点的权重(可选,值 >= 0,默认值为 1)
|
||||||
|
"heatmap-intensity": 1, // 热力图的强度,控制了所有的热力图点(可选,值 >= 0,默认值为 1)
|
||||||
|
"heatmap-color": [ // 热力图的颜色变化(可选,默认值如下)
|
||||||
|
"interpolate", ["linear"], ["heatmap-density"],
|
||||||
|
0, "rgba(0, 0, 255, 0)",
|
||||||
|
0.1, "royalblue",
|
||||||
|
0.3, "cyan",
|
||||||
|
0.5, "lime",
|
||||||
|
0.7, "yellow",
|
||||||
|
1, "red"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 坡面阴影
|
||||||
|
export const hillshadeLayer: LayerProps = {
|
||||||
|
"id": "hillshade-id", // 唯一 id (必填)
|
||||||
|
"type": "hillshade", // 类型(必填)
|
||||||
|
"metadata": { // 元数据(可选,用于为 layer 附加任意的属性。为避免冲突,建议添加前缀,如 mapbox:)
|
||||||
|
"mapbox:name": "test"
|
||||||
|
},
|
||||||
|
"source": "source-name", // 数据源的名称(除了 layer 的 type 为 background 外,source 必填)
|
||||||
|
"source-layer": "source-layer-name", // 数据源的图层(只有数据源 source 的 type 为 vector 时,才能设置 source-layer,其他类型的不可以设置)
|
||||||
|
"minzoom": 0, // 最小层级(可选,取值范围为 0 ~ 24。当 style 的 zoom 小于此 minzoom 时,layer 将被隐藏)
|
||||||
|
"maxzoom": 24, // 最大层级(可选,取值范围为 0 ~ 24。当 style 的 zoom 大于此 maxzoom 时,layer 将被隐藏)
|
||||||
|
"filter": [], // 过滤(可选,用特定的表达式过滤指定的数据源的要素。具体的表达式详见 expression)
|
||||||
|
"layout": { // 布局类属性
|
||||||
|
"visibility": "visible", // 可见性(可选,可选值为 none、visible,默认值为 visible)
|
||||||
|
},
|
||||||
|
"paint": { // 绘制类属性
|
||||||
|
"hillshade-illumination-direction": 335, // 光照的方向(可选,取值范围为 0 ~ 359,默认值为 335,单位:角度)
|
||||||
|
"hillshade-illumination-anchor": "viewport", // 光照的锚点(可选,可选值为 map、viewport,默认值为 viewport)
|
||||||
|
"hillshade-exaggeration": 0.5, // 阴影的强度(可选,取值范围为 0 ~ 1,默认值为 0.5)
|
||||||
|
"hillshade-shadow-color": "#000000", // 阴影的颜色(可选,默认值为 #000000)
|
||||||
|
"hillshade-highlight-color": "#ffffff", // 光照部分的颜色(可选,默认值为 #ffffff)
|
||||||
|
"hillshade-accent-color": "#000000" // 用于强调地形的颜色(可选,默认值为 #000000)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 三维填充
|
||||||
|
export const FillExtrusionLayer: LayerProps = {
|
||||||
|
"id": "fill-extrusion-id", // 唯一 id (必填)
|
||||||
|
"type": "fill-extrusion", // 类型(必填)
|
||||||
|
"metadata": { // 元数据(可选,用于为 layer 附加任意的属性。为避免冲突,建议添加前缀,如 mapbox:)
|
||||||
|
"mapbox:name": "test"
|
||||||
|
},
|
||||||
|
"source": "source-name", // 数据源的名称(除了 layer 的 type 为 background 外,source 必填)
|
||||||
|
"source-layer": "source-layer-name", // 数据源的图层(只有数据源 source 的 type 为 vector 时,才能设置 source-layer,其他类型的不可以设置)
|
||||||
|
"minzoom": 0, // 最小层级(可选,取值范围为 0 ~ 24。当 style 的 zoom 小于此 minzoom 时,layer 将被隐藏)
|
||||||
|
"maxzoom": 24, // 最大层级(可选,取值范围为 0 ~ 24。当 style 的 zoom 大于此 maxzoom 时,layer 将被隐藏)
|
||||||
|
"filter": [], // 过滤(可选,用特定的表达式过滤指定的数据源的要素。具体的表达式详见 expression)
|
||||||
|
"layout": { // 布局类属性
|
||||||
|
"visibility": "visible", // 可见性(可选,可选值为 none、visible,默认值为 visible)
|
||||||
|
},
|
||||||
|
"paint": { // 绘制类属性
|
||||||
|
"fill-extrusion-opacity": 1, // 三维填充的不透明度(可选,取值范围为 0 ~ 1,默认值为 1)
|
||||||
|
"fill-extrusion-pattern": "", // 三维填充的图案(可选,这里填写在 sprite 雪碧图中图标名称。为了图案能无缝填充,图标的高宽需要是 2 的倍数)
|
||||||
|
"fill-extrusion-color": "#000000", // 三维填充的颜色(可选,默认值为 #000000)
|
||||||
|
"fill-extrusion-translate": [0, 0], // 三维填充的平移(可选,通过平移 [x, y] 达到一定的偏移量。默认值为 [0, 0],单位:像素。)
|
||||||
|
"fill-extrusion-translate-anchor": "map", // 平移的锚点,即相对的参考物(可选,可选值为 map、viewport,默认为 map)
|
||||||
|
"fill-extrusion-height": 0, // 三维填充的高度(可选,值 >= 0,默认值为 0,单位:米)
|
||||||
|
"fill-extrusion-base": 0, // 三维填充的底部高度(可选,值 >= 0,默认值为 0,单位:米。值必须小于等于 fill-extrusion-height)
|
||||||
|
"fill-extrusion-vertical-gradient": true, // 是否开启垂直渐变(可选,默认值为 true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,21 +1,22 @@
|
|||||||
|
// @ts-nocheck
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { useState, cloneElement } from 'react';
|
import {useState, cloneElement} from 'react';
|
||||||
import { useControl } from 'react-map-gl';
|
import {useControl} from 'react-map-gl';
|
||||||
import { createPortal } from 'react-dom';
|
import {createPortal} from 'react-dom';
|
||||||
import type { MapboxMap, IControl } from 'react-map-gl';
|
import type { MapboxMap, IControl } from 'react-map-gl';
|
||||||
|
|
||||||
|
|
||||||
// Based on template in https://docs.mapbox.com/mapbox-gl-js/api/markers/#icontrol
|
// Based on template in https://docs.mapbox.com/mapbox-gl-js/api/markers/#icontrol
|
||||||
class OverlayControl implements IControl {
|
class OverlayControl implements IControl {
|
||||||
_map: MapboxMap | undefined;
|
_map: MapboxMap | undefined;
|
||||||
_container: HTMLDivElement | undefined;
|
_container: HTMLElement | undefined;
|
||||||
_redraw: () => void;
|
_redraw: () => void;
|
||||||
|
|
||||||
constructor(redraw: () => void) {
|
constructor(redraw: () => void) {
|
||||||
this._redraw = redraw;
|
this._redraw = redraw;
|
||||||
}
|
}
|
||||||
|
|
||||||
onAdd(map: MapboxMap) {
|
// @ts-ignore
|
||||||
|
onAdd(map) {
|
||||||
this._map = map;
|
this._map = map;
|
||||||
map.on('move', this._redraw);
|
map.on('move', this._redraw);
|
||||||
/* global document */
|
/* global document */
|
||||||
@ -40,20 +41,20 @@ class OverlayControl implements IControl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 自定义图层
|
* A custom control that rerenders arbitrary React content whenever the camera changes
|
||||||
*/
|
*/
|
||||||
const CustomOverlay = (props: {children: React.ReactElement}) => {
|
function CustomOverlay(props: {children: React.ReactElement}) {
|
||||||
const [, setVersion] = useState(0);
|
const [, setVersion] = useState(0);
|
||||||
|
|
||||||
const customControl = useControl<OverlayControl>(() => {
|
const ctrl = useControl<OverlayControl>(() => {
|
||||||
const forceUpdate = () => setVersion(v => v + 1);
|
const forceUpdate = () => setVersion(v => v + 1);
|
||||||
return new OverlayControl(forceUpdate);
|
return new OverlayControl(forceUpdate);
|
||||||
});
|
});
|
||||||
|
|
||||||
const map = customControl.getMap();
|
const map = ctrl.getMap();
|
||||||
|
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
return map && createPortal(cloneElement(props.children, { map }), customControl.getElement());
|
return map && createPortal(cloneElement(props.children, {map}), ctrl.getElement());
|
||||||
}
|
}
|
||||||
|
|
||||||
export default React.memo(CustomOverlay);
|
export default React.memo(CustomOverlay);
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
// @ts-nocheck
|
||||||
import '@mapbox/mapbox-gl-draw/dist/mapbox-gl-draw.css';
|
import '@mapbox/mapbox-gl-draw/dist/mapbox-gl-draw.css';
|
||||||
import MapboxDraw from '@mapbox/mapbox-gl-draw';
|
import MapboxDraw from '@mapbox/mapbox-gl-draw';
|
||||||
import type { DrawModes } from '@mapbox/mapbox-gl-draw';
|
import type { DrawModes } from '@mapbox/mapbox-gl-draw';
|
||||||
|
@ -18,12 +18,18 @@ import { useControl } from 'react-map-gl';
|
|||||||
import type { ControlPosition } from 'react-map-gl';
|
import type { ControlPosition } from 'react-map-gl';
|
||||||
import { MapContextValue } from 'react-map-gl/dist/esm/components/map';
|
import { MapContextValue } from 'react-map-gl/dist/esm/components/map';
|
||||||
|
|
||||||
type DrawControlProps = ConstructorParameters<typeof MapboxDraw>[0] & {
|
export type DrawControlProps = ConstructorParameters<typeof MapboxDraw>[0] & {
|
||||||
position?: ControlPosition;
|
position?: ControlPosition;
|
||||||
|
|
||||||
onCreate?: (evt: {features: object[]}) => void;
|
onCreate?: (evt: {features: object[]}) => void;
|
||||||
onUpdate?: (evt: {features: object[]; action: string}) => void;
|
onUpdate?: (evt: {features: object[]; action: string}) => void;
|
||||||
onDelete?: (evt: {features: object[]}) => void;
|
onDelete?: (evt: {features: object[]}) => void;
|
||||||
|
onRender?: (evt: {features: object[]}) => void;
|
||||||
|
onCombine?: (evt: {features: object[]}) => void;
|
||||||
|
onUncombine?: (evt: {features: object[]}) => void;
|
||||||
|
onModeChange?: (evt: {features: object[]}) => void;
|
||||||
|
onActionable?: (evt: {features: object[]}) => void;
|
||||||
|
onSelectionChange?: (evt: {features: object[]}) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
export interface DrawControlRefProps {
|
export interface DrawControlRefProps {
|
||||||
@ -61,12 +67,24 @@ const DrawControl = forwardRef<DrawControlRefProps, DrawControlProps>((props, re
|
|||||||
map.on('draw.create', e => props.onCreate?.(e));
|
map.on('draw.create', e => props.onCreate?.(e));
|
||||||
map.on('draw.update', e => props.onUpdate?.(e));
|
map.on('draw.update', e => props.onUpdate?.(e));
|
||||||
map.on('draw.delete', e => props.onDelete?.(e));
|
map.on('draw.delete', e => props.onDelete?.(e));
|
||||||
|
map.on('draw.render', e => props.onRender?.(e));
|
||||||
|
map.on('draw.combine', e => props.onCombine?.(e));
|
||||||
|
map.on('draw.uncombine', e => props.onUncombine?.(e));
|
||||||
|
map.on('draw.modechange', e => props.onModeChange?.(e));
|
||||||
|
map.on('draw.actionable', e => props.onActionable?.(e));
|
||||||
|
map.on('draw.selectionchange', e => props.onSelectionChange?.(e));
|
||||||
},
|
},
|
||||||
(context: MapContextValue) => {
|
(context: MapContextValue) => {
|
||||||
const { map } = context
|
const { map } = context
|
||||||
map.off('draw.create', props.onCreate);
|
map.off('draw.create', props.onCreate);
|
||||||
map.off('draw.update', props.onUpdate);
|
map.off('draw.update', props.onUpdate);
|
||||||
map.off('draw.delete', props.onDelete);
|
map.off('draw.delete', props.onDelete);
|
||||||
|
map.off('draw.render', e => props.onRender?.(e));
|
||||||
|
map.off('draw.combine', e => props.onCombine?.(e));
|
||||||
|
map.off('draw.uncombine', e => props.onUncombine?.(e));
|
||||||
|
map.off('draw.modechange', e => props.onModeChange?.(e));
|
||||||
|
map.off('draw.actionable', e => props.onActionable?.(e));
|
||||||
|
map.off('draw.selectionchange', e => props.onSelectionChange?.(e));
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
position: props.position
|
position: props.position
|
||||||
|
@ -1,18 +1,20 @@
|
|||||||
/**
|
/**
|
||||||
* Created by jiangzhixiong on 2024/05/23
|
* Created by jiangzhixiong on 2024/05/23
|
||||||
*/
|
*/
|
||||||
import React, { forwardRef, ReactNode, useContext, useImperativeHandle } from 'react'
|
import React, { forwardRef, ReactNode, useContext, useImperativeHandle, useState } from 'react'
|
||||||
import {
|
import {
|
||||||
Marker as MapboxMarker,
|
Marker as MapboxMarker,
|
||||||
MarkerProps as MapboxMarkerProps,
|
MarkerProps as MapboxMarkerProps,
|
||||||
MarkerEvent
|
MarkerEvent
|
||||||
} from 'react-map-gl'
|
} from 'react-map-gl'
|
||||||
import { Checkbox, ConfigProvider, Image } from '@zhst/meta'
|
import { Checkbox, ConfigProvider, Image } from '@zhst/meta'
|
||||||
|
import classNames from 'classnames'
|
||||||
import cameraBlue from '../../assets/icons/camera_blue.png'
|
import cameraBlue from '../../assets/icons/camera_blue.png'
|
||||||
import cameraGreen from '../../assets/icons/camera_green.png'
|
import cameraGreen from '../../assets/icons/camera_green.png'
|
||||||
import cameraGrey from '../../assets/icons/camera_grey.png'
|
import cameraGrey from '../../assets/icons/camera_grey.png'
|
||||||
import cameraRed from '../../assets/icons/camera_red.png'
|
import cameraRed from '../../assets/icons/camera_red.png'
|
||||||
import cameraYellow from '../../assets/icons/camera_yellow.png'
|
import cameraYellow from '../../assets/icons/camera_yellow.png'
|
||||||
|
import './index.less'
|
||||||
|
|
||||||
const { ConfigContext } = ConfigProvider
|
const { ConfigContext } = ConfigProvider
|
||||||
|
|
||||||
@ -28,13 +30,15 @@ const PIC_MAP = new Map([
|
|||||||
export interface MarkerProps extends MapboxMarkerProps {
|
export interface MarkerProps extends MapboxMarkerProps {
|
||||||
prefixCls?: string;
|
prefixCls?: string;
|
||||||
key: string;
|
key: string;
|
||||||
|
id: string;
|
||||||
title?: string;
|
title?: string;
|
||||||
|
disabled?: boolean;
|
||||||
checked?: boolean;
|
checked?: boolean;
|
||||||
|
showCheckBox?: boolean
|
||||||
|
showTooltip?: boolean
|
||||||
type?: 'camera' | 'cluster' | 'marker';
|
type?: 'camera' | 'cluster' | 'marker';
|
||||||
population?: string;
|
population?: string;
|
||||||
status?: 'blue' | 'green' | 'yellow' | 'grey' | 'red_border' | 'escape' | 'escape_border' | 'red_track'; // 摄像头状态
|
status?: 'blue' | 'green' | 'yellow' | 'grey' | 'red_border' | 'escape' | 'escape_border' | 'red_track'; // 摄像头状态
|
||||||
latitude: number;
|
|
||||||
longitude: number;
|
|
||||||
onClick?: (e?: MarkerEvent, data?: MarkerProps) => void;
|
onClick?: (e?: MarkerEvent, data?: MarkerProps) => void;
|
||||||
onMarkerClick?: (e?: MouseEvent, checked?: boolean, data?: MarkerProps) => void;
|
onMarkerClick?: (e?: MouseEvent, checked?: boolean, data?: MarkerProps) => void;
|
||||||
customMarkerRender?: (data: MarkerProps) => ReactNode
|
customMarkerRender?: (data: MarkerProps) => ReactNode
|
||||||
@ -46,41 +50,61 @@ export interface MarkerRefProps {
|
|||||||
const Marker = forwardRef<MarkerRefProps, MarkerProps>((props, ref) => {
|
const Marker = forwardRef<MarkerRefProps, MarkerProps>((props, ref) => {
|
||||||
const {
|
const {
|
||||||
prefixCls: customizePrefixCls,
|
prefixCls: customizePrefixCls,
|
||||||
longitude,
|
|
||||||
latitude,
|
|
||||||
checked = false,
|
checked = false,
|
||||||
type = 'camera',
|
type = 'camera',
|
||||||
status = 'blue',
|
status = 'blue',
|
||||||
|
disabled,
|
||||||
|
showCheckBox,
|
||||||
|
showTooltip,
|
||||||
onClick,
|
onClick,
|
||||||
onMarkerClick,
|
onMarkerClick,
|
||||||
customMarkerRender
|
customMarkerRender,
|
||||||
|
...rest
|
||||||
} = props
|
} = props
|
||||||
const { getPrefixCls } = useContext(ConfigContext)
|
const { getPrefixCls } = useContext(ConfigContext)
|
||||||
const componentName = getPrefixCls('-map-marker', customizePrefixCls);
|
const componentName = getPrefixCls('-map-marker', customizePrefixCls);
|
||||||
|
const [showTitle, setShowTitle] = useState(showTooltip)
|
||||||
|
|
||||||
useImperativeHandle(ref, () => ({}))
|
useImperativeHandle(ref, () => ({}))
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<MapboxMarker
|
<MapboxMarker
|
||||||
longitude={Number(longitude)}
|
|
||||||
latitude={Number(latitude)}
|
|
||||||
anchor="bottom"
|
anchor="bottom"
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
onClick={e => {
|
onClick={e => {
|
||||||
e.originalEvent.stopPropagation();
|
e.originalEvent.stopPropagation();
|
||||||
|
// @ts-ignore
|
||||||
onClick?.(e, props)
|
onClick?.(e, props)
|
||||||
}}
|
}}
|
||||||
|
{...rest}
|
||||||
>
|
>
|
||||||
{/* 自定义marker */}
|
{/* 自定义marker */}
|
||||||
{customMarkerRender?.(props) || (
|
{customMarkerRender?.(props) || (
|
||||||
<div className={componentName}>
|
<div className={componentName}>
|
||||||
<Checkbox value={checked} onClick={(e) => {
|
{showCheckBox && (
|
||||||
|
<Checkbox
|
||||||
|
className={classNames(`${componentName}-checkbox`)}
|
||||||
|
disabled={disabled}
|
||||||
|
checked={checked}
|
||||||
|
onClick={(e) => {
|
||||||
e.stopPropagation()
|
e.stopPropagation()
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
onMarkerClick?.(e, checked, props)
|
onMarkerClick?.(e, checked, props)
|
||||||
}}>
|
}}
|
||||||
<Image src={PIC_MAP.get(`${type}_${status}`)} preview={false} />
|
/>
|
||||||
</Checkbox>
|
)}
|
||||||
|
<Image
|
||||||
|
onMouseEnter={() => setShowTitle(true)}
|
||||||
|
onMouseLeave={() => setShowTitle(false)}
|
||||||
|
src={PIC_MAP.get(`${type}_${status}`)}
|
||||||
|
preview={false}
|
||||||
|
/>
|
||||||
|
{showTitle && (
|
||||||
|
<div className={classNames(`${componentName}-title`)}>
|
||||||
|
{props.title}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</MapboxMarker>
|
</MapboxMarker>
|
||||||
|
35
packages/map/src/components/marker/index.less
Normal file
35
packages/map/src/components/marker/index.less
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
.zhst--map-marker {
|
||||||
|
position: relative;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
&-checkbox {
|
||||||
|
position: absolute;
|
||||||
|
top: -6px;
|
||||||
|
right: -6px;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-title {
|
||||||
|
padding: 3px 6px;
|
||||||
|
position: absolute;
|
||||||
|
left: 50%;
|
||||||
|
bottom: -36px;
|
||||||
|
transform: translateX(-50%);
|
||||||
|
white-space: nowrap;
|
||||||
|
background-color: #fff;
|
||||||
|
border-radius: 3px;
|
||||||
|
box-shadow: 3px 3px 6px 3px rgba(0, 0, 0, 20%);
|
||||||
|
|
||||||
|
&::after {
|
||||||
|
position: absolute;
|
||||||
|
top: -12px;
|
||||||
|
left: 50%;
|
||||||
|
transform: translateX(-50%);
|
||||||
|
content: '';
|
||||||
|
width: 0;
|
||||||
|
height: 0;
|
||||||
|
border: 6px solid;
|
||||||
|
border-color: transparent transparent #fff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -18,6 +18,7 @@ export interface PopUpProps extends MapboxPopupProps {
|
|||||||
title?: string;
|
title?: string;
|
||||||
url?: string;
|
url?: string;
|
||||||
content?: string;
|
content?: string;
|
||||||
|
contentRender?: (props: PopUpProps) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface PopUpRefProps {
|
export interface PopUpRefProps {
|
||||||
@ -25,13 +26,12 @@ export interface PopUpRefProps {
|
|||||||
|
|
||||||
const PopUp = forwardRef<PopUpRefProps, PopUpProps>((props, ref) => {
|
const PopUp = forwardRef<PopUpRefProps, PopUpProps>((props, ref) => {
|
||||||
const {
|
const {
|
||||||
longitude,
|
|
||||||
latitude,
|
|
||||||
onClose,
|
|
||||||
title,
|
title,
|
||||||
content,
|
content,
|
||||||
url,
|
url,
|
||||||
prefixCls: customizePrefixCls
|
contentRender,
|
||||||
|
prefixCls: customizePrefixCls,
|
||||||
|
...rest
|
||||||
} = props
|
} = props
|
||||||
const { getPrefixCls } = useContext(ConfigContext)
|
const { getPrefixCls } = useContext(ConfigContext)
|
||||||
const componentName = getPrefixCls('map-popup', customizePrefixCls);
|
const componentName = getPrefixCls('map-popup', customizePrefixCls);
|
||||||
@ -42,15 +42,15 @@ const PopUp = forwardRef<PopUpRefProps, PopUpProps>((props, ref) => {
|
|||||||
<MapboxPopUp
|
<MapboxPopUp
|
||||||
anchor="top"
|
anchor="top"
|
||||||
className={componentName}
|
className={componentName}
|
||||||
longitude={Number(longitude)}
|
{...rest}
|
||||||
latitude={Number(latitude)}
|
|
||||||
onClose={onClose}
|
|
||||||
>
|
>
|
||||||
|
{contentRender?.(props) || (
|
||||||
<div className={classNames(`${componentName}-container`)}>
|
<div className={classNames(`${componentName}-container`)}>
|
||||||
{title && <h2>{title}</h2>}
|
{title && <h2>{title}</h2>}
|
||||||
{url && <Image src={url} />}
|
{url && <Image src={url} />}
|
||||||
{content && <p>{content}</p>}
|
{content && <p>{content}</p>}
|
||||||
</div>
|
</div>
|
||||||
|
)}
|
||||||
</MapboxPopUp>
|
</MapboxPopUp>
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
@ -4,7 +4,6 @@
|
|||||||
|
|
||||||
import React, { forwardRef, ReactNode, useContext, useImperativeHandle } from 'react'
|
import React, { forwardRef, ReactNode, useContext, useImperativeHandle } from 'react'
|
||||||
import { Button, ConfigProvider } from '@zhst/meta'
|
import { Button, ConfigProvider } from '@zhst/meta'
|
||||||
import { useToggle } from '@zhst/hooks'
|
|
||||||
import classNames from 'classnames'
|
import classNames from 'classnames'
|
||||||
import { IconFont } from '@zhst/icon'
|
import { IconFont } from '@zhst/icon'
|
||||||
import './index.less'
|
import './index.less'
|
||||||
@ -13,7 +12,8 @@ const { ConfigContext } = ConfigProvider
|
|||||||
|
|
||||||
export interface ToolsProps {
|
export interface ToolsProps {
|
||||||
prefixCls?: string
|
prefixCls?: string
|
||||||
defaultValue?: boolean;
|
open?: boolean;
|
||||||
|
onToolClick?: (e: React.MouseEvent<HTMLElement, MouseEvent>) => void
|
||||||
buttonList?: {
|
buttonList?: {
|
||||||
label: string
|
label: string
|
||||||
key: string
|
key: string
|
||||||
@ -29,11 +29,11 @@ const Tools = forwardRef<ToolsRefProps, ToolsProps>((props, ref) => {
|
|||||||
const {
|
const {
|
||||||
prefixCls: customizePrefixCls,
|
prefixCls: customizePrefixCls,
|
||||||
buttonList = [],
|
buttonList = [],
|
||||||
defaultValue
|
onToolClick,
|
||||||
|
open
|
||||||
} = props
|
} = props
|
||||||
const { getPrefixCls } = useContext(ConfigContext)
|
const { getPrefixCls } = useContext(ConfigContext)
|
||||||
const componentName = getPrefixCls('map-tools', customizePrefixCls)
|
const componentName = getPrefixCls('map-tools', customizePrefixCls)
|
||||||
const [state, { toggle }] = useToggle(defaultValue)
|
|
||||||
|
|
||||||
useImperativeHandle(ref, () => ({
|
useImperativeHandle(ref, () => ({
|
||||||
|
|
||||||
@ -41,7 +41,7 @@ const Tools = forwardRef<ToolsRefProps, ToolsProps>((props, ref) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={componentName}>
|
<div className={componentName}>
|
||||||
<ul className={classNames(`${componentName}-navs`, { [`${componentName}-navs_active`]: state })}>
|
<ul className={classNames(`${componentName}-navs`, { [`${componentName}-navs_active`]: open })}>
|
||||||
{buttonList.map((item) => (
|
{buttonList.map((item) => (
|
||||||
<li onClick={item.onClick} className={classNames(`${componentName}-navs-item`)} key={item.key}>
|
<li onClick={item.onClick} className={classNames(`${componentName}-navs-item`)} key={item.key}>
|
||||||
{typeof item.icon === 'string' ? (
|
{typeof item.icon === 'string' ? (
|
||||||
@ -57,8 +57,8 @@ const Tools = forwardRef<ToolsRefProps, ToolsProps>((props, ref) => {
|
|||||||
size='large'
|
size='large'
|
||||||
shape="circle"
|
shape="circle"
|
||||||
type="primary"
|
type="primary"
|
||||||
onClick={toggle}
|
onClick={onToolClick}
|
||||||
icon={<IconFont icon={state ? 'icon-guanbi' : 'icon-kuangxuangongju'} />}
|
icon={<IconFont icon={open ? 'icon-guanbi' : 'icon-kuangxuangongju'} />}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
240
packages/map/src/demo/.data/mock.ts
Normal file
240
packages/map/src/demo/.data/mock.ts
Normal file
@ -0,0 +1,240 @@
|
|||||||
|
export const sluterData = {
|
||||||
|
"features": [
|
||||||
|
{
|
||||||
|
"geometry": {
|
||||||
|
"type": "Point",
|
||||||
|
"coordinates": [
|
||||||
|
-151.5129,
|
||||||
|
63.1016,
|
||||||
|
0.0
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"geometry": {
|
||||||
|
"type": "Point",
|
||||||
|
"coordinates": [
|
||||||
|
-150.4048,
|
||||||
|
63.1224,
|
||||||
|
105.5
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"geometry": {
|
||||||
|
"type": "Point",
|
||||||
|
"coordinates": [
|
||||||
|
-151.3597,
|
||||||
|
63.0781,
|
||||||
|
0.0
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"geometry": {
|
||||||
|
"type": "Point",
|
||||||
|
"coordinates": [
|
||||||
|
-118.497,
|
||||||
|
34.299667,
|
||||||
|
7.64
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"geometry": {
|
||||||
|
"type": "Point",
|
||||||
|
"coordinates": [
|
||||||
|
-87.6901,
|
||||||
|
12.0623,
|
||||||
|
46.41
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"geometry": {
|
||||||
|
"type": "Point",
|
||||||
|
"coordinates": [
|
||||||
|
-151.5053,
|
||||||
|
63.0719,
|
||||||
|
0.0
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
|
||||||
|
"geometry": {
|
||||||
|
"type": "Point",
|
||||||
|
"coordinates": [
|
||||||
|
-178.4576,
|
||||||
|
-20.2873,
|
||||||
|
614.26
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
|
||||||
|
"geometry": {
|
||||||
|
"type": "Point",
|
||||||
|
"coordinates": [
|
||||||
|
-148.789,
|
||||||
|
63.1725,
|
||||||
|
7.5
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
|
||||||
|
"geometry": {
|
||||||
|
"type": "Point",
|
||||||
|
"coordinates": [
|
||||||
|
-120.993164,
|
||||||
|
36.421833,
|
||||||
|
6.37
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"geometry": {
|
||||||
|
"type": "Point",
|
||||||
|
"coordinates": [
|
||||||
|
-117.0155,
|
||||||
|
33.656333,
|
||||||
|
12.37
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"geometry": {
|
||||||
|
"type": "Point",
|
||||||
|
"coordinates": [
|
||||||
|
-151.512,
|
||||||
|
63.0879,
|
||||||
|
10.8
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"geometry": {
|
||||||
|
"type": "Point",
|
||||||
|
"coordinates": [
|
||||||
|
-151.4378,
|
||||||
|
63.0933,
|
||||||
|
0.0
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"geometry": {
|
||||||
|
"type": "Point",
|
||||||
|
"coordinates": [
|
||||||
|
-149.6538,
|
||||||
|
63.2272,
|
||||||
|
96.8
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"geometry": {
|
||||||
|
"type": "Point",
|
||||||
|
"coordinates": [
|
||||||
|
-151.5325,
|
||||||
|
63.0844,
|
||||||
|
0.0
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"geometry": {
|
||||||
|
"type": "Point",
|
||||||
|
"coordinates": [
|
||||||
|
-149.4752,
|
||||||
|
61.8518,
|
||||||
|
54.3
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"geometry": {
|
||||||
|
"type": "Point",
|
||||||
|
"coordinates": [
|
||||||
|
-150.8597,
|
||||||
|
61.6214,
|
||||||
|
50.0
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"geometry": {
|
||||||
|
"type": "Point",
|
||||||
|
"coordinates": [
|
||||||
|
-149.7142,
|
||||||
|
62.9656,
|
||||||
|
93.6
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"geometry": {
|
||||||
|
"type": "Point",
|
||||||
|
"coordinates": [
|
||||||
|
-151.2484,
|
||||||
|
61.2705,
|
||||||
|
69.1
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"geometry": {
|
||||||
|
"type": "Point",
|
||||||
|
"coordinates": [
|
||||||
|
-152.0732,
|
||||||
|
65.5942,
|
||||||
|
14.8
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"geometry": {
|
||||||
|
"type": "Point",
|
||||||
|
"coordinates": [
|
||||||
|
-90.5445,
|
||||||
|
13.5146,
|
||||||
|
54.36
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
|
||||||
|
"geometry": {
|
||||||
|
"type": "Point",
|
||||||
|
"coordinates": [
|
||||||
|
-118.819504,
|
||||||
|
37.605499,
|
||||||
|
4.14
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
|
||||||
|
"geometry": {
|
||||||
|
"type": "Point",
|
||||||
|
"coordinates": [
|
||||||
|
-118.930168,
|
||||||
|
37.636833,
|
||||||
|
-0.71
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
|
||||||
|
"geometry": {
|
||||||
|
"type": "Point",
|
||||||
|
"coordinates": [
|
||||||
|
-117.509167,
|
||||||
|
34.1555,
|
||||||
|
16.34
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
]
|
||||||
|
}
|
@ -1,12 +1,22 @@
|
|||||||
import React, { useRef, useEffect, useState } from 'react';
|
import React, { useRef, useEffect, useState } from 'react';
|
||||||
import { MapBox } from '@zhst/map';
|
import { MapBox, Marker } from '@zhst/map';
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import { FloatButton, Switch } from '@zhst/meta';
|
import { FloatButton, Switch } from '@zhst/meta';
|
||||||
|
import { MarkerProps } from '../components/marker';
|
||||||
|
import { getDistancesByStringLine, lineToPoly } from '../utils';
|
||||||
|
// import { sluterData } from './.data/mock.ts'
|
||||||
|
|
||||||
const demo = () => {
|
const demo = () => {
|
||||||
const [markerData, setMarkerData] = useState([])
|
const [markerData, setMarkerData] = useState<MarkerProps[]>([])
|
||||||
const [showMarker, setShowMarker] = useState(true)
|
const [showMarker, setShowMarker] = useState(true)
|
||||||
|
const [showCluster, setShowCluster] = useState(true)
|
||||||
|
const [canDraw, setCanDraw] = useState(false)
|
||||||
|
const [toolsBarOpen, setToolsBarOpen] = useState(false)
|
||||||
const [popupInfo, setPopupInfo] = useState()
|
const [popupInfo, setPopupInfo] = useState()
|
||||||
|
const [sluterData, setSluterData] = useState({})
|
||||||
|
const [showMouseTag, setShowMouseTag] = useState(false)
|
||||||
|
const [mousePosition, setMousePosition] = useState({ x: 0, y: 0 })
|
||||||
|
const [rangingList, setRangingList] = useState([])
|
||||||
const mapRef = useRef(null);
|
const mapRef = useRef(null);
|
||||||
|
|
||||||
// 初始化
|
// 初始化
|
||||||
@ -26,19 +36,41 @@ const demo = () => {
|
|||||||
method: 'post',
|
method: 'post',
|
||||||
url: 'http://10.0.0.120:30003/singer.DeviceService/ListCamera',
|
url: 'http://10.0.0.120:30003/singer.DeviceService/ListCamera',
|
||||||
headers: {
|
headers: {
|
||||||
Authorization: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3MTY3MTI5MTAsImp0aSI6IjEwOTYiLCJpYXQiOjE3MTY0NTM3MTAsInVzZXJJZCI6MSwidXNlcm5hbWUiOiJhZG1pbiIsImRhdGFSaWdodCI6MiwiY2FtZXJhUmlnaHQiOjEsImdwdVJpZ2h0IjoxLCJ1c2VybGVhZGVySWQiOjAsIm9yZ2FuaXphdGlvbklkIjoxLCJyb2xlSWQiOjF9.6s73alRI0iB-5oT-GcQH8lZSiScPTULk14xxz2Aak6k'
|
Authorization: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3MTcwNDAzNzEsImp0aSI6IjExMjgiLCJpYXQiOjE3MTY3ODExNzEsInVzZXJJZCI6MSwidXNlcm5hbWUiOiJhZG1pbiIsImRhdGFSaWdodCI6MiwiY2FtZXJhUmlnaHQiOjEsImdwdVJpZ2h0IjoxLCJ1c2VybGVhZGVySWQiOjAsIm9yZ2FuaXphdGlvbklkIjoxLCJyb2xlSWQiOjF9.XHbXIkXkfUuvqV6_qSV4d20xj-s7I0qOQZgL-zspMDc'
|
||||||
},
|
},
|
||||||
data: {"labelData":[],"filter":{"realtimeProcessingFilter":0,"cameraFilter":[{"opt":"ORNOT","cameraOpt":"CAMERAOPT_TYPE","value":"100"}]},"maxResults":50}
|
data: {"labelData":[],"filter":{"realtimeProcessingFilter":0,"cameraFilter":[{"opt":"ORNOT","cameraOpt":"CAMERAOPT_TYPE","value":"100"}]},"maxResults":50}
|
||||||
});
|
});
|
||||||
if (res.status === 200) {
|
if (res.status === 200) {
|
||||||
setMarkerData(res.data.cameras.map(item => ({
|
let markers = []
|
||||||
key: item.id,
|
let sluters = {
|
||||||
title: item.name,
|
features: []
|
||||||
population: item.id,
|
}
|
||||||
status: item.status,
|
res.data.cameras?.forEach(camera => {
|
||||||
latitude: item.latitude,
|
markers.push({
|
||||||
longitude: item.longitude
|
key: camera.id,
|
||||||
})))
|
id: camera.id,
|
||||||
|
title: camera.name,
|
||||||
|
population: camera.id,
|
||||||
|
checked: false,
|
||||||
|
disabled: false,
|
||||||
|
showCheckBox: true,
|
||||||
|
status: ['blue', 'yellow', 'red'][Math.floor(Math.random() * 3)],
|
||||||
|
latitude: camera.latitude,
|
||||||
|
longitude: camera.longitude
|
||||||
|
})
|
||||||
|
sluters.features.push({
|
||||||
|
"geometry": {
|
||||||
|
"type": "Point",
|
||||||
|
"coordinates": [
|
||||||
|
camera.longitude,
|
||||||
|
camera.latitude,
|
||||||
|
50
|
||||||
|
]
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
setMarkerData(markers)
|
||||||
|
setSluterData(sluters)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -54,32 +86,105 @@ const demo = () => {
|
|||||||
<MapBox
|
<MapBox
|
||||||
onLoad={handleMapLoad}
|
onLoad={handleMapLoad}
|
||||||
ref={mapRef}
|
ref={mapRef}
|
||||||
// draw
|
draw={canDraw}
|
||||||
onDrawCreate={e => console.log('Create', e)}
|
toolsBarOpen={toolsBarOpen}
|
||||||
|
onToolClick={e => {
|
||||||
|
setCanDraw(pre => !pre)
|
||||||
|
setToolsBarOpen(pre => !pre)
|
||||||
|
}}
|
||||||
|
onDrawCreate={e => {
|
||||||
|
const geojson = e.features[0]
|
||||||
|
const polygonJson = getDistancesByStringLine(geojson) || []
|
||||||
|
setRangingList(polygonJson.distanceArr)
|
||||||
|
}}
|
||||||
onDrawDelete={e => console.log('Delete', e)}
|
onDrawDelete={e => console.log('Delete', e)}
|
||||||
onDrawUpdate={e => console.log('Update', e)}
|
onDrawUpdate={e => {
|
||||||
|
const geojson = e.features[0]
|
||||||
|
const polygonJson = getDistancesByStringLine(geojson) || []
|
||||||
|
setRangingList(polygonJson.distanceArr)
|
||||||
|
}}
|
||||||
width='100%'
|
width='100%'
|
||||||
height='100vh'
|
height='100vh'
|
||||||
markerData={markerData}
|
mapStyle={{
|
||||||
|
sources: {
|
||||||
|
'osm-tiles': {
|
||||||
|
'type': 'raster',
|
||||||
|
tiles: [`http://10.0.0.120:30003/map/api/tilesets/mapfile/{z}/{x}/{y}.png`], //在线地址,先写死120
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
markerData={markerData || []}
|
||||||
showMarker={showMarker}
|
showMarker={showMarker}
|
||||||
showPopUp
|
showPopUp
|
||||||
popUpInfo={popupInfo}
|
sluterData={sluterData}
|
||||||
|
showCluster={showCluster}
|
||||||
|
// popUpInfo={popupInfo}
|
||||||
onPopUpClose={e => setPopupInfo(null)}
|
onPopUpClose={e => setPopupInfo(null)}
|
||||||
onMarkerClick={(e, status, data) => {
|
onMarkerClick={(e, status, data) => {
|
||||||
setPopupInfo({
|
setMarkerData(pre => pre.map(item => {
|
||||||
longitude: data?.longitude,
|
if (item.id === data.id) {
|
||||||
latitude: data?.latitude,
|
item.checked = !data?.checked
|
||||||
content: '测试'
|
}
|
||||||
})
|
return item
|
||||||
|
}))
|
||||||
|
// setPopupInfo({
|
||||||
|
// longitude: data?.longitude,
|
||||||
|
// latitude: data?.latitude,
|
||||||
|
// content: '测试'
|
||||||
|
// })
|
||||||
}}
|
}}
|
||||||
onZoomEnd={map => {
|
onZoomEnd={map => {
|
||||||
let zoom = map.target.getZoom() // 画面层级,用来判断标签是否显示隐藏
|
let zoom = map.target.getZoom() // 画面层级,用来判断标签是否显示隐藏
|
||||||
|
// 摄像头显示/隐藏
|
||||||
console.log('zoom', zoom)
|
setShowMarker(zoom > 5)
|
||||||
// setShowMarker(pre => !pre)
|
// 范围统计显示/隐藏
|
||||||
|
setShowCluster(zoom < 5)
|
||||||
|
}}
|
||||||
|
onClick={e => setShowMouseTag(true)}
|
||||||
|
onDblClick={e => {
|
||||||
|
setShowMouseTag(false)
|
||||||
|
// setCanDraw(false)
|
||||||
|
}}
|
||||||
|
onMouseMove={e => {
|
||||||
|
setMousePosition({ x: e.point.x, y: e.point.y })
|
||||||
}}
|
}}
|
||||||
// customMarkerRender={(_data) => <div>自定义标记</div>}
|
// customMarkerRender={(_data) => <div>自定义标记</div>}
|
||||||
/>
|
>
|
||||||
|
{canDraw && (
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
position: 'absolute',
|
||||||
|
fontSize: '16px',
|
||||||
|
top: mousePosition.y,
|
||||||
|
left: mousePosition.x,
|
||||||
|
pointerEvents: 'none'
|
||||||
|
}}
|
||||||
|
>{showMouseTag ? '双击完成绘制' : '单击以确定起点'}</div>
|
||||||
|
)}
|
||||||
|
{rangingList?.map((item, index) => {
|
||||||
|
return (
|
||||||
|
<Marker
|
||||||
|
key={index}
|
||||||
|
anchor="bottom"
|
||||||
|
longitude={item.to[0]}
|
||||||
|
latitude={item.to[1]}
|
||||||
|
onClick={e => e.originalEvent.stopPropagation()}
|
||||||
|
>
|
||||||
|
<div style={{ padding: '3px 6px', background: '#fff', border: '1px solid #000' }} >{(item.totalLength)}km</div>
|
||||||
|
</Marker>
|
||||||
|
)
|
||||||
|
})}
|
||||||
|
<Marker
|
||||||
|
anchor="bottom"
|
||||||
|
longitude={120}
|
||||||
|
latitude={31}
|
||||||
|
onClick={e => {
|
||||||
|
e.originalEvent.stopPropagation();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div style={{ padding: '12px', background: 'red', color: '#fff', border: '1px solid #000' }} >我是自定义的DOM!</div>
|
||||||
|
</Marker>
|
||||||
|
</MapBox>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -27,3 +27,5 @@ title: 快速上手
|
|||||||
[mapbox-gl-draw](https://github.com/mapbox/mapbox-gl-draw)
|
[mapbox-gl-draw](https://github.com/mapbox/mapbox-gl-draw)
|
||||||
[draw 绘制模式插件](https://github.com/mapbox/mapbox-gl-draw/blob/main/docs/MODES.md#available-custom-modes)
|
[draw 绘制模式插件](https://github.com/mapbox/mapbox-gl-draw/blob/main/docs/MODES.md#available-custom-modes)
|
||||||
[mapboxJS](https://www.naivemap.com/mapbox-gl-js-cookbook/starter/handlers/control.html)
|
[mapboxJS](https://www.naivemap.com/mapbox-gl-js-cookbook/starter/handlers/control.html)
|
||||||
|
[mapboxAPI详解](https://juejin.cn/post/6907068992607928328)
|
||||||
|
[mapbox Expressions语法学习](https://docs.mapbox.com/help/tutorials/mapbox-gl-js-expressions/)
|
||||||
|
@ -1 +1,2 @@
|
|||||||
export { default as MapBox } from './MapBox';
|
export { default as MapBox } from './MapBox';
|
||||||
|
export * from 'react-map-gl'
|
||||||
|
@ -1,20 +1,22 @@
|
|||||||
|
import { MapProps } from 'react-map-gl'
|
||||||
|
|
||||||
export const mapboxAccessToken =
|
export const mapboxAccessToken =
|
||||||
'pk.eyJ1IjoiZGluZ2xpMTIzIiwiYSI6ImNra204ODhjczBobTgyeHJ6MmJpZHMxNWgifQ.NbKrXh_hb2gvjr5CEMDnyQ';
|
'pk.eyJ1IjoiZGluZ2xpMTIzIiwiYSI6ImNra204ODhjczBobTgyeHJ6MmJpZHMxNWgifQ.NbKrXh_hb2gvjr5CEMDnyQ';
|
||||||
|
|
||||||
export const MAP_CENTER = {
|
const mapSourceUrl = 'http://10.0.0.120:30003/map';
|
||||||
longitude: 120.2667694313269,
|
|
||||||
latitude: 30.180942826533766,
|
|
||||||
}; //地图中心
|
|
||||||
|
|
||||||
const MapUrl = 'http://10.0.0.120:30003/map';
|
export const defaultMapConfig: MapProps = {
|
||||||
export const defaultMapConfig = {
|
|
||||||
mapboxAccessToken,
|
mapboxAccessToken,
|
||||||
maxZoom: 18,
|
maxZoom: 18,
|
||||||
minZoom: 4,
|
minZoom: 4,
|
||||||
|
initialViewState: {
|
||||||
|
longitude: 120.2667694313269,
|
||||||
|
latitude: 30.180942826533766,
|
||||||
|
},
|
||||||
dragRotate: false,
|
dragRotate: false,
|
||||||
mapStyle: {
|
mapStyle: {
|
||||||
version: 8,
|
version: 8,
|
||||||
name: 'Mapbox Streets',
|
name: 'zhst mapbox',
|
||||||
// sprite: `${location.origin}/mapbox/sprite`, // 地图图标
|
// sprite: `${location.origin}/mapbox/sprite`, // 地图图标
|
||||||
glyphs: 'mapbox://fonts/mapbox/{fontstack}/{range}.pbf', // 字体
|
glyphs: 'mapbox://fonts/mapbox/{fontstack}/{range}.pbf', // 字体
|
||||||
sources: {
|
sources: {
|
||||||
@ -24,7 +26,7 @@ export const defaultMapConfig = {
|
|||||||
// Z-瓦片层级,一般支持0-18级,越大代表越清晰;
|
// Z-瓦片层级,一般支持0-18级,越大代表越清晰;
|
||||||
// X-瓦片列号,从西向东(0->360),依次0,1,2,……;
|
// X-瓦片列号,从西向东(0->360),依次0,1,2,……;
|
||||||
// Y-瓦片行号,从北向南(有些也可能是从南向北),依次0,1,2,……;
|
// Y-瓦片行号,从北向南(有些也可能是从南向北),依次0,1,2,……;
|
||||||
tiles: [`${MapUrl}/api/tilesets/mapfile/{z}/{x}/{y}.png`], //在线地址,先写死120
|
tiles: [`${mapSourceUrl}/api/tilesets/mapfile/{z}/{x}/{y}.png`], //在线地址,先写死120
|
||||||
tileSize: 256, //切片的最小展示尺寸(可选,单位:像素,默认值为 512,即 1024/2
|
tileSize: 256, //切片的最小展示尺寸(可选,单位:像素,默认值为 512,即 1024/2
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -35,8 +37,9 @@ export const defaultMapConfig = {
|
|||||||
type: 'raster', //类型 栅格。circle,symbol,line...
|
type: 'raster', //类型 栅格。circle,symbol,line...
|
||||||
source: 'osm-tiles',
|
source: 'osm-tiles',
|
||||||
// 'source-layer': 'osmtiles',//数据源必须是type:vector
|
// 'source-layer': 'osmtiles',//数据源必须是type:vector
|
||||||
minZoom: 4, //最小层级
|
minzoom: 4, //最小层级
|
||||||
maxZoom: 17, //最大层级
|
maxzoom: 17, //最大层级
|
||||||
|
// @ts-ignore
|
||||||
renderingMode: '2d',
|
renderingMode: '2d',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
0
packages/map/src/utils/formater.ts
Normal file
0
packages/map/src/utils/formater.ts
Normal file
@ -1,5 +1,5 @@
|
|||||||
|
// @ts-ignore
|
||||||
import * as turf from '@turf/turf';
|
import * as turf from '@turf/turf';
|
||||||
import union from '@turf/union';
|
|
||||||
|
|
||||||
// 判断参数类型
|
// 判断参数类型
|
||||||
const getRawType = (val: any) => {
|
const getRawType = (val: any) => {
|
||||||
@ -196,14 +196,63 @@ export const lineToPoly = (geojson: { geometry: { coordinates: string | any[] }
|
|||||||
let _union;
|
let _union;
|
||||||
try {
|
try {
|
||||||
//todo: 新版本union和老版本行为不一致 先用老版本 后续观察原因
|
//todo: 新版本union和老版本行为不一致 先用老版本 后续观察原因
|
||||||
// _union = turf.union(...circlePolygon, ...linesPolygon);
|
_union = turf.union(...circlePolygon, ...linesPolygon);
|
||||||
_union = union(...circlePolygon, ...linesPolygon);
|
// _union = union(...circlePolygon, ...linesPolygon);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(e);
|
console.error(e);
|
||||||
}
|
}
|
||||||
return _union;
|
return _union;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取在图形中的点
|
||||||
|
* @param _points 点坐标集
|
||||||
|
* @param polygon 图形
|
||||||
|
* @returns 在图形中的坐标集
|
||||||
|
*/
|
||||||
|
export const getPointByShape = (_points: [number, number][], polygon: [number, number][]) => {
|
||||||
|
let points = turf.points(_points);
|
||||||
|
// TODO:首未坐标要一致
|
||||||
|
let searchWithin = turf.polygon([polygon]);
|
||||||
|
|
||||||
|
return turf.pointsWithinPolygon(points, searchWithin);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通过绘制的线段获取距离
|
||||||
|
* @param geojson 点坐标集
|
||||||
|
* @param config 额外的 turf.distance 配置(可选)
|
||||||
|
* @returns distanceArr,totalLength
|
||||||
|
*/
|
||||||
|
export const getDistancesByStringLine = (
|
||||||
|
geojson: { geometry: { coordinates: [number, number][], [key: string]: any }, type: 'line' },
|
||||||
|
config?: any
|
||||||
|
) => {
|
||||||
|
let distanceArr: {
|
||||||
|
distance: number,
|
||||||
|
from: [number, number],
|
||||||
|
to: [number, number],
|
||||||
|
totalLength: number | string
|
||||||
|
}[] = []
|
||||||
|
let totalLength = 0
|
||||||
|
for (let i = 0; i < geojson.geometry.coordinates.length - 1; i++) {
|
||||||
|
const [pointA, pointB] = [geojson.geometry.coordinates[i], geojson.geometry.coordinates[i + 1]];
|
||||||
|
|
||||||
|
const tempDistance = turf.distance(pointA, pointB, config);
|
||||||
|
totalLength += tempDistance
|
||||||
|
distanceArr.push({
|
||||||
|
distance: tempDistance.toFixed(2),
|
||||||
|
totalLength: totalLength.toFixed(2),
|
||||||
|
from: pointA,
|
||||||
|
to: pointB
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
distanceArr,
|
||||||
|
totalLength: totalLength.toFixed(2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description 创建 node,绑定 node 到对应父级,
|
* @description 创建 node,绑定 node 到对应父级,
|
||||||
* @param {string} className 类名
|
* @param {string} className 类名
|
||||||
|
@ -1,5 +1,13 @@
|
|||||||
# @zhst/material
|
# @zhst/material
|
||||||
|
|
||||||
|
## 0.18.3
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies
|
||||||
|
- @zhst/meta@0.22.0
|
||||||
|
- @zhst/biz@0.22.3
|
||||||
|
|
||||||
## 0.18.2
|
## 0.18.2
|
||||||
|
|
||||||
### Patch Changes
|
### Patch Changes
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@zhst/material",
|
"name": "@zhst/material",
|
||||||
"version": "0.18.2",
|
"version": "0.18.3",
|
||||||
"description": "物料库",
|
"description": "物料库",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"business",
|
"business",
|
||||||
|
@ -1,5 +1,16 @@
|
|||||||
# @zhst/utils
|
# @zhst/utils
|
||||||
|
|
||||||
|
## 0.22.0
|
||||||
|
|
||||||
|
### Minor Changes
|
||||||
|
|
||||||
|
- zhst/map:拓展地图 api,加入 tools 组件、cluster 组价、marker 组件、draw 组件、popup 组件;zhst/mata:添加 floatButton 组件
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies
|
||||||
|
- @zhst/meta@0.22.0
|
||||||
|
|
||||||
## 0.21.2
|
## 0.21.2
|
||||||
|
|
||||||
### Patch Changes
|
### Patch Changes
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@zhst/meta",
|
"name": "@zhst/meta",
|
||||||
"version": "0.21.2",
|
"version": "0.22.0",
|
||||||
"description": "原子组件",
|
"description": "原子组件",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"meta",
|
"meta",
|
||||||
|
Loading…
Reference in New Issue
Block a user