JS下载地图离线数据,前端下载谷歌离线地图

news/2024/11/29 3:45:01/

去年做了java下载天地图数据的工具,由于每次都要手动查找再更改经纬度范围,用着不太方便,正好前段时间学习了JS打包下载文件的技术,于是花了点时间做了这个前端配置选择地图信息并下载离线地图的工具。

不过经实际测试,天地图数据通过JS下载时会报403拒绝访问,因为天地图服务端会识别出数据pa取并拒绝访问(应该是请求头或者什么的有特殊的识别码)

不过fan墙下载谷歌卫星地图是非常奈斯的。

注:JS下载不能完美解决跨域问题,但是对于需要浏览器代理访问的地图源是非常友好的。

请看示例:


 HTML部分代码:

<body><div class="content"><div class="title">地图源设置</div><div class="optionGroup"><div class="option"><div class="left">地图URL:</div><div class="right"><input type="text" style="width:500px" id="mapUrl" value="https://khms{s}.google.com/kh/v=930?x={x}&y={y}&z={z}"/><label class="detail">示例:https://khms{s}.google.com/kh/v=930?x={x}&y={y}&z={z}。其中{s}是可选的,若存在将使用主机编号值;{x}、{y}、{z}是必不可少的。</label></div></div><div class="option"><div class="left">主机编号[开始]:</div><div class="right"><input type="text" id="minServer" style="width:80px;" value="0" oninput="this.value=this.value.replace(/[^\d]/g,'')"></div></div><div class="option"><div class="left">主机编号[结束]:</div><div class="right"><input type="text" id="maxServer" style="width:80px;" value="3" oninput="this.value=this.value.replace(/[^\d]/g,'')"></div></div><div class="option"><div class="left">最大级别:</div><div class="right"><select id="maxZoom"><option value="1">1</option><option value="2">2</option><option value="3">3</option><option value="4">4</option><option value="5">5</option><option value="6">6</option><option value="7">7</option><option value="8">8</option><option value="9">9</option><option value="10">10</option><option value="11">11</option><option value="12">12</option><option value="13">13</option><option value="14">14</option><option value="15">15</option><option value="16">16</option><option value="17">17</option><option value="18" selected="selected">18</option><option value="19">19</option><option value="20">20</option><option value="21">21</option><option value="22">22</option><option value="23">23</option><option value="24">24</option><option value="25">25</option></select></div></div><div class="option"><div class="left">投影类型:</div><div class="right"><input type="radio" name="projection" value="mkt" checked="cheched"><label>墨卡托</label>&nbsp;&nbsp;<input type="radio" name="projection" value="lonlat"><label>等经纬度</label></div></div><div class="option"><div class="left">图片大小:</div><div class="right"><input type="radio" name="tileSize" value="256" checked="cheched">256像素</div></div></div><div class="title">下载设置</div><div class="optionGroup"><div class="option"><div class="left">下载级别[开始]:</div><div class="right"><input type="text" id="startZoom" style="width:80px;" value="1" oninput="this.value=this.value.replace(/[^\d]/g,'')"></div></div><div class="option"><div class="left">下载级别[结束]:</div><div class="right"><input type="text" id="endZoom" style="width:80px;" value="7" oninput="this.value=this.value.replace(/[^\d]/g,'')"></div></div><div class="option" style="height:120px;"><div class="left">下载范围:</div><div class="right" style="height:120px;"><div style="float:left;width:200px;height:120px;border-right:dotted 1px #888;">左上角纬度:<input type="text" id="maxLat" style="width:80px;" value="41" oninput="this.value=this.value.replace(/[^\d.]/g,'')"></br>左上角经度:<input type="text" id="minLon" style="width:80px;" value="115" oninput="this.value=this.value.replace(/[^\d.]/g,'')"></br>右下角纬度:<input type="text" id="minLat" style="width:80px;" value="39" oninput="this.value=this.value.replace(/[^\d.]/g,'')"></br>右下角经度:<input type="text" id="maxLon" style="width:80px;" value="118" oninput="this.value=this.value.replace(/[^\d.]/g,'')"></br></div><div class="button" id="chooesRange" style="float:left;width:auto;height:26px;padding:0px 10px;margin-top:90px;font:normal 14px/26px '微软雅黑';color:#333;background:#ccc;border-radius:3px;cursor:pointer">框选地图范围</div></div></div><div class="option"><div class="left">保存格式:</div><div class="right"><input type="radio" name="imageFormat" value="jpg" checked="cheched">jpg</div></div><div class="option"><label class="detail" style="color:red;">注:文件将{yyyyMMddHHmmss}.zip格式命名打包下载,其中瓦片数据文件存放规则为{z}/{y}/{x}.jpg</label></div></div><div class="buttonGroup"><div class="button" id="checkMap">验证地图配置</div><div class="button" id="downloadMap">开始下载</div></div></div><div class="mark" id="mark"></div><div class="mapView" id="mapView"><div class="view-top"><div class="label" id="view-title">验证地图配置</div><div class="view-close" id="view-close"></div></div><div class="view-content"><div id="mapDiv"></div><div class="drawUtil" id="drawUtil"><div class="button" id="submit">确定</div><div class="button" id="redraw">重新框选</div></div><div class="bottomUtil"><div id="currentZoom"></div><div id="currentCoordinate"></div></div></div></div><div class="waitMark" id="waitMark"><div class="waitInfo" id="waitInfo">处理中,请稍等...</div></div>
</body>

CSS部分代码:

<style>body{min-width:720px;padding:20px;position:relative;}.title{width:100%;height:40px;text-align:left;font:bold 18px/40px '微软雅黑';}.optionGroup{width:100%;height:auto;padding:10px;}.option{width:100%;height:auto;min-height:30px;}.option .left{float:left;width:160px;height:auto;min-height:30px;text-align:right;font:normal 16px/30px '微软雅黑';}.option .right{float:left;width:calc(100% - 305px);padding-left:5px;height:auto;min-height:30px;font:normal 14px/30px '微软雅黑';}.option .right input[type="text"]{height:22px;padding:1px 2px;margin-top:2px;border:solid 1px #555;border-radius:3px;}.option .detail{width:auto;height:auto;min-height:30px;height:30px;text-align:left;padding-left:10px;font:normal 14px/30px '微软雅黑';color:#888;}.buttonGroup{width:100%;height:30px;padding:10px;margin-top:20px;}.button{float:left;width:auto;height:30px;padding:0px 20px;margin-left:40px;font:normal 16px/30px '微软雅黑';color:#ffffff;background:#0075ff;border-radius:3px;cursor:pointer}.mark{width:100%;height:100%;background:rgba(0,0,0,0.7);position:fixed;top:0px;left:0px;display:none;z-index:100;}.mapView{width:90%;height:80%;background:#fff;position:fixed;top:10%;left:5%;border-radius:3px;overflow:hidden;display:none;z-index:1001;}.mapView .view-top{width:100%;height:29px;background:#e4e7eb;border-bottom:solid 1px #fff;}.mapView .view-top .label{float:left;width:auto;height:29px;margin-left:10px;font:normal 14px/30px '微软雅黑';color:#333;}.mapView .view-top .view-close{float:right;width:30px;height:30px;font:normal 18px/30px '微软雅黑';color:#888;text-align:center;cursor:pointer;}.mapView .view-top .view-close:before{content:"\2716";font:normal 18px/30px '微软雅黑';color:#888;text-align:center;}.mapView .view-top .view-close:hover:before{content:"\2716";font:normal 18px/30px '微软雅黑';color:#f00;text-align:center;}.mapView .view-content{width:100%;height:calc(100% - 30px);position:relative;}.mapView .view-content #mapDiv{width:100%;height:100%;}.mapView .view-content .drawUtil{width:100%;height:50px;position:absolute;right:0px;bottom:30px;z-index:1999;pointer-events:none;display:none;}.mapView .view-content .drawUtil #submit{float:right;margin:0px;margin-right:20px;pointer-events:auto;}.mapView .view-content .drawUtil #redraw{float:right;margin:0px;margin-right:20px;pointer-events:auto;}.mapView .view-content .bottomUtil{width:100%;height:30px;position:absolute;left:0px;bottom:0px;z-index:1999;pointer-events:none;background:rgba(255,255,255,0.5);}.mapView .view-content .bottomUtil #currentZoom{float:left;width:auto;height:30px;margin-left:30px;font:normal 14px/30px '微软雅黑';color:#000;}.mapView .view-content .bottomUtil #currentCoordinate{float:left;width:auto;height:30px;margin-left:30px;font:normal 14px/30px '微软雅黑';color:#000;}.waitMark{width:100%;height:100%;background:rgba(0,0,0,0.7);position:fixed;top:0px;left:0px;display:none;cursor:wait;z-index:100;}.waitMark .waitInfo{width:100%;height:30px;position:fixed;top:calc(50% - 15px);left:0px;font:normal 14px/30px '微软雅黑';color:#fff;text-align:center;z-index:1001;}
</style>

JS部分代码(篇幅太长,截取小部分):

function downloadMap(){$("#waitInfo").html("处理中,请稍等...");var mapUrl = $("#mapUrl").val();var minServer = $("#minServer").val();var maxServer = $("#maxServer").val();var maxZoom = $("#maxZoom").val();var projection = $("input[name='projection']").val();var serverArr = [];if(typeof(mapUrl)=="undefined" || mapUrl==null || mapUrl==""){alert("请输入地图连接");return false;}if(mapUrl.indexOf("{s}") > -1){var isServerOk = true;try{minServer = parseInt(minServer);maxServer = parseInt(maxServer);}catch(e){isServerOk = false;}if(isServerOk){for(var i=minServer; i<=maxServer; i++){serverArr.push(i+"");}}else{alert("主机编号设置错误");return false;}if(serverArr.length == 0){alert("主机编号设置错误");return false;}}var imageFormat = $("input[name='imageFormat']").val();var startLat = parseFloat($("#maxLat").val());//左上角纬度:开始纬度(从北到南)var endLat = parseFloat($("#minLat").val());//右下角纬度:结束纬度(从北到南)var startLon = parseFloat($("#minLon").val());//左上角经度:开始经度(从西到东)var endLon = parseFloat($("#maxLon").val());//右下角经度:结束经度(从西到东)var minZoom = parseInt($("#startZoom").val());//下载级别[开始]var maxZoom = parseInt($("#endZoom").val());//下载级别[结束]if(typeof(startLat)=="undefined" || startLat==null || startLat==""){alert("请输入左上角纬度");return false;}if(typeof(startLon)=="undefined" || startLon==null || startLon==""){alert("请输入左上角经度");return false;}if(typeof(endLat)=="undefined" || endLat==null || endLat==""){alert("请输入右下角纬度");return false;}if(typeof(minZoom)=="undefined" || minZoom==null || minZoom==""){alert("请输入下载级别[开始]");console.log(22)return false;}if(typeof(maxZoom)=="undefined" || maxZoom==null || maxZoom==""){alert("请输入下载级别[结束]");return false;}zip = new JSZip();zipName = new Date().format('yyyyMMddHHmmss');fileFolder = zip.folder(zipName);fileList = [];fileCount = 0;allCount = 0;promiseArr = [];//异步代码集合if(projection == "lonlat"){//等经纬度//先计算出一共需要下载多少个for(var z=minZoom; z<=maxZoom; z++){var deg = 360.0 / Math.pow(2, z) / 256;//一个像素点代表多少度var startX = parseInt((startLon + 180) / deg / 256);//减数取整var endX = parseInt((endLon + 180) / deg / 256);//加数取整var startY = parseInt((90 - startLat) / deg / 256);var endY = parseInt((90 - endLat) / deg / 256);allCount += (endY-startY+1) * (endX-startX+1);}//再执行下载,下载是异步的,需要通过allCount判断是否全部下载完毕for(var z=minZoom; z<=maxZoom; z++){var deg = 360.0 / Math.pow(2, z) / 256;//一个像素点代表多少度var startX = parseInt((startLon + 180) / deg / 256);//减数取整var endX = parseInt((endLon + 180) / deg / 256);//加数取整var startY = parseInt((90 - startLat) / deg / 256);var endY = parseInt((90 - endLat) / deg / 256);for(var y=startY; y<=endY; y++){for(var x=startX; x<=endX; x++){var url = mapUrl.replace("{s}", serverArr[parseInt(Math.random()*serverArr.length)]).replace("{z}", z+"").replace("{y}", y+"").replace("{x}", x+"");var name = z+"/"+y+"/"+x+"."+imageFormat;savePictureZip(url, name);//savePictureZip2(url, name);}}}}else{//墨卡托//先计算出一共需要下载多少个for(var z=minZoom; z<=maxZoom; z++){var deg = 360.0 / Math.pow(2, z) / 256;//一个像素点代表多少度var startX = parseInt((startLon + 180) / deg / 256);var endX = parseInt((endLon + 180) / deg / 256);var startY = parseInt((parseInt(Math.pow(2, z) * 256 / 2) - parseInt((Math.log(Math.tan((90 + startLat) * Math.PI / 360)) / (Math.PI / 180)) / (360/Math.pow(2, z)/256) + 0.5)) / 256);var endY = parseInt((parseInt(Math.pow(2, z) * 256 / 2) - parseInt((Math.log(Math.tan((90 + endLat) * Math.PI / 360)) / (Math.PI / 180)) / (360/Math.pow(2, z)/256) + 0.5)) / 256);allCount += (endY-startY+1) * (endX-startX+1);}//再执行下载,下载是异步的,需要通过allCount判断是否全部下载完毕for(var z=minZoom; z<=maxZoom; z++){var deg = 360.0 / Math.pow(2, z) / 256;//一个像素点代表多少度var startX = parseInt((startLon + 180) / deg / 256);var endX = parseInt((endLon + 180) / deg / 256);var startY = parseInt((parseInt(Math.pow(2, z) * 256 / 2) - parseInt((Math.log(Math.tan((90 + startLat) * Math.PI / 360)) / (Math.PI / 180)) / (360/Math.pow(2, z)/256) + 0.5)) / 256);var endY = parseInt((parseInt(Math.pow(2, z) * 256 / 2) - parseInt((Math.log(Math.tan((90 + endLat) * Math.PI / 360)) / (Math.PI / 180)) / (360/Math.pow(2, z)/256) + 0.5)) / 256);for(var y=startY; y<=endY; y++){for(var x=startX; x<=endX; x++){var url = mapUrl.replace("{s}", serverArr[parseInt(Math.random()*serverArr.length)]).replace("{z}", z+"").replace("{y}", y+"").replace("{x}", x+"");var name = z+"/"+y+"/"+x+"."+imageFormat;savePictureZip(url, name);//savePictureZip2(url, name);}}}}var t = window.setInterval(function(){if(fileCount == allCount){$("#waitMark").css("display", "none");if(fileList.length < fileCount){alert("部分文件下载失败,请重新尝试下载");}window.clearInterval(t);}}, 50);
}function savePictureZip(url, name){try{var xhr = new XMLHttpRequest();xhr.open('get', url, true);xhr.responseType = 'blob';//二进制对象,binaryxhr.onload = function(){fileCount++;$("#waitInfo").html("正在下载:"+url);var blob = xhr.response;//response 属性返回响应的正文,取决于 responseType 属性。if(blob.type.indexOf("image") > -1){fileList.push({name: name, content: blob});if (fileCount==allCount && fileList.length==fileCount) {if (fileList.length > 0) {$("#waitInfo").html("正在打包");for (var k = 0; k < fileList.length; k++) {// 往文件夹中,添加个文件的数据fileFolder.file(fileList[k].name, fileList[k].content, {binary: true //二进制})}zip.generateAsync({type: 'blob'}).then(function(content){saveAs(content, zipName+'.zip');})}else{alert("没有文件");}$("#waitMark").css("display", "none");};}};xhr.ontimeout = function(){fileCount++;$("#waitInfo").html("正在下载:"+url);};xhr.onerror = function(){fileCount++;$("#waitInfo").html("正在下载:"+url);};xhr.send(null);}catch(e){}
}

完整代码请点击链接下载:https://download.csdn.net/download/qq_33427869/86790578

java下载天地图数据,天地图离线地图,可指定经纬度范围_RainingTime的博客-CSDN博客_天地图离线地图需要用到天地图开发者秘钥。注意天地图API访问次数限制。代码分享:import java.io.BufferedOutputStream;import java.io.File;import java.io.FileOutputStream;import java.io.InputStream;import java.io.OutputStream;import java.util.concurrent.ExecutorService;import java.util.concur..https://blog.csdn.net/qq_33427869/article/details/120347939


http://www.ppmy.cn/news/624863.html

相关文章

Chrome 离线下载最佳方法

工作原因&#xff0c;需要使用内网环境&#xff0c;操作系统是Ubuntu 20.4 ,自带浏览器是FirreFox ,因为长期使用Chrome&#xff0c;所以想在Ubuntu中安装Chrome&#xff0c;然而Chrome离线安装包官方没有明显提供地址。如何找到合适的Chrome安装包下载地址呢&#xff1f; 目的…

离线包简介

原文链接&#xff1a;https://help.aliyun.com/document_detail/59594.html 传统的 H5 技术容易受到网络环境影响&#xff0c;因而降低 H5 页面的性能。通过使用离线包&#xff0c;可以解决该问题&#xff0c;同时保留 H5 的优点。 离线包&#xff1a;是将包括 HTML、JavaScri…

注意营养,这可能是目前最好的离线下载方式

说到离线下载可能大家会想到BT、种子、磁力等词汇&#xff0c;这类链接资源非常丰富&#xff0c;但下载却很不方便 常见的下载工具如迅雷、uTorrent 、BitComet等&#xff0c;在遇到敏感资源、少种、S链等情况都很难正常下载 作为一个合格的LSJ&#xff0c;应对这类状况最好的…

chrome浏览器离线安装包下载地址

在谷歌官网下载的chrome浏览器&#xff0c;下载的是安装器&#xff0c;要通过联网安装&#xff0c;谷歌浏览器官网&#xff1a;https://www.google.com/intl/zh-CN/chrome/https://www.google.com/intl/zh-CN/chrome/ 最新版本的统一下载链接&#xff0c;通过以下链接下载的都是…

谷歌浏览器离线下载地址

谷歌浏览器离线下载地址 整理了一些可以直接下载 Google Chrome 离线完整包的地址&#xff1a; 官方渠道&#xff1a; 1、链接直接打开就可以下载&#xff0c;最新版实时更新。 32位&#xff08;x86&#xff09;&#xff1a;https://dl.google.com/tag/s/installdataindex/up…

react中父组件如何直接调用子组件的方法和属性,以及对比vue3.0父组件调用子组件的方法和属性

react中父组件如何直接调用子组件的方法和属性,以及对比vue3.0父组件调用子组件的方法和属性 react hookvue setup父组件子组件 react hook forwardRef(render) useImperativeHandle(ref, createHandle, dependencies?) import {forwardRef,useEffect,useImperativeHandle,u…

可视化大屏开发适配(二)

这是前一篇 “可视化大屏开发适配“ 文中提到的第二种transform:scale方法实现的大屏开发&#xff0c;在这分享给大家&#xff1b;至此 可视化大屏开发相对好用的两种方法都介绍完啦 【前端大屏实战1】VueEcharts-- 大屏自适应缩放解决方案 > 使用transform:scale &#xff…

变压器的试验原理及方法

规程规定它是变压器大修时、无载开关调级后、变压器出口短路后和3~5年1次等必试项目。 在变压器的所有试验项目中是一项较为方便而有效的考核绕组纵绝缘和电流回路连接状况的试验。它能够反映绕组匝间短路、绕组断股、分接开关接触状态以及导线电阻的差异和接头接触不良等缺陷…