arcgis for js4.xx 打印地图模仿GIS打印出图

原理:是使用地图的view.takeScreenshot方法返回地图的图像,再创建一个新的画布,然后把生成的地图图形putImageData到画布里。

效果图:(图上黑色是后来编辑添加上去的,怕涉密,哈哈!)

 

 

开始打印出图:


    /**
     * 开始执行打印出图
     * @param {*} priter_width 设置图片的宽度
     * @param {*} priter_height 设置图片的高度
     * @param {*} pixelRatio 分辨率
     */
    function startPrint(priter_width, priter_height, pixelRatio) {
        require(["esri/geometry/Point",
            "esri/geometry/support/webMercatorUtils",
            "utils/GisCommon"], function (Point, webMercatorUtils, GisCommon) { /* code goes here */
                //把度格式分为度分秒的接口
                var gisUnit = new GisCommon();
                var c = document.createElement("CANVAS");
                c.id = "printC";
                //document.body.appendChild(c);              
                if (true) {
                    var options = {
                        width: priter_width * pixelRatio,
                        height: priter_height * pixelRatio
                    };
                    //selectExtent 使用GIS的draw的Rect框选出的范围extent
                    if (selectExtent) {
                        //把点坐标转为平面坐标
                        var ltPoint = new Point({ x: selectExtent.xmin, y: selectExtent.ymax });
                        var _ltPoint = viewer.toScreen(ltPoint);
                        //设置打印的平面范围xy与大小
                        options = {};
                        options.area = {
                            x: _ltPoint.x,
                            y: _ltPoint.y,
                            width: priter_width * pixelRatio,
                            height: priter_height * pixelRatio
                        }
                    }
                    /* if(viewer.map.layers.length){
                        options.layers = viewer.map.layers;
                    } */
                    viewer.takeScreenshot(options).then(function (screenshot) {
                        var cWidth = screenshot.data.width;
                        var cheight = screenshot.data.height;
                        //第一个框的边距
                        var padding = (widgetConfig.mapborder && widgetConfig.mapborder.padding) ? widgetConfig.mapborder.padding : 10;
                        //内外边框的间隔
                        var borderWidth = (widgetConfig.mapborder && widgetConfig.mapborder.borderWidth) ? widgetConfig.mapborder.borderWidth : 50;
                        //标题高度
                        var titleHeight = (widgetConfig.mapborder && widgetConfig.mapborder.titleHeight) ? widgetConfig.mapborder.titleHeight : 25;

                        cWidth = cWidth + borderWidth + padding
                        cheight = cheight + borderWidth + padding + titleHeight;

                        c.width = cWidth;
                        c.height = cheight;
                        c.style.backgroundColor = "#FFF";
                        var ctx = c.getContext("2d");
                        ctx.rect(0, 0, cWidth, cheight);
                        ctx.fillStyle = "#FFF";
                        ctx.fill();
                        ctx.putImageData(screenshot.data, (padding + borderWidth) / 2, (padding + borderWidth) / 2 + titleHeight);
                        drawCanvas(c, ctx, cWidth, cheight, padding, titleHeight, borderWidth, webMercatorUtils, gisUnit);

                    });
                }
            });
    }

 制作图片的内容方法:

/**
     * 生成Canvas
     * @param {*} c 创建的Canvas
     * @param {*} ctx  Canvas的2D内容 
     * @param {*} cWidth 图片宽度
     * @param {*} cheight 图片高度
     * @param {*} padding 边距
     * @param {*} titleHeight 标题高度
     * @param {*} borderWidth 内外边框的间隔
     * @param {*} webMercatorUtils 
     * @param {*} gisUnit 
     */
    function drawCanvas(c, ctx, cWidth, cheight, padding, titleHeight, borderWidth, webMercatorUtils, gisUnit) {
        var box = 2, box2 = 5;
        var sleep = 0;
        var nx = (padding / 2) + (borderWidth / 2), ny = (padding + borderWidth) / 2 + titleHeight;
        var nwidth = cWidth - padding - borderWidth, nheight = cheight - padding - titleHeight - borderWidth;
        ctx.strokeStyle = '#000'; //strokeStyle设置边框颜色
        //绘制外边框
        if (borderWidth > 0) {
            ctx.strokeRect((padding / 2), (padding / 2) + titleHeight, cWidth - padding, cheight - padding - titleHeight);
        }
        //绘制内边框
        ctx.strokeRect(nx, ny, nwidth, nheight);
        ctx.fillStyle = "#000";
        ctx.textBaseline = "alphabetic";
        ctx.texAlign = "center";
        ctx.font = "bold 20px SimSun";
        ctx.fillText($('.priter-title').val(), (cWidth / 2), titleHeight);
        //显示内框四角坐标
        if (true || widgetConfig.mapborder && widgetConfig.mapborder.bboxCoord) {
            var extent = selectExtent == null ? webMercatorUtils.webMercatorToGeographic(viewer.extent) : selectExtent;
            //左上角坐标
            ctx.font = "14px SimSun";
            ctx.fillText(gisUnit.formatDegree(extent.xmin, true), nx + box2, ny - box);
            ctx.save();
            var lbl = gisUnit.formatDegree(extent.ymax, true);
            var strwidth = ctx.measureText(lbl).width;
            ctx.translate(nx - box2, ny + strwidth);
            f(-90, lbl);
            ctx.restore();
            //右上角坐标
            ctx.fillText(gisUnit.formatDegree(extent.xmax, true), nx + nwidth - strwidth - box2 * 2, ny - box);
            ctx.save();
            ctx.translate(nx + nwidth + box2 * 2.5, ny + strwidth);
            f(-90, lbl);
            ctx.restore();
            //左下角坐标
            ctx.fillText(gisUnit.formatDegree(extent.xmin, true), nx, ny + nheight + box2 * 2.5);
            lbl = gisUnit.formatDegree(extent.ymin, true);
            strwidth = ctx.measureText(lbl).width;
            ctx.save();
            ctx.translate(nx - box2, ny + nheight);
            f(-90, lbl);
            ctx.restore();
            //右下角坐标
            ctx.fillText(gisUnit.formatDegree(extent.xmax, true), nx + nwidth - strwidth - box2, ny + nheight + box2 * 2.5);
            ctx.save();
            ctx.translate(nx + nwidth + box2 * 2.5, ny + nheight);
            f(-90, lbl);
            ctx.restore();
        }
        //图例
        var leng = $(".esri-legend__service").parent();
        if ($(".esri-legend__service").length || (widgetConfig.mapborder && widgetConfig.mapborder.legend)) {
            ctx.save();
            ctx.fillStyle = "#FFF";
            var mn = 70;
            var lengy = ny + nheight - leng.height() + mn;
            var lengwidth = leng.width();
            var length2 = lengwidth / 3;
            var lengPadd = 10, lblheight = 22;
            ctx.fillRect(nx + 1, lengy, lengwidth + 1, leng.height() - mn);
            ctx.strokeRect(nx + 1, lengy, lengwidth + 1, leng.height() - mn);
            ctx.restore();
            ctx.save();
            ctx.fillStyle = "#000";
            ctx.textBaseline = "middle";
            ctx.texAlign = "center";
            var rowtotal = 0;
            var loadInt = 0;
            $(".esri-legend__service").each(function (i) {
                sleep++;
                var title = $(this).children()[0].innerHTML;
                var rows = $(this).children("div.esri-legend__layer").children().children("div.esri-legend__layer-body").children();
                var txty = lengy + lengPadd;
                if (i > 0) {
                    var liney = lengy + lengPadd + (lblheight * (i + 1)) + (rowtotal * 33);
                    txty = lengy + lengPadd + (lblheight * (i + 1)) + (rowtotal * 33) + 10;
                    ctx.beginPath();
                    ctx.moveTo(nx, liney);
                    ctx.lineTo(nx + lengwidth, liney);
                    ctx.stroke();
                }
                ctx.font = "bold 14px SimSun";
                ctx.fillText(title, nx + 5 + length2, txty);
                rowtotal += rows.length; 
                ctx.font = "12px SimSun";
                ctx.save();
                ctx.textBaseline = "Top";
                rows.map(function (index, row) {
                    var svg = $(row).find("svg");
                    var svgimg = new Image();
                    var rowname = $($(row).children()[1]).html();
                    var serializer = new XMLSerializer()
                    var toExport = svg[0].cloneNode(true); // 克隆
                    var bb = svg[0].getBBox(); // getBBox方法返回一个包含svg元素的最小矩形的坐标对象。 包含(x,y)、width、height 需要用来解决svg中的图超出边界时无法全部完整保存问题
                    toExport.setAttribute('viewBox', (bb.x - 20) + ' ' + (bb.y - 20) + ' ' + (bb.width + 40) + ' ' + (bb.height + 40)); // 重新设置svg目前的视口
                    toExport.setAttribute('width', bb.width + 36); // 重新设置svg目前的宽度
                    toExport.setAttribute('height', bb.height + 36); // 重新设置svg目前的高度
                    var source = '<?xml version="1.0" standalone="no"?>\r\n' + serializer.serializeToString(toExport);
                    svgimg.src = "data:image/svg+xml;charset=utf-8," + encodeURIComponent(source);
                    svgimg.alt = escape2Html(rowname);
                    svgimg.setAttribute("name", txty);
                    svgimg.setAttribute("i", i);
                    svgimg.setAttribute("index", index);
                    svgimg.onload = function (evt) {
                        var numser = parseInt($(evt.target).attr("name"));
                        var iI = parseInt($(evt.target).attr("i"));
                        var indexI = parseInt($(evt.target).attr("index"));
                        var svgy = numser + (23 * indexI);
                        ctx.drawImage(svgimg, nx, svgy + (indexI * 10));
                        //ctx.save();
                        ctx.fillText($(evt.target).attr("alt"), nx + svgimg.width - 8, svgy + (svgimg.height / 2) + 5 + (indexI * 10));
                        loadInt++;
                        if (loadInt == rowtotal) {
                            exportRaw("printer.png", c.toDataURL());
                        }
                    }
                });
            });
            ctx.restore();
        }
        //指北针
        if (true || widgetConfig.mapborder && widgetConfig.mapborder.compass) {
            ctx.save();
            //<img id="zhibeiz" src="images/zhibeiz64.png" style="display: none;" />
            var img = document.getElementById("zhibeiz");
            ctx.drawImage(img, nx + nwidth - 150, ny + 60);
            ctx.restore();
        }
        //比例尺
        if (true || widgetConfig.mapborder && widgetConfig.mapborder.scale) {
            ctx.save();
            var scale = "1:" + (viewer.scale).toFixed("");
            ctx.fillStyle = "#FFF";
            ctx.fillRect((cWidth / 2), ny + nheight - 25, ctx.measureText(scale).width + 10, 25);
            ctx.strokeRect((cWidth / 2), ny + nheight - 25, ctx.measureText(scale).width + 10, 25);

            ctx.fillStyle = "#000";
            ctx.textBaseline = "middle";
            ctx.texAlign = "center";
            ctx.fillText(scale, (cWidth / 2) + 5, ny + nheight - 12);
            ctx.restore();
        }
        if (sleep == 0) { exportRaw("printer.png", c.toDataURL()); }
        function f(i, txt) {
            var deg = Math.PI / 180 * i
            ctx.rotate(deg)
            /**
                1. 中心点移动到文字正中
                2. 坐标(0,0)时,中心点为文字左下角点
                3. 所以:横坐标左移一半长,纵坐标下移一半宽
            */
            ctx.fillText(txt, 0, 0);
        }
    }

 

/**
     * html编码转html字符
     * @param {*} str 
     * @returns 
     */
    function escape2Html(str) {
        var arrEntities={'lt':'<','gt':'>','nbsp':' ','amp':'&','quot':'"'};
        return str.replace(/&(lt|gt|nbsp|amp|quot);/ig,function(all,t){return arrEntities[t];});
    }

 导出下载图片:

function fakeClick(obj) {
        var ev = document.createEvent("MouseEvents");
        ev.initMouseEvent("click", true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
        obj.dispatchEvent(ev);
        selectExtent = null;
    }
    function exportRaw(name, data) {
        //var urlObject = window.URL || window.webkitURL || window;
        //var export_blob = new Blob([data]);
        var save_link = document.createElementNS("http://www.w3.org/1999/xhtml", "a")
        save_link.href = data;//urlObject.createObjectURL(export_blob);
        save_link.download = name;
        fakeClick(save_link);
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值