1.实现思路

参照百度or高德地图的测距功能,主要由两种元素组成,标记点和连线。

其中连线很好解决,Qt 提供了 MapPolyline 类型,可以用来绘制折线,并且提供了增删的便捷函数:

对于标记点,我们可以用 MapQuickItem 来实现,里面包含一个标记圆圈、长度Text、删除按钮。对于一组 MapQuickItem,我使用 MapItemView 来管理。而求两个坐标点的距离,直接调用的  coordinate 类型的 distanceTo 函数,总长直接遍历求距离就行了。

接下来就是封装一个 Ruler 的组件,实现多次测距的绘制。每次开始测距时,通过 createObject 动态创建一个 Ruler 组件,然后往里面添加坐标点。坐标点我是在 Map 上放了一个 MouseArea ,然后用 Map 的 toCoordinate 方法把 point 转换成坐标点。

此外,如果要自己计算两点距离,可以参考网上球面两点距离的公式,如:

上面参考的表示法应该是十进制的,如果是度分秒的形式,可以先转化下:

2.实现代码及git链接

下面是实现效果:

有一点还没解决,那就是 MapPolyline 这种图元设置 layer 实现平滑效果的话,放大之后很卡。另外就是,一个 Ruler 所有元素被删之后我也没有析构它。

Ruler组件的实现代码:

//MapRuler.qml
import QtQuick 2.12
import QtQuick.Controls 2.12
import QtLocation 5.12
import QtPositioning 5.12// 一次测距里包含多个标记点以及连线
MapItemGroup{id: controlMapPolyline {id: item_lineline.color: "red"line.width: 2//平滑后放大有点卡//layer.enabled: true//layer.smooth: true//layer.samples: 8function getDistanceCount(){var distance_count=0;for(var i=1;i<pathLength();i++){distance_count+=item_line.coordinateAt(i).distanceTo(item_line.coordinateAt(i-1));}return Math.round(distance_count);}}MapItemView{id: item_viewadd: Transition {}remove: Transition {}model: ListModel{id: item_model}delegate: MapQuickItem{id: ietm_delegatesourceItem: Rectangle {width: 14height: 14radius: 7color: "white"border.width: 2border.color: "red"Rectangle{anchors.left: parent.rightanchors.top: parent.bottomwidth: item_text.width+5+5+14+5height: item_text.height+10border.color: "gray"Text {id: item_textx: 5anchors.verticalCenter: parent.verticalCentertext: index<=0? "起点": (index==item_model.count-1)? ("总长 "+item_line.getDistanceCount()/1000+" km"):(Math.round(ietm_delegate.coordinate.distanceTo(item_line.coordinateAt(index-1)))/1000+" km")}Rectangle{width: 14height: 14anchors.right: parent.rightanchors.rightMargin: 5anchors.verticalCenter: parent.verticalCenterborder.color: "red"Text {color: "red"anchors.centerIn: parenttext: "+"rotation: 45}MouseArea{anchors.fill: parentonClicked: {//最后一个全部删除,否则一个一个的删除//为0的时候发送信号给group请求删除if(index==item_model.count-1){item_line.path=[];item_model.clear();//control.destroy();}else{item_line.removeCoordinate(index);item_model.remove(index);}}}}}//Component.onDestruction: console.log("destory item");}//通过listmodel来设置数据coordinate{latitude: latitudevallongitude: longitudeval}anchorPoint: Qt.point(sourceItem.width/2, sourceItem.height/2)}}function appendPoint(coord){//var coord=the_map.toCoordinate(Qt.point(mouseX,mouseY),false);//console.log("area",coord.latitude,coord.longitude);item_model.append({"latitudeval":coord.latitude,"longitudeval":coord.longitude});item_line.addCoordinate(coord);//mouse_area._closePath=false;//console.log("ruler append",item_model.count,item_line.pathLength())}function followMouse(coord){if(item_line.pathLength()<=0)return;if(item_line.pathLength()===item_model.count){item_line.addCoordinate(coord);}else{item_line.replaceCoordinate(item_line.pathLength()-1,coord);}}function closePath(){while(item_line.pathLength()>item_model.count){item_line.removeCoordinate(item_line.pathLength()-1);}}
}

在 Window 中调用下面组件来展示 Demo:

//Demo.qml
import QtQuick 2.12
import QtQuick.Controls 2.12
import QtLocation 5.12
import QtPositioning 5.12//地图自定义
Item{id: control//地图的模式// 0:普通浏览// 1:测距property int mapMode: 0property MapRuler currentRuler: nullproperty alias map: the_mapclip: trueonMapModeChanged: {console.log("map mode",mapMode);if(control.mapMode!=1&&currentRuler){currentRuler.closePath();currentRuler=null;}}//缩放等级,维度,精度function viewPoint(zoomLevel,latitude,longitude){the_map.zoomLevel=zoomLevel;the_map.center=QtPositioning.coordinate(latitude, longitude);}Row{RadioButton{text: "Normal"checked: trueonCheckedChanged: if(checked)control.mapMode=0;}RadioButton{text: "Ruler"onCheckedChanged: if(checked)control.mapMode=1;}}Map {id: the_mapanchors.fill: parentanchors.topMargin: 40minimumZoomLevel: 4maximumZoomLevel: 16zoomLevel: 10center: QtPositioning.coordinate(30.6562, 104.0657)plugin: Plugin {name: "esri" //"esri" "mapbox" "osm" "here"}//显示缩放等级与centerRectangle{anchors{left: the_map.leftbottom: the_map.bottommargins: 5}width: content.width+20height: content.height+10Text {id: contentx: 10y: 5font.pixelSize: 14text: "Zoom Level "+Math.floor(the_map.zoomLevel)+" Center:"+the_map.center.latitude+"  "+the_map.center.longitude}}MouseArea{id: map_mouseanchors.fill: parentenabled: control.mapMode!=0//画了一个点后跟随鼠标,除非双击hoverEnabled: trueonClicked: {// 1 测距if(control.mapMode===1){if(!currentRuler){currentRuler=ruler_comp.createObject(the_map);if(currentRuler)the_map.addMapItemGroup(currentRuler);}if(currentRuler){var coord=the_map.toCoordinate(Qt.point(mouseX,mouseY),false);currentRuler.appendPoint(coord);}}}onDoubleClicked: {// 1 测距if(control.mapMode===1){if(currentRuler){currentRuler.closePath();currentRuler=null;}}}onPositionChanged: {// 1 测距if(control.mapMode===1){if(currentRuler){var coord=the_map.toCoordinate(Qt.point(mouseX,mouseY),false);currentRuler.followMouse(coord);}}}}}Component{id: ruler_compMapRuler{}}
}

代码 github 链接:https://github.com/gongjianbo/MyQtLocation

QML QtLocation地图应用学习-2:实现测距功能相关推荐

  1. QML QtLocation地图应用学习-1:在Map中展示图元 Item

    目录 0.前言 1.开始 2.在Map中展示图元 3.一个完整的例子 4.Bug:当其他控件具有焦点时,地图上有灰白色方块 0.前言 Qt Location模块可用于轻量级的地图应用开发,不过官方示例 ...

  2. QML Map中测距——QtLocation轻量级地图应用学习

    QML Map中测距 1. 实现思路 2. 实现代码及git链接 本文转载于:QML QtLocation轻量级地图应用学习:实现测距功能 所有的热爱都要不遗余力,真正喜欢它便给它更高的优先级,和更多 ...

  3. (jQuery,SVG)使用jQuery和svg仿QQ地图测距功能(抛砖引玉)

    不久前看到了QQ地图的测距功能,觉得挺好玩的,就思考模仿一下.本来想通过canvas来画图,可惜对canvas不是很熟悉,就准备用svg了,其实我对svg也不是很熟,纯粹是学习. 代码只是简单的生成图 ...

  4. 高德地图JSAPI测距功能优化

    文章目录 前言 测距实现思路 使用测距插件 开启测距 关闭测距 前言 高德提供了一个距离测量插件可直接使用,但是没有完全满足需求.在测距过程中只会显示新增节点到起始点的总长度,而不会在鼠标移动过程中显 ...

  5. QT5百度地图开发学习——qt调用JavaScript函数并传参

    文章目录 前言 一.通信桥梁bridge 二.QT与JS相互通信(调用函数) 1.QT调用js函数 前言 在上文<QT5百度地图开发学习--控件提升展示地图>中,我们通过控件提升的方式在同 ...

  6. 使用Google地图的测距功能

    使用google地图API的测距功能 首先需要引入对应的Google地图的库(drawing,geometry,spherical) 引入方法在 <script src="https: ...

  7. 百度地图 测距功能 DistanceTool 在不同浏览器下标注不一致的解决办法,打开新地图测距不生效的解决办法

    1. 在项目中用到百度地图的测距功能,在主页面的地图中用没问题,如果从主页的地图跳转到详情页的地图,在返回到主页,打开地图的测距功能,测距一直不显示.下面是解决办法 将测距功能的工具类函数下载到本地, ...

  8. Android百度地图测距功能

    临近春节假期,业务开发进入收尾.空闲时间做的技术储备: 百度地图测距 为什么做这个技术储备,1 年尾有时间 2 我们现有的地图业务基于百度地图 3 这个功能竞品某壳等没有但是很实用 个人在看房时候经常 ...

  9. arcgis地图开发测面、测距、定位小工具

    arcgis小工具(测面.测线.定位等) 一下三个功能用到的arcgis文件汇总: import Graphic from "@arcgis/core/Graphic"; impo ...

最新文章

  1. 解决Kali LinuxVI编辑器无法复制问题
  2. Oracle存在修改,不存在插入记录
  3. MicroStation VBA 操作提示
  4. Mac升级自带ruby方法
  5. “堆外内存泄漏”排查及经验总结
  6. canva画图 图片居中裁剪_css实现不定宽高的图片img居中裁剪_类似微信朋友圈图片效果...
  7. RedisTemplate value序列化导致的问题
  8. bootstrap-table使用 带条件查询翻页及数据更新的问题。
  9. Spark API 详解/大白话解释 之 map、mapPartitions、mapValues、mapWith、flatMap、flatMapWith、flatMapValues
  10. 互联网架构“高并发”
  11. PHP 图片上传类 缩略图
  12. Nginx 下部署 HTTPS 与安全调优
  13. 【C++ Primer】第六章(分支语句和逻辑操作符)
  14. 【机器学习系列】MCMC第二讲:Markov Chain Monte Carlo基本概念和核心思想
  15. bootdo框架中使用shiro控制的权限(bootstrap)
  16. openv学习—Template Matching
  17. Elasticsearch:部署 ECE (Elastic Cloud Enterprise)
  18. java 同比数据怎么算的_如何计算同比的计算公式?
  19. 计算机程序运行异常处理,Win7电脑运行程序出现appcrash错误怎么解决?
  20. 响应式嵌入 iframe Pym.js

热门文章

  1. oracle 取某一年1月1日的多种方法
  2. neat神经网络算法的线性回归拟合(Python)
  3. EZ-USB FX2单片机原理、编程及应用 读书笔记
  4. 【git】 Please tell me who you are解决方法
  5. V4L2视频采集与H264编码2—v4l2采集YUV数据
  6. 腾讯人均月薪7.5w,我这是又被平均了?
  7. 征信报告 加密文档_PDF文档如何加密?看完这个方法你就知道了
  8. Rancher Labs获2000万美元B轮融资, CEO 梁胜出任有容云联席CTO
  9. S-Trees UVA - 712(建树即可)
  10. selenium.common.exceptions.WebDriverException: Message: unable to set