Qt/C++載入不同的地圖控制元件/地圖型別/縮放標尺/縮圖/比例尺/實時路況/全景檢視等

飞扬青云發表於2024-10-10

一、前言說明

在展示地圖的時候,有些常規的操作,比如調整地圖的縮放級別,切換到衛星圖等,希望能夠在地圖上直接操作實現,於是就有了一堆地圖控制元件,可以根據自己的需求動態的新增和刪除,這樣就更直接更快捷,而不是透過函式去設定。幾乎每個地圖廠家都提供了類似的控制元件,儘管命名可能有些差別,常見的地圖控制元件有地圖型別、縮放標尺、縮圖(也叫鷹眼檢視)、比例尺、實時路況等。

記得當初第一版的地圖元件設計的時候,每個地圖控制元件對應一個enable變數,在生成地圖網頁程式碼之前,設定好enable的值,然後根據這個值去決定要不要加入控制元件到地圖中。現在的版本是定義一堆列舉值,每一種控制元件對應一個列舉值,地圖基類中定一個變數mapControl用來控制需要哪些地圖控制元件,列舉值的值依次是1/2/4/8這種,方便於判斷進行設定。縱觀各種第三方輪子,好多都是這種方式。

二、功能特點

2.1 地圖功能

  1. 支援多種地圖核心,預設採用百度地圖,可選高德地圖、天地圖、騰訊地圖、谷歌地圖等。
  2. 同時支援線上地圖和離線地圖兩種模式,離線地圖方便在不聯網的場景中使用。
  3. 支援各種地圖控制元件的啟用,比如地圖導航、地圖型別、縮圖、比例尺、全景導航、實時路況、繪圖工具、結果皮膚等。
  4. 支援多種地圖功能的動態啟用禁用,比如地圖拖曳、鍵盤操作、滾輪縮放、雙擊放大、連續縮放、地圖測距等。
  5. 提供眾多js函式介面用於互動,引數極其豐富,能夠想到的應用場景需求都有。
  6. 統一的訊號槽機制,地圖中的結果統一訊號傳送出去,收到後根據type型別區分。
  7. 支援地圖互動,比如滑鼠按下獲取對應位置的經緯度。單擊標註點彈出對應點的資訊。
  8. 支援新增標註、刪除標註、移動標註、清空標註。
  9. 標註點可以指定圖示圖片和尺寸,支援gif動圖,支援指定以圖片中心對齊還是底部中心對齊。可以設定旋轉角度,帶富文字提示資訊。
  10. 標註點事件支援單擊發訊號通知和自己彈框顯示資訊。
  11. 提供地址轉座標和座標轉地址介面。
  12. 支援各種圖形繪製,包括折線圖、多邊形、矩形、圓形、弧線等。
  13. 可顯示懸浮的繪圖工具欄,直接在地圖上劃線、標註點、矩形、圓形等。
  14. 支援各種區域搜尋,比如矩形區域、圓形區域,可以按照關鍵字匹配將搜尋結果顯示在地圖中。
  15. 可動態新增離線的行政區邊界點資料。可以搜尋行政區劃並獲取該區域的邊界點資料。資料可以儲存到檔案以便離線使用。
  16. 支援點聚合功能,多個小標註點合併到一個大標註點,防止點密集導致互動不友好。
  17. 可以新增海量點,每個點都可以單擊獲取對應座標和資訊。
  18. 所有的覆蓋物資訊比如標註點、矩形、多邊形、折線圖等,都可以主動獲取對應的資訊比如座標點和路徑等。
  19. 支援路徑規劃,支援公交路線、自駕路線、步行路線、騎行路線,不同查詢支援不同策略,可選最少時間、最少換乘、不走高架等。
  20. 路徑規劃結果可以顯示在地圖中,也可以獲取到路徑點座標集合。這個資料可以儲存到檔案,以便發給機器人或者無人機做導航用來軌跡移動。
  21. 可以設定不同的地圖檢視比如街道圖、衛星圖、混合圖。
  22. 可以設定不同的樣式,比如午夜藍、青草綠等樣式風格。
  23. 可以設定地圖的旋轉角度和傾斜角度。
  24. 提供經緯度座標糾偏轉換功能,比如傳入的GPS座標需要轉換到百度地圖座標或者高德地圖座標。各種座標系轉換全部離線函式,支援地球座標系WGS-84、火星座標系GCJ-02、百度座標系BD-09之間的互相轉換,涵蓋了各種地圖的座標系。
  25. 提供動態軌跡點移動功能,按照給定的經緯度座標集合平滑移動。
  26. 同時支援qwidget和qml,支援編譯到安卓系統執行。

2.2 其他功能

  1. 提供離線地圖下載模組,可以選擇不同的地圖核心比如百度地圖或者谷歌地圖,不同的地圖型別比如下載街道圖還是衛星圖,不同的地圖層級,多執行緒極速下載。
  2. 表格行實時顯示對應的瓦片下載進度,有下載超時時間,重試次數,每個瓦片下載完成都傳送訊號通知,引數包括下載用時。
  3. 提供省市輪廓圖下載模組,自動下載各個地區的輪廓圖,儲存到指令碼檔案或者文字檔案。
  4. 支援手動調整不同區域的輪廓邊界,調整後可以主動獲取調整後的邊界點集合。
  5. 提供動態點位示例,手動在地圖上選點並新增標註,附帶自定義的資訊比如速度和時間等。
  6. 提供海量點位示例,批次新增標註點、點聚合、海量點。用於測試環境中支援的最大點位效能。
  7. 提供動態軌跡示例,在地圖上滑鼠按下選擇起點和終點後,查詢路線,獲取路徑軌跡點,模擬軌跡平滑移動。可以篩選資料將過多的路徑點篩選到設定的點數。
  8. 提供軌跡回放示例,按照指定的軌跡點列表回放,也可以匯入軌跡點資料進行回放。同時支援在街道圖、衛星圖、混合圖中回放軌跡。
  9. 提供省市區域地圖示例,採用echart元件,同時支援閃爍點圖、遷徙圖、區域地圖、世界地圖、儀表盤等。可以設定標題、提示資訊、背景顏色、文字顏色、線條顏色、區域顏色等各種顏色。
  10. 省市區域地圖示例,內建世界地圖、全國地圖、省份地圖、地區地圖,可以精確到縣,所有地圖全部離線使用。可設定城市的名稱、值、經緯度集合。
  11. 內建通用瀏覽器元件,同時支援webkit/webengine/miniblink等核心。提供網頁控制元件示例,演示開啟網頁和本地網頁檔案。
  12. 支援任意Qt版本、任意系統、任意編譯器。

三、相關連結

  1. 體驗地址:https://pan.baidu.com/s/1ZxG-oyUKe286LPMPxOrO2A 提取碼:o05q 檔名:bin_map.zip
  2. 國內站點:https://gitee.com/feiyangqingyun
  3. 國際站點:https://github.com/feiyangqingyun

四、效果圖

五、相關程式碼

void MapObjBase::addHead(const QStringList &scripts)
{
    //構建網頁頭部
    html << QString("<html>");
    html << QString("<head>");
    html << QString("<title>%1</title>").arg(title);
    html << QString("<meta charset=\"utf-8\">");
    html << QString("<meta name=\"viewport\" content=\"initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width\">");

    //新增網頁樣式
    this->addCss();

    //新增不同地圖不同的指令碼檔案
    foreach (QString script, scripts) {
        html << script;
    }

    //引入Qt中網頁互動用的js檔案
#ifdef webengine
    html << QString("<script type=\"text/javascript\" src=\"qrc:/qwebchannel.js\"></script>");
#endif
    html << QString("</head>");
}

void MapObjBase::addCss()
{
    //構建頁面樣式
    html << QString("<style type=\"text/css\">");
    //地圖尺寸
    html << QString("  #map{height:%1;width:100%;}").arg((mapControl & MapControl_Panel) ? QString("%1px").arg(mapHeight) : "100%");
    //結果皮膚樣式
    html << QString("  #panel,#panel table{width:100%;font-size:12px;}");
    //隱藏左下角的logo
    html << QString("  .anchorBL,.amap-logo,.amap-copyright,.tdt-control-copyright{opacity:0;}");
    //全域性字型樣式
    html << QString("  html,body{font-family:微軟雅黑;height:100%;width:100%;margin:0px;padding:0px;}");

    //webkit瀏覽器捲軸樣式
    html << QString("  ::-webkit-scrollbar{width:0.8em;}");
    html << QString("  ::-webkit-scrollbar-track{background:rgb(241,241,241);}");
    html << QString("  ::-webkit-scrollbar-thumb{background:rgb(188,188,188);}");

    html << QString("</style>");
}

void MapObjBase::addBody()
{
    //構建網頁主體部分內容
    html << QString("<body>");
    html << QString("  <div id='map'></div>");

    //新增結果皮膚/比如路徑查詢和周邊搜尋等結果可以有個皮膚直接展示
    panelName = "";
    if (mapControl & MapControl_Panel) {
        panelName = "panel";
        html << QString("  <div id='%1'></div>").arg(panelName);
    }

    html << QString("</body>");

    //引入js檔案
    html << QString("<script type=\"text/javascript\">");
#ifdef mapweb
    html << QString("  var socket = new WebSocket('ws://127.0.0.1:6001');");
#endif

    //通用返回資料函式
    html << QString("  function receiveData(type, data) {");
#ifdef mapweb
    html << QString("    if (socket) {");
    html << QString("      socket.send(type + '_' + data);");
    html << QString("    }");
#else
#ifdef webminiblink
    html << QString("    objName_receiveData(type, data);");
#else
    html << QString("    objName.receiveData(type, data);");
#endif
#endif
    html << QString("  }");

    //生成QWebChannel通訊物件用於js互動
#ifndef webkit
#ifdef webengine
    html << QString("  new QWebChannel(qt.webChannelTransport, function(channel){window.objName = channel.objects.objName;})");
#endif
#endif
}

void MapObjBase::addFun()
{
    //沒有啟用新增互動函式則不用繼續/方便測試簡單的網頁內容
    MapObjFun::mapCore = mapCore;
    if (!mapFun) {
        return;
    }

    this->addLayer();
    this->addEvent();
    this->addOther();

    this->getPoint();
    this->getPoints();

    this->getMarkers();
    this->getPathPoints();
    this->getBounds();

    this->getCenterAndZoom();
    this->setCenterAndZoom();
    this->getRotateAndTilt();
    this->setRotateAndTilt();

    this->setEnable();
    this->setMapStyle();
    this->setMapType();
    this->setAutoView();

    //線上地圖才有地址轉換等功能
    if (!mapLocal) {
        this->addConvertor();
        this->addGeocoder();
        this->addSearch();
        this->addRoute();
        this->searchRoute();
    }

    this->drawRoute();
    this->addDrawingTool();
    this->addDistanceTool();

    this->clearData();
    this->clearOverlay();
    this->deleteOverlay();
    this->editOverlay();
    this->getOverlayInfo();
    this->getOverlayProperty();

    this->setClick();
    this->addMarker();
    this->setMarker();
    this->deleteMarker();

    this->initPolyline();
    this->setPolyline();
    this->deletePolyline();

    this->addMove();
    this->addLine();
    this->moveEvent();
    this->findMove();
    this->doMove();

    this->addPolyline();
    this->addPolygon();
    this->addRectangle();
    this->addCircle();
    this->addCurveLine();

    this->searchBoundary();
    this->getBoundary();
    this->addBoundary();

    this->addMarkerCluster();
    this->addPointCollection();
}

void MapObjBase::addEnd()
{
    html << QString("</script>");
    html << QString("</html>");
}

相關文章