头部背景图片
吉水于人的笔记 |
吉水于人的笔记 |

地图导出

前言

gis开发侧重于专业知识,相比于其他的前端开发领域,gis功能开发的资料相对较少,我会根据自己的日常项目和学习逐一进行整理,丰富开发资料。由于esri提供的api是用dojo框架开发的,所以在我的博客里涉及到gis开发例子的将是使用dojo语法。今天要给大家介绍一下地图导出模块核心代码。

导出地图需要以下参数:center(地图中心)、scale(导出地图比例尺)、WMTSLayers(WMTS图层)、ArcLayers(arcMap图层)、dpi(像素)、width(地图宽度)、height(地图高度)、extent(当前地图显示范围)、proxyUrl(代理地址)。
根据上面的参数,我们需要封装一个ExportMapImg类,包含初始化地图、加载图层、初始化图层导出坐标系、打印几个方法。

具体实现

初始化地图
我们创建一个容器存放当前的地图,并顺利获取地图的空间范围、中心、比例尺等属性。

       _initMap: function () {
            $('body').append($('<div id="' + this.mapId + '" style="height:' + this.option.height
                + 'px;width:' + this.option.width + 'px;z-index:-12;position:absolute;"></div>'));

            this.map = new map(this.mapId, { logo: false, slider: false });
            this.map.extent = this.option.extent;
            var defs = [];
            if (this.option.center) {
                defs.push(this.map.centerAt(this.option.center));
            }
            if (this.option.scale) {
                defs.push(this.map.setScale(this.option.scale));
            }
            all(defs).then(lang.hitch(this,this._addLayers));
        }

地图创建好了以后,添加图层。常用的图层服务分为WMTSdynamictiled三种。WMTS是Web地图切片服务,dynamic是动态地图服务,tiled是地图瓦片服务。不同类型的地图服务的加载方法不一样,ersi的开发者文档中有详细的例子可以参照。在我们这个例子中,添加图层是用于map的初始化,所以WMTS图层全部添加,而arcgis图层则只添加一个图层。

 _addLayers: function () {
            var defs = [];
            if (this.option.WMTSLayers.length) {//保证行列号完全正确,所有wmts图层都添加
                defs = this.option.WMTSLayers.map(function (item) {
                    var def = new Deferred();
                    item.on('update-end', function () {
                        def.resolve();
                    });
                    this.map.addLayer(item);
                    return def;
                }, this);
            }
            if (!this.option.WMTSLayers.length && this.option.ArcLayers.length) {//当未添加wmts图层时,只添加一个图层用于map初始化
                var def = new Deferred();
                var layerItem = this.option.ArcLayers[0];
                var layer = new ArcGISDynamicMapServiceLayer(layerItem.url);
                layer.setVisibleLayers(layerItem.visibleLayers);
                layer.on('load', function () {
                    def.resolve();
                });
                this.map.addLayer(layer);
                defs.push(def);
            }
            if (this.option.graphics.length) {
                var graLayer = new GraphicsLayer();
                this.map.addLayer(graLayer);
                this.option.graphics.map(function (gra) {
                    if (!gra.symbol) {
                        gra.setSymbol(this._getSymbol(gra.geometry.type));
                    }
                    graLayer.add(new Graphic(gra.geometry, gra.symbol));
                }, this);
            }

            all(defs).then(lang.hitch(this, this._print));
        },

地图导出相对来说比较复杂,因为要将地图服务生成图片,这里我选择的是将arcgis图层使用export接口输出为png图片,并转为base64;将WMTS图层的瓦片转为base64。

        /**
         *ArcGis 图层全部使用export接口输出png图片,并转换为base64
         * @returns {Deferred}
         * @private
         */
        _getExportPngs: function () {
            var pngsDef = new Deferred();
            var $pngRoot = $('<div style="width: 100%;height: 100%;position: absolute;"></div>');
            var defs = this.option.ArcLayers.map(function (item) {
                return this._exportPng(item.url, this.map.extent, this.option.dpi, this.option.height,
                    this.option.width, item.visibleLayers, this.option.innerSR, this.option.outSR);
            }, this);
            all(defs).then(lang.hitch(this, function (results) {
                results.map(function (img) {
                    $pngRoot.append($('<img alt="" style="width: 100%;height: 100%;position: inherit;" src="' + img + '">'));
                });
                pngsDef.resolve($pngRoot);
            }));
            return pngsDef;
        },

         /**
         * 将wmts图层的瓦片转为base64,并返回瓦片位置变换后的div节点
         * @returns {Deferred}
         * @private
         */
        _getTileLayerImgs: function () {
            var layersDef = new Deferred();
            var scale = this.map.getScale();
            var rect = this.map.__visibleRect;
            var $layersRoot = $('<div></div>');
            var layerTileStr = 'position:absolute;border:none;margin:0;padding:0;visibility:inherit;';
            var layerDivStr = 'position:absolute;overflow:visible;transition:-webkit-transform 500ms ease 0s;';
            var tileLayersStr = 'position:absolute;overflow:visible;display:block;';
            var layerDefs = [];
            this.option.WMTSLayers.map(function (item) {//图层
                var layer = this.map._layers[item.id];
                if (scale < layer.maxScale && scale > layer.minScale) return;
                var layerDef = new Deferred();
                var $root = $('<div style="height: ' + rect.height + 'px;width: ' + rect.width + 'px;' +
                    'transform: translate(' + layer.__coords_dx + 'px,' + layer.__coords_dy + 'px);' + tileLayersStr + '"></div>');
                var $layer = $('<div style="height: ' + rect.height + 'px;width: ' + rect.width + 'px;' + layerDivStr + '"></div>');
                var tiles = layer._tileIds;
                var tileBs = layer._tileBounds;
                var tileImgs = layer._tiles;
                var defs = tiles.map(function (id) {//瓦片
                    var tileItem = tileBs[id];
                    var def = new Deferred();
                    var imgSrc = (this.option.proxyUrl === '' ? '' : this.option.proxyUrl + '?') + tileImgs[id].src;
                    // console.log(imgSrc);
                    this._getImgBase64(imgSrc, 'png', tileItem.height, tileItem.width).then(
                        lang.hitch(this, function (url) {
                            $layer.append($('<img style="height: ' + tileItem.height + 'px;width: ' + tileItem.width + 'px;' +
                                'transform: translate(' + tileItem.x + 'px,' + tileItem.y + 'px);' + layerTileStr + '" src="' + url + '">'));
                            def.resolve();
                        })
                    );
                    return def;
                }, this);
                $root.append($layer);
                all(defs).then(lang.hitch(this, function () {
                    layerDef.resolve($root);
                }));
                layerDefs.push(layerDef);
            }, this);
            all(layerDefs).then(lang.hitch(this, function ($layers) {
                $layersRoot.append($layers);
                layersDef.resolve($layersRoot);
            }));
            return layersDef;
        }