[Qt]QML文件-2

void MainWindow::updateCoordinates(double lat, double lon)
{
QQuickWidget *quickWidget = ui->quickWidget;
if (!quickWidget) return;

QQuickItem *rootObject = quickWidget->rootObject();
if (!rootObject) return;

QVariantMap coord;
coord[“latitude”] = lat;
coord[“longitude”] = lon;
rootObject->setProperty(“centerCoordinate”, coord);

QMetaObject::invokeMethod(rootObject, “updateVisibleTiles”);
}

//QML

import QtQuick 2.15
import QtQuick.Controls 2.15

Item {
id: root
width: 640
height: 480

property var centerCoordinate: { “latitude”: 36.35, “longitude”: 117.0 }
property int tileSize: 512
property int zoomLevel: 16
property string tileRoot: “file:///home/orangepi/Layer”

Flickable {
id: flick
anchors.fill: parent
clip: true
interactive: true
contentWidth: 20000
contentHeight: 20000

Item {
id: tileContainer
width: flick.contentWidth
height: flick.contentHeight
property var tilesCache: ({}) // 缓存瓦片对象
}

Rectangle {
id: redDot
width: 12
height: 12
color: “red”
radius: 6
anchors.centerIn: parent
}

onContentXChanged: updateVisibleTiles()
onContentYChanged: updateVisibleTiles()
}

function updateVisibleTiles() {
if (!tileContainer || !root.centerCoordinate) return;

var zoom = root.zoomLevel;
var n = Math.pow(2, zoom);
var center = root.centerCoordinate;

// 中心瓦片浮点坐标
var centerTileXf = (center.longitude + 180) / 360 * n;
var centerTileYf = (1 – Math.log(Math.tan(center.latitude*Math.PI/180) + 1/Math.cos(center.latitude*Math.PI/180)) / Math.PI) / 2 * n;

var tilesX = Math.ceil(flick.width / root.tileSize) + 2;
var tilesY = Math.ceil(flick.height / root.tileSize) + 2;

var startX = Math.floor(centerTileXf – tilesX/2);
var startY = Math.floor(centerTileYf – tilesY/2);

// 记录当前视野瓦片 key
var currentKeys = {};
for (var x = startX; x < startX + tilesX; x++) { for (var y = startY; y < startY + tilesY; y++) { var key = x + "_" + y; currentKeys[key] = true; var path = root.tileRoot + "/" + zoom + "/" + x + "/" + y + ".png"; if (!tileContainer.tilesCache[key]) { var tile = Qt.createQmlObject( 'import QtQuick 2.15; Image { width:' + root.tileSize + '; height:' + root.tileSize + '; source: "' + path + '"; fillMode: Image.PreserveAspectFit }', tileContainer ); tileContainer.tilesCache[key] = tile; } // 更新位置 var tileObj = tileContainer.tilesCache[key]; tileObj.x = (x - startX) * root.tileSize; tileObj.y = (y - startY) * root.tileSize; } } // 删除超出视野的瓦片 for (var key in tileContainer.tilesCache) { if (!currentKeys[key]) { tileContainer.tilesCache[key].destroy(); delete tileContainer.tilesCache[key]; } } // 移动 tileContainer,使中心瓦片在 Flickable 中心 var offsetX = (centerTileXf - startX) * root.tileSize - flick.width/2; var offsetY = (centerTileYf - startY) * root.tileSize - flick.height/2; tileContainer.x = -offsetX; tileContainer.y = -offsetY; // 红点始终在视口中心 redDot.x = flick.width / 2 - redDot.width/2; redDot.y = flick.height / 2 - redDot.height/2; } Component.onCompleted: updateVisibleTiles() }

发表评论

邮箱地址不会被公开。 必填项已用*标注