-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
ad34396
commit 43bb1d6
Showing
4 changed files
with
46 additions
and
72 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
import { createContext } from 'react'; | ||
|
||
import type { Map } from 'mapbox-gl'; | ||
|
||
export interface MapContextValue { | ||
map: Map; | ||
} | ||
|
||
export const MapContext = createContext<MapContextValue>({} as MapContextValue); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
a.mapboxgl-ctrl-logo, | ||
.mapboxgl-ctrl-attrib.mapboxgl-compact { | ||
display: none; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,88 +1,49 @@ | ||
import * as Mapbox from 'mapbox-gl'; | ||
import { forwardRef, useEffect, useRef, useState, useImperativeHandle } from 'react'; | ||
import { useBoolean } from '@pansy/react-hooks'; | ||
import { getTargetElement } from '@pansy/shared/react'; | ||
import MapboxWorker from 'mapbox-gl/dist/mapbox-gl-csp-worker'; | ||
|
||
import { MapContext } from '@/context'; | ||
import { useReact } from '@/hooks/useReact'; | ||
|
||
import { allProps, mapEventMap, setterMap, converterMap } from './config'; | ||
import mapbox from 'mapbox-gl'; | ||
import React, { useRef, useState, useEffect, forwardRef, useImperativeHandle } from 'react'; | ||
import { MapContext } from './context'; | ||
|
||
import 'mapbox-gl/dist/mapbox-gl.css'; | ||
import './map.css'; | ||
|
||
import type { MapboxOptions } from 'mapbox-gl'; | ||
import type { MapProps, EventMapping } from './types'; | ||
import type { MapContextValue } from './context'; | ||
|
||
// @ts-ignore | ||
Mapbox['workerClass'] = MapboxWorker; | ||
export interface MapProps { | ||
/** 地图加载前的加载效果 */ | ||
loading?: React.ReactNode; | ||
children?: React.ReactNode; | ||
} | ||
|
||
export const Map = forwardRef<Mapbox.Map, MapProps>((props, ref) => { | ||
export const Map: React.FC<MapProps> = (props) => { | ||
const { loading, children } = props; | ||
const containerRef = useRef<HTMLDivElement>(null); | ||
const [ready, readyAction] = useBoolean(); | ||
const [map, setMap] = useState<Mapbox.Map>(); | ||
|
||
const { onInstanceCreated } = useReact<MapProps, Mapbox.Map, EventMapping>(props, { | ||
ins: map, | ||
events: mapEventMap, | ||
setterMap, | ||
converterMap, | ||
}); | ||
const [mapInstance, setMapInstance] = useState<mapbox.Map>(); | ||
|
||
useImperativeHandle(ref, () => map as Mapbox.Map, [map]); | ||
const { current: contextValue } = useRef<MapContextValue>({} as MapContextValue); | ||
|
||
useEffect(() => { | ||
const container = getTargetElement(containerRef); | ||
|
||
if (!container) return; | ||
|
||
createInstance().then((map) => { | ||
onInstanceCreated(); | ||
|
||
map.once('load', () => { | ||
readyAction.setTrue(); | ||
}); | ||
|
||
setMap(map); | ||
if (!containerRef.current) return; | ||
let instance: mapbox.Map; | ||
|
||
mapbox.accessToken = | ||
'pk.eyJ1IjoienQyMDIzMTEwOSIsImEiOiJjbG9xdGgxcDMwbDAyMmpwODVrNG5seXphIn0.1xKSk8Ll-80kkEwtzfLWhw'; | ||
instance = new mapbox.Map({ | ||
container: containerRef.current, | ||
style: 'mapbox://styles/mapbox/streets-v12', | ||
center: [-74.5, 40], | ||
zoom: 0, | ||
}); | ||
}, []); | ||
|
||
/** 创建地图实例 */ | ||
const createInstance = () => { | ||
const options = getCreateOptions(); | ||
return Promise.resolve(new Mapbox.Map(options)); | ||
}; | ||
|
||
/** 获取创建地图的参数 */ | ||
const getCreateOptions = () => { | ||
const container = getTargetElement(containerRef) as HTMLDivElement; | ||
|
||
const options: MapboxOptions = { | ||
container, | ||
}; | ||
contextValue.map = instance; | ||
|
||
allProps.forEach((key) => { | ||
if (key in props) { | ||
// @ts-ignore | ||
options[key] = props[key]; | ||
} | ||
instance.once('load', () => { | ||
setMapInstance(instance); | ||
}); | ||
|
||
return options; | ||
}; | ||
}, [containerRef]); | ||
|
||
return ( | ||
<MapContext.Provider value={map}> | ||
<div ref={containerRef} style={{ height: '100%', width: '100%' }}> | ||
{ready && props.children} | ||
</div> | ||
</MapContext.Provider> | ||
<div ref={containerRef} style={{ width: 500, height: 500 }}> | ||
{!mapInstance && loading} | ||
{mapInstance && <MapContext.Provider value={contextValue}>{children}</MapContext.Provider>} | ||
</div> | ||
); | ||
}); | ||
|
||
Map.defaultProps = { | ||
attributionControl: false, | ||
style: 'mapbox://styles/mapbox/navigation-preview-night-v2', | ||
accessToken: | ||
'pk.eyJ1IjoiYmVpamluZ3NlbnNvcm8iLCJhIjoiY2wzNDhwMGU2MDAxdzNkbXB2eG5qcGJ4bSJ9.9YrZb00BwBNTsfMTdgj-oA', | ||
}; |