├── .gitignore
├── Demo
├── QML-Loaders-Demo.pro
├── android
│ ├── AndroidManifest.xml
│ ├── build.gradle
│ ├── gradle
│ │ └── wrapper
│ │ │ ├── gradle-wrapper.jar
│ │ │ └── gradle-wrapper.properties
│ ├── gradlew
│ ├── gradlew.bat
│ └── res
│ │ ├── drawable-hdpi
│ │ └── icon.png
│ │ ├── drawable-ldpi
│ │ └── icon.png
│ │ ├── drawable-mdpi
│ │ └── icon.png
│ │ └── values
│ │ └── libs.xml
├── images
│ └── icon
│ │ └── android
│ │ ├── feature_graphic.png
│ │ ├── mipmap-hdpi
│ │ └── ic_launcher.png
│ │ ├── mipmap-ldpi
│ │ └── ic_launcher.png
│ │ ├── mipmap-mdpi
│ │ └── ic_launcher.png
│ │ ├── mipmap-xhdpi
│ │ └── ic_launcher.png
│ │ ├── mipmap-xxhdpi
│ │ └── ic_launcher.png
│ │ ├── mipmap-xxxhdpi
│ │ └── ic_launcher.png
│ │ └── playstore-icon.png
├── main.cpp
├── qml.qrc
├── qml
│ ├── DemoCard.qml
│ ├── DemoCardList.qml
│ ├── Loaders
│ │ ├── BlockLoader.qml
│ │ ├── ClockSpinner.qml
│ │ ├── FishSpinner.qml
│ │ ├── LineSpinner.qml
│ │ ├── PulseLoader.qml
│ │ ├── RectangleLoader.qml
│ │ └── SharinganLoader.qml
│ └── main.qml
└── src
│ ├── QMLManager.h
│ ├── ScreenHelper.cpp
│ └── ScreenHelper.h
├── Loaders
├── BlockLoader.qml
├── ClockSpinner.qml
├── FishSpinner.qml
├── LineSpinner.qml
├── PulseLoader.qml
├── RectangleLoader.qml
└── SharinganLoader.qml
├── README.md
└── demo.gif
/.gitignore:
--------------------------------------------------------------------------------
1 | # C++ objects and libs
2 |
3 | *.slo
4 | *.lo
5 | *.o
6 | *.a
7 | *.la
8 | *.lai
9 | *.so
10 | *.dll
11 | *.dylib
12 |
13 | # Qt-es
14 |
15 | /.qmake.cache
16 | /.qmake.stash
17 | *.pro.user
18 | *.pro.user.*
19 | *.qbs.user
20 | *.qbs.user.*
21 | *.moc
22 | moc_*.cpp
23 | qrc_*.cpp
24 | ui_*.h
25 | Makefile*
26 | *build-*
27 |
28 | # QtCreator
29 |
30 | *.autosave
31 |
32 | # QtCtreator Qml
33 | *.qmlproject.user
34 | *.qmlproject.user.*
35 |
36 | # QtCtreator CMake
37 | CMakeLists.txt.user
38 |
39 |
--------------------------------------------------------------------------------
/Demo/QML-Loaders-Demo.pro:
--------------------------------------------------------------------------------
1 | # Application icon is from here: https://pixabay.com/en/loading-animation-web-design-green-1863182/
2 |
3 | TEMPLATE = app
4 |
5 | QT += qml quick
6 | CONFIG += c++11
7 |
8 | SOURCES += main.cpp
9 |
10 | win32: {
11 | CONFIG(release, debug|release): {
12 | RESOURCES += qml.qrc
13 | }
14 | }
15 | else: {
16 | RESOURCES += qml.qrc
17 | }
18 |
19 | # Additional import path used to resolve QML modules in Qt Creator's code model
20 | QML_IMPORT_PATH =
21 |
22 | # Additional import path used to resolve QML modules just for Qt Quick Designer
23 | QML_DESIGNER_IMPORT_PATH =
24 |
25 | # The following define makes your compiler emit warnings if you use
26 | # any feature of Qt which as been marked deprecated (the exact warnings
27 | # depend on your compiler). Please consult the documentation of the
28 | # deprecated API in order to know how to port your code away from it.
29 | DEFINES += QT_DEPRECATED_WARNINGS
30 |
31 | # You can also make your code fail to compile if you use deprecated APIs.
32 | # In order to do so, uncomment the following line.
33 | # You can also select to disable deprecated APIs only up to a certain version of Qt.
34 | #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
35 |
36 | # Default rules for deployment.
37 | qnx: target.path = /tmp/$${TARGET}/bin
38 | else: unix:!android: target.path = /opt/$${TARGET}/bin
39 | !isEmpty(target.path): INSTALLS += target
40 |
41 | HEADERS += \
42 | src/QMLManager.h \
43 | src/ScreenHelper.h \
44 |
45 | SOURCES += \
46 | src/ScreenHelper.cpp
47 |
48 | DISTFILES += \
49 | android/AndroidManifest.xml \
50 | android/gradle/wrapper/gradle-wrapper.jar \
51 | android/gradlew \
52 | android/res/values/libs.xml \
53 | android/build.gradle \
54 | android/gradle/wrapper/gradle-wrapper.properties \
55 | android/gradlew.bat
56 |
57 | ANDROID_PACKAGE_SOURCE_DIR = $$PWD/android
58 |
--------------------------------------------------------------------------------
/Demo/android/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
71 |
72 |
73 |
75 |
76 |
77 |
78 |
--------------------------------------------------------------------------------
/Demo/android/build.gradle:
--------------------------------------------------------------------------------
1 | buildscript {
2 | repositories {
3 | jcenter()
4 | }
5 |
6 | dependencies {
7 | classpath 'com.android.tools.build:gradle:1.1.0'
8 | }
9 | }
10 |
11 | allprojects {
12 | repositories {
13 | jcenter()
14 | }
15 | }
16 |
17 | apply plugin: 'com.android.application'
18 |
19 | dependencies {
20 | compile fileTree(dir: 'libs', include: ['*.jar'])
21 | }
22 |
23 | android {
24 | /*******************************************************
25 | * The following variables:
26 | * - androidBuildToolsVersion,
27 | * - androidCompileSdkVersion
28 | * - qt5AndroidDir - holds the path to qt android files
29 | * needed to build any Qt application
30 | * on Android.
31 | *
32 | * are defined in gradle.properties file. This file is
33 | * updated by QtCreator and androiddeployqt tools.
34 | * Changing them manually might break the compilation!
35 | *******************************************************/
36 |
37 | compileSdkVersion androidCompileSdkVersion.toInteger()
38 |
39 | buildToolsVersion androidBuildToolsVersion
40 |
41 | sourceSets {
42 | main {
43 | manifest.srcFile 'AndroidManifest.xml'
44 | java.srcDirs = [qt5AndroidDir + '/src', 'src', 'java']
45 | aidl.srcDirs = [qt5AndroidDir + '/src', 'src', 'aidl']
46 | res.srcDirs = [qt5AndroidDir + '/res', 'res']
47 | resources.srcDirs = ['src']
48 | renderscript.srcDirs = ['src']
49 | assets.srcDirs = ['assets']
50 | jniLibs.srcDirs = ['libs']
51 | }
52 | }
53 |
54 | lintOptions {
55 | abortOnError false
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/Demo/android/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Furkanzmc/QML-Loaders/08cb9e0d8a8c4c73aa79c82158a7649c4efb3a4e/Demo/android/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/Demo/android/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Wed Apr 10 15:27:10 PDT 2013
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=http\://services.gradle.org/distributions/gradle-1.12-all.zip
7 |
--------------------------------------------------------------------------------
/Demo/android/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
10 | DEFAULT_JVM_OPTS=""
11 |
12 | APP_NAME="Gradle"
13 | APP_BASE_NAME=`basename "$0"`
14 |
15 | # Use the maximum available, or set MAX_FD != -1 to use that value.
16 | MAX_FD="maximum"
17 |
18 | warn ( ) {
19 | echo "$*"
20 | }
21 |
22 | die ( ) {
23 | echo
24 | echo "$*"
25 | echo
26 | exit 1
27 | }
28 |
29 | # OS specific support (must be 'true' or 'false').
30 | cygwin=false
31 | msys=false
32 | darwin=false
33 | case "`uname`" in
34 | CYGWIN* )
35 | cygwin=true
36 | ;;
37 | Darwin* )
38 | darwin=true
39 | ;;
40 | MINGW* )
41 | msys=true
42 | ;;
43 | esac
44 |
45 | # For Cygwin, ensure paths are in UNIX format before anything is touched.
46 | if $cygwin ; then
47 | [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
48 | fi
49 |
50 | # Attempt to set APP_HOME
51 | # Resolve links: $0 may be a link
52 | PRG="$0"
53 | # Need this for relative symlinks.
54 | while [ -h "$PRG" ] ; do
55 | ls=`ls -ld "$PRG"`
56 | link=`expr "$ls" : '.*-> \(.*\)$'`
57 | if expr "$link" : '/.*' > /dev/null; then
58 | PRG="$link"
59 | else
60 | PRG=`dirname "$PRG"`"/$link"
61 | fi
62 | done
63 | SAVED="`pwd`"
64 | cd "`dirname \"$PRG\"`/" >&-
65 | APP_HOME="`pwd -P`"
66 | cd "$SAVED" >&-
67 |
68 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
69 |
70 | # Determine the Java command to use to start the JVM.
71 | if [ -n "$JAVA_HOME" ] ; then
72 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
73 | # IBM's JDK on AIX uses strange locations for the executables
74 | JAVACMD="$JAVA_HOME/jre/sh/java"
75 | else
76 | JAVACMD="$JAVA_HOME/bin/java"
77 | fi
78 | if [ ! -x "$JAVACMD" ] ; then
79 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
80 |
81 | Please set the JAVA_HOME variable in your environment to match the
82 | location of your Java installation."
83 | fi
84 | else
85 | JAVACMD="java"
86 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
87 |
88 | Please set the JAVA_HOME variable in your environment to match the
89 | location of your Java installation."
90 | fi
91 |
92 | # Increase the maximum file descriptors if we can.
93 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
94 | MAX_FD_LIMIT=`ulimit -H -n`
95 | if [ $? -eq 0 ] ; then
96 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
97 | MAX_FD="$MAX_FD_LIMIT"
98 | fi
99 | ulimit -n $MAX_FD
100 | if [ $? -ne 0 ] ; then
101 | warn "Could not set maximum file descriptor limit: $MAX_FD"
102 | fi
103 | else
104 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
105 | fi
106 | fi
107 |
108 | # For Darwin, add options to specify how the application appears in the dock
109 | if $darwin; then
110 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
111 | fi
112 |
113 | # For Cygwin, switch paths to Windows format before running java
114 | if $cygwin ; then
115 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
116 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
117 |
118 | # We build the pattern for arguments to be converted via cygpath
119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
120 | SEP=""
121 | for dir in $ROOTDIRSRAW ; do
122 | ROOTDIRS="$ROOTDIRS$SEP$dir"
123 | SEP="|"
124 | done
125 | OURCYGPATTERN="(^($ROOTDIRS))"
126 | # Add a user-defined pattern to the cygpath arguments
127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
129 | fi
130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
131 | i=0
132 | for arg in "$@" ; do
133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
135 |
136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
138 | else
139 | eval `echo args$i`="\"$arg\""
140 | fi
141 | i=$((i+1))
142 | done
143 | case $i in
144 | (0) set -- ;;
145 | (1) set -- "$args0" ;;
146 | (2) set -- "$args0" "$args1" ;;
147 | (3) set -- "$args0" "$args1" "$args2" ;;
148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
154 | esac
155 | fi
156 |
157 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
158 | function splitJvmOpts() {
159 | JVM_OPTS=("$@")
160 | }
161 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
162 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
163 |
164 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
165 |
--------------------------------------------------------------------------------
/Demo/android/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
12 | set DEFAULT_JVM_OPTS=
13 |
14 | set DIRNAME=%~dp0
15 | if "%DIRNAME%" == "" set DIRNAME=.
16 | set APP_BASE_NAME=%~n0
17 | set APP_HOME=%DIRNAME%
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windowz variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 | if "%@eval[2+2]" == "4" goto 4NT_args
53 |
54 | :win9xME_args
55 | @rem Slurp the command line arguments.
56 | set CMD_LINE_ARGS=
57 | set _SKIP=2
58 |
59 | :win9xME_args_slurp
60 | if "x%~1" == "x" goto execute
61 |
62 | set CMD_LINE_ARGS=%*
63 | goto execute
64 |
65 | :4NT_args
66 | @rem Get arguments from the 4NT Shell from JP Software
67 | set CMD_LINE_ARGS=%$
68 |
69 | :execute
70 | @rem Setup the command line
71 |
72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
73 |
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
76 |
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if "%ERRORLEVEL%"=="0" goto mainEnd
80 |
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
85 | exit /b 1
86 |
87 | :mainEnd
88 | if "%OS%"=="Windows_NT" endlocal
89 |
90 | :omega
91 |
--------------------------------------------------------------------------------
/Demo/android/res/drawable-hdpi/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Furkanzmc/QML-Loaders/08cb9e0d8a8c4c73aa79c82158a7649c4efb3a4e/Demo/android/res/drawable-hdpi/icon.png
--------------------------------------------------------------------------------
/Demo/android/res/drawable-ldpi/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Furkanzmc/QML-Loaders/08cb9e0d8a8c4c73aa79c82158a7649c4efb3a4e/Demo/android/res/drawable-ldpi/icon.png
--------------------------------------------------------------------------------
/Demo/android/res/drawable-mdpi/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Furkanzmc/QML-Loaders/08cb9e0d8a8c4c73aa79c82158a7649c4efb3a4e/Demo/android/res/drawable-mdpi/icon.png
--------------------------------------------------------------------------------
/Demo/android/res/values/libs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | - https://download.qt.io/ministro/android/qt5/qt-5.7
5 |
6 |
7 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/Demo/images/icon/android/feature_graphic.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Furkanzmc/QML-Loaders/08cb9e0d8a8c4c73aa79c82158a7649c4efb3a4e/Demo/images/icon/android/feature_graphic.png
--------------------------------------------------------------------------------
/Demo/images/icon/android/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Furkanzmc/QML-Loaders/08cb9e0d8a8c4c73aa79c82158a7649c4efb3a4e/Demo/images/icon/android/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/Demo/images/icon/android/mipmap-ldpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Furkanzmc/QML-Loaders/08cb9e0d8a8c4c73aa79c82158a7649c4efb3a4e/Demo/images/icon/android/mipmap-ldpi/ic_launcher.png
--------------------------------------------------------------------------------
/Demo/images/icon/android/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Furkanzmc/QML-Loaders/08cb9e0d8a8c4c73aa79c82158a7649c4efb3a4e/Demo/images/icon/android/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/Demo/images/icon/android/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Furkanzmc/QML-Loaders/08cb9e0d8a8c4c73aa79c82158a7649c4efb3a4e/Demo/images/icon/android/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/Demo/images/icon/android/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Furkanzmc/QML-Loaders/08cb9e0d8a8c4c73aa79c82158a7649c4efb3a4e/Demo/images/icon/android/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/Demo/images/icon/android/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Furkanzmc/QML-Loaders/08cb9e0d8a8c4c73aa79c82158a7649c4efb3a4e/Demo/images/icon/android/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/Demo/images/icon/android/playstore-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Furkanzmc/QML-Loaders/08cb9e0d8a8c4c73aa79c82158a7649c4efb3a4e/Demo/images/icon/android/playstore-icon.png
--------------------------------------------------------------------------------
/Demo/main.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 | // Local
6 | #include "src/QMLManager.h"
7 | #include "src/ScreenHelper.h"
8 |
9 | int main(int argc, char *argv[])
10 | {
11 | QGuiApplication app(argc, argv);
12 |
13 | QQmlApplicationEngine engine;
14 |
15 | ScreenHelper screenHelper;
16 | engine.rootContext()->setContextProperty("SH", &screenHelper);
17 |
18 | #if defined(QT_DEBUG) && defined(_WIN32)
19 | QMLManager manager(&engine);
20 | manager.setMainQMLFile("file:///E:/Development/SourceTree/GitHub/QML-Loaders/Demo/qml/main.qml");
21 | engine.rootContext()->setContextProperty("QM", &manager);
22 | engine.rootContext()->setContextProperty("QML_DEBUG", true);
23 | engine.load(QUrl(QStringLiteral("file:///E:/Development/SourceTree/GitHub/QML-Loaders/Demo/qml/main.qml")));
24 | #else
25 | engine.rootContext()->setContextProperty("QM", nullptr);
26 | engine.rootContext()->setContextProperty("QML_DEBUG", false);
27 | engine.load(QUrl(QStringLiteral("qrc:/qml/main.qml")));
28 | #endif // QT_DEBUG
29 |
30 | return app.exec();
31 | }
32 |
--------------------------------------------------------------------------------
/Demo/qml.qrc:
--------------------------------------------------------------------------------
1 |
2 |
3 | qml/main.qml
4 | qml/Loaders/SharinganLoader.qml
5 | qml/Loaders/PulseLoader.qml
6 | qml/Loaders/LineSpinner.qml
7 | qml/Loaders/FishSpinner.qml
8 | qml/Loaders/BlockLoader.qml
9 | qml/Loaders/RectangleLoader.qml
10 | qml/DemoCard.qml
11 | qml/DemoCardList.qml
12 | qml/Loaders/ClockSpinner.qml
13 |
14 |
15 |
--------------------------------------------------------------------------------
/Demo/qml/DemoCard.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.7
2 |
3 | Rectangle {
4 |
5 | // ----- Public Properties ----- //
6 |
7 | property alias title: lbTitle.text
8 | property var loaderComponent: undefined
9 | readonly property bool opened: root.state === "open"
10 |
11 | // ----- Private Properties ----- //
12 |
13 | property int _height: 0
14 |
15 | id: root
16 | radius: SH.dp(7)
17 | clip: true
18 | states: [
19 | State {
20 | name: "open"
21 | PropertyChanges { target: root; height: root._height + loader.item.height }
22 | PropertyChanges { target: lbTitle; opacity: 0 }
23 | PropertyChanges { target: loader; opacity: 1 }
24 | }
25 | ]
26 | transitions: [
27 | Transition {
28 | from: "*"; to: "open"
29 |
30 | NumberAnimation { target: root; property: "height"; duration: 300; easing.type: Easing.OutBack }
31 | NumberAnimation { target: loader; property: "opacity"; duration: 300; easing.type: Easing.OutBack }
32 | NumberAnimation { target: lbTitle; property: "opacity"; duration: 300; easing.type: Easing.OutBack }
33 | },
34 | Transition {
35 | from: "open"; to: "*"
36 |
37 | NumberAnimation { target: root; property: "height"; duration: 300; easing.type: Easing.InBack }
38 | NumberAnimation { target: loader; property: "opacity"; duration: 300; easing.type: Easing.InBack }
39 | NumberAnimation { target: lbTitle; property: "opacity"; duration: 300; easing.type: Easing.InBack }
40 | }
41 | ]
42 |
43 | Component.onCompleted: {
44 | root._height = root.height;
45 | }
46 |
47 | Text {
48 | id: lbTitle
49 | color: "white"
50 | font {
51 | pixelSize: SH.dp(15)
52 | }
53 | anchors {
54 | top: parent.top
55 | left: parent.left
56 | topMargin: SH.dp(10)
57 | leftMargin: SH.dp(10)
58 | }
59 | }
60 |
61 | Loader {
62 | id: loader
63 | anchors.centerIn: parent
64 | opacity: 0
65 | visible: !(opacity === 0)
66 | }
67 |
68 | MouseArea {
69 | anchors.fill: parent
70 | onClicked: {
71 | if (loader.sourceComponent === null) {
72 | loader.sourceComponent = root.loaderComponent;
73 | }
74 |
75 | root.state = root.state === "open" ? "" : "open";
76 | }
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/Demo/qml/DemoCardList.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.7
2 | import "Loaders"
3 |
4 | ListView {
5 |
6 | // ----- Private Properties ----- //
7 |
8 | property var _colors: ["#FF4CA7", "#ED87E7", "#FF716D", "#52CBE5"]
9 | property var _components: [
10 | {"component": sharinganComponent, "title": "Sharingan Loader"},
11 | {"component": pulseThree, "title": "Pulse Loader"},
12 | {"component": pulseFour, "title": "Pulse Loader 4 Bars"},
13 | {"component": pulseFive, "title": "Pulse Loader 5 Bars"},
14 | {"component": classicLoader, "title": "Classic Loader"},
15 | {"component": lineLoader, "title": "Line Loader"},
16 | {"component": fishSpinner, "title": "Fish Spinner"},
17 | {"component": fishSpinnerDouble, "title": "Double Fish Spinner"},
18 | {"component": blockLoader, "title": "Block Loader"},
19 | {"component": rectLoader, "title": "Rectangle Loader"},
20 | {"component": clockLoader, "title": "Clock Spinner"}
21 | ]
22 |
23 | id: root
24 | model: _components.length
25 | spacing: SH.dp(10)
26 | delegate: Component {
27 | DemoCard {
28 | width: parent.width
29 | height: SH.dp(60)
30 | title: root._components[index].title
31 | color: root._colors[root.getRandomInt(1, root._colors.length) - 1]
32 | loaderComponent: root._components[index].component
33 | }
34 | }
35 | clip: true
36 |
37 |
38 | // ----- Components ----- //
39 |
40 | Component {
41 | id: sharinganComponent
42 | SharinganLoader { radius: SH.dp(15) }
43 | }
44 | Component {
45 | id: pulseThree
46 | PulseLoader { width: barCount * SH.dp(10); height: SH.dp(30); barCount: 3; spacing: SH.dp(2) }
47 | }
48 | Component {
49 | id: pulseFour
50 | PulseLoader { width: barCount * SH.dp(10); height: SH.dp(30); barCount: 4; spacing: SH.dp(2) }
51 | }
52 | Component {
53 | id: pulseFive
54 | PulseLoader { width: barCount * SH.dp(10); height: SH.dp(30); barCount: 5; spacing: SH.dp(2) }
55 | }
56 |
57 | Component {
58 | id: classicLoader
59 | SharinganLoader { radius: SH.dp(15); useCircle: true }
60 | }
61 | Component {
62 | id: lineLoader
63 | LineSpinner { width: SH.dp(40); height: width; lineThickness: SH.dp(2) }
64 | }
65 | Component {
66 | id: fishSpinner
67 | FishSpinner { radius: SH.dp(25) }
68 | }
69 | Component {
70 | id: fishSpinnerDouble
71 | FishSpinner { radius: SH.dp(25); useDouble: true }
72 | }
73 |
74 | Component {
75 | id: blockLoader
76 | BlockLoader { width: SH.dp(50); height: SH.dp(20) }
77 | }
78 | Component {
79 | id: rectLoader
80 | RectangleLoader { width: SH.dp(50); height: SH.dp(50) }
81 | }
82 | Component {
83 | id: clockLoader
84 | ClockSpinner { width: SH.dp(50); height: SH.dp(50); turnClockwise: false }
85 | }
86 |
87 | // ----- Private Functions ----- //
88 |
89 | /**
90 | * Returns a random integer between min (inclusive) and max (inclusive)
91 | * Using Math.round() will give you a non-uniform distribution!
92 | */
93 | function getRandomInt(min, max) {
94 | return Math.floor(Math.random() * (max - min + 1)) + min;
95 | }
96 | }
97 |
--------------------------------------------------------------------------------
/Demo/qml/Loaders/BlockLoader.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.7
2 |
3 | /**
4 | * The design is taken from here: https://dribbble.com/shots/3250272-Animated-Loader-Principle-Freebie
5 | **/
6 | Item {
7 |
8 | // ----- Public Properties ----- //
9 |
10 | property int spacing: 2
11 | property int horizontalBlockCount: 4
12 | property int verticalBlockCount: 3
13 |
14 | id: root
15 |
16 | Repeater {
17 | id: repeater
18 | model: root.horizontalBlockCount
19 | delegate: Component {
20 | Column {
21 | // ----- Private Properties ----- //
22 | property int _columnIndex: index
23 |
24 | id: column
25 | spacing: root.spacing
26 | x: root._getRectSize().width * index + ((index - 1) * root.spacing)
27 |
28 | Repeater {
29 | // ----- Private Properties ----- //
30 | property alias _columnIndex: column._columnIndex
31 |
32 | id: blockRepeater
33 | model: root.verticalBlockCount
34 | delegate: Component {
35 | Rectangle {
36 | id: rect
37 | width: root._getRectSize().width
38 | height: root._getRectSize().height
39 | radius: 2
40 | smooth: true
41 | transformOrigin: Item.BottomRight
42 |
43 | SequentialAnimation {
44 | id: rotationAnimation
45 | loops: Animation.Infinite
46 |
47 | RotationAnimation {
48 | target: rect
49 | duration: 1000
50 | from: 0
51 | to: 90
52 | easing.type: Easing.InOutQuint
53 | }
54 |
55 | PauseAnimation { duration: blockRepeater._columnIndex * 300 + 300 * blockRepeater._columnIndex }
56 |
57 | RotationAnimation {
58 | target: rect
59 | duration: 1000
60 | from: 90
61 | to: 0
62 | easing.type: Easing.InOutQuint
63 | }
64 |
65 | PauseAnimation { duration: (blockRepeater.model - blockRepeater._columnIndex) * 300 + 300 * (blockRepeater.model - blockRepeater._columnIndex) }
66 | }
67 |
68 | function startAnimation() {
69 | if (rotationAnimation.running === false) {
70 | rotationAnimation.start();
71 | }
72 | }
73 | }
74 | }
75 | }
76 |
77 | // ----- Public Functions ----- //
78 |
79 | function startAnimation() {
80 | var count = blockRepeater.model;
81 | for (var index = 0; index < count; index++) {
82 | blockRepeater.itemAt(index).startAnimation();
83 | }
84 | }
85 | }
86 | }
87 | }
88 |
89 | Timer {
90 | // ----- Private Properties ----- //
91 | property int _blockIndex: root.horizontalBlockCount - 1
92 |
93 | interval: 300
94 | repeat: true
95 | onTriggered: {
96 | if (_blockIndex === -1) {
97 | stop();
98 | }
99 | else {
100 | repeater.itemAt(_blockIndex).startAnimation();
101 | _blockIndex--;
102 | }
103 | }
104 | Component.onCompleted: start()
105 | }
106 |
107 | // ----- Private Functions ----- //
108 |
109 | function _getRectSize() {
110 | var w = root.width / root.horizontalBlockCount;
111 | return Qt.size(w, w);
112 | }
113 | }
114 |
--------------------------------------------------------------------------------
/Demo/qml/Loaders/ClockSpinner.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.7
2 |
3 | Item {
4 |
5 | // ----- Public Properties ----- //
6 |
7 | property int lineThickness: 2
8 | property color color: "white"
9 | property alias running: rotationAnimation.paused
10 |
11 | property bool turnClockwise: true
12 |
13 | id: root
14 |
15 | Rectangle {
16 | id: line
17 | color: root.color
18 | width: root.lineThickness
19 | height: root.width / 2
20 | x: root.width / 2
21 | y: root.height / 2
22 | transformOrigin: Item.Top
23 | rotation: 180
24 | antialiasing: true
25 | }
26 |
27 | Rectangle {
28 | id: hourLine
29 | color: root.color
30 | width: root.lineThickness
31 | height: root.width / 3
32 | x: root.width / 2
33 | y: root.height / 2
34 | transformOrigin: Item.Top
35 | rotation: 180
36 | antialiasing: true
37 | }
38 |
39 | NumberAnimation {
40 | id: rotationAnimation
41 | target: line
42 | property: "rotation"
43 | duration: 500
44 | from: 180 * (root.turnClockwise ? 1 : -1)
45 | to: 540 * (root.turnClockwise ? 1 : -1)
46 | running: true
47 | easing.type: Easing.Linear
48 | loops: Animation.Infinite
49 | }
50 |
51 | NumberAnimation {
52 | id: hourAnimation
53 | target: hourLine
54 | property: "rotation"
55 | duration: 6000
56 | from: 180 * (root.turnClockwise ? 1 : -1)
57 | to: 540 * (root.turnClockwise ? 1 : -1)
58 | running: rotationAnimation.running
59 | paused: rotationAnimation.paused
60 | easing.type: Easing.Linear
61 | loops: Animation.Infinite
62 | }
63 | }
64 |
65 |
--------------------------------------------------------------------------------
/Demo/qml/Loaders/FishSpinner.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.7
2 |
3 | Rectangle {
4 |
5 | // ----- Public Properties ----- //
6 |
7 | property int radius: 25
8 | property bool useDouble: false
9 |
10 | // ----- Private Properties ----- //
11 |
12 | property int _innerRadius: radius * 0.7
13 | property int _circleRadius: (radius - _innerRadius) * 0.5
14 |
15 | id: root
16 | width: radius * 2
17 | height: radius * 2
18 | color: "transparent"
19 |
20 | Repeater {
21 | id: repeater
22 | model: root.useDouble ? 10 : 4
23 | delegate: Component {
24 | Rectangle {
25 | // ----- Private Properties ----- //
26 | property int _currentAngle: _getStartAngle()
27 |
28 | id: rect
29 | width: _getWidth()
30 | height: width
31 | radius: width
32 | transformOrigin: Item.Center
33 | x: root._getPosOnCircle(_currentAngle).x
34 | y: root._getPosOnCircle(_currentAngle).y
35 | antialiasing: true
36 |
37 | SequentialAnimation {
38 | id: anim
39 | loops: Animation.Infinite
40 |
41 | NumberAnimation {
42 | target: rect
43 | property: "_currentAngle"
44 | duration: root.useDouble ? 1800 : 1000
45 | from: rect._getStartAngle()
46 | to: 360 + rect._getStartAngle()
47 | easing.type: Easing.OutQuad
48 | }
49 |
50 | PauseAnimation { duration: 500 }
51 | }
52 |
53 | // ----- Public Functions ----- //
54 |
55 | function playAnimation() {
56 | if (anim.running == false) {
57 | anim.start();
58 | }
59 | }
60 |
61 | // ----- Private Functions ----- //
62 |
63 | function _getStartAngle() {
64 | var ang = 90;
65 | if (root.useDouble) {
66 | ang = index < 5 ? 90 : 270;
67 | }
68 |
69 | return ang;
70 | }
71 |
72 | function _getWidth() {
73 | var w = (root._circleRadius) * 0.5 * (repeater.model - index);
74 | if (root.useDouble) {
75 | w = (root._circleRadius) * 0.5 * ((repeater.model / 2) - Math.abs(repeater.model / 2 - index))
76 | }
77 |
78 | return w;
79 | }
80 | }
81 | }
82 | }
83 |
84 | Timer {
85 | // ----- Private Properties ----- //
86 | property int _circleIndex: 0
87 |
88 | interval: 100
89 | repeat: true
90 | onTriggered: {
91 | var maxIndex = root.useDouble ? repeater.model / 2 : repeater.model;
92 | if (_circleIndex === maxIndex) {
93 | stop();
94 | }
95 | else {
96 | repeater.itemAt(_circleIndex).playAnimation();
97 | if (root.useDouble) {
98 | repeater.itemAt(repeater.model - _circleIndex - 1).playAnimation();
99 | }
100 |
101 | _circleIndex++;
102 | }
103 | }
104 | Component.onCompleted: start()
105 | }
106 |
107 | // ----- Private Functions ----- //
108 |
109 | function _toRadian(degree) {
110 | return (degree * 3.14159265) / 180.0;
111 | }
112 |
113 | function _getPosOnCircle(angleInDegree) {
114 | var centerX = root.width / 2, centerY = root.height / 2;
115 | var posX = 0, posY = 0;
116 |
117 | posX = centerX + root._innerRadius * Math.cos(_toRadian(angleInDegree));
118 | posY = centerY - root._innerRadius * Math.sin(_toRadian(angleInDegree));
119 | return Qt.point(posX, posY);
120 | }
121 | }
122 |
--------------------------------------------------------------------------------
/Demo/qml/Loaders/LineSpinner.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.7
2 |
3 | Item {
4 |
5 | // ----- Public Properties ----- //
6 |
7 | property int lineThickness: 2
8 | property alias color: line.color
9 |
10 | id: root
11 | Component.onCompleted: rotationAnimation.start()
12 |
13 | Rectangle {
14 | id: line
15 | width: root.width / 2
16 | height: root.lineThickness
17 | x: root.width / 2
18 | y: root.height / 2
19 | transformOrigin: Item.Left
20 | antialiasing: true
21 | }
22 |
23 | NumberAnimation {
24 | id: rotationAnimation
25 | target: line
26 | property: "rotation"
27 | duration: 1500
28 | from: 0
29 | to: 360
30 | easing.type: Easing.OutExpo
31 | loops: Animation.Infinite
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/Demo/qml/Loaders/PulseLoader.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.7
2 |
3 | Item {
4 |
5 | // ----- Public Properties ----- //
6 |
7 | property alias barCount: repeater.model
8 | property color color: "white"
9 | property int spacing: 5
10 |
11 | id: root
12 |
13 | Repeater {
14 | id: repeater
15 | delegate: Component {
16 | Rectangle {
17 | width: (root.width / root.barCount) - root.spacing
18 | height: root.height
19 | x: index * width + root.spacing * index
20 | transform: Scale {
21 | id: rectScale
22 | origin {
23 | x: width / 2
24 | y: height / 2
25 | }
26 | }
27 | transformOrigin: Item.Center
28 | color: root.color
29 |
30 | SequentialAnimation {
31 | id: anim
32 | loops: Animation.Infinite
33 |
34 | NumberAnimation { target: rectScale; property: "yScale"; from: 1; to: 1.5; duration: 300 }
35 | NumberAnimation { target: rectScale; property: "yScale"; from: 1.5; to: 1; duration: 300 }
36 | PauseAnimation { duration: root.barCount * 150 }
37 | }
38 |
39 | function playAnimation() {
40 | if (anim.running == false) {
41 | anim.start();
42 | }
43 | }
44 | }
45 | }
46 | }
47 |
48 | Timer {
49 | // ----- Private Properties ----- //
50 | property int _barIndex: 0
51 |
52 | interval: 80
53 | repeat: true
54 | onTriggered: {
55 | if (_barIndex === root.barCount) {
56 | stop();
57 | }
58 | else {
59 | repeater.itemAt(_barIndex).playAnimation();
60 | _barIndex++;
61 | }
62 | }
63 | Component.onCompleted: start()
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/Demo/qml/Loaders/RectangleLoader.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.7
2 |
3 | /**
4 | * Design by Enes Özgör: ens.ninja
5 | **/
6 | Item {
7 |
8 | // ----- Public Properties ----- //
9 |
10 | property alias color: rect.color
11 |
12 | id: root
13 |
14 | Rectangle {
15 | id: rect
16 | width: root.width / 2
17 | height: root.height / 2
18 | transformOrigin: Item.BottomRight
19 | x: 0
20 | y: 0
21 | transform: Scale {
22 | id: transformScale
23 | origin {
24 | x: rect.width
25 | y: rect.height
26 | }
27 | }
28 |
29 | SequentialAnimation {
30 | running: true
31 | loops: Animation.Infinite
32 |
33 | // Top right
34 | ParallelAnimation {
35 | NumberAnimation {
36 | target: transformScale; property: "xScale"; from: 1; to: -1; duration: 500; easing.type: Easing.OutQuint
37 | }
38 |
39 | SequentialAnimation {
40 | NumberAnimation {
41 | target: transformScale; property: "yScale"; from: 1; to: 1.4; duration: 250; easing.type: Easing.OutQuart
42 | }
43 |
44 | NumberAnimation {
45 | target: transformScale; property: "yScale"; from: 1.4; to: 1; duration: 250; easing.type: Easing.OutQuart
46 | }
47 | }
48 | }
49 |
50 | // Bottom right
51 | ParallelAnimation {
52 | NumberAnimation {
53 | target: transformScale; property: "yScale"; from: 1; to: -1; duration: 500; easing.type: Easing.OutQuint
54 | }
55 |
56 | SequentialAnimation {
57 | NumberAnimation {
58 | target: transformScale; property: "xScale"; from: -1; to: -1.4; duration: 250; easing.type: Easing.OutQuart
59 | }
60 |
61 | NumberAnimation {
62 | target: transformScale; property: "xScale"; from: -1.4; to: -1; duration: 250; easing.type: Easing.OutQuart
63 | }
64 | }
65 | }
66 |
67 | // Bottom left
68 | ParallelAnimation {
69 | NumberAnimation {
70 | target: transformScale; property: "xScale"; from: -1; to: 1; duration: 500; easing.type: Easing.OutQuint
71 | }
72 |
73 | SequentialAnimation {
74 | NumberAnimation {
75 | target: transformScale; property: "yScale"; from: -1; to: -1.4; duration: 250; easing.type: Easing.OutQuart
76 | }
77 |
78 | NumberAnimation {
79 | target: transformScale; property: "yScale"; from: -1.4; to: -1; duration: 250; easing.type: Easing.OutQuart
80 | }
81 | }
82 | }
83 |
84 | // Top left
85 | ParallelAnimation {
86 | NumberAnimation {
87 | target: transformScale; property: "yScale"; from: -1; to: 1; duration: 500; easing.type: Easing.OutQuint
88 | }
89 |
90 | SequentialAnimation {
91 | NumberAnimation {
92 | target: transformScale; property: "xScale"; from: 1; to: 1.4; duration: 250; easing.type: Easing.OutQuart
93 | }
94 |
95 | NumberAnimation {
96 | target: transformScale; property: "xScale"; from: 1.4; to: 1; duration: 250; easing.type: Easing.OutQuart
97 | }
98 | }
99 | }
100 | }
101 | }
102 | }
103 |
--------------------------------------------------------------------------------
/Demo/qml/Loaders/SharinganLoader.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.7
2 |
3 | Item {
4 |
5 | // ----- Public Properties ----- //
6 |
7 | property int radius: 25
8 | property color color: "#FAFAFA"
9 | property bool useCircle: false
10 |
11 | // ----- Private Properties ----- //
12 |
13 | property int _innerRadius: radius * 0.7
14 | property int _currentIndex: 0
15 |
16 | id: root
17 | width: radius * 2
18 | height: radius * 2
19 | Component.onCompleted: timer.start()
20 |
21 | Repeater {
22 | id: repeater
23 | model: 8
24 | delegate: Component {
25 | Rectangle {
26 | // ----- Private Properties ----- //
27 | property int _rotation: (360 / repeater.model) * index
28 | property int _maxIndex: root._currentIndex + 1
29 | property int _minIndex: root._currentIndex - 1
30 |
31 | width: root.useCircle ? (root.radius - root._innerRadius) * 2 : root.width - (root._innerRadius * 2)
32 | height: root.useCircle ? width : width * 0.5
33 | x: _getPosOnCircle(_rotation).x
34 | y: _getPosOnCircle(_rotation).y
35 | radius: root.useCircle ? width : 0
36 | color: root.color
37 | opacity: (index >= _minIndex && index <= _maxIndex) || (index === 0 && root._currentIndex + 1 > 7) ? 1 : 0.3
38 | transform: Rotation {
39 | angle: 360 - _rotation
40 | origin {
41 | x: 0
42 | y: height / 2
43 | }
44 | }
45 | transformOrigin: index >= repeater.model / 2 ? Item.Center : Item.Center
46 |
47 | Behavior on opacity { NumberAnimation { duration: 200 } }
48 | }
49 | }
50 | }
51 |
52 | Timer {
53 | id: timer
54 | interval: 80
55 | repeat: true
56 | onTriggered: {
57 | if (root._currentIndex === 7) {
58 | root._currentIndex = 0;
59 | }
60 | else {
61 | root._currentIndex++;
62 | }
63 | }
64 | }
65 |
66 | // ----- Private Functions ----- //
67 |
68 | function _toRadian(degree) {
69 | return (degree * 3.14159265) / 180.0;
70 | }
71 |
72 | function _getPosOnCircle(angleInDegree) {
73 | var centerX = root.width / 2, centerY = root.height / 2;
74 | var posX = 0, posY = 0;
75 |
76 | posX = centerX + root._innerRadius * Math.cos(_toRadian(angleInDegree));
77 | posY = centerY - root._innerRadius * Math.sin(_toRadian(angleInDegree));
78 | return Qt.point(posX, posY);
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/Demo/qml/main.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.7
2 | import QtQuick.Window 2.2
3 |
4 | Window {
5 | id: mainWindow
6 | visible: true
7 | width: 320
8 | height: 480
9 | title: qsTr("QML Loaders Demo")
10 | color: "#FDFAFB"
11 | Component.onCompleted: {
12 | if (QML_DEBUG) {
13 | QM.setWindow(mainWindow)
14 | }
15 | }
16 |
17 | Text {
18 | text: "Refresh"
19 | anchors {
20 | left: parent.left
21 | top: parent.top
22 | }
23 | font.pointSize: 13
24 | visible: QML_DEBUG
25 |
26 | MouseArea {
27 | anchors.fill: parent
28 | onClicked: {
29 | QM.reload();
30 | }
31 | }
32 | }
33 |
34 | DemoCardList {
35 | anchors {
36 | fill: parent
37 | margins: SH.dp(25)
38 | }
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/Demo/src/QMLManager.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include
7 | // STD
8 | #include
9 |
10 | /**
11 | * @brief The QMLManager is a helper class to reload QML on runtime. To use it, pass the QQmlApplicationEngine pointer and call the reload function when you need.
12 | * For more information about runtime reloading go here -> http://www.slideshare.net/ICSinc/how-best-to-realize-a-runtime-reload-of-qml
13 | * @code
14 | * // in main.cpp
15 | * QMLManager manager(&engine);
16 | * manager.setMainQMLFile("file:///E:/Development/Playground/Live-QML/qml/main.qml");
17 | * engine.rootContext()->setContextProperty("QM", &manager);
18 | * @endcode
19 | *
20 | * Pass the `QQuickWindow` to `QMLManager`, then use QM.relad() to reload at runtime!
21 | * @code
22 | * Window {
23 | * id: mainWindow
24 | * Component.onCompleted: QM.setWindow(mainWindow)
25 | *
26 | * MouseArea {
27 | * anchors.fill: parent
28 | * onClicked: {
29 | * QM.reload();
30 | * }
31 | * }
32 | * }
33 | * @endcode
34 | */
35 | class QMLManager : public QObject
36 | {
37 | Q_OBJECT
38 |
39 | public:
40 | explicit QMLManager(QQmlApplicationEngine *engine, QObject *parent = 0)
41 | : QObject(parent)
42 | , m_Engine(engine)
43 | , m_Window(nullptr)
44 | {
45 |
46 | }
47 |
48 | Q_INVOKABLE void reload(float delay = 0.f)
49 | {
50 | if (delay == 0.f) {
51 | reloadCache();
52 | }
53 | else {
54 | QTimer::singleShot(delay * 1000, this, &QMLManager::reloadCache);
55 | }
56 | }
57 |
58 | Q_INVOKABLE void setWindow(QQuickWindow *window)
59 | {
60 | m_Window = window;
61 | }
62 |
63 | Q_INVOKABLE QString MainQMLFile() const
64 | {
65 | return m_MainQMLFile;
66 | }
67 |
68 | Q_INVOKABLE void setMainQMLFile(const QString &file)
69 | {
70 | m_MainQMLFile = file;
71 | }
72 |
73 | private:
74 | QQmlApplicationEngine *m_Engine;
75 | QQuickWindow *m_Window;
76 | QString m_MainQMLFile;
77 |
78 | private:
79 | void reloadCache()
80 | {
81 | if (m_MainQMLFile.length() == 0) {
82 | qDebug() << "m_MainQMLFile is empty.";
83 | return;
84 | }
85 |
86 | if (m_Window) {
87 | m_Window->close();
88 | }
89 |
90 | m_Engine->clearComponentCache();
91 | m_Engine->load(QUrl(m_MainQMLFile));
92 | }
93 | };
94 |
--------------------------------------------------------------------------------
/Demo/src/ScreenHelper.cpp:
--------------------------------------------------------------------------------
1 | #include "ScreenHelper.h"
2 | // Qt
3 | #include
4 | #include
5 |
6 | ScreenHelper::ScreenHelper(QObject *parent)
7 | : QObject(parent)
8 | , m_DPI(QGuiApplication::primaryScreen()->physicalDotsPerInch())
9 | {
10 |
11 | }
12 |
13 | qreal ScreenHelper::dp(const qreal &size)
14 | {
15 | #ifdef _WIN32
16 | return qRound(size * (m_DPI / 90.0));
17 | #else
18 | return qRound(size * (m_DPI / 160.0));
19 | #endif // _WIN32
20 | }
21 |
--------------------------------------------------------------------------------
/Demo/src/ScreenHelper.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include
3 |
4 | class ScreenHelper : public QObject
5 | {
6 | Q_OBJECT
7 |
8 | public:
9 | explicit ScreenHelper(QObject *parent = 0);
10 |
11 | Q_INVOKABLE qreal dp(const qreal &size);
12 |
13 | private:
14 | const qreal m_DPI;
15 |
16 | };
17 |
--------------------------------------------------------------------------------
/Loaders/BlockLoader.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.7
2 |
3 | /**
4 | * The design is taken from here: https://dribbble.com/shots/3250272-Animated-Loader-Principle-Freebie
5 | **/
6 | Item {
7 |
8 | // ----- Public Properties ----- //
9 |
10 | property int spacing: 2
11 | property int horizontalBlockCount: 4
12 | property int verticalBlockCount: 3
13 |
14 | id: root
15 |
16 | Repeater {
17 | id: repeater
18 | model: root.horizontalBlockCount
19 | delegate: Component {
20 | Column {
21 | // ----- Private Properties ----- //
22 | property int _columnIndex: index
23 |
24 | id: column
25 | spacing: root.spacing
26 | x: root._getRectSize().width * index + ((index - 1) * root.spacing)
27 |
28 | Repeater {
29 | // ----- Private Properties ----- //
30 | property alias _columnIndex: column._columnIndex
31 |
32 | id: blockRepeater
33 | model: root.verticalBlockCount
34 | delegate: Component {
35 | Rectangle {
36 | id: rect
37 | width: root._getRectSize().width
38 | height: root._getRectSize().height
39 | radius: 2
40 | smooth: true
41 | transformOrigin: Item.BottomRight
42 |
43 | SequentialAnimation {
44 | id: rotationAnimation
45 | loops: Animation.Infinite
46 |
47 | RotationAnimation {
48 | target: rect
49 | duration: 1000
50 | from: 0
51 | to: 90
52 | easing.type: Easing.InOutQuint
53 | }
54 |
55 | PauseAnimation { duration: blockRepeater._columnIndex * 300 + 300 * blockRepeater._columnIndex }
56 |
57 | RotationAnimation {
58 | target: rect
59 | duration: 1000
60 | from: 90
61 | to: 0
62 | easing.type: Easing.InOutQuint
63 | }
64 |
65 | PauseAnimation { duration: (blockRepeater.model - blockRepeater._columnIndex) * 300 + 300 * (blockRepeater.model - blockRepeater._columnIndex) }
66 | }
67 |
68 | function startAnimation() {
69 | if (rotationAnimation.running === false) {
70 | rotationAnimation.start();
71 | }
72 | }
73 | }
74 | }
75 | }
76 |
77 | // ----- Public Functions ----- //
78 |
79 | function startAnimation() {
80 | var count = blockRepeater.model;
81 | for (var index = 0; index < count; index++) {
82 | blockRepeater.itemAt(index).startAnimation();
83 | }
84 | }
85 | }
86 | }
87 | }
88 |
89 | Timer {
90 | // ----- Private Properties ----- //
91 | property int _blockIndex: root.horizontalBlockCount - 1
92 |
93 | interval: 300
94 | repeat: true
95 | onTriggered: {
96 | if (_blockIndex === -1) {
97 | stop();
98 | }
99 | else {
100 | repeater.itemAt(_blockIndex).startAnimation();
101 | _blockIndex--;
102 | }
103 | }
104 | Component.onCompleted: start()
105 | }
106 |
107 | // ----- Private Functions ----- //
108 |
109 | function _getRectSize() {
110 | var w = root.width / root.horizontalBlockCount;
111 | return Qt.size(w, w);
112 | }
113 | }
114 |
--------------------------------------------------------------------------------
/Loaders/ClockSpinner.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.7
2 |
3 | Item {
4 |
5 | // ----- Public Properties ----- //
6 |
7 | property int lineThickness: 2
8 | property color color: "white"
9 | property alias running: rotationAnimation.paused
10 |
11 | property bool turnClockwise: true
12 |
13 | id: root
14 |
15 | Rectangle {
16 | id: line
17 | color: root.color
18 | width: root.lineThickness
19 | height: root.width / 2
20 | x: root.width / 2
21 | y: root.height / 2
22 | transformOrigin: Item.Top
23 | rotation: 180
24 | antialiasing: true
25 | }
26 |
27 | Rectangle {
28 | id: hourLine
29 | color: root.color
30 | width: root.lineThickness
31 | height: root.width / 3
32 | x: root.width / 2
33 | y: root.height / 2
34 | transformOrigin: Item.Top
35 | rotation: 180
36 | antialiasing: true
37 | }
38 |
39 | NumberAnimation {
40 | id: rotationAnimation
41 | target: line
42 | property: "rotation"
43 | duration: 500
44 | from: 180 * (root.turnClockwise ? 1 : -1)
45 | to: 540 * (root.turnClockwise ? 1 : -1)
46 | running: true
47 | easing.type: Easing.Linear
48 | loops: Animation.Infinite
49 | }
50 |
51 | NumberAnimation {
52 | id: hourAnimation
53 | target: hourLine
54 | property: "rotation"
55 | duration: 6000
56 | from: 180 * (root.turnClockwise ? 1 : -1)
57 | to: 540 * (root.turnClockwise ? 1 : -1)
58 | running: rotationAnimation.running
59 | paused: rotationAnimation.paused
60 | easing.type: Easing.Linear
61 | loops: Animation.Infinite
62 | }
63 | }
64 |
65 |
--------------------------------------------------------------------------------
/Loaders/FishSpinner.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.7
2 |
3 | Item {
4 |
5 | // ----- Public Properties ----- //
6 |
7 | property int radius: 25
8 | property bool useDouble: false
9 | property bool running: true
10 |
11 | property color color: "white"
12 |
13 | // ----- Private Properties ----- //
14 |
15 | property int _innerRadius: radius * 0.7
16 | property int _circleRadius: (radius - _innerRadius) * 0.5
17 |
18 | id: root
19 | width: radius * 2
20 | height: radius * 2
21 | onRunningChanged: {
22 | if (running === false) {
23 | for (var i = 0; i < repeater.model; i++) {
24 | if (repeater.itemAt(i)) {
25 | repeater.itemAt(i).stopAnimation();
26 | }
27 | }
28 | }
29 | else {
30 | for (var i = 0; i < repeater.model; i++) {
31 | if (repeater.itemAt(i)) {
32 | repeater.itemAt(i).playAnimation();
33 | }
34 | }
35 | }
36 | }
37 |
38 | Repeater {
39 | id: repeater
40 | model: root.useDouble ? 10 : 4
41 | delegate: Component {
42 | Rectangle {
43 | // ----- Private Properties ----- //
44 | property int _currentAngle: _getStartAngle()
45 |
46 | id: rect
47 | width: _getWidth()
48 | height: width
49 | radius: width
50 | color: root.color
51 | transformOrigin: Item.Center
52 | x: root._getPosOnCircle(_currentAngle).x
53 | y: root._getPosOnCircle(_currentAngle).y
54 | antialiasing: true
55 |
56 | SequentialAnimation {
57 | id: anim
58 | loops: Animation.Infinite
59 |
60 | NumberAnimation {
61 | target: rect
62 | property: "_currentAngle"
63 | duration: root.useDouble ? 1800 : 1000
64 | from: rect._getStartAngle()
65 | to: 360 + rect._getStartAngle()
66 | easing.type: Easing.OutQuad
67 | }
68 |
69 | PauseAnimation { duration: 500 }
70 | }
71 |
72 | // ----- Public Functions ----- //
73 |
74 | function playAnimation() {
75 | if (anim.running == false) {
76 | anim.start();
77 | }
78 | else if (anim.paused) {
79 | anim.resume();
80 | }
81 | }
82 |
83 | function stopAnimation() {
84 | if (anim.running) {
85 | anim.pause();
86 | }
87 | }
88 |
89 | // ----- Private Functions ----- //
90 |
91 | function _getStartAngle() {
92 | var ang = 90;
93 | if (root.useDouble) {
94 | ang = index < 5 ? 90 : 270;
95 | }
96 |
97 | return ang;
98 | }
99 |
100 | function _getWidth() {
101 | var w = (root._circleRadius) * 0.5 * (repeater.model - index);
102 | if (root.useDouble) {
103 | w = (root._circleRadius) * 0.5 * ((repeater.model / 2) - Math.abs(repeater.model / 2 - index))
104 | }
105 |
106 | return w;
107 | }
108 | }
109 | }
110 | }
111 |
112 | Timer {
113 | // ----- Private Properties ----- //
114 | property int _circleIndex: 0
115 |
116 | id: timer
117 | interval: 100
118 | repeat: true
119 | running: true
120 | onTriggered: {
121 | var maxIndex = root.useDouble ? repeater.model / 2 : repeater.model;
122 | if (_circleIndex === maxIndex) {
123 | stop();
124 | _circleIndex = 0;
125 | }
126 | else {
127 | repeater.itemAt(_circleIndex).playAnimation();
128 | if (root.useDouble) {
129 | repeater.itemAt(repeater.model - _circleIndex - 1).playAnimation();
130 | }
131 |
132 | _circleIndex++;
133 | }
134 | }
135 | }
136 |
137 | // ----- Private Functions ----- //
138 |
139 | function _toRadian(degree) {
140 | return (degree * 3.14159265) / 180.0;
141 | }
142 |
143 | function _getPosOnCircle(angleInDegree) {
144 | var centerX = root.width / 2, centerY = root.height / 2;
145 | var posX = 0, posY = 0;
146 |
147 | posX = centerX + root._innerRadius * Math.cos(_toRadian(angleInDegree));
148 | posY = centerY - root._innerRadius * Math.sin(_toRadian(angleInDegree));
149 | return Qt.point(posX, posY);
150 | }
151 | }
152 |
--------------------------------------------------------------------------------
/Loaders/LineSpinner.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.7
2 |
3 | Item {
4 |
5 | // ----- Public Properties ----- //
6 |
7 | property int lineThickness: 2
8 | property alias color: line.color
9 |
10 | id: root
11 | Component.onCompleted: rotationAnimation.start()
12 |
13 | Rectangle {
14 | id: line
15 | width: root.width / 2
16 | height: root.lineThickness
17 | x: root.width / 2
18 | y: root.height / 2
19 | transformOrigin: Item.Left
20 | antialiasing: true
21 | }
22 |
23 | NumberAnimation {
24 | id: rotationAnimation
25 | target: line
26 | property: "rotation"
27 | duration: 1500
28 | from: 0
29 | to: 360
30 | easing.type: Easing.OutExpo
31 | loops: Animation.Infinite
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/Loaders/PulseLoader.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.7
2 |
3 | Item {
4 |
5 | // ----- Public Properties ----- //
6 |
7 | property alias barCount: repeater.model
8 | property color color: "white"
9 | property int spacing: 5
10 |
11 | property bool running: true
12 |
13 | id: root
14 | onRunningChanged: {
15 | if (barCount !== repeater.count || timer._barIndex <= barCount - 1) {
16 | return;
17 | }
18 |
19 | for (var barIndex = 0; barIndex < barCount; barIndex++) {
20 | if (running) {
21 | if (repeater.itemAt(barIndex)) {
22 | repeater.itemAt(barIndex).playAnimation();
23 | }
24 | }
25 | else {
26 | if (repeater.itemAt(barIndex)) {
27 | repeater.itemAt(barIndex).pauseAnimation();
28 | }
29 | }
30 | }
31 | }
32 |
33 | Repeater {
34 | id: repeater
35 | delegate: Component {
36 | Rectangle {
37 | width: (root.width / root.barCount) - root.spacing
38 | height: root.height
39 | x: index * width + root.spacing * index
40 | transform: Scale {
41 | id: rectScale
42 | origin {
43 | x: width / 2
44 | y: height / 2
45 | }
46 | }
47 | transformOrigin: Item.Center
48 | color: root.color
49 |
50 | SequentialAnimation {
51 | id: anim
52 | loops: Animation.Infinite
53 |
54 | NumberAnimation { target: rectScale; property: "yScale"; from: 1; to: 1.5; duration: 300 }
55 | NumberAnimation { target: rectScale; property: "yScale"; from: 1.5; to: 1; duration: 300 }
56 | PauseAnimation { duration: root.barCount * 150 }
57 | }
58 |
59 | function playAnimation() {
60 | if (anim.running == false) {
61 | anim.running = true;
62 | }
63 |
64 | if (anim.paused) {
65 | anim.paused = false;
66 | }
67 | }
68 |
69 | function pauseAnimation() {
70 | if (anim.running) {
71 | anim.paused = true;
72 | }
73 | }
74 | }
75 | }
76 | }
77 |
78 | Timer {
79 | // ----- Private Properties ----- //
80 | property int _barIndex: 0
81 |
82 | id: timer
83 | interval: 80
84 | repeat: true
85 | onTriggered: {
86 | if (_barIndex === root.barCount) {
87 | stop();
88 | }
89 | else {
90 | repeater.itemAt(_barIndex).playAnimation();
91 | if (root.running === false) {
92 | repeater.itemAt(_barIndex).pauseAnimation();
93 | }
94 |
95 | _barIndex++;
96 | }
97 | }
98 | Component.onCompleted: start()
99 | }
100 | }
101 |
--------------------------------------------------------------------------------
/Loaders/RectangleLoader.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.7
2 |
3 | /**
4 | * Design by Enes Özgör: ens.ninja
5 | **/
6 | Item {
7 |
8 | // ----- Public Properties ----- //
9 |
10 | property alias color: rect.color
11 |
12 | id: root
13 |
14 | Rectangle {
15 | id: rect
16 | width: root.width / 2
17 | height: root.height / 2
18 | transformOrigin: Item.BottomRight
19 | x: 0
20 | y: 0
21 | transform: Scale {
22 | id: transformScale
23 | origin {
24 | x: rect.width
25 | y: rect.height
26 | }
27 | }
28 |
29 | SequentialAnimation {
30 | running: true
31 | loops: Animation.Infinite
32 |
33 | // Top right
34 | ParallelAnimation {
35 | NumberAnimation {
36 | target: transformScale; property: "xScale"; from: 1; to: -1; duration: 500; easing.type: Easing.OutQuint
37 | }
38 |
39 | SequentialAnimation {
40 | NumberAnimation {
41 | target: transformScale; property: "yScale"; from: 1; to: 1.4; duration: 250; easing.type: Easing.OutQuart
42 | }
43 |
44 | NumberAnimation {
45 | target: transformScale; property: "yScale"; from: 1.4; to: 1; duration: 250; easing.type: Easing.OutQuart
46 | }
47 | }
48 | }
49 |
50 | // Bottom right
51 | ParallelAnimation {
52 | NumberAnimation {
53 | target: transformScale; property: "yScale"; from: 1; to: -1; duration: 500; easing.type: Easing.OutQuint
54 | }
55 |
56 | SequentialAnimation {
57 | NumberAnimation {
58 | target: transformScale; property: "xScale"; from: -1; to: -1.4; duration: 250; easing.type: Easing.OutQuart
59 | }
60 |
61 | NumberAnimation {
62 | target: transformScale; property: "xScale"; from: -1.4; to: -1; duration: 250; easing.type: Easing.OutQuart
63 | }
64 | }
65 | }
66 |
67 | // Bottom left
68 | ParallelAnimation {
69 | NumberAnimation {
70 | target: transformScale; property: "xScale"; from: -1; to: 1; duration: 500; easing.type: Easing.OutQuint
71 | }
72 |
73 | SequentialAnimation {
74 | NumberAnimation {
75 | target: transformScale; property: "yScale"; from: -1; to: -1.4; duration: 250; easing.type: Easing.OutQuart
76 | }
77 |
78 | NumberAnimation {
79 | target: transformScale; property: "yScale"; from: -1.4; to: -1; duration: 250; easing.type: Easing.OutQuart
80 | }
81 | }
82 | }
83 |
84 | // Top left
85 | ParallelAnimation {
86 | NumberAnimation {
87 | target: transformScale; property: "yScale"; from: -1; to: 1; duration: 500; easing.type: Easing.OutQuint
88 | }
89 |
90 | SequentialAnimation {
91 | NumberAnimation {
92 | target: transformScale; property: "xScale"; from: 1; to: 1.4; duration: 250; easing.type: Easing.OutQuart
93 | }
94 |
95 | NumberAnimation {
96 | target: transformScale; property: "xScale"; from: 1.4; to: 1; duration: 250; easing.type: Easing.OutQuart
97 | }
98 | }
99 | }
100 | }
101 | }
102 | }
103 |
--------------------------------------------------------------------------------
/Loaders/SharinganLoader.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.7
2 |
3 | Item {
4 |
5 | // ----- Public Properties ----- //
6 |
7 | property int radius: 25
8 | property color color: "#FAFAFA"
9 | property bool useCircle: false
10 |
11 | property alias running: timer.running
12 |
13 | // ----- Private Properties ----- //
14 |
15 | property int _innerRadius: radius * 0.7
16 | property int _currentIndex: 0
17 |
18 | id: root
19 | width: radius * 2
20 | height: radius * 2
21 |
22 | Repeater {
23 | id: repeater
24 | model: 8
25 | delegate: Component {
26 | Rectangle {
27 | // ----- Private Properties ----- //
28 | property int _rotation: (360 / repeater.model) * index
29 | property int _maxIndex: root._currentIndex + 1
30 | property int _minIndex: root._currentIndex - 1
31 |
32 | width: root.useCircle ? (root.radius - root._innerRadius) * 2 : root.width - (root._innerRadius * 2)
33 | height: root.useCircle ? width : width * 0.5
34 | x: _getPosOnCircle(_rotation).x
35 | y: _getPosOnCircle(_rotation).y
36 | radius: root.useCircle ? width : 0
37 | color: root.color
38 | opacity: (index >= _minIndex && index <= _maxIndex) || (index === 0 && root._currentIndex + 1 > 7) ? 1 : 0.3
39 | transform: Rotation {
40 | angle: 360 - _rotation
41 | origin {
42 | x: 0
43 | y: height / 2
44 | }
45 | }
46 | transformOrigin: index >= repeater.model / 2 ? Item.Center : Item.Center
47 |
48 | Behavior on opacity { NumberAnimation { duration: 200 } }
49 | }
50 | }
51 | }
52 |
53 | Timer {
54 | id: timer
55 | interval: 80
56 | repeat: true
57 | running: true
58 | onTriggered: {
59 | if (root._currentIndex === 7) {
60 | root._currentIndex = 0;
61 | }
62 | else {
63 | root._currentIndex++;
64 | }
65 | }
66 | }
67 |
68 | // ----- Private Functions ----- //
69 |
70 | function _toRadian(degree) {
71 | return (degree * 3.14159265) / 180.0;
72 | }
73 |
74 | function _getPosOnCircle(angleInDegree) {
75 | var centerX = root.width / 2, centerY = root.height / 2;
76 | var posX = 0, posY = 0;
77 |
78 | posX = centerX + root._innerRadius * Math.cos(_toRadian(angleInDegree));
79 | posY = centerY - root._innerRadius * Math.sin(_toRadian(angleInDegree));
80 | return Qt.point(posX, posY);
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # QML-Loaders
2 |
3 | Beautiful and smooth loading indicator implementations in QML.
4 | Many of the designs were taken from [here](https://github.com/nntuyen/mkloader).
5 | There are/will be also other designs taken from various places.
6 |
7 | 
8 |
9 | # Supported Types
10 |
11 | - Sharingan
12 | - BlockLoader
13 | - FishSpinner
14 | - DoubleFishSpiner
15 | - PulseLoader
16 | - LineSpinner
17 | - RectangleLoader (Concept by [Enes Özgör](https://github.com/enszgr))
18 | - ClockSpinner (Implementation by [@majidkamali1370](https://github.com/majidkamali1370))
19 |
20 | # Demo
21 |
22 | You can find the demo app [here](https://play.google.com/store/apps/details?id=org.zmc.qml_loading).
23 |
--------------------------------------------------------------------------------
/demo.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Furkanzmc/QML-Loaders/08cb9e0d8a8c4c73aa79c82158a7649c4efb3a4e/demo.gif
--------------------------------------------------------------------------------