JS下载地图离线数据,前端下载谷歌离线地图
去年做了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> <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
總結
以上是生活随笔為你收集整理的JS下载地图离线数据,前端下载谷歌离线地图的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 软件技术基础
- 下一篇: root + vm vh 实现响应式字体