feat: 完善地图组件

This commit is contained in:
lifan 2024-03-25 17:13:42 +08:00
parent b2df3e3a7c
commit 6f65746373
8 changed files with 542 additions and 212 deletions

4
.gitignore vendored
View File

@ -9,6 +9,6 @@ vueuse
/temp
# packages/**/es
# packages/**/lib
/es
/lib
# /es
# /lib
pnpm-lock.yaml

View File

@ -1,60 +1,9 @@
import 'mapbox-gl/dist/mapbox-gl.css';
import type { CSSProperties } from 'react';
import Map, { MapRef } from 'react-map-gl';
import './index.less';
export const mapboxAccessToken =
'pk.eyJ1IjoiZGluZ2xpMTIzIiwiYSI6ImNra204ODhjczBobTgyeHJ6MmJpZHMxNWgifQ.NbKrXh_hb2gvjr5CEMDnyQ';
export const MAP_CENTER = {
longitude: 120.2667694313269,
latitude: 30.180942826533766,
}; //地图中心
const MapUrl = 'http://10.0.0.120:30003/map';
export const MapConfig = {
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依次012……
// Y-瓦片行号从北向南有些也可能是从南向北依次012……
tiles: [`${MapUrl}/api/tilesets/mapfile/{z}/{x}/{y}.png`], //在线地址先写死120
tileSize: 256, //切片的最小展示尺寸(可选,单位:像素,默认值为 512即 1024/2
},
},
layers: [
// 图层。图层指定了如何渲染数据源提供的数据
{
id: 'zhstLayer', //唯一id
type: 'raster', //类型 栅格。circlesymbolline...
source: 'osm-tiles',
// 'source-layer': 'osmtiles',//数据源必须是type:vector
minZoom: 4, //最小层级
maxZoom: 17, //最大层级
renderingMode: '2d',
},
],
},
};
interface MapProps {
onLoad?: (e: mapboxgl.MapboxEvent<undefined>) => void;
onDrawCreate?: () => void;
mapRef?: React.MutableRefObject<MapRef | undefined>;
style?: CSSProperties;
children?: JSX.Element | JSX.Element[] | Array<JSX.Element | undefined>;
defaultMode?: string;
setIsReady?: (ready: boolean) => void;
}
import { MapProps } from './interface';
import { merge } from './utils';
import { MAP_CENTER, defaultMapConfig } from './constants';
const MapBox: React.FC<MapProps> = (props) => {
const {
@ -62,13 +11,10 @@ const MapBox: React.FC<MapProps> = (props) => {
children,
mapRef,
onLoad,
defaultMode,
onDrawCreate,
setIsReady,
mapCenter = MAP_CENTER,
mapConfig = {},
...others
} = props || {};
let mapCneter = MAP_CENTER;
return (
//@ts-ignore
<Map
@ -78,12 +24,11 @@ const MapBox: React.FC<MapProps> = (props) => {
}
}}
onLoad={(e) => {
setIsReady && setIsReady(true);
onLoad && onLoad(e);
}}
style={{ width: '100%', height: 600, ...style }}
{...MapConfig}
initialViewState={{ ...mapCneter, zoom: 10 }}
{...merge(defaultMapConfig, mapConfig)}
initialViewState={{ ...mapCenter, zoom: 10 }}
{...others}
>
{children}

View File

@ -0,0 +1,42 @@
export const mapboxAccessToken =
'pk.eyJ1IjoiZGluZ2xpMTIzIiwiYSI6ImNra204ODhjczBobTgyeHJ6MmJpZHMxNWgifQ.NbKrXh_hb2gvjr5CEMDnyQ';
export const MAP_CENTER = {
longitude: 120.2667694313269,
latitude: 30.180942826533766,
}; //地图中心
const MapUrl = 'http://10.0.0.120:30003/map';
export const defaultMapConfig = {
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依次012……
// Y-瓦片行号从北向南有些也可能是从南向北依次012……
tiles: [`${MapUrl}/api/tilesets/mapfile/{z}/{x}/{y}.png`], //在线地址先写死120
tileSize: 256, //切片的最小展示尺寸(可选,单位:像素,默认值为 512即 1024/2
},
},
layers: [
// 图层。图层指定了如何渲染数据源提供的数据
{
id: 'zhstLayer', //唯一id
type: 'raster', //类型 栅格。circlesymbolline...
source: 'osm-tiles',
// 'source-layer': 'osmtiles',//数据源必须是type:vector
minZoom: 4, //最小层级
maxZoom: 17, //最大层级
renderingMode: '2d',
},
],
},
};

View File

@ -1,11 +1,23 @@
import React from 'react';
import React, { useRef } from 'react';
import { MapBox } from '@zhst/map';
const demo = () => {
const mapRef = useRef(null);
const handleMapLoad = (e: mapboxgl.MapboxEvent<undefined>) => {
const map = e.target;
if (!map) {
return;
}
map.flyTo({
center: [120,30],
zoom: map?.getMaxZoom(),
});
};
return (
<div>
<MapBox/>
<MapBox onLoad={handleMapLoad}
mapRef={mapRef}
style={{ width: '100%', height: 300 }}/>
</div>
);
};

View File

@ -8,4 +8,13 @@ title: 快速上手
<embed src="../README.md" ></embed>
<code src="./demo/basic.tsx">基本用法</code>
## API
| 参数 | 说明 | 类型 | 默认值 | 版本 |
| --- | --- | --- | --- | --- |
| mapRef | 标题 | React.MutableRefObject<MapRef或undefined> | '' | - |
| style | 地图样式 | cssProperties | {} | - |
| children | 内部元素 | JSX.Element或JSX.Element[]或Array<JSX.Element或undefined> | {} | - |
| mapConfig | 地图配置 | MapConfigProps | defaultMapConfig | - |
| onLoad | 地图加载事件 | function | ()=>{} | - |
| onDrawCreate | 地图绘制事件 | string | '' | - |

View File

@ -0,0 +1,18 @@
import { CSSProperties } from "react";
import { MapRef, MapStyle } from "react-map-gl";
export interface MapProps {
onLoad?: (e: mapboxgl.MapboxEvent<undefined>) => void;
mapRef?: React.MutableRefObject<MapRef | undefined>;
style?: CSSProperties;
children?: JSX.Element | JSX.Element[] | Array<JSX.Element | undefined>;
mapConfig?: MapConfigProps
}
export interface MapConfigProps {
mapboxAccessToken?: string; //token
minZoom?: number; //最小层级
maxZoom?: number; //最大层级
dragRotate?: boolean; //是否支持拖拽旋转
mapStyle?: MapStyle; //地图样式
}

35
packages/map/src/utils.ts Normal file
View File

@ -0,0 +1,35 @@
const getRawType = (val) => {
return Object.prototype.toString.call(val).slice(8, -1)
}
const isPlainObjectOrArray = (val) => {
return isPlainObject(val) || Array.isArray(val)
}
const isPlainObject = (val) => {
return getRawType(val) === 'Object'
}
export const merge = (object, ...sources) => {
for(const source of sources) {
for(const 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;
}

File diff suppressed because it is too large Load Diff