1.0.6 • Published 4 years ago

ol5-react v1.0.6

Weekly downloads
7
License
MIT
Repository
-
Last release
4 years ago

Openlayers With React Hooks

文件介绍

  • map.js
  • context
    • layersContext.js
    • openlayersContext.js 提供OpenlayersContext、MapContext
  • hooks
    • useFeatchWindData.js 获取风场数据
    • useLayer.js
    • useMap.js 提供map
    • useMapEvent.js
    • useMapTarget.js
    • useObservable.js 地图点击事件使用
    • useStopEvent.js
    • useView.js
  • layers
    • imageLayer.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);
1.0.6

4 years ago

1.0.5

5 years ago

1.0.4

5 years ago

1.0.3

5 years ago

1.0.2

5 years ago

1.0.1

5 years ago

1.0.0

5 years ago