一、前言
網上其實有很多各種各樣的離線地圖下載器,大部分都是要收費的,免費的要么是限制了下載的瓦片數量或者級別,要么是下載的瓦片圖打上了水印,看起來很難看,由於經常需要用到離線地圖,擺脫這個限制,特意花了點時間重新研究了瓦片地圖的原理,做了個離線地圖下載器,其實瓦片地圖下載沒有那么復雜,其實就是從開放的幾個服務器地址組建要請求的瓦片地圖的地址,發送請求以后會自動將圖片返回給你,你只需要拿到圖片數據保存成圖片即可。
瓦片地圖下載流程步驟如下:
- 獲取可視區域或者行政區域的范圍
- 拿到區域的左下角右上角經緯度坐標
- 根據層級數計算對應層級的瓦片數
- 自動生成下載瓦片地圖的地址並發出請求
- 解析收到的數據保存成圖片
- 更新對應界面的下載數量和進度
- 可選擇對應保存的目錄、全選層級、中途停止下載等
- 可選擇是下載街道圖還是衛星圖等
二、功能特點
- 多線程同步下載多級別瓦片地圖,不卡界面。
- 內置多個離線地圖下載請求地址,自動隨機選擇一個發送請求。
- 下載地圖類型同時支持街道圖和衛星圖。
- 自動計算可視區域或者行政區域的下載瓦片數量。
- 下載的級別可以自定義范圍和選擇。
- 每個瓦片下載完成都發送信號通知,參數包括下載用時。
- 可設置下載最大超時時間,超過了則丟棄跳到下一個下載任務。
- 實時顯示下載進度,以及當前級別已經下載的瓦片數和總瓦片數。
- 下載過程中可以停止下載,下載完成自動統計總用時。
- 內置經緯度和屏幕坐標互相轉換函數。
- 目前支持百度地圖,其他地圖比如谷歌地圖、騰訊地圖、高德地圖可以定制。
- 函數接口友好和統一,使用簡單方便,就一個類。
- 支持任意Qt版本、任意系統、任意編譯器。
三、體驗地址
- 體驗地址:https://pan.baidu.com/s/1ZxG-oyUKe286LPMPxOrO2A 提取碼:o05q 名稱:bin_map.zip
- 國內站點:https://gitee.com/feiyangqingyun
- 國際站點:https://github.com/feiyangqingyun
- 個人主頁:https://blog.csdn.net/feiyangqingyun
- 知乎主頁:https://www.zhihu.com/people/feiyangqingyun/
四、效果圖
五、相關代碼
void MapDownload::download(const QString &url, const QString &dirName, const QString &fileName, int zoom)
{
if (url.isEmpty()) {
return;
}
//啟動計時
QTime time;
time.start();
//先判斷文件夾是否存在,不存在則新建
QDir dir(dirName);
if (!dir.exists()) {
dir.mkpath(dirName);
}
//局部的事件循環,不卡主界面
QEventLoop eventLoop;
QNetworkReply *reply = manager->get(QNetworkRequest(QUrl(url)));
connect(reply, SIGNAL(finished()), &eventLoop, SLOT(quit()));
//設置下載超時
QTimer timer;
connect(&timer, SIGNAL(timeout()), &eventLoop, SLOT(quit()));
timer.setSingleShot(true);
timer.start(timeout);
eventLoop.exec();
bool error = false;
if (reply->bytesAvailable() > 0 && reply->error() == QNetworkReply::NoError) {
//讀取所有數據保存成文件
QByteArray data = reply->readAll();
QFile file(dirName + fileName);
if (file.open(QFile::WriteOnly | QFile::Truncate)) {
file.write(data);
file.close();
}
} else {
//可以自行增加下載失敗的統計
error = true;
qDebug() << TIMEMS << "下載出錯" << reply->errorString();
}
int useTime = time.elapsed();
emit finsh(url, fileName, zoom, useTime, error);
}