diff --git a/example/qml/window/MainWindow.qml b/example/qml/window/MainWindow.qml index 9e9a6e2..805bb7e 100644 --- a/example/qml/window/MainWindow.qml +++ b/example/qml/window/MainWindow.qml @@ -80,25 +80,25 @@ CustomWindow { id:flipable anchors.fill: parent property bool flipped: false + property real flipAngle: 0 transform: Rotation { id: rotation origin.x: flipable.width/2 origin.y: flipable.height/2 axis { x: 0; y: 1; z: 0 } - angle: 0 + angle: flipable.flipAngle } states: State { - name: "back" - PropertyChanges { target: rotation; angle: 180 } + PropertyChanges { target: flipable; flipAngle: 180 } when: flipable.flipped } transitions: Transition { - NumberAnimation { target: rotation; property: "angle"; duration: 1000 ; easing.type: Easing.OutQuad} + NumberAnimation { target: flipable; property: "flipAngle"; duration: 1000 ; easing.type: Easing.OutQuad} } back: Item{ anchors.fill: flipable - visible: rotation.angle !== 0 + visible: flipable.flipAngle !== 0 FluAppBar { anchors { top: parent.top @@ -108,6 +108,7 @@ CustomWindow { darkText: lang.dark_mode showDark: true z:7 + darkClickListener:(button)=>handleDarkChanged(button) } FluIconButton{ iconSource: FluentIcons.ChromeBack @@ -126,7 +127,8 @@ CustomWindow { } } front: Item{ - visible: rotation.angle !== 180 + id:page_front + visible: flipable.flipAngle !== 180 anchors.fill: flipable FluAppBar { anchors { @@ -136,6 +138,7 @@ CustomWindow { } darkText: lang.dark_mode showDark: true + darkClickListener:(button)=>handleDarkChanged(button) z:7 } FluNavigationView{ @@ -182,4 +185,83 @@ CustomWindow { } } } + + Image{ + id:img_cache + visible: false + anchors.fill: flipable + } + + Canvas{ + id:canvas + anchors.fill: flipable + property int centerX: canvas.width / 2 + property int centerY: canvas.height / 2 + property real radius: 0 + property int maxRadius: 0 + property url imageUrl + Behavior on radius{ + id:anim_radius + NumberAnimation { + target: canvas + property: "radius" + duration: 666 + easing.type: Easing.BezierSpline + easing.bezierCurve: [0,0,0,1] + } + } + onRadiusChanged: { + canvas.requestPaint() + } + onPaint: { + var ctx = canvas.getContext("2d"); + ctx.setTransform(1, 0, 0, 1, 0, 0); + ctx.clearRect(0, 0, canvas.width, canvas.height); + ctx.save() + if(img_cache.source.toString().length!==0){ + try{ + ctx.drawImage(img_cache.source, 0, 0, canvas.width, canvas.height, 0, 0, canvas.width, canvas.height) + }catch(e){ + img_cache.source = "" + } + } + clearArc(ctx, centerX, centerY, radius) + ctx.restore() + } + function clearArc(ctx,x, y, radius, startAngle, endAngle) { + ctx.beginPath() + ctx.globalCompositeOperation = 'destination-out' + ctx.fillStyle = 'black' + ctx.arc(x, y, radius, 0, 2*Math.PI); + ctx.fill(); + ctx.closePath(); + } + } + + function distance(x1,y1,x2,y2){ + return Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2)) + } + + function handleDarkChanged(button){ + var pos = button.mapToItem(flipable,0,0) + var mouseX = pos.x + var mouseY = pos.y + canvas.maxRadius = Math.max(distance(mouseX,mouseY,0,0),distance(mouseX,mouseY,canvas.width,0),distance(mouseX,mouseY,0,canvas.height),distance(mouseX,mouseY,canvas.width,canvas.height)) + window.contentItem.grabToImage(function(result) { + img_cache.source = result.url + canvas.requestPaint() + if(FluTheme.dark){ + FluTheme.darkMode = FluDarkMode.Light + }else{ + FluTheme.darkMode = FluDarkMode.Dark + } + canvas.centerX = mouseX + canvas.centerY = mouseY + anim_radius.enabled = false + canvas.radius = 0 + anim_radius.enabled = true + canvas.radius = canvas.maxRadius + }) + } + } diff --git a/src/imports/FluentUI/Controls/FluAppBar.qml b/src/imports/FluentUI/Controls/FluAppBar.qml index 3704480..8319e51 100644 --- a/src/imports/FluentUI/Controls/FluAppBar.qml +++ b/src/imports/FluentUI/Controls/FluAppBar.qml @@ -22,6 +22,25 @@ Rectangle{ property bool titleVisible: true property bool isMac: FluTools.isMacos() property color borerlessColor : FluTheme.dark ? FluTheme.primaryColor.lighter : FluTheme.primaryColor.dark + property var maxClickListener : function(){ + if (d.win.visibility === Window.Maximized) + d.win.visibility = Window.Windowed + else + d.win.visibility = Window.Maximized + } + property var minClickListener: function(){ + d.win.visibility = Window.Minimized + } + property var closeClickListener : function(){ + d.win.close() + } + property var darkClickListener: function(){ + if(FluTheme.dark){ + FluTheme.darkMode = FluDarkMode.Light + }else{ + FluTheme.darkMode = FluDarkMode.Dark + } + } id:root color: Qt.rgba(0,0,0,0) height: visible ? 30 : 0 @@ -67,14 +86,9 @@ Rectangle{ color:root.textColor } FluToggleSwitch{ + id:btn_dark checked: FluTheme.dark - clickListener: function(){ - if(FluTheme.dark){ - FluTheme.darkMode = FluDarkMode.Light - }else{ - FluTheme.darkMode = FluDarkMode.Dark - } - } + clickListener:()=> darkClickListener(btn_dark) } } FluIconButton{ @@ -89,9 +103,7 @@ Rectangle{ visible: !isMac iconColor: root.textColor color: hovered ? minimizeHoverColor : minimizeNormalColor - onClicked: { - d.win.visibility = Window.Minimized - } + onClicked: minClickListener() } FluIconButton{ id:btn_maximize @@ -105,12 +117,7 @@ Rectangle{ iconColor: root.textColor text:d.isRestore?restoreText:maximizeText iconSize: 11 - onClicked: { - if (d.win.visibility === Window.Maximized) - d.win.visibility = Window.Windowed - else - d.win.visibility = Window.Maximized - } + onClicked: maxClickListener() } FluIconButton{ id:btn_close @@ -124,9 +131,7 @@ Rectangle{ iconSize: 10 iconColor: hovered ? Qt.rgba(1,1,1,1) : root.textColor color:hovered ? closeHoverColor : closeNormalColor - onClicked: { - d.win.close() - } + onClicked: closeClickListener() } }