QT使用QML实现地图绘制虚线

QML提供了MapPolyline用于在地图上绘制线段,该线段是实线,因此我使用Canvas自定义绘制的方式在地图上绘制线段,如图:

鼠标在地图上点击后,在点击位置添加图标 ,当有多个图标被添加到地图上后,计算各个图标间的距离,并创建一个新的虚线线段组件,连接两个图标点,显示距离数值。如果对自定义图标添加拖动属性,效果如图:

MapDashLine.qml属性:

  • beginCoordinate:线段起始经纬度坐标

  • endCoordinate:线段终点经纬度坐标

  • lineDash:虚线样式

  • lineColor:虚线颜色

  • lineWidth:虚线粗细

  • textColor:显示距离文字颜色

  • textPixelSize:字体大小

MapDashLine.qml源码(我使用的是Qt5.15):

import QtQuick 2.15
import QtPositioning 5.15
 
Item {
    id:mapDashLine
    anchors.fill: parent
    property var beginCoordinate: QtPositioning.coordinate()
    property var endCoordinate: QtPositioning.coordinate()
    property var lineDash: [4,4]
    property color lineColor: "crimson"
    property int lineWidth: 2
    property color textColor: "crimson"
    property int textPixelSize: 14
    readonly property var mapItem: mapDashLine.parent
 
 
    Canvas{
        id:myCanvas
        anchors.fill: parent
        onPaint: {
            if(!mapDashLine.beginCoordinate.isValid || !mapDashLine.endCoordinate.isValid)
                return
            var ctx = getContext("2d")
            ctx.clearRect(0,0,myCanvas.width,myCanvas.height)
            ctx.strokeStyle = mapDashLine.lineColor
            ctx.lineWidth = mapDashLine.lineWidth
            ctx.setLineDash(mapDashLine.lineDash)
            //**绘制虚线
            ctx.beginPath()
            var beginPos = mapDashLine.mapItem.fromCoordinate(mapDashLine.beginCoordinate,false)
            ctx.moveTo(beginPos.x,beginPos.y)
            var endPos = mapDashLine.mapItem.fromCoordinate(mapDashLine.endCoordinate,false)
            ctx.lineTo(endPos.x,endPos.y)
            ctx.stroke()
            ctx.save()
            //**绘制文字
            var azimuth = endCoordinate.azimuthTo(beginCoordinate)
            if(azimuth>=180)
                azimuth = azimuth - 180
            var distance = endCoordinate.distanceTo(beginCoordinate)
            var text = (distance/1000).toFixed(0)+"Km"
            ctx.fillStyle = mapDashLine.textColor
            ctx.font = mapDashLine.textPixelSize+"px Arial"
            ctx.textAlign = "center"
            var centerX =  (beginPos.x+endPos.x)/2
            var centerY = (beginPos.y+endPos.y)/2
            ctx.translate(centerX,centerY)
            ctx.rotate(azimuth*Math.PI/180-Math.PI/2)
            ctx.fillText(text,0,-mapDashLine.textPixelSize/2)
            ctx.restore()
        }
    }
 
    onBeginCoordinateChanged: {
        update()
    }
    onEndCoordinateChanged: {
        update()
    }
    onLineDashChanged: {
        update()
    }
    onLineColorChanged: {
        update()
    }
    onLineWidthChanged: {
        update()
    }
    onTextColorChanged: {
        update()
    }
    onTextPixelSizeChanged: {
        update()
    }
 
    Connections{
        target: mapDashLine.mapItem
        function onZoomLevelChanged(){
            update()
        }
        function onVisibleRegionChanged(){
            update()
        }
    }
 
    function update(){
        myCanvas.requestPaint()
    }
}

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

芯动大师

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值