一、前言
最常用的地圖交互就幾個,比如鼠標在地圖上按下的時候可以拾取經緯度坐標,然后傳給Qt程序,再比如對設置的設備點進行單擊的時候,通知Qt程序單擊了哪一個設備點,好讓Qt程序識別並作出反應比如彈出對應點的詳細信息或者視頻預覽等。讓網頁執行js函數這種單向的操作,其實無論何種瀏覽器內核都支持的,並不需要注入類或者添加qwebchannel.js文件之類的,你只需要放心大膽的調用runJavaScript或者evaluateJavaScript函數。而如果想要網頁發送對應的數據給Qt程序的話,就需要額外的處理了。
在webkit中要實現從網頁傳回數據交互,只需要在網頁載入完畢的信號loadFinished中注入類對象即可 webView->page()->mainFrame()->addToJavaScriptWindowObject("objName", webJsData);,而在webengine控件中需要增加兩步,第一步是需要在網頁里面引入js文件 <script type="text/javascript" src="qwebchannel.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://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/
四、效果圖
五、相關代碼
//需要自定義繼承自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(" }");