import QtQuick import AntiClipSettings Item { id: root property int dargWidth: 10 property var openDoorAreaPoints: [] Image { id: image anchors.centerIn: parent cache: false fillMode: Image.PreserveAspectFit source: "image://videoframe/" property real aspectRatio: 16 / 9 width: Math.min(root.width, root.height * aspectRatio) height: width / aspectRatio Canvas { id: canvas anchors.fill: parent onPaint: { var ctx = canvas.getContext("2d") ctx.clearRect(0, 0, canvas.width, canvas.height) if (openDoorAreaPoints.length > 0) { ctx.strokeStyle = "red" ctx.lineWidth = 2 ctx.beginPath() let point = scaledPoint(openDoorAreaPoints[0], width, height) ctx.moveTo(point.x, point.y) for (var i = 1; i < openDoorAreaPoints.length; i++) { point = scaledPoint(openDoorAreaPoints[i], width, height) ctx.lineTo(point.x, point.y) } ctx.closePath() ctx.stroke() } } } Repeater { id: repeater model: openDoorAreaPoints delegate: Rectangle { width: dargWidth height: dargWidth color: "red" x: scaledPoint(modelData, canvas.width, canvas.height).x - width / 2 y: scaledPoint(modelData, canvas.width, canvas.height).y - height / 2 } } MouseArea { anchors.fill: parent property int draggedPointIndex: -1 onPressed: mouse => { for (var i = 0; i < openDoorAreaPoints.length; i++) { let point = scaledPoint(openDoorAreaPoints[i], canvas.width, canvas.height) if (isInside(mouse.x, mouse.y, point)) { draggedPointIndex = i break } } } onReleased: { draggedPointIndex = -1 } onPositionChanged: mouse => { if (draggedPointIndex >= 0) { openDoorAreaPoints[draggedPointIndex] = standardPoint( Qt.point(mouse.x, mouse.y), canvas.width, canvas.height) canvas.requestPaint() repeater.model = openDoorAreaPoints } } function isInside(x, y, point) { let edge = dargWidth / 2 return x >= point.x - edge && x <= point.x + edge && y >= point.y - edge && y <= point.y + edge } } } // 转换为显示画点 function scaledPoint(point, width, height) { let x = point.x * width / 640 let y = point.y * height / 360 return Qt.point(x, y) } function standardPoint(point, width, height) { // 转换为设备画点(640x360) let x = point.x * 640 / width let y = point.y * 360 / height return Qt.point(x, y) } Connections { target: App function onNewVideoFrame() { image.source = "" image.source = "image://videoframe/" } function onCurrentOpenDoorAreaPointsChanged() { canvas.requestPaint() } } }