基于ArcGis 4.13 for JavaScript打造gis开发工具集

对于开发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();
        }
    }
})

个人博客

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 224,242评论 6 522
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 95,953评论 3 402
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 171,299评论 0 366
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 60,709评论 1 300
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 69,723评论 6 399
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 53,236评论 1 314
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 41,629评论 3 428
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 40,594评论 0 279
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 47,135评论 1 324
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 39,156评论 3 345
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 41,285评论 1 354
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 36,914评论 5 350
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 42,600评论 3 336
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 33,073评论 0 25
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 34,203评论 1 275
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 49,798评论 3 381
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 46,339评论 2 365