C
Qt Quick Ultralite swipe_game Demo
/****************************************************************************** ** ** Copyright (C) 2021 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the Qt Quick Ultralite module. ** ** $QT_BEGIN_LICENSE:COMM$ ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see http://www.qt.io/terms-conditions. For further ** information use the contact form at http://www.qt.io/contact-us. ** ** $QT_END_LICENSE$ ** ******************************************************************************/import QtQuick 2.0 import StyleModule 1.0 /* This component provides circular gesture recognition. */ MouseArea { id: root // NOTE: overwrite the Style and Globals value assignments if you want to use the component outside of this project // determines which distance a touch coordinate needs to have from the center to count as valid property int circleMinDistance: Style.swipeCircleMinDistance // determines the angle a circular gesture needs to cover to be recognized as a swipe property int arcThreshold: Style.swipeArcThreshold // the image used for visual feedback. Set to empty string if you want to try this component outside of this project property string highlightSource: "mask_circle_highlight_right.svg" // can be activated in the config view as a guide for users property bool showTouchArea: Globals.showTouchAreas signal clockwiseTriggered() signal counterClockwiseTriggered() implicitWidth: Style.appSize implicitHeight: Style.appSize onPressed: { var distanceFromCenter = internal.calculateDistanceFromCenter(mouseX, mouseY) // reject touch coordinates outside a circular strip if (distanceFromCenter >= internal.radius || distanceFromCenter < root.circleMinDistance) { mouse.accepted = false } else { internal.startAngle = internal.calculateAngle(mouseX, mouseY) internal.currentAngle = internal.startAngle highlight.visible = true } } onPositionChanged: { var distanceFromCenter = internal.calculateDistanceFromCenter(mouseX, mouseY) if (distanceFromCenter >= internal.radius || distanceFromCenter < root.circleMinDistance) { highlight.visible = false // reset the startAngle if the touch coordinates move outside the desired area internal.startAngle = internal.calculateAngle(mouseX, mouseY) } else { internal.currentAngle = internal.calculateAngle(mouseX, mouseY) var arcLength = internal.currentAngle - internal.startAngle // take care to handle the transition between 180 and -180 properly, since Math.atan2 used // to calculate the angle returns angles from -180 to 180 if (arcLength < -180) { arcLength += 360 } else if (arcLength > 180) { arcLength -= 360 } // trigger a signal if the angle between the start point and the current point exceeds a given threshold if (arcLength >= root.arcThreshold) { root.clockwiseTriggered() internal.startAngle = internal.currentAngle } else if (arcLength <= -root.arcThreshold) { root.counterClockwiseTriggered() internal.startAngle = internal.currentAngle } highlight.visible = true } } // can be activated in the config view as a guide for users Rectangle { id: areaVisualizer anchors.fill: parent radius: width * 0.5 color: "magenta" opacity: 0.4 visible: root.showTouchArea } Rectangle { anchors.centerIn: areaVisualizer width: 2 * root.circleMinDistance height: width radius: width * 0.5 color: "#1b1d1e" visible: root.showTouchArea } onReleased: { highlight.visible = false } Image { id: highlight anchors.verticalCenter: parent.verticalCenter anchors.left: parent.horizontalCenter height: parent.height width: parent.width/2 source: root.highlightSource transform: Rotation { origin.x: 0 origin.y: height/2 angle: internal.currentAngle } // don't use a binding to the pressed property of the MouseArea to show the highlight since // we explicitly don't want to show the highlight for touch coordinates outside a specific range visible: false } QtObject { id: internal property int startAngle: 0 property int currentAngle: 0 readonly property real radius: root.width * 0.5 // returns the angle calculated from the given x,y coordinates function calculateAngle(x : int, y : int) : int { return radianToDegree(Math.atan2(y - radius, x - radius)) } // converts a given radian value to degrees function radianToDegree(radian : real) : int { return radian * 180/Math.PI } // returns the distance the given x,y coordinates have to the center function calculateDistanceFromCenter(x : int, y : int) : int { return Math.sqrt((x - radius) * (x - radius) + (y - radius) * (y - radius)) } } }