mirror of
https://github.com/zhuzichu520/FluentUI.git
synced 2025-06-03 09:14:02 +08:00
feat: FluTour增加指示器和动画效果
This commit is contained in:
parent
e27f1591b0
commit
97e88dbd6f
@ -2737,49 +2737,60 @@ Some contents...</source>
|
||||
<name>T_Tour</name>
|
||||
<message>
|
||||
<location filename="qml/page/T_Tour.qml" line="15"/>
|
||||
<location filename="qml/page/T_Tour.qml" line="23"/>
|
||||
<source>Upload File</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/page/T_Tour.qml" line="15"/>
|
||||
<location filename="qml/page/T_Tour.qml" line="23"/>
|
||||
<source>Put your files here.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/page/T_Tour.qml" line="16"/>
|
||||
<location filename="qml/page/T_Tour.qml" line="52"/>
|
||||
<location filename="qml/page/T_Tour.qml" line="54"/>
|
||||
<location filename="qml/page/T_Tour.qml" line="24"/>
|
||||
<location filename="qml/page/T_Tour.qml" line="74"/>
|
||||
<location filename="qml/page/T_Tour.qml" line="76"/>
|
||||
<source>Save</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/page/T_Tour.qml" line="16"/>
|
||||
<location filename="qml/page/T_Tour.qml" line="24"/>
|
||||
<source>Save your changes.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/page/T_Tour.qml" line="17"/>
|
||||
<location filename="qml/page/T_Tour.qml" line="25"/>
|
||||
<source>Other Actions</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/page/T_Tour.qml" line="17"/>
|
||||
<location filename="qml/page/T_Tour.qml" line="25"/>
|
||||
<source>Click to see other actions.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/page/T_Tour.qml" line="31"/>
|
||||
<location filename="qml/page/T_Tour.qml" line="46"/>
|
||||
<source>Begin Tour</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/page/T_Tour.qml" line="45"/>
|
||||
<location filename="qml/page/T_Tour.qml" line="47"/>
|
||||
<location filename="qml/page/T_Tour.qml" line="52"/>
|
||||
<source>Begin Tour with custom indicator</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/page/T_Tour.qml" line="67"/>
|
||||
<location filename="qml/page/T_Tour.qml" line="69"/>
|
||||
<source>Upload</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/page/T_Tour.qml" line="61"/>
|
||||
<location filename="qml/page/T_Tour.qml" line="83"/>
|
||||
<source>More</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
|
@ -552,7 +552,7 @@
|
||||
<message>
|
||||
<location filename="qml/global/ItemsOriginal.qml" line="448"/>
|
||||
<source>Tour</source>
|
||||
<translation type="unfinished">游览</translation>
|
||||
<translation type="unfinished">漫游式引导</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/global/ItemsOriginal.qml" line="454"/>
|
||||
@ -2938,56 +2938,67 @@ Some contents...</source>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/page/T_Tour.qml" line="15"/>
|
||||
<location filename="qml/page/T_Tour.qml" line="23"/>
|
||||
<source>Upload File</source>
|
||||
<translation type="unfinished">上传文件</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/page/T_Tour.qml" line="15"/>
|
||||
<location filename="qml/page/T_Tour.qml" line="23"/>
|
||||
<source>Put your files here.</source>
|
||||
<translation type="unfinished">把你的文件放在这里</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/page/T_Tour.qml" line="16"/>
|
||||
<location filename="qml/page/T_Tour.qml" line="52"/>
|
||||
<location filename="qml/page/T_Tour.qml" line="54"/>
|
||||
<location filename="qml/page/T_Tour.qml" line="24"/>
|
||||
<location filename="qml/page/T_Tour.qml" line="74"/>
|
||||
<location filename="qml/page/T_Tour.qml" line="76"/>
|
||||
<source>Save</source>
|
||||
<translation type="unfinished">保存</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/page/T_Tour.qml" line="16"/>
|
||||
<location filename="qml/page/T_Tour.qml" line="24"/>
|
||||
<source>Save your changes.</source>
|
||||
<translation type="unfinished">保存更改</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/page/T_Tour.qml" line="17"/>
|
||||
<location filename="qml/page/T_Tour.qml" line="25"/>
|
||||
<source>Other Actions</source>
|
||||
<translation type="unfinished">其他操作</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/page/T_Tour.qml" line="17"/>
|
||||
<location filename="qml/page/T_Tour.qml" line="25"/>
|
||||
<source>Click to see other actions.</source>
|
||||
<translation type="unfinished">点击查看其他操作</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/page/T_Tour.qml" line="31"/>
|
||||
<location filename="qml/page/T_Tour.qml" line="46"/>
|
||||
<source>Begin Tour</source>
|
||||
<translation type="unfinished">开始游览</translation>
|
||||
<translation type="unfinished">开始导览</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/page/T_Tour.qml" line="45"/>
|
||||
<location filename="qml/page/T_Tour.qml" line="47"/>
|
||||
<location filename="qml/page/T_Tour.qml" line="52"/>
|
||||
<source>Begin Tour with custom indicator</source>
|
||||
<translation type="unfinished">以自定义指示器开始导览</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/page/T_Tour.qml" line="67"/>
|
||||
<location filename="qml/page/T_Tour.qml" line="69"/>
|
||||
<source>Upload</source>
|
||||
<translation type="unfinished">上传</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/page/T_Tour.qml" line="61"/>
|
||||
<location filename="qml/page/T_Tour.qml" line="83"/>
|
||||
<source>More</source>
|
||||
<translation type="unfinished">更多</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="qml/page/T_Tour.qml" line="10"/>
|
||||
<source>Tour</source>
|
||||
<translation type="unfinished">游览</translation>
|
||||
<translation type="unfinished">漫游式引导</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
|
@ -17,20 +17,42 @@ FluScrollablePage{
|
||||
{title:qsTr("Other Actions"),description: qsTr("Click to see other actions."),target:()=>btn_more}
|
||||
]
|
||||
}
|
||||
FluTour{
|
||||
id:tour_custom_indicator
|
||||
steps:[
|
||||
{title:qsTr("Upload File"),description: qsTr("Put your files here."),target:()=>btn_upload},
|
||||
{title:qsTr("Save"),description: qsTr("Save your changes."),target:()=>btn_save},
|
||||
{title:qsTr("Other Actions"),description: qsTr("Click to see other actions."),target:()=>btn_more}
|
||||
]
|
||||
indicator: Component{
|
||||
FluText {
|
||||
text: "%1 / %2".arg(current + 1).arg(total)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FluFrame{
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: 130
|
||||
padding: 10
|
||||
|
||||
FluFilledButton{
|
||||
Row{
|
||||
anchors{
|
||||
top: parent.top
|
||||
topMargin: 14
|
||||
}
|
||||
text: qsTr("Begin Tour")
|
||||
onClicked: {
|
||||
tour.open()
|
||||
spacing: 20
|
||||
FluFilledButton{
|
||||
text: qsTr("Begin Tour")
|
||||
onClicked: {
|
||||
tour.open()
|
||||
}
|
||||
}
|
||||
FluFilledButton{
|
||||
text: qsTr("Begin Tour with custom indicator")
|
||||
onClicked: {
|
||||
tour_custom_indicator.open()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -7,8 +7,10 @@ import FluentUI 1.0
|
||||
Popup{
|
||||
property var steps : []
|
||||
property int targetMargins: 5
|
||||
property int targetRadius: 2
|
||||
property Component nextButton: com_next_button
|
||||
property Component prevButton: com_prev_button
|
||||
property Component indicator: com_indicator
|
||||
property int index : 0
|
||||
property string finishText: qsTr("Finish")
|
||||
property string nextText: qsTr("Next")
|
||||
@ -22,12 +24,12 @@ Popup{
|
||||
contentItem: Item{}
|
||||
onVisibleChanged: {
|
||||
if(visible){
|
||||
d.animationEnabled = false
|
||||
control.index = 0
|
||||
d.updatePos()
|
||||
d.animationEnabled = true
|
||||
}
|
||||
}
|
||||
onIndexChanged: {
|
||||
canvas.requestPaint()
|
||||
}
|
||||
Component{
|
||||
id: com_next_button
|
||||
FluFilledButton{
|
||||
@ -50,10 +52,32 @@ Popup{
|
||||
}
|
||||
}
|
||||
}
|
||||
Component{
|
||||
id: com_indicator
|
||||
Row{
|
||||
spacing: 10
|
||||
Repeater{
|
||||
model: total
|
||||
delegate: Rectangle{
|
||||
width: 8
|
||||
height: 8
|
||||
radius: 4
|
||||
scale: current === index ? 1.2 : 1
|
||||
color:{
|
||||
if(current === index){
|
||||
return FluTheme.primaryColor
|
||||
}
|
||||
return FluTheme.dark ? Qt.rgba(99/255,99/255,99/255,1) : Qt.rgba(214/255,214/255,214/255,1)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Item{
|
||||
id:d
|
||||
property var window: Window.window
|
||||
property point pos: Qt.point(0,0)
|
||||
property bool animationEnabled: true
|
||||
property var step: steps[index]
|
||||
property var target: {
|
||||
if(steps[index]){
|
||||
@ -73,15 +97,22 @@ Popup{
|
||||
}
|
||||
return control.width
|
||||
}
|
||||
function updatePos(){
|
||||
if(d.target && d.window){
|
||||
d.pos = d.target.mapToGlobal(0,0)
|
||||
d.pos = Qt.point(d.pos.x-d.window.x,d.pos.y-d.window.y)
|
||||
}
|
||||
}
|
||||
onTargetChanged: {
|
||||
updatePos()
|
||||
}
|
||||
}
|
||||
Connections{
|
||||
target: d.window
|
||||
function onWidthChanged(){
|
||||
canvas.requestPaint()
|
||||
timer_delay.restart()
|
||||
}
|
||||
function onHeightChanged(){
|
||||
canvas.requestPaint()
|
||||
timer_delay.restart()
|
||||
}
|
||||
}
|
||||
@ -89,39 +120,128 @@ Popup{
|
||||
id: timer_delay
|
||||
interval: 200
|
||||
onTriggered: {
|
||||
canvas.requestPaint()
|
||||
d.updatePos()
|
||||
}
|
||||
}
|
||||
Canvas{
|
||||
id: canvas
|
||||
anchors.fill: parent
|
||||
onPaint: {
|
||||
d.pos = d.target.mapToGlobal(0,0)
|
||||
d.pos = Qt.point(d.pos.x-d.window.x,d.pos.y-d.window.y)
|
||||
var ctx = canvas.getContext("2d")
|
||||
ctx.clearRect(0, 0, canvasSize.width, canvasSize.height)
|
||||
ctx.save()
|
||||
ctx.fillStyle = "#88000000"
|
||||
ctx.fillRect(0, 0, canvasSize.width, canvasSize.height)
|
||||
ctx.globalCompositeOperation = 'destination-out'
|
||||
ctx.fillStyle = 'black'
|
||||
var rect = Qt.rect(d.pos.x-control.targetMargins,d.pos.y-control.targetMargins, d.target.width+control.targetMargins*2, d.target.height+control.targetMargins*2)
|
||||
drawRoundedRect(rect,2,ctx)
|
||||
ctx.restore()
|
||||
Item{
|
||||
id: targetRect
|
||||
x: d.pos.x - control.targetMargins
|
||||
y: d.pos.y - control.targetMargins
|
||||
width: d.target ? d.target.width + control.targetMargins * 2 : 0
|
||||
height: d.target ? d.target.height + control.targetMargins * 2 : 0
|
||||
Behavior on x {
|
||||
enabled: d.animationEnabled && FluTheme.animationEnabled
|
||||
NumberAnimation {
|
||||
duration: 167
|
||||
}
|
||||
}
|
||||
function drawRoundedRect(rect, r, ctx) {
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(rect.x + r, rect.y);
|
||||
ctx.lineTo(rect.x + rect.width - r, rect.y);
|
||||
ctx.arcTo(rect.x + rect.width, rect.y, rect.x + rect.width, rect.y + r, r);
|
||||
ctx.lineTo(rect.x + rect.width, rect.y + rect.height - r);
|
||||
ctx.arcTo(rect.x + rect.width, rect.y + rect.height, rect.x + rect.width - r, rect.y + rect.height, r);
|
||||
ctx.lineTo(rect.x + r, rect.y + rect.height);
|
||||
ctx.arcTo(rect.x, rect.y + rect.height, rect.x, rect.y + rect.height - r, r);
|
||||
ctx.lineTo(rect.x, rect.y + r);
|
||||
ctx.arcTo(rect.x, rect.y, rect.x + r, rect.y, r);
|
||||
ctx.closePath();
|
||||
ctx.fill()
|
||||
Behavior on y {
|
||||
enabled: d.animationEnabled && FluTheme.animationEnabled
|
||||
NumberAnimation {
|
||||
duration: 167
|
||||
}
|
||||
}
|
||||
Behavior on width {
|
||||
enabled: d.animationEnabled && FluTheme.animationEnabled
|
||||
NumberAnimation {
|
||||
duration: 167
|
||||
}
|
||||
}
|
||||
Behavior on height {
|
||||
enabled: d.animationEnabled && FluTheme.animationEnabled
|
||||
NumberAnimation {
|
||||
duration: 167
|
||||
}
|
||||
}
|
||||
}
|
||||
Shape {
|
||||
anchors.fill: parent
|
||||
layer.enabled: true
|
||||
layer.samples: 4
|
||||
layer.smooth: true
|
||||
ShapePath {
|
||||
fillColor: "#88000000"
|
||||
strokeWidth: 0
|
||||
strokeColor: "transparent"
|
||||
|
||||
// draw background
|
||||
PathMove {
|
||||
x: 0
|
||||
y: 0
|
||||
}
|
||||
PathLine {
|
||||
x: control.width
|
||||
y: 0
|
||||
}
|
||||
PathLine {
|
||||
x: control.width
|
||||
y: control.height
|
||||
}
|
||||
PathLine {
|
||||
x: 0
|
||||
y: control.height
|
||||
}
|
||||
PathLine {
|
||||
x: 0
|
||||
y: 0
|
||||
}
|
||||
|
||||
// draw highlight
|
||||
PathMove {
|
||||
x: targetRect.x + control.targetRadius
|
||||
y: targetRect.y
|
||||
}
|
||||
PathLine {
|
||||
x: targetRect.x + targetRect.width - control.targetRadius
|
||||
y: targetRect.y
|
||||
}
|
||||
PathArc {
|
||||
x: targetRect.x + targetRect.width
|
||||
y: targetRect.y + control.targetRadius
|
||||
radiusX: control.targetRadius
|
||||
radiusY: control.targetRadius
|
||||
useLargeArc: false
|
||||
direction: PathArc.Clockwise
|
||||
}
|
||||
|
||||
PathLine {
|
||||
x: targetRect.x + targetRect.width
|
||||
y: targetRect.y + targetRect.height - control.targetRadius
|
||||
}
|
||||
PathArc {
|
||||
x: targetRect.x + targetRect.width - control.targetRadius
|
||||
y: targetRect.y + targetRect.height
|
||||
radiusX: control.targetRadius
|
||||
radiusY: control.targetRadius
|
||||
useLargeArc: false
|
||||
direction: PathArc.Clockwise
|
||||
}
|
||||
|
||||
PathLine {
|
||||
x: targetRect.x + control.targetRadius
|
||||
y: targetRect.y + targetRect.height
|
||||
}
|
||||
PathArc {
|
||||
x: targetRect.x
|
||||
y: targetRect.y + targetRect.height - control.targetRadius
|
||||
radiusX: control.targetRadius
|
||||
radiusY: control.targetRadius
|
||||
useLargeArc: false
|
||||
direction: PathArc.Clockwise
|
||||
}
|
||||
|
||||
PathLine {
|
||||
x: targetRect.x
|
||||
y: targetRect.y + control.targetRadius
|
||||
}
|
||||
PathArc {
|
||||
x: targetRect.x + control.targetRadius
|
||||
y: targetRect.y
|
||||
radiusX: control.targetRadius
|
||||
radiusY: control.targetRadius
|
||||
useLargeArc: false
|
||||
direction: PathArc.Clockwise
|
||||
}
|
||||
}
|
||||
}
|
||||
FluFrame{
|
||||
@ -151,6 +271,18 @@ Popup{
|
||||
return 0
|
||||
}
|
||||
border.width: 0
|
||||
Behavior on x {
|
||||
enabled: d.animationEnabled && FluTheme.animationEnabled
|
||||
NumberAnimation {
|
||||
duration: 167
|
||||
}
|
||||
}
|
||||
Behavior on y {
|
||||
enabled: d.animationEnabled && FluTheme.animationEnabled
|
||||
NumberAnimation {
|
||||
duration: 167
|
||||
}
|
||||
}
|
||||
FluShadow{
|
||||
radius: 5
|
||||
}
|
||||
@ -193,10 +325,21 @@ Popup{
|
||||
leftMargin: 15
|
||||
}
|
||||
}
|
||||
FluLoader{
|
||||
readonly property int total: steps.length
|
||||
readonly property int current: control.index
|
||||
sourceComponent: control.indicator
|
||||
anchors{
|
||||
bottom: parent.bottom
|
||||
left: parent.left
|
||||
bottomMargin: 15
|
||||
leftMargin: 15
|
||||
}
|
||||
}
|
||||
FluLoader{
|
||||
id: loader_next
|
||||
property bool isEnd: control.index === steps.length-1
|
||||
sourceComponent: com_next_button
|
||||
sourceComponent: control.nextButton
|
||||
anchors{
|
||||
top: text_desc.bottom
|
||||
topMargin: 10
|
||||
@ -207,7 +350,7 @@ Popup{
|
||||
FluLoader{
|
||||
id: loader_prev
|
||||
visible: control.index !== 0
|
||||
sourceComponent: com_prev_button
|
||||
sourceComponent: control.prevButton
|
||||
anchors{
|
||||
right: loader_next.left
|
||||
top: loader_next.top
|
||||
@ -246,5 +389,17 @@ Popup{
|
||||
}
|
||||
return 0
|
||||
}
|
||||
Behavior on x {
|
||||
enabled: d.animationEnabled && FluTheme.animationEnabled
|
||||
NumberAnimation {
|
||||
duration: 167
|
||||
}
|
||||
}
|
||||
Behavior on y {
|
||||
enabled: d.animationEnabled && FluTheme.animationEnabled
|
||||
NumberAnimation {
|
||||
duration: 167
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4328,8 +4328,10 @@ Module {
|
||||
defaultProperty: "contentData"
|
||||
Property { name: "steps"; type: "QVariant" }
|
||||
Property { name: "targetMargins"; type: "int" }
|
||||
Property { name: "targetRadius"; type: "int" }
|
||||
Property { name: "nextButton"; type: "QQmlComponent"; isPointer: true }
|
||||
Property { name: "prevButton"; type: "QQmlComponent"; isPointer: true }
|
||||
Property { name: "indicator"; type: "QQmlComponent"; isPointer: true }
|
||||
Property { name: "index"; type: "int" }
|
||||
Property { name: "finishText"; type: "string" }
|
||||
Property { name: "nextText"; type: "string" }
|
||||
|
@ -7,8 +7,10 @@ import FluentUI
|
||||
Popup{
|
||||
property var steps : []
|
||||
property int targetMargins: 5
|
||||
property int targetRadius: 2
|
||||
property Component nextButton: com_next_button
|
||||
property Component prevButton: com_prev_button
|
||||
property Component indicator: com_indicator
|
||||
property int index : 0
|
||||
property string finishText: qsTr("Finish")
|
||||
property string nextText: qsTr("Next")
|
||||
@ -22,12 +24,12 @@ Popup{
|
||||
contentItem: Item{}
|
||||
onVisibleChanged: {
|
||||
if(visible){
|
||||
d.animationEnabled = false
|
||||
control.index = 0
|
||||
d.updatePos()
|
||||
d.animationEnabled = true
|
||||
}
|
||||
}
|
||||
onIndexChanged: {
|
||||
canvas.requestPaint()
|
||||
}
|
||||
Component{
|
||||
id: com_next_button
|
||||
FluFilledButton{
|
||||
@ -50,10 +52,32 @@ Popup{
|
||||
}
|
||||
}
|
||||
}
|
||||
Component{
|
||||
id: com_indicator
|
||||
Row{
|
||||
spacing: 10
|
||||
Repeater{
|
||||
model: total
|
||||
delegate: Rectangle{
|
||||
width: 8
|
||||
height: 8
|
||||
radius: 4
|
||||
scale: current === index ? 1.2 : 1
|
||||
color:{
|
||||
if(current === index){
|
||||
return FluTheme.primaryColor
|
||||
}
|
||||
return FluTheme.dark ? Qt.rgba(99/255,99/255,99/255,1) : Qt.rgba(214/255,214/255,214/255,1)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Item{
|
||||
id:d
|
||||
property var window: Window.window
|
||||
property point pos: Qt.point(0,0)
|
||||
property bool animationEnabled: true
|
||||
property var step: steps[index]
|
||||
property var target: {
|
||||
if(steps[index]){
|
||||
@ -73,15 +97,22 @@ Popup{
|
||||
}
|
||||
return control.width
|
||||
}
|
||||
function updatePos(){
|
||||
if(d.target && d.window){
|
||||
d.pos = d.target.mapToGlobal(0,0)
|
||||
d.pos = Qt.point(d.pos.x-d.window.x,d.pos.y-d.window.y)
|
||||
}
|
||||
}
|
||||
onTargetChanged: {
|
||||
updatePos()
|
||||
}
|
||||
}
|
||||
Connections{
|
||||
target: d.window
|
||||
function onWidthChanged(){
|
||||
canvas.requestPaint()
|
||||
timer_delay.restart()
|
||||
}
|
||||
function onHeightChanged(){
|
||||
canvas.requestPaint()
|
||||
timer_delay.restart()
|
||||
}
|
||||
}
|
||||
@ -89,39 +120,128 @@ Popup{
|
||||
id: timer_delay
|
||||
interval: 200
|
||||
onTriggered: {
|
||||
canvas.requestPaint()
|
||||
d.updatePos()
|
||||
}
|
||||
}
|
||||
Canvas{
|
||||
id: canvas
|
||||
anchors.fill: parent
|
||||
onPaint: {
|
||||
d.pos = d.target.mapToGlobal(0,0)
|
||||
d.pos = Qt.point(d.pos.x-d.window.x,d.pos.y-d.window.y)
|
||||
var ctx = canvas.getContext("2d")
|
||||
ctx.clearRect(0, 0, canvasSize.width, canvasSize.height)
|
||||
ctx.save()
|
||||
ctx.fillStyle = "#88000000"
|
||||
ctx.fillRect(0, 0, canvasSize.width, canvasSize.height)
|
||||
ctx.globalCompositeOperation = 'destination-out'
|
||||
ctx.fillStyle = 'black'
|
||||
var rect = Qt.rect(d.pos.x-control.targetMargins,d.pos.y-control.targetMargins, d.target.width+control.targetMargins*2, d.target.height+control.targetMargins*2)
|
||||
drawRoundedRect(rect,2,ctx)
|
||||
ctx.restore()
|
||||
Item{
|
||||
id: targetRect
|
||||
x: d.pos.x - control.targetMargins
|
||||
y: d.pos.y - control.targetMargins
|
||||
width: d.target ? d.target.width + control.targetMargins * 2 : 0
|
||||
height: d.target ? d.target.height + control.targetMargins * 2 : 0
|
||||
Behavior on x {
|
||||
enabled: d.animationEnabled && FluTheme.animationEnabled
|
||||
NumberAnimation {
|
||||
duration: 167
|
||||
}
|
||||
}
|
||||
function drawRoundedRect(rect, r, ctx) {
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(rect.x + r, rect.y);
|
||||
ctx.lineTo(rect.x + rect.width - r, rect.y);
|
||||
ctx.arcTo(rect.x + rect.width, rect.y, rect.x + rect.width, rect.y + r, r);
|
||||
ctx.lineTo(rect.x + rect.width, rect.y + rect.height - r);
|
||||
ctx.arcTo(rect.x + rect.width, rect.y + rect.height, rect.x + rect.width - r, rect.y + rect.height, r);
|
||||
ctx.lineTo(rect.x + r, rect.y + rect.height);
|
||||
ctx.arcTo(rect.x, rect.y + rect.height, rect.x, rect.y + rect.height - r, r);
|
||||
ctx.lineTo(rect.x, rect.y + r);
|
||||
ctx.arcTo(rect.x, rect.y, rect.x + r, rect.y, r);
|
||||
ctx.closePath();
|
||||
ctx.fill()
|
||||
Behavior on y {
|
||||
enabled: d.animationEnabled && FluTheme.animationEnabled
|
||||
NumberAnimation {
|
||||
duration: 167
|
||||
}
|
||||
}
|
||||
Behavior on width {
|
||||
enabled: d.animationEnabled && FluTheme.animationEnabled
|
||||
NumberAnimation {
|
||||
duration: 167
|
||||
}
|
||||
}
|
||||
Behavior on height {
|
||||
enabled: d.animationEnabled && FluTheme.animationEnabled
|
||||
NumberAnimation {
|
||||
duration: 167
|
||||
}
|
||||
}
|
||||
}
|
||||
Shape {
|
||||
anchors.fill: parent
|
||||
layer.enabled: true
|
||||
layer.samples: 4
|
||||
layer.smooth: true
|
||||
ShapePath {
|
||||
fillColor: "#88000000"
|
||||
strokeWidth: 0
|
||||
strokeColor: "transparent"
|
||||
|
||||
// draw background
|
||||
PathMove {
|
||||
x: 0
|
||||
y: 0
|
||||
}
|
||||
PathLine {
|
||||
x: control.width
|
||||
y: 0
|
||||
}
|
||||
PathLine {
|
||||
x: control.width
|
||||
y: control.height
|
||||
}
|
||||
PathLine {
|
||||
x: 0
|
||||
y: control.height
|
||||
}
|
||||
PathLine {
|
||||
x: 0
|
||||
y: 0
|
||||
}
|
||||
|
||||
// draw highlight
|
||||
PathMove {
|
||||
x: targetRect.x + control.targetRadius
|
||||
y: targetRect.y
|
||||
}
|
||||
PathLine {
|
||||
x: targetRect.x + targetRect.width - control.targetRadius
|
||||
y: targetRect.y
|
||||
}
|
||||
PathArc {
|
||||
x: targetRect.x + targetRect.width
|
||||
y: targetRect.y + control.targetRadius
|
||||
radiusX: control.targetRadius
|
||||
radiusY: control.targetRadius
|
||||
useLargeArc: false
|
||||
direction: PathArc.Clockwise
|
||||
}
|
||||
|
||||
PathLine {
|
||||
x: targetRect.x + targetRect.width
|
||||
y: targetRect.y + targetRect.height - control.targetRadius
|
||||
}
|
||||
PathArc {
|
||||
x: targetRect.x + targetRect.width - control.targetRadius
|
||||
y: targetRect.y + targetRect.height
|
||||
radiusX: control.targetRadius
|
||||
radiusY: control.targetRadius
|
||||
useLargeArc: false
|
||||
direction: PathArc.Clockwise
|
||||
}
|
||||
|
||||
PathLine {
|
||||
x: targetRect.x + control.targetRadius
|
||||
y: targetRect.y + targetRect.height
|
||||
}
|
||||
PathArc {
|
||||
x: targetRect.x
|
||||
y: targetRect.y + targetRect.height - control.targetRadius
|
||||
radiusX: control.targetRadius
|
||||
radiusY: control.targetRadius
|
||||
useLargeArc: false
|
||||
direction: PathArc.Clockwise
|
||||
}
|
||||
|
||||
PathLine {
|
||||
x: targetRect.x
|
||||
y: targetRect.y + control.targetRadius
|
||||
}
|
||||
PathArc {
|
||||
x: targetRect.x + control.targetRadius
|
||||
y: targetRect.y
|
||||
radiusX: control.targetRadius
|
||||
radiusY: control.targetRadius
|
||||
useLargeArc: false
|
||||
direction: PathArc.Clockwise
|
||||
}
|
||||
}
|
||||
}
|
||||
FluFrame{
|
||||
@ -151,6 +271,18 @@ Popup{
|
||||
return 0
|
||||
}
|
||||
border.width: 0
|
||||
Behavior on x {
|
||||
enabled: d.animationEnabled && FluTheme.animationEnabled
|
||||
NumberAnimation {
|
||||
duration: 167
|
||||
}
|
||||
}
|
||||
Behavior on y {
|
||||
enabled: d.animationEnabled && FluTheme.animationEnabled
|
||||
NumberAnimation {
|
||||
duration: 167
|
||||
}
|
||||
}
|
||||
FluShadow{
|
||||
radius: 5
|
||||
}
|
||||
@ -193,10 +325,21 @@ Popup{
|
||||
leftMargin: 15
|
||||
}
|
||||
}
|
||||
FluLoader{
|
||||
readonly property int total: steps.length
|
||||
readonly property int current: control.index
|
||||
sourceComponent: control.indicator
|
||||
anchors{
|
||||
bottom: parent.bottom
|
||||
left: parent.left
|
||||
bottomMargin: 15
|
||||
leftMargin: 15
|
||||
}
|
||||
}
|
||||
FluLoader{
|
||||
id: loader_next
|
||||
property bool isEnd: control.index === steps.length-1
|
||||
sourceComponent: com_next_button
|
||||
sourceComponent: control.nextButton
|
||||
anchors{
|
||||
top: text_desc.bottom
|
||||
topMargin: 10
|
||||
@ -207,7 +350,7 @@ Popup{
|
||||
FluLoader{
|
||||
id: loader_prev
|
||||
visible: control.index !== 0
|
||||
sourceComponent: com_prev_button
|
||||
sourceComponent: control.prevButton
|
||||
anchors{
|
||||
right: loader_next.left
|
||||
top: loader_next.top
|
||||
@ -246,5 +389,17 @@ Popup{
|
||||
}
|
||||
return 0
|
||||
}
|
||||
Behavior on x {
|
||||
enabled: d.animationEnabled && FluTheme.animationEnabled
|
||||
NumberAnimation {
|
||||
duration: 167
|
||||
}
|
||||
}
|
||||
Behavior on y {
|
||||
enabled: d.animationEnabled && FluTheme.animationEnabled
|
||||
NumberAnimation {
|
||||
duration: 167
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user