C
Qt Quick Ultralite map example
// Copyright (C) 2025 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial import QtQuick import QtPositioning import QtLocation Item { id: root property geoCoordinate prevCoordinate: QtPositioning.coordinate(65.05877, 25.45545) property real zoomLevel: mapParameters.zoomLevel property real nextZoomLevel: root.zoomLevel + 1 property real prevZoomLevel: root.zoomLevel - 1 signal startDemoMode(bool paused) signal endDemoMode MapParameters { id: mapParameters } function zoom(zoomType: string) { if (zoomType === "In" && root.zoomLevel < map.maximumZoomLevel) { zoomInAnimation.stop() zoomInAnimation.start() } else if (zoomType === "Out" && root.zoomLevel > map.minimumZoomLevel) { zoomOutAnimation.stop() zoomOutAnimation.start() } } function incrementZoomLevel() { if (root.zoomLevel < map.maximumZoomLevel) root.zoomLevel += 1 } function decrementZoomLevel() { if (root.zoomLevel > map.minimumZoomLevel) root.zoomLevel -= 1 } function startDemo(paused: bool) { if (paused) { posSource.active = false demoStartPause.imageSource = "start-resume.png" demoStartPause.demoPaused = true return } // start/resume posSource.active = true demoStartPause.imageSource = "pause.png" demoStartPause.demoPaused = false demoStop.visible = true routeInfo.visible = true currentLocationAnimation.start() } function endDemo() { posSource.active = false IndexManager.setIndex(0) demoStartPause.imageSource = "start-resume.png" demoStartPause.demoPaused = true demoStop.visible = false routeInfo.visible = false } onStartDemoMode: startDemo(paused) onEndDemoMode: endDemo() PositionSource { id: posSource active: false updateInterval: 1000 onPositionChanged: { bearingAnimation.start() changeLocationAnimation.start() } onSourceErrorChanged: { if (sourceError === PositionSource.ClosedError) endDemo() } } Map { id: map anchors.fill: parent center: QtPositioning.coordinate(mapParameters.latitude, mapParameters.longitude) bearing: mapParameters.bearing zoomLevel: root.zoomLevel minimumZoomLevel: mapParameters.minimumZoomLevel maximumZoomLevel: mapParameters.maximumZoomLevel MapRoute { id: myroute property real distance: Math.round(myroute.route.distance / 1000) property int travelTime: Math.round(myroute.route.travelTime / 60) route: RouteService.routeData line.color: "#12834b" line.width: 5 } MapMarker { id: currentLocation imageSource: "nav-arrow.png" coordinate: posSource.position.coordinate visible: !mapParameters.showButtons } MapMarker { id: poiQt imageSource: "location-marker.png" markerText: "The Qt Company" coordinate: QtPositioning.coordinate(65.05877, 25.45545) visible: !mapParameters.showButtons } MapMarker { id: poiMarket imageSource: "location-marker.png" markerText: "Supermarket" coordinate: QtPositioning.coordinate(65.054274, 25.456213) visible: !mapParameters.showButtons } MapMarker { id: poiStation imageSource: "location-marker.png" markerText: "Gas Station" coordinate: QtPositioning.coordinate(65.055253, 25.456561) visible: !mapParameters.showButtons } MouseArea { id: mapPan anchors.fill: parent property real pressPointX: 0 property real pressPointY: 0 property real translationX: 0 property real translationY: 0 onPressed: { pressPointX = mouse.x pressPointY = mouse.y translationX = 0 translationY = 0 } onPositionChanged: { var x = mouse.x - pressPointX var y = mouse.y - pressPointY var deltaX = x - translationX var deltaY = y - translationY translationX = x translationY = y map.pan(-deltaX, -deltaY) } } MapButton { id: zoomIn visible: mapParameters.showButtons width: root.width / 10 height: width anchors.top: parent.top anchors.right: parent.right anchors.topMargin: 10 anchors.rightMargin: 10 imageSource: "plus.png" backgroundColor: "#e0e0e0" onButtonClicked: { if (zoomOutAnimation.running) { zoomOutAnimation.stop() } zoom("In") } } MapButton { id: zoomOut visible: mapParameters.showButtons width: root.width / 10 height: width anchors.top: zoomIn.bottom anchors.right: parent.right anchors.topMargin: 5 anchors.rightMargin: 10 imageSource: "minus.png" backgroundColor: "#e0e0e0" onButtonClicked: { if (zoomInAnimation.running) { zoomInAnimation.stop() } zoom("Out") } } MapButton { id: rotateRight visible: mapParameters.showButtons width: root.width / 10 height: width anchors.top: zoomOut.bottom anchors.right: parent.right anchors.topMargin: 5 anchors.rightMargin: 10 imageSource: "rotate-right.png" backgroundColor: "#e0e0e0" onButtonClicked: { map.bearing -= 5 } } MapButton { id: rotateLeft visible: mapParameters.showButtons width: root.width / 10 height: width anchors.top: zoomOut.bottom anchors.right: rotateRight.left anchors.topMargin: 5 anchors.rightMargin: 10 imageSource: "rotate-left.png" backgroundColor: "#e0e0e0" onButtonClicked: { map.bearing += 5 } } MapButton { id: demoStartPause property bool demoPaused: true width: root.width / 10 height: width anchors.top: parent.top anchors.right: zoomIn.left anchors.topMargin: 10 anchors.rightMargin: 10 imageSource: "start-resume.png" backgroundColor: "#e0e0e0" onButtonClicked: { startDemoMode(!demoPaused) } } MapButton { id: demoStop visible: false width: root.width / 10 height: width anchors.top: parent.top anchors.left: demoStartPause.right anchors.topMargin: 10 anchors.leftMargin: 10 imageSource: "stop.png" backgroundColor: "#e0e0e0" onButtonClicked: { endDemoMode() } onVisibleChanged: { if (visible) { // only on demo start not on resume mapParameters.showButtons = false root.zoomLevel = 17 map.minimumZoomLevel = 17 map.maximumZoomLevel = 17 } else { mapParameters.showButtons = true root.zoomLevel = mapParameters.zoomLevel map.minimumZoomLevel = mapParameters.minimumZoomLevel map.maximumZoomLevel = mapParameters.maximumZoomLevel map.bearing = mapParameters.bearing } } } MapText { id: copyrighttxt anchors.bottom: parent.bottom anchors.right: parent.right text: "© OpenStreetMap contributors" backgroundColor: "#e0e0e0" } MapText { id: routeInfo visible: false anchors.top: parent.top anchors.left: parent.left text: "distance: %1 km \ntravel time: %2 mins".arg (myroute.distance).arg(myroute.travelTime) backgroundColor: "#e0e0e0" } } PropertyAnimation { id: zoomInAnimation target: map property: "zoomLevel" from: root.zoomLevel to: root.nextZoomLevel running: false alwaysRunToEnd: false duration: 500 onStopped: incrementZoomLevel() } PropertyAnimation { id: zoomOutAnimation target: map property: "zoomLevel" from: root.zoomLevel to: root.prevZoomLevel running: false alwaysRunToEnd: false duration: 500 onStopped: decrementZoomLevel() } PropertyAnimation { id: bearingAnimation target: map property: "bearing" from: map.bearing to: posSource.position.direction running: true duration: 2000 } CoordinateAnimation { id: currentLocationAnimation target: map property: "center" from: map.center to: currentLocation.coordinate duration: 2000 } ParallelAnimation { id: changeLocationAnimation running: false CoordinateAnimation { target: map property: "center" from: prevCoordinate to: posSource.position.coordinate } CoordinateAnimation { target: currentLocation property: "coordinate" from: prevCoordinate to: posSource.position.coordinate } onStopped: { prevCoordinate = map.center } } }