经验大分享:QML动态标注线

简介: 经验大分享:QML动态标注线

QML动态标注线

1,目的

有些情况对某个位置进行标注,但是背景过于复杂, 需要将标注点和标注内容进行分离,这时就需要用到标注线。我们即明确知道了标注的的信息也让界面更加均衡。

效果图:

图1

图2

2,设计分析

如果单纯将标识点连线到标注区,这样在标注内容较多时是会给人杂乱不堪的感觉。这里我们先使用30度倾角拉出斜线,再使用水平画线延伸到目标点。后期在逻辑上控制斜线尽量不发生交叉,那么给人的感觉就较为整齐。

基本原理:我们已知信息是起始点、结束点坐标,首先通过起始点向结束的点的水平面画倾角30度的斜线,与结束点水平面重叠时转为画水平线直至结束坐标。

3,设计内容

首先在主qml中创建tagLine.qml组件,添加组件属性和基本元素。代码如下:

import QtQuick 2.0

Item {

id: tagLine

property point startPoint: Qt.point(0, 0)

property point endPoint: Qt.point(0, 0)

property var lineColor: "70ffe42f"

property var lineWidth: 1

//斜线长度

property var oblLineLength: 0

//水平线长度

property var horLineLength: 0

Rectangle{

id: oblLine

antialiasing: true

height: lineWidth

color: lineColor

transformOrigin: Item.TopLeft

}

Rectangle{

id: horLine

antialiasing: true

height: lineWidth

color: lineColor

transformOrigin: Item.TopLeft

}

}

从代码中可知 我们是使用rectangle作为线条进行绘制。现在基本元素已经齐全,下一步就是计算线条长度,和添加画线动画。

我们先实现线条长度计算函数。

首先我们需要了解界面的坐标系,水平方向右是x轴正向,垂直向下是y轴正向。

图3

在这个坐标系中,结束点可能会出现在起始点的如下4个区域中,我们先实现区域1中的计数,其他区域只需要在这个基础上稍微调整角度即可。

图4

下图5所示,我们最终需要的是a,c这两条线长。利用三角函数,已知b、f先算a=b/cos30°,d=btan30° 。下图是收藏的常用三角函数值表图6

图5

图6

这里还有一种情况就是d大于f的情况,这时我们就不能使用30度斜边改用垂线。实现代码如下

function drawCala() {

//相对角度

var angle= 0

//实际角度值

var realAngle = 0;

var newOblLeng = 0;

var newHorLeng = 0;

var tmpx = Math.abs(startPoint.x - endPoint.x);

var tmpy = Math.abs(startPoint.y - endPoint.y);

//情况1 30°夹角

if (tmpx >= Math.floor((Math.sqrt(3) / 3) tmpy))

{

newOblLeng = Math.floor(tmpy / (Math.sqrt(3) / 2));

newHorLeng = tmpx - Math.floor((Math.floor((Math.sqrt(3) / 3) tmpy)));

angle = 60;

}

//情况2 垂线和直线配合

else

{

newOblLeng = tmpy;

newHorLeng = tmpx;

angle = 90;

}

oblLine.width = newOblLeng;

horLine.width = newHorLeng;

}

到此我们已经计算出了这两根线的线长。还需要继续处理如下内容才算完成。

1,计算出c/a交汇的位置坐标,作为水平线c的起始点;

2,根据终点在起点的4个不同区域内,计算出线段a的倾角;

3,根据终点在起点的4个不同区域内,计算出水平线c的延伸方向;

4,添加动画,在a从起点开始延伸到达计算值后,水平线开始延伸,最终到达终点。

这里就不多说了,直接看代码吧,效果如下

图7

最终实现的代码:

tagLine.qml

import QtQuick 2.0

Item {

property point startPoint: Qt.point(0, 0)

property point endPoint: Qt.point(0, 0)

property var lineColor: "#70ffe42f"

property var lineWidth: 1

//斜线长度

property var oblLineLength: 0

//水平线长度

property var horLineLength: 0

onStartPointChanged: {

drawCala();

}

onEndPointChanged: {

drawCala();

}

function drawCala() {

//相对角度

var angle= 0

//实际角度值

var realAngle = 0;

var newOblLeng = 0;

var newHorLeng = 0;

var tmpx = Math.abs(startPoint.x - endPoint.x);

var tmpy = Math.abs(startPoint.y - endPoint.y);

//情况1 30°夹角

if (tmpx >= Math.floor((Math.sqrt(3) / 3) tmpy))

{

newOblLeng = Math.floor(tmpy / (Math.sqrt(3) / 2));

newHorLeng = tmpx - Math.floor((Math.floor((Math.sqrt(3) / 3) * tmpy)));

angle = 60;

}

//情况2 垂线和直线配合

else

{

newOblLeng = tmpy;

newHorLeng = tmpx;

angle = 90;

}

//水平线的Y坐标 和结束点Y坐标相同

horLine.y = endPoint.y;

//结束的点在起始点的左上方

if ((startPoint.x >= endPoint.x) (startPoint.y >= endPoint.y))

{

realAngle = 180 + angle;

horLine.x = endPoint.x + newHorLeng;

horLine.rotation = 180;

}

//结束的点在起始点的右上方

else if ((startPoint.x = endPoint.y))

{

realAngle = -angle;

horLine.x = endPoint.x - newHorLeng;

horLine.rotation = 0;

}

//结束的点在起始点的右下方

else if ((startPoint.x <= endPoint.x) (startPoint.y = endPoint.x) (startPoint.y 0)

{

oblAnimation.restart();

}

else

{

//当使用垂线时斜线长度清零

oblLine.width = oblLineLength;

//直接进行水平延伸

horLine.visible = true;

horAnimation.restart();

}

}

Rectangle{

id: oblLine

antialiasing: true

height: lineWidth

color: lineColor

transformOrigin: Item.TopLeft

}

Rectangle{

id: horLine

antialiasing: true

height: lineWidth

color: lineColor

transformOrigin: Item.TopLeft

}//代码效果参考:http://www.ezhiqi.com/zx/art_7400.html

PropertyAnimation {

id: oblAnimation

target: oblLine

property: "width"

duration: 500

from: 0

to: oblLineLength

onStopped: {

if (horLineLength > 0)

{

horLine.visible = true

horAnimation.restart()

}

}

onStarted: {

horLine.visible = false

}

}

PropertyAnimation {

id: horAnimation

target: horLine

property: "width"

duration: 600

from: 0

to: horLineLength

}

}

使用标注线main.qml

import QtQuick 2.5

import QtQuick.Window 2.2

Window {

visible: true

width: 480

height: 240

color: "#1f1f1f"

TagLine {

id: myTagLine

}

MouseArea {

anchors.fill: parent

onClicked: {

myTagLine.startPoint = Qt.point(parent.width / 2, parent.height / 2)

myTagLine.endPoint = Qt.point(50, 50)

}

}

}

4,总结

利用Rectangle组件进行画线,然后再进行动画拼接,最终实现线条延伸效果,此组件比较适合应用在标识内容较多的场合。后续还可以配合标识框的组合动画让效果更佳。对以上代码稍作调整可实现如图1,2的效果。

下来大家发现有什么问题或需要讨论交流,可以在简书、博客园、或邮箱将问题进行留言,我会及时回复和更新。

邮箱: whqcxz@163.com

原创:

相关文章
|
5月前
|
Linux iOS开发 MacOS
【随手记】maplotlib.use函数设置图像的呈现方式
【随手记】maplotlib.use函数设置图像的呈现方式
55 0
|
6月前
|
JSON 定位技术 API
HTML新特性【规划公交路线、规划步行路线、定位、自定义视角动画、账号和获取密钥、初始化、变更地图类型、添加控件、改变控件位置】(五)-全面详解(学习总结---从入门到深化)(下)
HTML新特性【规划公交路线、规划步行路线、定位、自定义视角动画、账号和获取密钥、初始化、变更地图类型、添加控件、改变控件位置】(五)-全面详解(学习总结---从入门到深化)
70 0
|
数据可视化 物联网
Threejs物联网,养殖场3D可视化(三)模型展示,轨道控制器设置,模型沿着路线运动,模型添加边框,自定义样式显示标签,点击模型获取信息
Threejs物联网,养殖场3D可视化(三)模型展示,轨道控制器设置,模型沿着路线运动,模型添加边框,自定义样式显示标签,点击模型获取信息
941 15
Threejs物联网,养殖场3D可视化(三)模型展示,轨道控制器设置,模型沿着路线运动,模型添加边框,自定义样式显示标签,点击模型获取信息
|
6月前
|
移动开发 JavaScript 前端开发
HTML新特性【规划公交路线、规划步行路线、定位、自定义视角动画、账号和获取密钥、初始化、变更地图类型、添加控件、改变控件位置】(五)-全面详解(学习总结---从入门到深化)(上)
HTML新特性【规划公交路线、规划步行路线、定位、自定义视角动画、账号和获取密钥、初始化、变更地图类型、添加控件、改变控件位置】(五)-全面详解(学习总结---从入门到深化)
97 0
|
机器学习/深度学习 数据采集 PyTorch
图片风格自动分析模型
图片风格自动分析模型
210 0
|
存储 数据可视化 atlas
maftools | 从头开始绘制发表级oncoplot(瀑布图)
maftools | 从头开始绘制发表级oncoplot(瀑布图)
418 0
|
存储 JSON 数据可视化
ChatGPT工作提效之数据可视化大屏组件Echarts的实战方案(大数据量加载、伪3D饼图、地图各省cp中心坐标属性、map3D材质)
ChatGPT工作提效之数据可视化大屏组件Echarts的实战方案(大数据量加载、伪3D饼图、地图各省cp中心坐标属性、map3D材质)
638 0
|
数据采集 监控 数据可视化
做出酷炫的动态统计图表,不一定要写代码
首先这个名字很长的,就是上面 GDP 图表的作者 Jannchie见齐 基于 D3.js 开发的 将历史数据排名转化为动态柱状图图表 的项目,并在 github 上开源了。
|
数据安全/隐私保护
平面设计实验四 绘制工具和修饰工具
平面设计实验四 绘制工具和修饰工具
67 0
|
前端开发
前端知识案例学习9-可调整尺寸得UI
前端知识案例学习9-可调整尺寸得UI
133 0
前端知识案例学习9-可调整尺寸得UI