Java vue天地图离线开发

27,789次阅读
没有评论

共计 9756 个字符,预计需要花费 25 分钟才能阅读完成。

一、应用场景:

基于天地图开发时需要远程调用天地图的 js、css 以及各层级瓦片数据,但是在内网环境或者非互联网环境下无法远程访问资源,下面详细介绍本人离线开发的步骤。


二、天地图资源下载

1. 天地图 key 申请

进入天地图网址天地图 API。

Java vue 天地图离线开发

点击“控制台”进行账号注册,注册成功后,点击右上角“创建新应用”,得到 Key 名称。

Java vue 天地图离线开发

2. 天地图 js、css 资源下载

需要下载的天地图静态资源包括:

tiandituApi.js(http://api.tianditu.gov.cn/api?v=4.0&tk=)

components.js(https://api.tianditu.gov.cn/v4.0/components.js)

military.js(https://api.tianditu.gov.cn/v4.0/military.js)

service.js(https://api.tianditu.gov.cn/v4.0/service.js)

tianditu4.0.css(http://api.tianditu.gov.cn/v4.0/css/tianditu4.0.css)

将四个文件的代码复制到本地。

3. 天地图瓦片数据下载

在天地图官网,点击“地图 API”。

Java vue 天地图离线开发

网站最下面有个瓦片数据连接地址。

Java vue 天地图离线开发

但是不同的瓦片有不同的下载地址,上两张图中有瓦片的分类,包括:矢量底图、矢量注记、影像底图等等,不同的瓦片图不同的下载地址。

如果根据瓦片地址一个个去下载,工作量巨大,而且各个点位不清晰,无法采用人工方式去下载,我们可以使用 java 代码去统一抓取瓦片数据。

java 抓取瓦片代码:

public class TileDownload {

    // 不同的瓦片采用不同的下载地址,一般用的比较多的还是矢量地图
    // 矢量(行政)- 等经纬度
    public static String vec_c = "http://{server}.tianditu.gov.cn/vec_c/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=vec&STYLE=default&TILEMATRIXSET=c&FORMAT=tiles&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}&tk={tk}";
    // 矢量(行政)- 墨卡托
    public static String vec_w = "http://{server}.tianditu.gov.cn/vec_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=vec&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}&tk={tk}";
    // 矢量注记(行政)- 等经纬度
    public static String cva_c = "http://{server}.tianditu.gov.cn/cva_c/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=cva&STYLE=default&TILEMATRIXSET=c&FORMAT=tiles&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}&tk={tk}";
    // 矢量注记(行政)- 墨卡托
    public static String cva_w = "http://{server}.tianditu.gov.cn/cva_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=cva&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}&tk={tk}";

    // 影像 - 等经纬度
    public static String img_c = "http://{server}.tianditu.gov.cn/img_c/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=img&STYLE=default&TILEMATRIXSET=c&FORMAT=tiles&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}&tk={tk}";
    // 影像 - 墨卡托
    public static String img_w = "http://{server}.tianditu.gov.cn/img_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=img&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}&tk={tk}";
    // 影像注记 - 等经纬度
    public static String cia_c = "http://{server}.tianditu.gov.cn/cia_c/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=cia&STYLE=default&TILEMATRIXSET=c&FORMAT=tiles&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}&tk={tk}";
    // 影像注记 - 墨卡托
    public static String cia_w = "http://{server}.tianditu.gov.cn/cia_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=cia&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}&tk={tk}";

    // 地形 - 等经纬度
    public static String ter_c = "http://{server}.tianditu.gov.cn/ter_c/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=ter&STYLE=default&TILEMATRIXSET=c&FORMAT=tiles&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}&tk={tk}";
    // 地形 - 墨卡托
    public static String ter_w = "http://{server}.tianditu.gov.cn/ter_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=ter&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}&tk={tk}";
    // 地形注记 - 等经纬度
    public static String cta_c = "http://{server}.tianditu.gov.cn/cta_c/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=cta&STYLE=default&TILEMATRIXSET=c&FORMAT=tiles&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}&tk={tk}";
    // 地形注记 - 墨卡托
    public static String cta_w = "http://{server}.tianditu.gov.cn/cta_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=cta&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}&tk={tk}";

    public static String[] servers = {"t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7"};


    public static void main(String[] args){
        String basePath = "D:/lianyungangtianditu";// 设置下载的路径

        // 这里放你的天地图开发者秘钥,注意天地图 API 访问次数限制
        String tk = "1125258295c5d403d7fbf5e096***";

        // 将需要下载的图层地址放到一个数组中,不需要下载的可以去掉
        String[] urlArr = {vec_c, vec_w, cva_c, cva_w, img_c, img_w, cia_c, cia_w, ter_c, ter_w, cta_c, cta_w};

        // 天地图一共有 18 个图层,从 1 -18,越往后,瓦片数据量越大
        int minZoom = 1;
        int maxZoom = 18;
        // 中国的经纬度
        //double startLat = 53.58;// 开始纬度(从北到南)//double endLat = 2.7;// 结束纬度(从北到南)//double startLon = 73.2;// 开始经度(从西到东)//double endLon = 135.15;// 结束经度(从西到东)// 江苏连云港的经纬度,这边经纬度可以根据自己需要下载的地市或者省份去百度查询经纬度信息,我这边只下载连云港
        double startLat = 35.07;// 开始纬度(从北到南)double endLat = 34.12;// 结束纬度(从北到南)double startLon = 118.24;// 开始经度(从西到东)double endLon = 119.48;// 结束经度(从西到东)ExecutorService exe = Executors.newFixedThreadPool(15);
        for(int i=0; i -1){out.write(b, 0, len);
                                                    out.flush();}
                                                out.close();
                                                in.close();
                                                loop = false;
                                            } catch (Exception e) {loop = true;}
                                        }
                                        if(loop){System.out.println("下载失败:"+newUrl);
                                            System.exit(0);// 下载失败后停止任务
                                        }
                                    }
                                }
                            });
                        }
                    }
                }
            }else{
                // 墨卡托
                if(startLat> 85.051128){startLat = 85.051128;}
                if(endLat  -1){out.write(b, 0, len);
                                                    out.flush();}
                                                out.close();
                                                in.close();
                                                loop = false;
                                            } catch (Exception e) {loop = true;}
                                        }
                                        if(loop){System.out.println("下载失败:"+newUrl);
                                            System.exit(0);// 下载失败后停止任务
                                        }
                                    }
                                }
                            });
                        }
                    }
                }
            }
        }
        exe.shutdown();
        while (true) {
            try {Thread.sleep(1000L);
            } catch (InterruptedException e) { }
            if (exe.isTerminated()) {break;}
        }
    }


    public static InputStream getFileInputStream(String url) throws Exception{
        InputStream is = null;
        CloseableHttpClient httpclient = HttpClients.createDefault();
        HttpGet request = new HttpGet(url);
        request.setHeader("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)");
        HttpResponse response = httpclient.execute(request);
        response.setHeader("Content-Type", "application/octet-stream");
        int statusCode = response.getStatusLine().getStatusCode();
        if (statusCode == HttpStatus.SC_OK) {HttpEntity entity = response.getEntity();
            is = entity.getContent();}
        return is;
    }




}

下载的时间会特别长,下载后的文件路径如下:

Java vue 天地图离线开发

4. 瓦片下载问题汇总

问题一:下载失败

解决:将代码中 tk 变量改成自己申请的 key。

问题二:下载中断

解决:下载中断的原因是 key 的访问次数受限制,个人 key 每天只能访问 1 万次,如果中途下载终端,只需要再次新建应用,采用新应用的 key 进行再次访问,每个账号可以申请五个 key 信息。

问题二:中断后重新下载,又会重头开始下载

解决一:根据下载的瓦片层级,需要手动调整代码,如果需要可以直接问我;

解决二:采用下面的实时加载方法,下面有介绍。

三、Java 后端读取瓦片数据

瓦片数据下载成功后,前端需要访问数据库加载瓦片信息,代码如下:

@GetMapping("getTiles/{LAYER}")
    public void getTiles(HttpServletResponse response, @PathVariable("LAYER") String LAYER,
                         @RequestParam("TILECOL") String TILECOL,
                         @RequestParam("TILEROW") String TILEROW,
                         @RequestParam("TILEMATRIX")String TILEMATRIX) throws IOException {

        String tilesPath = "D:lianyungangtianditu";
        String tk = "e4237d5eefb7b69a4a472fd64f***";
        ServletOutputStream out = null;
        try {BufferedImage image = ImageIO.read(Files.newInputStream(Paths.get(tilesPath + "/" + LAYER + "/" + TILEMATRIX + "/" + TILEROW + "/" + TILECOL + ".png")));
            response.setContentType("image/png");
            response.setHeader("Cache-Control", "public");
            out = response.getOutputStream();
            ImageIO.write(image, "png", out);
        } catch (Exception e) {response.setStatus(HttpServletResponse.SC_NOT_FOUND);
        } finally {if (out != null) {out.flush();
                out.close();}
        }
    }

代码采用 restful 风格,四个参数分别为:

LAYER:瓦片类型(cva_c、cva_w、vec_c 等)

TILEMATRIX、TILEROW 代表:当前瓦片类型下的文件夹

TILECOL 代表:瓦片号

四、Vue 前端静态资源修改

1. 引入天地图.js

在 vue 的 index.html 中分别引入之前下载的 4 个 js 文件和 css 文件。





2. 修改 tiandituApi.js

天地图 js 文件默认远程访问瓦片数据,需要将远程访问瓦片的方式改成访问本地瓦片。

Java vue 天地图离线开发

定义一个本地服务器的变量,将需要访问的瓦片请求链接修改成刚刚我们自己写的后端请求路径。

// 定义一个本地服务器地址变量
window.TMAP_URL = 'http://localhost:8080/tiles';


// 修改 js 中瓦片访问地址,本人只用了天地图的矢量瓦片,所以其他的就不需要修改了
r:function(){return window.TMAP_URL+"/getTiles/vec_c?"},
T:function(){return window.TMAP_URL+"/getTiles/cva_c?"},
t:function(){return window.TMAP_URL+"/getTiles/vec_w?"},
Y:function(){return window.TMAP_URL+"/getTiles/cva_w?"}

以上就是整个方案的修改。

 

五、瓦片实时加载(有需要再用)

问题:当使用 java 方法进行下载瓦片数据时,受限于 key 的访问次数限制、天地图图层数等原因,尤其是到最后面,图层越高,瓦片数据量越大,会导致下载中断。

解决:可以采用按需加载的方式,在地图进行访问的时候,根据访问的位置,进行实时下载瓦片到本地。代码如下:

@RestController
public class MapController {



    /**
     *
     * @param response
     * @param LAYER
     * @param TILECOL
     * @param TILEROW
     * @param TILEMATRIX
     * @throws IOException
     */
    @GetMapping("getTiles/{LAYER}")
    public void getTiles(HttpServletResponse response, @PathVariable("LAYER") String LAYER,
                         @RequestParam("TILECOL") String TILECOL,
                         @RequestParam("TILEROW") String TILEROW,
                         @RequestParam("TILEMATRIX")String TILEMATRIX) throws IOException {

        String tilesPath = "D:lianyungangtianditu";
        String tk = "e4237d5eefb7b69a4a472fd64f***";
        ServletOutputStream out = null;
        try {BufferedImage image = ImageIO.read(Files.newInputStream(Paths.get(tilesPath + "/" + LAYER + "/" + TILEMATRIX + "/" + TILEROW + "/" + TILECOL + ".png")));

            if(null!=imageGary){image=imageGary;}*/

            response.setContentType("image/png");
            response.setHeader("Cache-Control", "public");
            out = response.getOutputStream();
            ImageIO.write(image, "png", out);
        } catch (Exception e) {
            // 如果没有找到图片,就去下载,然后保存进去
            //response.setStatus(HttpServletResponse.SC_NOT_FOUND);
            this.saveImg(tilesPath, LAYER, TILEMATRIX, TILEROW, TILECOL, tk);
            response.setStatus(HttpServletResponse.SC_NOT_FOUND);
        } finally {if (out != null) {out.flush();
                out.close();}
        }
    }

    public void saveImg(String path, String layer, String TILEMATRIX, String TILEROW, String TILECOL, String tk){StringBuffer sb = new StringBuffer();
        sb.append("http://t0.tianditu.gov.cn/")
                .append(layer);
        if (layer.equals("cva_w") || layer.equals("cva_c")){sb.append("/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=cva&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles");
        }else {sb.append("/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=vec&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles");
        }
        sb.append("&TILEMATRIX=").append(TILEMATRIX)
                .append("&TILEROW=").append(TILEROW)
                .append("&TILECOL=").append(TILECOL)
                .append("&tk=").append(tk);
        System.out.println(sb.toString());

        String filePath = path + "/" + layer + "/" + TILEMATRIX + "/" + TILEROW + "/" + TILECOL + ".png";

        File file = new File(filePath);
        if(!file.exists()){if(!file.getParentFile().exists()){file.getParentFile().mkdirs();}
            try {InputStream in = getFileInputStream(sb.toString());
                OutputStream out = new BufferedOutputStream(new FileOutputStream(file));
                byte[] b = new byte[8192];
                int len = 0;
                while((len = in.read(b)) > -1){out.write(b, 0, len);
                    out.flush();}
                out.close();
                in.close();} catch (Exception e) {}}

    }

    public static InputStream getFileInputStream(String url) throws Exception{
        InputStream is = null;
        CloseableHttpClient httpclient = HttpClients.createDefault();
        HttpGet request = new HttpGet(url);
        request.setHeader("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)");
        HttpResponse response = httpclient.execute(request);
        response.setHeader("Content-Type", "application/octet-stream");
        int statusCode = response.getStatusLine().getStatusCode();
        if (statusCode == HttpStatus.SC_OK) {HttpEntity entity = response.getEntity();
            is = entity.getContent();}
        return is;
    }


}

 

 

原文地址: Java vue 天地图离线开发

    正文完
     0
    Yojack
    版权声明:本篇文章由 Yojack 于2024-11-10发表,共计9756字。
    转载说明:
    1 本网站名称:优杰开发笔记
    2 本站永久网址:https://yojack.cn
    3 本网站的文章部分内容可能来源于网络,仅供大家学习与参考,如有侵权,请联系站长进行删除处理。
    4 本站一切资源不代表本站立场,并不代表本站赞同其观点和对其真实性负责。
    5 本站所有内容均可转载及分享, 但请注明出处
    6 我们始终尊重原创作者的版权,所有文章在发布时,均尽可能注明出处与作者。
    7 站长邮箱:laylwenl@gmail.com
    评论(没有评论)