gis

基于ArcGis 4.13 for JavaScript打造gi

2019-12-11  本文已影响0人  写前端的大叔

对于开发webgis来说,无论做什么样的项目,都有一些基础的功能,比如地图初始化,地图放大缩小、加载图层、绘制图形、要素查询、添加点、线、面等。为了方便日后开发,特意对这些功能进行了封装,方便以后进行扩展和提升工具效率。下面主要从地图初始化、添加图层、绘制、查询、添加图形等方面来介绍一下代码的封装。

1.创建封装类

基于js的特性,可以使用面向对象和原型的思想来封装工具类,首先创建一个JTMapKit类用于封装属性和方法,具体代码如下所示:

function JTMapKit(option) {
    this.mapOption = {};
    this._init(option || {});
    //默认点符号
    this.pointSymbol = {
        type: "simple-marker",
        style: "square",
        color: "red",
        size: "16px",
        outline: {
            color: [255, 255, 0],
            width: 3
        }
    }
    //默认线符号
    this.lineSymbol = {
        type: "simple-line",
        color: [4, 90, 141],
        width: 3,
        cap: "round",
        join: "round"
    }
    //默认面符号
    this.fillSymbol = {
        type: "simple-fill",
        color: "purple",
        style: "solid",
        outline: {
            color: "white",
            width: 1
        }
    }
    this.isDrawing = false;//正在绘制中,用于控制多点绘制
}

在类中主要添加了如下属性:
_init:用于初始化地图和一些参数。
mapOption:用于保存地图的一些属性。
pointSymbol:用于创建默认的点符号。
lineSymbol:用于创建默认的线符号。
fillSymbol:用于创建默认的面符号。
isDrawing:标识正在绘制中,用于控制多点绘制
然后再通过一个extend方法来合并原型中添加的方法,如下所示:

JTMapKit.prototype.extend = function (option) {
    for (key in option) {
        JTMapKit.prototype[key] = option[key];
    }
}

2.地图初始化

地图初始化主要是对地图加载、地图基本操作的封装,首先通过调用_init来进行初始化,_init方法有一个option参数,该参数主要用于设置地图的选择器、加载完成后的回调、地图类型、底图、中心点,全图范围等等。具体如下所示:

JTMapKit.prototype.extend({
    //初始化配置信息
    _init: function (option) {
        this.selector = option.selector || 'map';//地图选择器
        this.onMapReady = option.onMapReady;//地图加载完后处理
        this.onViewReady = option.onViewReady;//mapView加载完成后添加底图
        this.mapType = option.mapType || '2d';//地图类型,2d,3d
        //地图相关参数
        this.mapOption.basemap = option.basemap;//底图
        this.mapOption.center = option.center;//中心点
        this.mapOption.extent = option.extent;//全图
        if (this.mapType.toLocaleLowerCase() === '3d') {

        } else {
            this._init2dMap();
        }
    },
    //初始化地图
    _init2dMap: function () {
        var self = this;
        require(["esri/Map", "esri/views/MapView"], function (Map, MapView) {
            self.map = new Map({
                basemap: self.mapOption.basemap
            });
            self.mapView = new MapView({
                container: self.selector,
                map: self.map,
            })

            if (self.onViewReady) {
                self.onViewReady(self.mapView);
            }
            self.mapView.when(function () {
                //地图加载完成
                if (self.onMapReady) {
                    self.onMapReady(self.map, self.mapView);
                }
            }, function (error) {
                console.log("地图加载失败", error);
            });
        });
    },
    setExtent: function (extent) {
        this.mapView.extent = extent;
    },
    setZoom: function (zoom) {
        this.mapView.zoom = zoom;
    },
    setCenter: function (center) {
        this.mapView.center = center;
    },
    setScale: function (scale) {
        this.mapView.scale = scale;
    },
    // 隐藏放大缩小的工具条
    hidenZoomToolBar: function () {
        this.mapView.ui.remove("zoom");
    },
    //隐藏底部的logo
    hidenLogo: function () {
        this.mapView.ui.remove("attribution");
    },
    //放大
    zoomIn:function () {
        var self = this;
        require(["esri/widgets/Zoom"], function(Zoom) {
            var zoom = new Zoom({
                view: self.mapView
            });
            zoom.zoomIn();
        });
    },
    //缩小
    zoomOut:function () {
        var self = this;
        require(["esri/widgets/Zoom"], function(Zoom) {
            var zoom = new Zoom({
                view: self.mapView
            });
            zoom.zoomOut();
        });
    }
})

常用方法

setExtent:用于设置地图的全图范围。
setZoom:用于设置地图的缩放级别。
setCenter:用于设置地图的中心点。
setScale:用于设置地图的缩放比例尺。
hidenZoomToolBar:用于隐藏地图上的放大缩小组件。
hidenLogo:用于隐藏地图上面的logo。
zoomIn:用于放大地图。
zoomOut:用于缩小地图。

3.添加图层

主要是用于方便添加图层,主要包括添加动态图层、添加要素图层、添加titleLayer,其它的等以后需要用到时再慢慢补充。方法中的option参数主要用于设置图层相关的属性、比如地图的url,id,title,visible等属性。

JTMapKit.prototype.extend(
    {
       //添加动态图层
        addDynamicLayer: function (option) {
            if (!option) {
                return
            }
            var self = this;
            require(["esri/layers/MapImageLayer"], function (MapImageLayer) {
                var layer = new MapImageLayer(option);
                self.map.layers.add(layer);
                return layer;
            });
        },

        //添加要素图层
        addFeatureLayer: function (option) {
            if (!option) {
                return
            }
            option.outFields ? option.outFields : ["*"];
            var self = this;
            require(["esri/layers/FeatureLayer"], function (FeatureLayer) {
                var layer = new FeatureLayer(option);
                self.map.layers.add(layer);
                return layer;
            });
        },

       //添加titleLayer
        addTileLayer: function (option) {
            if (!option) {
                return
            }
            var self = this;
            require(["esri/layers/TileLayer"], function (TileLayer) {
                var layer = new TileLayer(option);
                self.map.layers.add(layer);
                return layer;
            });
        }
    }
)

4.绘制图形

绘制图形主要包括绘制点、线、面、圆、矩形等。将所有绘制的方法进行了封装、在html中调用的时候,只需要传递图形符号就行。具体的代码实现如下所示:

JTMapKit.prototype.extend({
    _draw:function (type,option) {
        var self = this;
        require([
                "esri/views/draw/Draw",
                "esri/layers/GraphicsLayer",
                "esri/Graphic"],
            function (Draw, GraphicsLayer, Graphic) {
                self.clearGraphic();
                if (!self.graphicsLayer) {
                    self.graphicsLayer = new GraphicsLayer();
                    self.map.layers.add(self.graphicsLayer);
                }
                var draw = new Draw({
                    view: self.mapView
                });
                var action = draw.create(type);

                option.type = type;
                //添加点
                action.on("vertex-add", function (evt) {
                    self._drawActionHandler(evt,option,Graphic);
                });

                //绘制结束
                action.on("draw-complete", function (evt) {
                    self._drawActionHandler(evt,option,Graphic);
                });

                //删除点
                action.on("vertex-remove", function (evt) {
                    self._drawActionHandler(evt,option,Graphic);
                });

                action.on("cursor-update",function (evt) {
                    if(type === 'circle'){
                        self._drawActionHandler(evt,option,Graphic);
                    }else if(type === 'rectangle'){
                        self._drawActionHandler(evt,option,Graphic);
                    }
                })

                if(type === 'multipoint'){
                    self.mapView.on('click',function (evt) {
                        self._addMultipoint(evt,option,Graphic)
                    })
                }
            });
    },
    //绘制处理事件
    _drawActionHandler(evt,option,Graphic){
        if(option.type === 'circle'){
            this._drawCircleActionHandler(evt,option,Graphic);
            return;
        }else if(option.type === 'rectangle'){
            this._drawRectangleActionHandler(evt,option,Graphic);
            return;
        }

        var geometry;
        if(evt.coordinates){//绘制单个点时获取的是coordinates
            var coordinates = evt.coordinates;
            geometry = {
                type: "point",
                x: coordinates[0],
                y: coordinates[1],
                spatialReference: this.mapView.spatialReference
            };

        }else if(evt.vertices){
            var vertices = evt.vertices;
            var type = option.type;
            geometry = {
                spatialReference: this.mapView.spatialReference
            };
            //多点
            if(type === 'multipoint'){
                this.isDrawing = false;
                geometry.points = vertices;
                geometry.type = "multipoint";
            }else if(type === 'polyline'){
                geometry.paths = vertices;
                geometry.type = "polyline";
            }else{
                geometry.rings = vertices;
                geometry.type = "polygon";
            }
        }
        var graphic = new Graphic({
            geometry: geometry,
            symbol: option.symbol
        });
        this.graphicsLayer.add(graphic);
    },
    //绘制圆
    _drawCircleActionHandler(evt,option,Graphic){
        var self = this;
        require(["esri/geometry/Circle",
                "esri/geometry/Point"], function(Circle,Point) {
            var vertices = evt.vertices;
            if(vertices.length<2){
                return
            }
            self.graphicsLayer.removeAll();
            var center=new Point({
                hasZ: false,
                hasM: false,
                x:vertices[0][0],
                y:vertices[0][1],
                spatialReference: self.mapView.spatialReference
            });
            var radius=center.distance(new Point({
                hasZ: false,
                hasM: false,
                x:vertices[1][0],
                y:vertices[1][1],
                spatialReference: self.mapView.spatialReference
            }));
            var graphic = new Graphic({
                geometry: new Circle({
                    hasZ: false,
                    hasM: false,
                    center:center,
                    radius:radius,
                    spatialReference: self.mapView.spatialReference
                }),
                symbol: option.symbol
            });
            self.graphicsLayer.add(graphic);
        });

    },
    //绘制矩形
    _drawRectangleActionHandler(evt,option,Graphic){
        var self = this;
        require(["esri/geometry/Circle",
            "esri/geometry/Polygon"], function(Circle,Polygon) {
            //获取所有顶点
            var vertices = evt.vertices;

            if(vertices.length<2){
                return
            }
            var rings=[vertices[0],[vertices[0][0],vertices[1][1]],vertices[1],[vertices[1][0],vertices[0][1]]];
            self.graphicsLayer.removeAll();

            var graphic = new Graphic({
                geometry: new Polygon({
                    hasZ: false,
                    hasM: false,
                    rings: [rings],
                    spatialReference: self.mapView.spatialReference
                }),
                symbol: option.symbol
            });
            self.graphicsLayer.add(graphic);
        });

    },
    //绘制多个点
    _addMultipoint:function(evt,option,Graphic){
        if(this.isDrawing){
            var graphic = new Graphic({
                geometry: evt.mapPoint,
                symbol: option.symbol
            });
            this.graphicsLayer.add(graphic);
        }

    },
    //绘制单个点
    drawPoint:function(option){
        var options = option || {};
        if(!options.symbol){
            options.symbol = this.pointSymbol;
        }
        this._draw('point',options);
    },

    //绘制多个点
    drawMultiPoint:function(option){
        this.isDrawing = true;
        var options = option || {};
        if(!options.symbol){
            options.symbol = this.pointSymbol;
        }
        this._draw('multipoint',options);
    },
    //绘制线
    drawPolyline:function(option){
        var options = option || {};
        if(!options.symbol){
            options.symbol = this.lineSymbol;
        }
        this._draw('polyline',options);
    },
    //绘制多边形
    drawPolygon:function(option){
        var options = option || {};
        if(!options.symbol){
            options.symbol = this.fillSymbol;
        }
        this._draw('polygon',options);
    },
    //绘制矩形
    drawRectangle:function(option){
        var options = option || {};
        if(!options.symbol){
            options.symbol = this.fillSymbol;
        }
        this._draw('rectangle',options);
    },
    //绘制圆
    drawCircle:function(option){
        var options = option || {};
        if(!options.symbol){
            options.symbol = this.fillSymbol;
        }
        this._draw('circle',options);
    },
    //清空绘制图层
    clearGraphic:function () {
        if(this.graphicsLayer){
            this.graphicsLayer.removeAll();
        }
    }
})

绘制图形的大致思路是先实例Draw对象,然后再根据绘制的类型来调用create方法,然后再监听vertex-adddraw-completevertex-removecursor-update等事件来生成geometry对象,再创建Graphic添加到图层中。

5.要素查询

图形要素查询主要使用QueryTaskQuery来完成,首先用QueryTask创建一个查询任务,QueryTask可以设置查询的图层地址,然后再创建一个Query对象,来设置查询的条件,是否返回图形、返回的字段信息等 。查询数据后,可以将要素添加到地图上进行高亮显示。具体代码如下所示:

JTMapKit.prototype.extend({
    /*
    * 图层查询
    * */
    query:function (uri,where,callback) {
        var self = this;
        require([
                "esri/tasks/QueryTask",
                "esri/tasks/support/Query"],
            function(QueryTask,Query){
                var queryTask = new QueryTask(uri);
                var query = new Query();
                query.outSpatialReference = self.mapView.spatialReference;
                query.returnGeometry = true;
                query.outFields = ["*"];
                query.where = where;
                queryTask.execute(query).then(function(results){
                    if(callback){
                        callback(results);
                    }
                })
            })
    },
    addFeatures2Map:function (features,options) {
        options = options || {};
        options.symbol = options.symbol || {};
        var self = this;
        require([
                "esri/layers/GraphicsLayer",
                "esri/Graphic"],
            function ( GraphicsLayer, Graphic){
                if (!self.featureLayer) {
                    self.featureLayer = new GraphicsLayer();
                    self.map.layers.add(self.featureLayer);
                }else{
                    this.featureLayer.removeAll();
                }
                if (features.length === 0) return;
                for (var i = 0; i <features.length; i++) {
                    var feature = features[i];
                    var type = feature.geometry.type;
                    var symbol; // 要素高亮符号
                    if (type === "polygon") {
                        symbol = options.symbol.polygon || self.fillSymbol;
                    }else if(type === "polyline"){
                        symbol = options.symbol.polyline || self.lineSymbol;
                    }else if(type === "point"){
                        symbol = options.symbol.point || self.pointSymbol;
                    }
                    var params = {
                        geometry: feature.geometry,
                        symbol: symbol
                    };
                    var extent = options.extent;
                    if(extent){//扩展参数
                        for(var key in extent){
                            if(extent[key]){
                                params[key] = extent[key];
                            }
                        }
                    }
                    var graphic = new Graphic(params);
                    self.featureLayer.add(graphic);
                }
                self.map.add(self.featureLayer);
            });
    }
})

6.添加点、线、面

添加点、线、面的方法跟绘制图形的方法差不多,只是这里是直接通过传递的坐标进行绘制,具体实现代码如下所示:

JTMapKit.prototype.extend({
    //添加点
    addPoint:function (option) {
        option.type = 'point';
        this._addTempLayer(option)
    },
    //添加线
    addLine:function (option) {
        option.type = 'polyline';
        this._addTempLayer(option)
    },
    //添加面
    addPolygon:function (option) {
        option.type = 'polygon';
        this._addTempLayer(option)
    },

    //添加临时图层,用于添加点、线、面
    _addTempLayer:function (option) {
        var self = this;
        require(["esri/layers/GraphicsLayer","esri/Graphic"], function(GraphicsLayer,Graphic) {
            if (!self.tempLayer) {
                self.tempLayer = new GraphicsLayer();
                self.map.layers.add(self.tempLayer);
            }
            var type = option.type,symbol;
            var geometry = {
                type: type,
                spatialReference: self.mapView.spatialReference
            };
            option.symbol = option.symbol || {};
            if(type === 'point'){
                geometry.longitude = option.x;
                geometry.latitude = option.y;
                symbol = option.symbol.point || self.pointSymbol;
            }else if(type === 'polyline'){
                geometry.paths = option.paths;
                symbol = option.symbol.polyline || self.lineSymbol;
            }else if(type === 'polygon'){
                geometry.rings = option.rings;
                symbol = option.symbol.polygon || self.fillSymbol;
            }
            var graphic = new Graphic({
                geometry: geometry,
                symbol: symbol
            });
            self.tempLayer.add(graphic);
        });
    },
    clearTempLayer:function () {
        if(this.tempLayer){
            this.tempLayer.removeAll();
        }
    }
})

个人博客

上一篇下一篇

猜你喜欢

热点阅读