ArcGis的React組件開發

來源:互聯網
上載者:User
背景

最近有個採用React的項目用到了ArcGis,發現跟之前的用法非常不同,而且經過我們調研後發現,相關資料並不多見,並且相當分散,主要集中在github和arcgis for developer上。這也算是踩過的一個比較深的坑,在這裡總結一下,希望能幫到大家。 基本原理

要在react中使用arcgis的api可能要比大家想象的要複雜一些,因為arcgis並沒有給大家提供標準的react組件,而是要依賴esri-loader-react,esri-loader等多個組件的聯合使用才可以。
有時間的同志可以看看看這篇文章,拜讀一下大神的文章一切都明白了。
最核心的下面這段話

The ArcGIS API for JavaScript is written in Dojo and distributed as large library of AMD modules. Unfortunately, most module loaders, including webpack, implement the AMD “standard” differently than the way that Dojo does, specifically in the area of plugins. There is a Dojo loader for webpack that tries to address those differences, but as of time of writing it is not capable of loading ArcGIS modules. Even once that issue is resolved, I still think you’ll want to understand the workarounds below so you can decide which is the best solution for your application.

簡單的說就是arcgisapi的JavaScript是基於Dojo實現的,並且需要通過AMD模組匯入。但是呢,webpack的AMD實現方式與Dojo不同,因此產生了衝突,因此我們需要採用各種奇怪的方法來曲線救國解決這兩者的衝突。


在本文中我們採用了建立專用的地圖載入模組的方案,即通過esriLoader的dojoRequire來引入arcgis的類。
範例程式碼如下所示

//匯入esri-loaderimport * as esriLoader from 'esri-loader';// 使用dojoRequire來一如esri/map類esriLoader.dojoRequire(['esri/map'], (Map) => {  // 使用Map類建立地圖  let map = new Map('mapNode', {    center: [-118, 34.5],    zoom: 8,    basemap: 'dark-gray'  });});
實際代碼

來跟著我大喊一句,show me the code。
封裝控制項

import React from 'react';import { dojoRequire } from 'esri-loader'import EsriLoader from 'esri-loader-react'export default class Map extends React.Component {    //採用建構函式的方法解決不用頁面同時調用地圖組件產生id衝突問題    constructor(props) {        super(props);        let timeStample = new Date().getTime();        this.state = {            mapDivId: "mapdiv" + timeStample,            mainMap: {}        };    }    render() {        const mapOptions = {            url: 'http://ip:8080/arcgis_js_api/library/3.9/3.9/init.js'        }        let flag = this.props.getShowType();        let mapStyle;        if (flag !== "index") {            //使用自適應大小            mapStyle = { height: '400px', width: '430px' };        } else {            mapStyle = { height: '100vh', width: '70vw' };        }        return (            <div>                <EsriLoader options={mapOptions} ready={() => console.timeEnd('JSAPI loaded')} />                <div id={this.state.mapDivId} style={mapStyle}>                </div>            </div>        )    }    componentDidMount() {        dojoRequire(            ['esri/layers/WebTiledLayer', 'esri/map'], (WebTiledLayer, EsriMap,InfoTemplate) => {                this.state.mainMap = new EsriMap(this.state.mapDivId, {                    autoResize: true,                    zoom: 5,                    maxZoom: 15,                    center: [107.5, 27]                });                let thisMap=this;                this.state.mainMap.on("load", function(){                    thisMap.state.mainMap.graphics.enableMouseEvents();                  });                let bgMapUrl = 'http://ip:8080';                bgMapUrl = bgMapUrl + '/WebMapTileServer/map/WebMap/Tiles?x=${col}&y=${row}&z=${level}';                //瓦片底圖                let baseMap = new WebTiledLayer(bgMapUrl);                this.state.mainMap.addLayer(baseMap);//google地圖                this.setExtent({ minLat: "23", maxLat: "31", maxLon: "111.5", minLon: "103.5" });            }        );    }    addEventCallBack2Layer(layer,event, cb) {        dojo.connect(layer,event, cb);    }    showInfoTemplate(info){        //彈出infoWindow        this.state.mainMap.infoWindow.show();    }    setExtent(scope) {        // scope={"minLon":"0","maxLon":"10","minLat":"0","maxLat":"10"};        console.info("setExtent");        dojoRequire(["esri/geometry/Extent"], (Extent) => {            let extent = new Extent({                "xmin": parseFloat(scope.minLon),                "ymin": parseFloat(scope.minLat),                "xmax": parseFloat(scope.maxLon),                "ymax": parseFloat(scope.maxLat),                "spatialReference": {                    "wkid": 4326                }            });            this.state.mainMap.setExtent(extent);        });    }    //增加圖層;    addLayer(layerName) {        dojoRequire(            ['esri/layers/GraphicsLayer'], (GraphicsLayer) => {                let layer;                layer = new GraphicsLayer();                layer.id = layerName;                this.state.mainMap.addLayer(layer);                return layer;            });    }    // 清除一個圖層;    clearLayer(layerName) {        let layer = this.state.mainMap.getLayer(layerName);        if (layer !== null)            layer.clear();    }    getLayer(layerName) {        return this.state.mainMap.getLayer(layerName);    }    //清除所有圖層;    clearAllLayers() {        var arr = mainMap.graphicsLayerIds;        arr.forEach((layer) => {            this.state.mainMap.clearLayer(layer);        });    }    ////增加表徵圖marker    addMarker(data) {        // 添加marker到地圖中,例如人員、裝置、任務        let locatedPoint = {            "geometry": {                "x": data.marker.lng,//經度                "y": data.marker.lat,//緯度                "spatialReference": {                    "wkid": 4326                },            },            "symbol": {                "url": "/style/images/" + data.marker.type + ".png",                "height": data.marker.height,                "width": data.marker.width,                "angle": data.marker.angle,                "type": "esriPMS"            }        };        // 檢測是否設定infowindow資訊        if (data.infoTemplate !== null) {            locatedPoint.geometry.infoTemplate = data.infoTemplate;        }        //建立地圖資訊        dojoRequire(            ['esri/graphic'], (Graphic) => {                let gra = new Graphic(locatedPoint);                if( data.marker.attrs===undefined)                    data.marker.attrs={};                // 設定屬性                if( data.marker.attrs===undefined) data.marker.attrs={};                data.marker.attrs.graphic_id = data.marker.id;                gra.setAttributes(data.marker.attrs);                // 檢測是否有當前marker所需添加到的圖層,如果沒有建立圖層                let layer = this.state.mainMap.getLayer(data.layer);                if (layer === null) {                    layer = this.state.mainMap.addLayer(data.layer);                }                return layer.add(gra);                console.log("bigon");            });    }    closeWindowInfo(evt){        this.state.mainMap.infoWindow.hide();    }    showWindowInfo(evt){        this.state.mainMap.infoWindow.setContent(evt.graphic.geometry.infoTemplate.content);        this.state.mainMap.infoWindow.show(evt.screenPoint,this.state.mainMap.getInfoWindowAnchor(evt.screenPoint));    }    // 繪製軌跡    addPath(pathParameters) {        // 首先擷取圖層, 如果不存在則建立新圖層        let pathLayer = this.state.mainMap.getLayer(pathParameters.layer);        // 建立路徑        let lineSymbol = {};        let s=pathParameters.from;        let e=pathParameters.to;        let geo=[[s.x,s.y],[e.x,e.y]];        lineSymbol.geometry = {            "paths":[geo],            "spatialReference": {                "wkid": 4326            }        };        lineSymbol.symbol = {            "color": [255, 0, 0, 255],            "width": 5,            "type": "esriSLS",            "style": "esriSLSSolid"        };        dojoRequire(            ['esri/graphic'], (Graphic) => {                // 添加路徑到圖層                pathLayer.add(new Graphic(lineSymbol));            });    }}

package.json

{  "name": "ZEWDemo",  "version": "1.0.0",  "description": "",  "main": "index.js",  "scripts": {    "test": "echo \"Error: no test specified\" && exit 1",    "build": "webpack",    "start": "webpack-dev-server  --host 0.0.0.0 --port 9001 --colors --hot --inline  --content-base ./build"  },  "author": "",  "license": "ISC",  "devDependencies": {    "babel-core": "^6.26.0",    "babel-loader": "^7.1.2",    "babel-preset-es2015": "^6.24.1",    "babel-preset-react": "^6.24.1",    "css-loader": "^0.28.7",    "esri-loader-react": "^0.2.2",    "file-loader": "^0.11.1",    "jsx-loader": "^0.13.2",    "less": "^2.7.2",    "less-loader": "^4.0.5",    "react": "^15.6.1",    "react-dom": "^15.6.1",    "require": "2.4.20",    "style-loader": "^0.18.2",    "url-loader": "^0.5.8",    "webpack": "^3.5.5",    "webpack-dev-server": "^2.7.1"  },  "dependencies": {    "bootstrap": "^3.3.7",    "echarts-for-react": "^1.4.4",    "esri-loader": "^0.3.0",    "esri-loader-react": "^0.2.2",    "mqtt": "^2.11.0",    "rc-tree-select": "^1.10.7",    "react": "^15.6.1",    "react-bootstrap": "^0.31.2",    "react-bootstrap-date-time-picker": "0.0.3",    "react-bootstrap-table": "^4.0.2",    "react-date-range": "^0.9.4",    "react-datetime": "^2.10.1",    "react-dom": "^15.6.1",    "react-echarts": "^0.1.1",    "react-ui-tree": "^3.0.0"  }}
參考資料

1.http://tomwayson.com/2016/11/27/using-the-arcgis-api-for-javascript-in-applications-built-with-webpack/
2.https://github.com/Esri/esri-loader
3.https://developers.arcgis.com/

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.