美文网首页Gis专辑gisGIS之家
arcgis api for js入门开发系列二十打印地图的那些

arcgis api for js入门开发系列二十打印地图的那些

作者: gis之家 | 来源:发表于2018-04-03 21:25 被阅读240次

    前面我写过关于利用arcgis api for js打印地图的,但是打印地图服务都是基于arcgis server发布的,arcgis api加载在线地图,比如天地图、百度地图、高德地图等,底图都是打印不出来的;这个在GIS之家群里也有很多giser问过,我一直也没抽出时间好好整理研究,碰巧一个师妹遇到这种打印问题并且解决了,于是我向她邀稿,才有这里的这篇文章。本文是‘猴妹‘师妹授权给我来发表的,介绍都是师妹的研究成果,在此,非常感谢‘猴妹‘师妹。


    记录了通过ArcGIS的PringTask进行地图打印,以及借助html2canvas实现屏幕截图的方法。两个方法各有适用的情景。过程中涉及的相关资源和问题给出链接,自行查看。

    1.需求背景

    地图打印,这是地图应用系统的基本工具了。多数使用者都希望能够将地图,连带着查询结果、统计结果以及自己绘制的各种图形输出,将其保存到本地,以供他用。本文描述两类情况:一类是通过ArcGIS Server发布的地图服务,一类是调用其他数据源的地图切片形成的地图。


    2.通过ArcGIS Server发布的地图服务

    这个网上很多例子啦,官方API也有详细例子。上个链接:https://developers.arcgis.com/javascript/3/jssamples/#search/PrintTask

    这个的思路就是通过printTask执行一个打印任务。截一段代码给大伙看看:

    arcgisPrint=function(){
        var printTask = new PrintTask("http://172.28.1.131:6080/arcgis/rest/services/Utilities/PrintingTools/GPServer/Export%20Web%20Map%20Task");
        var template = new PrintTemplate();
         
        template.layoutOptions = {
            "authorText": "paq",
            "copyrightText": "copyright info here",
            "legendLayers": [],
            "titleText": "Pool Permits",
            "scalebarUnit": "Miles"
        };
        template.exportOptions = {
            width: 800,
            height: 600,
            dpi: Number(90)
        };
        template.format = "png32";
        template.layout = "MAP_ONLY";
        template.preserveScale = false;
        var params = new PrintParameters();
        params.map = map;
        params.template = template;
        printTask.execute(params, function (evt) {
            window.open(evt.url, "_blank");
        });
    };
    

    这种方法的打印对于ArcGIS Server发布的服务来讲方便好用,但是如果是调用其他地方的切片(比如通过继承WebTiledLayer调用天地图、百度地图),那么输出的会是空白。如图,底图是天地图,中国范围内叠加了一个MapServer方便区别:

    image

    用PrintTask打印出来是这个样子,底图天地图是空白的:

    image

    /* *题外话:

      *如何通过ArcGIS JS API调用百度地图和天地图自行百度,提供几个链接:
    
      *[http://www.cnblogs.com/angelapaq/p/7595831.html](http://www.cnblogs.com/angelapaq/p/7595831.html)
    
    *[https://blog.csdn.net/oldmonkeyyu_s/article/details/53710779](https://blog.csdn.net/oldmonkeyyu_s/article/details/53710779)
    

    *总结调用切片三点:确定好级别、分辨率、比例尺;调整好图片大小、切图原点;把行列号和层级号拼成能够访问的URL,这些做好了,不管百度谷歌还是高德超图都是一个道理。

    **/


    3.借助html2canvas实现屏幕截图

    思考之后,决定换方法,不用ArcGIS提供的方法,转向通用的屏幕输出,网上有很多关于html2canvas截图插件的使用,我们也拿来一用。

    html2canvas官方网站: http://html2canvas.hertzen.com/

    这个插件的使用详情可自行百度,我这里贴出自己的代码,大致流程是:确定截图区域,克隆一份,把不需要截图的dom移除,调用插件把html片段转成canvas,输出。

    canvasPrint=function () {
        var targetDom = $("#map");
        //克隆截图区域
        var copyDom = targetDom.clone();
        copyDom.width(targetDom.width() + "px");
        copyDom.height(targetDom.height() + "px");
        copyDom.attr("id", "copyDom");
        $("body").append(copyDom);
        //移除不需要截图的区域
        $(".base-map").remove();
     
        var pathName = document.location.pathname;
        var ctxPath = pathName.substring(1, pathName.substr(1).indexOf('/') + 1);
        html2canvas(copyDom[0], {
            useCORS: true,
            imageTimeout:0
            //, proxy: "/" + ctxPath + "/proxy/proxyScreenShot"
        }).then(function (canvas) {
            var url = canvas.toDataURL();
            //创建下载a标签
            var a = document.createElement("a");
            a.setAttribute("id", "download");
            document.body.appendChild(a);
            //以下代码为下载此图片功能
            var triggerDownload = $("#download").attr("href", url).attr("download", "img.png");
            triggerDownload[0].click();
            //移除下载a标签
            document.body.removeChild(a);
            //克隆DOM删除
            copyDom.remove();
        });
    }
    

    按理说,这样就可以输出了,奈何我们的那些个小切片,不在一个域,跨域了,跨域了。找了各种方法,发现通过代理访问比较靠谱。以下是操作步骤:

    ① 跨域,首先想到ArcGIS提供的跨域解决方法,详情戳链接,参照这个方法进行配置即可:

    https://blog.csdn.net/wpz0713/article/details/50245041

    ② 在继承WebTiledLayer的getTileUrl方法时,返回图片URL前加上代理地址,例如:

    <pre style="margin: 0px; padding: 0px; white-space: pre-wrap; word-wrap: break-word; font-family: "Courier New" !important; font-size: 12px !important;">getTileUrl: function (level, row, col) { return "http://192.168.0.117:8080/Java/proxy.jsp?"+"http://t" + row % 8 + ".tianditu.cn/cva_c/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=cva&STYLE=default&TILEMATRIXSET=c&TILEMATRIX=" + level + "&TILEROW=" + row + "&TILECOL=" + col + "&FORMAT=tiles";
    }</pre>

    现在来看看结果是什么:

    image

    看来,这个跨域方法并没有达到我们想要的效果,那么就改造吧,仔细看跨域的那个proxy.jsp,在fetchAndPassBackToClient方法内190行添加以下一行代码,允许跨域。

    clientResponse.setHeader("Access-Control-Allow-Origin","")*

    好了,大功告成,下图是截屏输出的图片:

    image

    另外,在简单补一补跨域和代理的问题:https://www.cnblogs.com/fanyx/p/5775939.html


    '猴妹'师妹技术交流QQ:446412700

    备注:团队承接webgis/gis毕业设计以及webgis项目等业务,欢迎有相关需求的客户来咨询
    GIS之家接受webgis开发遇到的技术疑点难点在线咨询收费模式,有需要的加QQ:406503412,具体详情见:咨询模式
    GIS作品:GIS之家
    GIS之家知乎专栏:GIS之家知乎专栏
    GIS之家交流群一:432512093(已满)
    GIS之家交流群二:296438295(已满)
    GIS之家交流群三:632467934

    相关文章

      网友评论

      • 7d8366b4f915:楼主老哥~
        我截图出来了,但是arcgis 的服务与天地图的底图差生了错位是什么原因。不截图情况下,地图上显示是正常的。
      • IT人故事会:谢谢分享已经收藏了。

      本文标题:arcgis api for js入门开发系列二十打印地图的那些

      本文链接:https://www.haomeiwen.com/subject/nizchftx.html