1、写在前面
上一篇中我们简单讲解了 Qml 中实现电子放大的几种方式以及之间的优劣。
而我们的 SkeyeARS
经过多次测试和基于多种场景考虑,选用的是 直接更改 width 和 height
实现电子放大。
表面上看似乎非常简单,然而我们的目标是实现细节缩放即 鼠标中心放大
。
并且,再插入平滑动画则更加完美,当然,也就相当复杂了。
2、正文开始
首先,思考一下,我们应该如何基于鼠标位置来进行放大。
- 计算鼠标在
VideoOutput
中的坐标,使用Item.mapToItem()
。 - 计算鼠标坐标相对宽高的比例
xFactor
和yFactor
。 - 计算缩放后的宽高。
- 移动
VideoOutput
至原位置。 - 使用
Animation
控制宽高和 坐标的变化。
现在来看看正确实现的关键代码:
MouseArea {
id: mouseArea
anchors.fill: parent
hoverEnabled: true
onWheel: {
let step = wheel.angleDelta.y / 15;
videoOutput.addScaleFactor(step * 0.004);
}
VideoOutput {
id: videoOutput
width: parent.width
height: parent.height
source: panoramicProvider
//缩放因子,原始源大小时为1.0
property real scaleFactor: containerSize.width / sourceRect.width
property real minScale: 0.05
property real maxScale: sourceRect.width / parent.width + 10000.0
//容器大小(即parent.size)
property size containerSize: Qt.size(parent.width, parent.height)
property real ratio: sourceRect.height / sourceRect.width
/**
* @brief 增加缩放因子,用此函数调整缩放
* @param factor默认0.08
* @param isCenter是否中心缩放
*/
function addScaleFactor(factor = 0.08, isCenter = false) {
if (painterButtons.fixedFillButton.checked) return;
scaleFactor += factor;
if (scaleFactor < minScale) {
scaleFactor = minScale;
} else if (scaleFactor > maxScale) {
scaleFactor = maxScale;
}
if (scaleAnimation.running) scaleAnimation.stop();
scaleWidthAnimation.to = sourceRect.width * scaleFactor;
scaleHeightAnimation.to = sourceRect.height * scaleFactor;
if (isCenter) {
scaleXAnimation.to = (rect.width - scaleWidthAnimation.to) / 2;
scaleYAnimation.to = (rect.height - scaleHeightAnimation.to) / 2;
} else {
let mapPos = mouseArea.mapToItem(videoOutput, mouseArea.mouseX, mouseArea.mouseY);
let xFactor = mapPos.x / width;
let yFactor = mapPos.y / height;
let diffX = scaleWidthAnimation.to - width;
let diffY = scaleHeightAnimation.to - height;
scaleXAnimation.to = x - xFactor * diffX;
scaleYAnimation.to = y - yFactor * diffY;
}
scaleAnimation.restart();
}
ParallelAnimation {
id: scaleAnimation
NumberAnimation {
id: scaleWidthAnimation
property: "width"
target: videoOutput
duration: 220
}
NumberAnimation {
id: scaleHeightAnimation
property: "height"
target: videoOutput
duration: 220
}
NumberAnimation {
id: scaleXAnimation
property: "x"
target: videoOutput
duration: 220
}
NumberAnimation {
id: scaleYAnimation
property: "y"
target: videoOutput
duration: 220
}
}
}
}
至于如何使用?实际上在 onWheel
中已经给出了方式。
例如,我们想要放大到 2.0x
,只需要这样:
videoOutput.addScaleFactor(2.0 - videoOutput.scaleFactor);
而缩小同理,并且,addScaleFactor
第二参数支持 中心放大模式
,可以在需要时传入即可。
最后我们通过使用 ParallelAnimation
并行动画,就可以实现平滑流畅的 4K、8K超高清视频电子放大
效果。
免费下载体验:SkeyeARS 全景 AR 增强监视系统
## 关于SkeyeARS ##
SkeyeARS全景AR增强监视系统, 是视开科技开发的一款基于宽场景多路视频无缝拼接、视频实时增强、监视目标增强显示、目标自动跟踪、视频存储回放、远程数据传输和多通道全景视频同步显示等功能的综合视频AR增强监视系统,广泛应用于智慧交通、智慧城市、智慧机场等大场景智能监控领域。