1.0.6 • Published 5 years ago
ol5-react v1.0.6
Openlayers With React Hooks
文件介绍
map.jscontextlayersContext.jsopenlayersContext.js提供OpenlayersContext、MapContext
hooksuseFeatchWindData.js获取风场数据useLayer.jsuseMap.js提供mapuseMapEvent.jsuseMapTarget.jsuseObservable.js地图点击事件使用useStopEvent.jsuseView.js
layersimageLayer.js加载png类型的图片时使用layers.js包裹各类型图层 提供addLayer,removeLayer方法titleLayer.js加载底图,服务器图层时使用vectorLayer.js调用接口,前端绘制时使用windLayer.js风场图
popup弹窗utils工具类
用法参考
## index.js
import React, { useState, useRef, useEffect } from 'react'
import ReactDOM from 'react-dom';
import OlMap from 'ol/Map';
import View from 'ol/View';
import XYZ from 'ol/source/XYZ';
import VectorSource from 'ol/source/Vector';
import TileWMS from 'ol/source/TileWMS';
import Static from 'ol/source/ImageStatic';
import Point from 'ol/geom/Point';
import Projection from 'ol/proj/Projection';
import { Style, Icon } from 'ol/style';
import { transform, transformExtent } from 'ol/proj';
import { defaults as defaultControls } from 'ol/control';
import Map from './map';
import Layer from './layers';
import Popup from './popup';
import { OpenlayersContext } from './context';
import { useObservable, useFetchWindData } from './hooks';
import sensor from './sensor.json';
import './map.css';
import { Feature } from 'ol';
const initView = new View({
projection: 'EPSG:3857',
center: transform([116, 40], 'EPSG:4326', 'EPSG:3857'),
zoom: 7
});
// 初始化地图实例
const map = new OlMap({
loadTilesWhileAnimating: true,
pixelRatio: 1,
controls: defaultControls({ attribution: false, zoom: false, rotate: false }),
});
// 风场空数据
const initData = [
{
data: [],
header: {
parameterCategory: 2,
parameterNumber: 2
}
},
{
data: [],
header: {
parameterCategory: 2,
parameterNumber: 3
}
}
];
const App = () => {
const refMap = useRef();
const [view, setView] = useState(initView);
const [visible, setVisible] = useState(true);
const url = 'http://101.201.70.8:9087/pic_server/windy_json/gfs.2020061900/2020061913.json';
const [layerUrl, setLayerUrl] = useState('http://www.google.cn/maps/vt/pb=!1m4!1m3!1i{z}!2i{x}!3i{y}!2m3!1e0!2sm!3i380072576!3m8!2szh-CN!3scn!5e1105!12m4!1e68!2m2!1sset!2sRoadmap!4e0!5m1!1e0')
const [{ data, isLoading, isError }, setUrl] = useFetchWindData(url, initData);
const [features, setFeatures] = useState([]);
const [feature, setFeature] = useState(null);
const [showPopup, setShowPopup] = useState(true);
const [position, setPosition] = useState([0, 0]);
// useEffect(() => {
//
// }, [refMap]);
const originExtent = [115.4168938, 39.442185, 117.5082261, 41.0592191];
const iamgeExtent = transformExtent(originExtent, 'EPSG:4326', 'EPSG:3857')
const projection = new Projection({
code: 'xkcd-image',
units: 'pixels',
extent: iamgeExtent
})
const style = new Style({
image: new Icon(({
anchor: [0.5, 46],
anchorXUnits: 'fraction',
anchorYUnits: 'pixels',
src: 'https://openlayers.org/en/v5.3.0/examples/data/icon.png'
}))
});
const btnClick = e => {
// const { setView, setCenter } = refMap.current;
// setCenter([112, 40], 9)
setView(new View({
projection: 'EPSG:3857',
center: transform([116, 40], 'EPSG:4326', 'EPSG:3857'),
zoom: 7
}))
setVisible(v => !v);
// setLayerUrl('http://www.google.cn/maps/vt/pb=!1m4!1m3!1i{z}!2i{x}!3i{y}!2m2!1e5!2sshading!2m2!1e6!2scontours!2m3!1e0!2sm!3i456160658!3m8!3scn!5e1105!12m1!1e67!12m1!1e63!12m1!1e3!4e0!5m2!5f1!6b1')
// setUrl('http://101.201.70.8:9087/pic_server/windy_json/gfs.2020061900/2020061914.json')
const features = sensor.filter((item, index) => index <= 10).map(item => {
const lng = Number(item.wgs84_lng);
const lat = Number(item.wgs84_lat);
const geometry = new Point(transform([lng, lat], 'EPSG:4326', 'EPSG:3857'));
const feature = new Feature({
geometry: geometry
})
return feature;
});
setFeatures(features);
}
useEffect(() => {
const features = sensor.map(item => {
const lng = Number(item.wgs84_lng);
const lat = Number(item.wgs84_lat);
const geometry = new Point(transform([lng, lat], 'EPSG:4326', 'EPSG:3857'));
const feature = new Feature({
geometry: geometry
})
return feature;
});
setFeatures(features);
}, [])
// 地图点击事件
useObservable(map, 'singleclick', (evts) => {
const pixel = evts.pixel;
const coordinate = evts.coordinate;
let layer = map.forEachLayerAtPixel(
pixel,
l => {
return l;
},
// 过滤条件
// {
// layerFilter: l => l.get('name') === 'vector'
// }
);
if (!layer) {
return;
}
const type = layer.type;
if (type === 'TILE') {
const source = layer.getSource();
const resolution = map.getView().getResolution();
const url = source.getGetFeatureInfoUrl(
coordinate,
resolution,
'EPSG:3857',
{ 'INFO_FORMAT': 'application/json' }
);
const fetchData = async () => {
const result = await fetch(url).then(response => response.json());
const feature = result.features[0];
setFeature(feature);
}
fetchData();
} else if (type === 'VECTOR') {
map.forEachFeatureAtPixel(pixel, function (feature) {
setFeature(feature);
setPosition(coordinate);
setShowPopup(true);
console.log(coordinate);
});
}
}, []);
// useEffect(() => {
// if (feature) {
// console.log(feature)
// }
// }, [feature]);
return (
<OpenlayersContext.Provider value={{
map: map
}}>
<Map
ref={refMap}
view={view}
listener={{
type: 'click',
callback: (e) => console.log(e)
}}
>
{/* <Overlay
onMount={(e) => console.log(e)}
position={[12574196.901024632, 3233836.6206729477]}
>
<div className="ol-b-line">
<span className="ol-popup-closer" onClick={e => console.log(e)}>x</span>
</div>
</Overlay> */}
<Layer.Group>
<Layer.TileLayer
source={
new XYZ({
url: layerUrl,
crossOrigin: 'Anonymous'
})
}
name="geoq"
/>
<Layer.TileLayer id="2" source={new TileWMS({
url: 'http://gis.airqualitychina.cn:10001/geoserver/hotgrid/wms',
params: {
LAYERS: 'hotgrid:china_regions_gcj',
TILED: true,
cql_filter: 'CITYID = 1'
},
serverType: 'geoserver',
crossOrigin: 'anonymous'
})} name="boundry" />
{/* <Layer.WindLayer
id="2"
name="windy"
map={map}
data={data}
/> */}
<Layer.VectorLayer
source={
new VectorSource({
features: features
})
}
style={style}
visible={visible}
name="vector"
zIndex={2}
/>
<Layer.ImageLayer
id="3"
source={
new Static({
projection: projection,
imageExtent: iamgeExtent,
// url: 'http://47.104.21.213:8781/gfs/TMP/1/1/0/0/hourly/20200620/clip_2020062011.png',
url: 'http://47.104.21.213:8781/gfs/RH/1/1/0/0/hourly/20200620/clip_2020062011.png',
})
}
visible={visible}
/>
</Layer.Group>
<Popup
// onMount={(e) => console.log(e)}
position={position}
show={showPopup}
onClose={() => setShowPopup(false)}
>
<h3>Jeck</h3>
</Popup>
</Map>
<button onClick={btnClick} style={{
position: 'absolute',
top: 20,
right: 20
}}>Click Me</button>
</OpenlayersContext.Provider>
)
}
const el = document.createElement('div');
el.id = 'root';
document.body.appendChild(el);
ReactDOM.render(<App />, el);