一、前言
最常用的地圖互動就幾個,比如滑鼠在地圖上按下的時候可以拾取經緯度坐标,然後傳給Qt程式,再比如對設定的裝置點進行單擊的時候,通知Qt程式單擊了哪一個裝置點,好讓Qt程式識别并作出反應比如彈出對應點的詳細資訊或者視訊預覽等。讓網頁執行js函數這種單向的操作,其實無論何種浏覽器核心都支援的,并不需要注入類或者添加qwebchannel.js檔案之類的,你隻需要放心大膽的調用runJavaScript或者evaluateJavaScript函數。而如果想要網頁發送對應的資料給Qt程式的話,就需要額外的處理了。
在webkit中要實作從網頁傳回資料互動,隻需要在網頁載入完畢的信号loadFinished中注入類對象即可 webView->page()->mainFrame()->addToJavaScriptWindowObject("objName", webJsData);,而在webengine控件中需要增加兩步,第一步是需要在網頁裡面引入js檔案 ,第二步是生成QWebChannel通信對象 new QWebChannel(qt.webChannelTransport, function(channel){window.receiveData = channel.objects.receiveData;}),第三步是注入類對象 QWebChannel *channel = new QWebChannel(this);channel->registerObject("objName", webJsData); webView->page()->setWebChannel(channel);
做完了上面的注入類以後,在網頁中寫好對應的window.receiveData即可,receiveData為對應的類的public的槽函數,這裡為了複用所有的資料傳回的情況,特意寫了通用的receiveData函數,void receiveData(const QString &type, const QVariant &data);定義兩個參數,這樣就涵蓋了所有的情況 type表示類型相當于唯一辨別,而data是QVariant類型,即可以是字元串也可以是整數或者數組,都能自動轉換的,這樣的話就一個類涵蓋了所有的各種可能的情況,都可以通過type來區分,通過data的類型去判斷并轉換資料。
二、功能特點
- 同時支援線上地圖和離線地圖兩種模式。
- 同時支援webkit核心、webengine核心、IE核心。
- 支援設定多個标注點,資訊包括名稱、位址、經緯度。
- 可設定地圖是否可單擊、拖動、滑鼠滾輪縮放。
- 可設定協定版本、秘鑰、主題樣式、中心坐标、中心城市、地理編碼位置等。
- 可設定地圖縮放比例和級别,縮略圖、比例尺、路況資訊等控件的可見。
- 支援地圖互動,比如滑鼠按下擷取對應位置的經緯度。
- 支援查詢路線,可設定起點位置、終點位置、路線模式、路線方式、路線方案(最少時間、最少換乘、最少步行、不乘地鐵、最短距離、避開高速)。
- 可顯示點線面工具,可直接在地圖上劃線、點、矩形、圓形等。
- 可設定行政區劃,指定某個城市區域繪制圖層,線上地圖自動輸出行政區劃邊界點集合到js檔案給離線地圖使用。
- 可靜态或者動态添加多個覆寫物。支援點、折線、多邊形、矩形、圓形、弧線、點聚合等。
- 函數接口友好和統一,使用簡單友善,就一個類。
- 支援js動态互動添加點、删除點、清空點、重置點,不需要重新整理頁面。
- 支援任意Qt版本、任意系統、任意編譯器。
三、體驗位址
- 國内站點: https://gitee.com/feiyangqingyun
- 國際站點: https://github.com/feiyangqingyun
- 個人首頁: https://blog.csdn.net/feiyangqingyun
- 知乎首頁: https://www.zhihu.com/people/feiyangqingyun/
四、效果圖
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsIiZpdmLzI2NjVGMwMjZiVDNjRmMzUTNkFzNwIGZ4YTN0ATMkN2YyEmZ5gjZy8CXt92Yu4GZjlGbh5SZslmZxl3Lc9CX6MHc0RHaiojIsJye.gif)
五、相關代碼
//需要自定義繼承自QObject的類來接收QWebEngineView互動資料,不然會列印很多煩人的資訊
class WebJsData : public QObject
{
Q_OBJECT
public:
static WebJsData *Instance();
explicit WebJsData(QObject *parent = 0);
public slots:
//定義兩個參數,這樣就涵蓋了所有的情況 type表示類型相當于唯一辨別
void receiveData(const QString &type, const QVariant &data);
signals:
void receiveDataFromJs(const QString &type, const QVariant &data);
};
WebJsData *WebJsData::Instance()
{
static WebJsData self;
return &self;
}
WebJsData::WebJsData(QObject *parent)
{
}
void WebJsData::receiveData(const QString &type, const QVariant &data)
{
//可以在這裡重新梳理好再發出去信号
emit receiveDataFromJs(type, data);
}
list << QString(" map.addEventListener(\"click\", function(e) {");
list << QString(" window.%1('point', e.point.lng + \",\" + e.point.lat);").arg(callFun);
list << QString(" });");
//自定義方法顯示标注詳細資訊
list << QString(" function addInfoWindow(marker, poi){");
list << QString(" var title = '<div style=\"color:#CE5521;\">' + poi.name + '</div>';");
list << QString(" var list = [];");
list << QString(" list.push('<table><tr style=\"vertical-align:top;line-height:25px;font-size:12px;\">');");
list << QString(" list.push('<td style=\"white-space:nowrap;word-break:keep-all;\">位址:</td>');");
list << QString(" list.push('<td>' + poi.addr + '</td>');");
list << QString(" list.push('</tr></table>');");
list << QString(" var infoWindow = new BMap.InfoWindow(list.join(\"\"),{title:title, width:60});");
//單擊以後彈出提示資訊或者發送信号出去
list << QString(" var markerClick = function() {");
#if 0
list << QString(" marker.openInfoWindow(infoWindow);");
#else
list << QString(" window.%1('marker', poi.name);").arg(callFun);
#endif
list << QString(" };");
//添加單擊監聽器
list << QString(" marker.addEventListener(\"click\", markerClick);");
list << QString(" }");