├── .gitignore ├── Android ├── .gitignore ├── build.gradle ├── gradle.properties ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── gaia │ │ └── MotionCurve │ │ ├── GaiaMotionCurveAccelerateInterpolator.java │ │ ├── GaiaMotionCurveAnticipateInterpolator.java │ │ ├── GaiaMotionCurveBounceInterpolator.java │ │ ├── GaiaMotionCurveCosineInterpolator.java │ │ ├── GaiaMotionCurveCubicBezierInterpolator.java │ │ ├── GaiaMotionCurveDecelerateInterpolator.java │ │ ├── GaiaMotionCurveLinearInterpolator.java │ │ ├── GaiaMotionCurveOvershootInterpolator.java │ │ ├── GaiaMotionCurveSpringInterpolator.java │ │ └── GaiaMotionCurveStandardInterpolator.java │ └── res │ └── values │ └── strings.xml ├── LICENSE ├── README.md ├── README_en.md ├── docs ├── assets │ ├── accelerate.gif │ ├── anticipate.gif │ ├── bounce.gif │ ├── cosine.gif │ ├── decelerate.gif │ ├── linear.gif │ ├── overshoot.gif │ ├── spring.gif │ └── standard.gif ├── en-US │ ├── accelerate.md │ ├── anticipate.md │ ├── bounce.md │ ├── cosine.md │ ├── decelerate.md │ ├── linear.md │ ├── overshoot.md │ ├── spring.md │ └── standard.md └── zh-CN │ ├── accelerate.md │ ├── anticipate.md │ ├── bounce.md │ ├── cosine.md │ ├── decelerate.md │ ├── linear.md │ ├── overshoot.md │ ├── spring.md │ └── standard.md ├── examples ├── Android │ ├── .gitignore │ ├── app │ │ ├── .gitignore │ │ ├── build.gradle │ │ ├── libs │ │ │ └── gaia-motion-curve-0.1.aar │ │ ├── proguard-rules.pro │ │ └── src │ │ │ ├── androidTest │ │ │ └── java │ │ │ │ └── com │ │ │ │ └── gaia │ │ │ │ └── demo │ │ │ │ └── ExampleInstrumentedTest.java │ │ │ ├── main │ │ │ ├── AndroidManifest.xml │ │ │ ├── java │ │ │ │ └── com │ │ │ │ │ └── gaia │ │ │ │ │ └── demo │ │ │ │ │ ├── AnimationActivity.java │ │ │ │ │ └── MainActivity.java │ │ │ └── res │ │ │ │ ├── drawable-v24 │ │ │ │ └── ic_launcher_foreground.xml │ │ │ │ ├── drawable │ │ │ │ └── ic_launcher_background.xml │ │ │ │ ├── layout │ │ │ │ ├── activity_animation.xml │ │ │ │ ├── activity_listview.xml │ │ │ │ └── activity_main.xml │ │ │ │ ├── mipmap-anydpi-v26 │ │ │ │ ├── ic_launcher.xml │ │ │ │ └── ic_launcher_round.xml │ │ │ │ ├── mipmap-hdpi │ │ │ │ ├── ic_launcher.webp │ │ │ │ └── ic_launcher_round.webp │ │ │ │ ├── mipmap-mdpi │ │ │ │ ├── ic_launcher.webp │ │ │ │ └── ic_launcher_round.webp │ │ │ │ ├── mipmap-xhdpi │ │ │ │ ├── ic_launcher.webp │ │ │ │ └── ic_launcher_round.webp │ │ │ │ ├── mipmap-xxhdpi │ │ │ │ ├── ic_launcher.webp │ │ │ │ └── ic_launcher_round.webp │ │ │ │ ├── mipmap-xxxhdpi │ │ │ │ ├── ic_launcher.webp │ │ │ │ └── ic_launcher_round.webp │ │ │ │ ├── values-night │ │ │ │ └── themes.xml │ │ │ │ └── values │ │ │ │ ├── colors.xml │ │ │ │ ├── strings.xml │ │ │ │ └── themes.xml │ │ │ └── test │ │ │ └── java │ │ │ └── com │ │ │ └── gaia │ │ │ └── demo │ │ │ └── ExampleUnitTest.java │ ├── build.gradle │ ├── gradle.properties │ ├── gradle │ │ └── wrapper │ │ │ ├── gradle-wrapper.jar │ │ │ └── gradle-wrapper.properties │ ├── gradlew │ ├── gradlew.bat │ └── settings.gradle └── iOS │ ├── GaiaMotionCurveDemo.xcodeproj │ └── project.pbxproj │ ├── GaiaMotionCurveDemo │ ├── AnimationViewController.h │ ├── AnimationViewController.m │ ├── AppDelegate.h │ ├── AppDelegate.m │ ├── Assets.xcassets │ │ ├── AppIcon.appiconset │ │ │ ├── 111.png │ │ │ ├── Contents.json │ │ │ └── Ico1n.png │ │ ├── Contents.json │ │ └── LaunchImage.launchimage │ │ │ ├── Contents.json │ │ │ └── 画板@2x.png │ ├── Info.plist │ ├── ViewController.h │ ├── ViewController.m │ └── main.m │ ├── Podfile │ └── Podfile.lock └── iOS ├── GaiaMotionCurve.podspec ├── GaiaMotionCurve.xcodeproj └── project.pbxproj ├── GaiaMotionCurve ├── CALayer+GaiaMotionCurve.h ├── CALayer+GaiaMotionCurve.m ├── GMCDefines.h ├── GMCFunctions.h ├── GMCFunctions.m ├── GMCHelper.h ├── GMCHelper.m ├── GMCModel+Internal.h ├── GMCModel+Internal.m ├── GMCModel.h ├── GMCModel.m ├── GaiaMotionCurve.h ├── NSValue+GMCCGFloat.h ├── NSValue+GMCCGFloat.m ├── NSValue+GMCUIColor.h └── NSValue+GMCUIColor.m ├── GaiaMotionCurveTests └── GaiaMotionCurveTests.m └── Podfile /.gitignore: -------------------------------------------------------------------------------- 1 | *.mode1 2 | *.mode1v3 3 | *.mode2v3 4 | *.perspective 5 | *.perspectivev3 6 | *.pbxuser 7 | *.xcworkspace 8 | *.framework/ 9 | xcuserdata 10 | examples/iOS/Pods/ 11 | src/iOS/Pods/ 12 | src/Android/build/ 13 | examples/Android/build/ 14 | **/.idea 15 | **/.vscode 16 | -------------------------------------------------------------------------------- /Android/.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea 5 | .DS_Store 6 | /build 7 | /captures 8 | .externalNativeBuild 9 | .cxx 10 | local.properties 11 | github.properties -------------------------------------------------------------------------------- /Android/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | apply plugin: 'maven-publish' 3 | 4 | allprojects { 5 | repositories { 6 | // The order in which you list these repositories matter. 7 | google() 8 | jcenter() 9 | maven { 10 | url "https://jitpack.io" 11 | } 12 | } 13 | } 14 | 15 | buildscript{ 16 | repositories{ 17 | google() 18 | jcenter() 19 | maven { 20 | url "https://jitpack.io" 21 | } 22 | } 23 | 24 | dependencies{ 25 | classpath "com.android.tools.build:gradle:7.0.2" 26 | } 27 | } 28 | 29 | android { 30 | compileSdk 32 31 | 32 | defaultConfig { 33 | minSdk 21 34 | targetSdk 32 35 | versionCode 1 36 | versionName "0.1.0" 37 | 38 | } 39 | 40 | 41 | lintOptions { 42 | abortOnError false 43 | } 44 | 45 | buildTypes { 46 | release { 47 | minifyEnabled false 48 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' 49 | } 50 | } 51 | compileOptions { 52 | sourceCompatibility JavaVersion.VERSION_1_8 53 | targetCompatibility JavaVersion.VERSION_1_8 54 | } 55 | } 56 | 57 | 58 | // Because the components are created only during the afterEvaluate phase, you must 59 | // configure your publications using the afterEvaluate() lifecycle method. 60 | afterEvaluate { 61 | publishing { 62 | publications { 63 | // Creates a Maven publication called "release". 64 | release(MavenPublication) { 65 | // Applies the component for the release build variant. 66 | from components.release 67 | 68 | // You can then customize attributes of the publication as shown below. 69 | groupId = 'com.github.alibaba' 70 | artifactId = 'gaia-motion-curve' 71 | version = '0.1.0' 72 | } 73 | // Creates a Maven publication called “debug”. 74 | debug(MavenPublication) { 75 | // Applies the component for the debug build variant. 76 | from components.debug 77 | 78 | groupId = 'com.github.alibaba' 79 | artifactId = 'gaia-motion-curve' 80 | version = '0.1.0-DEV' 81 | } 82 | } 83 | } 84 | } -------------------------------------------------------------------------------- /Android/gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | # IDE (e.g. Android Studio) users: 3 | # Gradle settings configured through the IDE *will override* 4 | # any settings specified in this file. 5 | # For more details on how to configure your build environment visit 6 | # http://www.gradle.org/docs/current/userguide/build_environment.html 7 | # Specifies the JVM arguments used for the daemon process. 8 | # The setting is particularly useful for tweaking memory settings. 9 | org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8 10 | # When configured, Gradle will run in incubating parallel mode. 11 | # This option should only be used with decoupled projects. More details, visit 12 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 13 | # org.gradle.parallel=true 14 | # AndroidX package structure to make it clearer which packages are bundled with the 15 | # Android operating system, and which are packaged with your app"s APK 16 | # https://developer.android.com/topic/libraries/support-library/androidx-rn 17 | android.useAndroidX=true 18 | # Automatically convert third-party libraries to use AndroidX 19 | android.enableJetifier=true -------------------------------------------------------------------------------- /Android/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alibaba/gaia-motion-curve/84f3567dd2725efb9e4dd459c3e303591eafcbfd/Android/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /Android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Thu Jan 06 14:12:50 CST 2022 2 | distributionBase=GRADLE_USER_HOME 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-bin.zip 4 | distributionPath=wrapper/dists 5 | zipStorePath=wrapper/dists 6 | zipStoreBase=GRADLE_USER_HOME 7 | -------------------------------------------------------------------------------- /Android/gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # 4 | # Copyright 2015 the original author or authors. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # https://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | 19 | ############################################################################## 20 | ## 21 | ## Gradle start up script for UN*X 22 | ## 23 | ############################################################################## 24 | 25 | # Attempt to set APP_HOME 26 | # Resolve links: $0 may be a link 27 | PRG="$0" 28 | # Need this for relative symlinks. 29 | while [ -h "$PRG" ] ; do 30 | ls=`ls -ld "$PRG"` 31 | link=`expr "$ls" : '.*-> \(.*\)$'` 32 | if expr "$link" : '/.*' > /dev/null; then 33 | PRG="$link" 34 | else 35 | PRG=`dirname "$PRG"`"/$link" 36 | fi 37 | done 38 | SAVED="`pwd`" 39 | cd "`dirname \"$PRG\"`/" >/dev/null 40 | APP_HOME="`pwd -P`" 41 | cd "$SAVED" >/dev/null 42 | 43 | APP_NAME="Gradle" 44 | APP_BASE_NAME=`basename "$0"` 45 | 46 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 47 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' 48 | 49 | # Use the maximum available, or set MAX_FD != -1 to use that value. 50 | MAX_FD="maximum" 51 | 52 | warn () { 53 | echo "$*" 54 | } 55 | 56 | die () { 57 | echo 58 | echo "$*" 59 | echo 60 | exit 1 61 | } 62 | 63 | # OS specific support (must be 'true' or 'false'). 64 | cygwin=false 65 | msys=false 66 | darwin=false 67 | nonstop=false 68 | case "`uname`" in 69 | CYGWIN* ) 70 | cygwin=true 71 | ;; 72 | Darwin* ) 73 | darwin=true 74 | ;; 75 | MINGW* ) 76 | msys=true 77 | ;; 78 | NONSTOP* ) 79 | nonstop=true 80 | ;; 81 | esac 82 | 83 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 84 | 85 | 86 | # Determine the Java command to use to start the JVM. 87 | if [ -n "$JAVA_HOME" ] ; then 88 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 89 | # IBM's JDK on AIX uses strange locations for the executables 90 | JAVACMD="$JAVA_HOME/jre/sh/java" 91 | else 92 | JAVACMD="$JAVA_HOME/bin/java" 93 | fi 94 | if [ ! -x "$JAVACMD" ] ; then 95 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 96 | 97 | Please set the JAVA_HOME variable in your environment to match the 98 | location of your Java installation." 99 | fi 100 | else 101 | JAVACMD="java" 102 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 103 | 104 | Please set the JAVA_HOME variable in your environment to match the 105 | location of your Java installation." 106 | fi 107 | 108 | # Increase the maximum file descriptors if we can. 109 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 110 | MAX_FD_LIMIT=`ulimit -H -n` 111 | if [ $? -eq 0 ] ; then 112 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 113 | MAX_FD="$MAX_FD_LIMIT" 114 | fi 115 | ulimit -n $MAX_FD 116 | if [ $? -ne 0 ] ; then 117 | warn "Could not set maximum file descriptor limit: $MAX_FD" 118 | fi 119 | else 120 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 121 | fi 122 | fi 123 | 124 | # For Darwin, add options to specify how the application appears in the dock 125 | if $darwin; then 126 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 127 | fi 128 | 129 | # For Cygwin or MSYS, switch paths to Windows format before running java 130 | if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then 131 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 132 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 133 | 134 | JAVACMD=`cygpath --unix "$JAVACMD"` 135 | 136 | # We build the pattern for arguments to be converted via cygpath 137 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 138 | SEP="" 139 | for dir in $ROOTDIRSRAW ; do 140 | ROOTDIRS="$ROOTDIRS$SEP$dir" 141 | SEP="|" 142 | done 143 | OURCYGPATTERN="(^($ROOTDIRS))" 144 | # Add a user-defined pattern to the cygpath arguments 145 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 146 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 147 | fi 148 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 149 | i=0 150 | for arg in "$@" ; do 151 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 152 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 153 | 154 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 155 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 156 | else 157 | eval `echo args$i`="\"$arg\"" 158 | fi 159 | i=`expr $i + 1` 160 | done 161 | case $i in 162 | 0) set -- ;; 163 | 1) set -- "$args0" ;; 164 | 2) set -- "$args0" "$args1" ;; 165 | 3) set -- "$args0" "$args1" "$args2" ;; 166 | 4) set -- "$args0" "$args1" "$args2" "$args3" ;; 167 | 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 168 | 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 169 | 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 170 | 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 171 | 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 172 | esac 173 | fi 174 | 175 | # Escape application args 176 | save () { 177 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done 178 | echo " " 179 | } 180 | APP_ARGS=`save "$@"` 181 | 182 | # Collect all arguments for the java command, following the shell quoting and substitution rules 183 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" 184 | 185 | exec "$JAVACMD" "$@" 186 | -------------------------------------------------------------------------------- /Android/gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem https://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | 17 | @if "%DEBUG%" == "" @echo off 18 | @rem ########################################################################## 19 | @rem 20 | @rem Gradle startup script for Windows 21 | @rem 22 | @rem ########################################################################## 23 | 24 | @rem Set local scope for the variables with windows NT shell 25 | if "%OS%"=="Windows_NT" setlocal 26 | 27 | set DIRNAME=%~dp0 28 | if "%DIRNAME%" == "" set DIRNAME=. 29 | set APP_BASE_NAME=%~n0 30 | set APP_HOME=%DIRNAME% 31 | 32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter. 33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi 34 | 35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 37 | 38 | @rem Find java.exe 39 | if defined JAVA_HOME goto findJavaFromJavaHome 40 | 41 | set JAVA_EXE=java.exe 42 | %JAVA_EXE% -version >NUL 2>&1 43 | if "%ERRORLEVEL%" == "0" goto execute 44 | 45 | echo. 46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 47 | echo. 48 | echo Please set the JAVA_HOME variable in your environment to match the 49 | echo location of your Java installation. 50 | 51 | goto fail 52 | 53 | :findJavaFromJavaHome 54 | set JAVA_HOME=%JAVA_HOME:"=% 55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 56 | 57 | if exist "%JAVA_EXE%" goto execute 58 | 59 | echo. 60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 61 | echo. 62 | echo Please set the JAVA_HOME variable in your environment to match the 63 | echo location of your Java installation. 64 | 65 | goto fail 66 | 67 | :execute 68 | @rem Setup the command line 69 | 70 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 71 | 72 | 73 | @rem Execute Gradle 74 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* 75 | 76 | :end 77 | @rem End local scope for the variables with windows NT shell 78 | if "%ERRORLEVEL%"=="0" goto mainEnd 79 | 80 | :fail 81 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 82 | rem the _cmd.exe /c_ return code! 83 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 84 | exit /b 1 85 | 86 | :mainEnd 87 | if "%OS%"=="Windows_NT" endlocal 88 | 89 | :omega 90 | -------------------------------------------------------------------------------- /Android/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile -------------------------------------------------------------------------------- /Android/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | -------------------------------------------------------------------------------- /Android/src/main/java/com/gaia/MotionCurve/GaiaMotionCurveAccelerateInterpolator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022, Alibaba Group Holding Limited; 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.gaia.MotionCurve; 18 | 19 | 20 | import android.view.animation.Interpolator; 21 | 22 | 23 | public class GaiaMotionCurveAccelerateInterpolator implements Interpolator { 24 | private float x1; 25 | private float y1; 26 | private float x2; 27 | private float y2; 28 | 29 | public GaiaMotionCurveAccelerateInterpolator() { 30 | x1 = 0.4f; 31 | y1 = 0.0f; 32 | x2 = 1.0f; 33 | y2 = 1.0f; 34 | } 35 | 36 | public GaiaMotionCurveAccelerateInterpolator(float a_x1, float a_y1, float a_x2, float a_y2) { 37 | x1 = a_x1; 38 | y1 = a_y1; 39 | x2 = a_x2; 40 | y2 = a_y2; 41 | } 42 | 43 | @Override 44 | public float getInterpolation(float p) { 45 | float x = p; 46 | float z; 47 | float ax, ay, bx, by, cx, cy; 48 | for (int i = 1; i < 14; i++) { 49 | cx = 3.0f * x1; 50 | bx = 3.0f * (x2 - x1) - cx; 51 | ax = 1.0f - cx - bx; 52 | float b = x * (cx + x * (bx + x * ax)); 53 | z = b - p; 54 | if (Math.abs(z) < 1e-3) { 55 | break; 56 | } 57 | float d = cx + x * (2.0f * bx + 3.0f * ax * x); 58 | x -= z / d; 59 | } 60 | cy = 3.0f * y1; 61 | by = 3.0f * (y2 - y1) - cy; 62 | ay = 1.0f - cy - by; 63 | return x * (cy + x * (by + x * ay)); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /Android/src/main/java/com/gaia/MotionCurve/GaiaMotionCurveAnticipateInterpolator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022, Alibaba Group Holding Limited; 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.gaia.MotionCurve; 18 | 19 | import android.view.animation.Interpolator; 20 | 21 | 22 | public class GaiaMotionCurveAnticipateInterpolator implements Interpolator { 23 | private float d, x1, y1, x2, y2, x3, y3, x4, y4; 24 | 25 | public GaiaMotionCurveAnticipateInterpolator() { 26 | d = 1.2f; 27 | x1 = 0.33f; 28 | y1 = 0.0f; 29 | x2 = 0.3f; 30 | y2 = 1.0f; 31 | x3 = 0.33f; 32 | y3 = 0.0f; 33 | x4 = 0.5f; 34 | y4 = 1.0f; 35 | } 36 | 37 | public GaiaMotionCurveAnticipateInterpolator(float a_d, float a_x1, float a_y1, float a_x2, float a_y2, float a_x3, float a_y3, float a_x4, float a_y4) { 38 | d = a_d; 39 | x1 = a_x1; 40 | y1 = a_y1; 41 | x2 = a_x2; 42 | y2 = a_y2; 43 | x3 = a_x3; 44 | y3 = a_y3; 45 | x4 = a_x4; 46 | y4 = a_y4; 47 | } 48 | 49 | @Override 50 | public float getInterpolation(float p) { 51 | if (p <= 0.3f) { 52 | return -d * mcx_standard_curve(p * 3.33f, x1, y1, x2, y2); 53 | } else { 54 | return -d * mcx_standard_curve(0.3f * 3.33f, x1, y1, x2, y2) + (1 + d) * mcx_standard_curve((p - 0.3f) * 1.42f, x3, y3, x4, y4); 55 | } 56 | } 57 | 58 | private float mcx_standard_curve(float p, float a_x1, float a_y1, float a_x2, float a_y2) { 59 | float x = p; 60 | float z; 61 | float ax, ay, bx, by, cx, cy; 62 | for (int i = 1; i < 14; i++) { 63 | cx = 3 * a_x1; 64 | bx = 3 * (a_x2 - a_x1) - cx; 65 | ax = 1 - cx - bx; 66 | float b = x * (cx + x * (bx + x * ax)); 67 | z = b - p; 68 | if (Math.abs(z) < 1e-3) { 69 | break; 70 | } 71 | float d = cx + x * (2 * bx + 3 * ax * x); 72 | x -= z / d; 73 | } 74 | cy = 3 * a_y1; 75 | by = 3 * (a_y2 - a_y1) - cy; 76 | ay = 1 - cy - by; 77 | return x * (cy + x * (by + x * ay)); 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /Android/src/main/java/com/gaia/MotionCurve/GaiaMotionCurveBounceInterpolator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022, Alibaba Group Holding Limited; 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.gaia.MotionCurve; 18 | 19 | import android.view.animation.Interpolator; 20 | 21 | 22 | 23 | public class GaiaMotionCurveBounceInterpolator implements Interpolator { 24 | private float v, d; 25 | 26 | public GaiaMotionCurveBounceInterpolator() { 27 | v = 1.0f; 28 | d = 1.0f; 29 | } 30 | 31 | public GaiaMotionCurveBounceInterpolator(float a_v, float a_d) { 32 | v = a_v; 33 | d = a_d; 34 | } 35 | 36 | @Override 37 | public float getInterpolation(float p) { 38 | float tp = p; 39 | float b = 2.75f*v; 40 | if (tp < (1.0f/b)) { 41 | return (float) Math.pow(b, 2.0f)*tp*tp; 42 | } else if (tp < (2.0f/b)) { 43 | return (float)Math.pow(b*d, 2.0f)*(tp - 1.5f/b)*(tp - 1.5f/b) + (float)(1.0f - Math.pow(b*d, 2.0f)*(1.0f/b - 1.5f/b)*(1.0f/b - 1.5f/b)); 44 | } else if (tp < (2.5f/b)) { 45 | return (float)Math.pow(b*d, 2.0f)*(tp - 2.25f/b)*(tp - 2.25f/b) + (float)(1.0f - Math.pow(b*d, 2.0f)*(2.0f/b- 2.25f/b)*(2.0f/b - 2.25f/b)); 46 | } else { 47 | return (float)Math.min(1.0f, Math.pow(b*d, 2.0f)*(tp - 2.625f/b)*(tp - 2.625f/b) + (float)(1.0f - Math.pow(b*d, 2.0f)*(2.5f/b - 2.625f/b)*(2.5f/b - 2.625f/b))) ; 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /Android/src/main/java/com/gaia/MotionCurve/GaiaMotionCurveCosineInterpolator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022, Alibaba Group Holding Limited; 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.gaia.MotionCurve; 18 | 19 | import android.view.animation.Interpolator; 20 | 21 | 22 | public class GaiaMotionCurveCosineInterpolator implements Interpolator { 23 | private float d, c; 24 | 25 | public GaiaMotionCurveCosineInterpolator() { 26 | d = 1.0f; 27 | c = 1.0f; 28 | } 29 | 30 | public GaiaMotionCurveCosineInterpolator(float a_d, float a_c) { 31 | d = a_d; 32 | c = a_c; 33 | } 34 | 35 | @Override 36 | public float getInterpolation(float p) { 37 | return d * 0.5f * (1.0f - (float) Math.cos(p * 2.0f * c * Math.PI)); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /Android/src/main/java/com/gaia/MotionCurve/GaiaMotionCurveCubicBezierInterpolator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022, Alibaba Group Holding Limited; 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.gaia.MotionCurve; 18 | 19 | import android.view.animation.Interpolator; 20 | 21 | 22 | public class GaiaMotionCurveCubicBezierInterpolator implements Interpolator { 23 | private float x1, y1, x2, y2; 24 | 25 | public GaiaMotionCurveCubicBezierInterpolator() { 26 | x1 = 0.4f; 27 | y1 = 0.0f; 28 | x2 = 0.1f; 29 | y2 = 1.0f; 30 | } 31 | 32 | public GaiaMotionCurveCubicBezierInterpolator(float a_x1, float a_y1, float a_x2, float a_y2) { 33 | x1 = a_x1; 34 | y1 = a_y1; 35 | x2 = a_x2; 36 | y2 = a_y2; 37 | } 38 | 39 | @Override 40 | public float getInterpolation(float p) { 41 | float x = p; 42 | float z; 43 | float ax, ay, bx, by, cx, cy; 44 | for (int i = 1; i < 14; i++) { 45 | cx = 3 * x1; 46 | bx = 3 * (x2 - x1) - cx; 47 | ax = 1 - cx - bx; 48 | float b = x * (cx + x * (bx + x * ax)); 49 | z = b - p; 50 | if (Math.abs(z) < 1e-3) { 51 | break; 52 | } 53 | float d = cx + x * (2 * bx + 3 * ax * x); 54 | x -= z / d; 55 | } 56 | cy = 3 * y1; 57 | by = 3 * (y2 - y1) - cy; 58 | ay = 1 - cy - by; 59 | return x * (cy + x * (by + x * ay)); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /Android/src/main/java/com/gaia/MotionCurve/GaiaMotionCurveDecelerateInterpolator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022, Alibaba Group Holding Limited; 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.gaia.MotionCurve; 18 | 19 | import android.view.animation.Interpolator; 20 | 21 | public class GaiaMotionCurveDecelerateInterpolator implements Interpolator { 22 | private float x1; 23 | private float y1; 24 | private float x2; 25 | private float y2; 26 | 27 | public GaiaMotionCurveDecelerateInterpolator() { 28 | x1 = 0.0f; 29 | y1 = 0.0f; 30 | x2 = 0.1f; 31 | y2 = 1.0f; 32 | } 33 | 34 | public GaiaMotionCurveDecelerateInterpolator(float a_x1, float a_y1, float a_x2, float a_y2) { 35 | x1 = a_x1; 36 | y1 = a_y1; 37 | x2 = a_x2; 38 | y2 = a_y2; 39 | } 40 | 41 | @Override 42 | public float getInterpolation(float p) { 43 | float x = p; 44 | float z; 45 | float ax, ay, bx, by, cx, cy; 46 | for (int i = 1; i < 14; i++) { 47 | cx = 3.0f * x1; 48 | bx = 3.0f * (x2 - x1) - cx; 49 | ax = 1.0f - cx - bx; 50 | float b = x * (cx + x * (bx + x * ax)); 51 | z = b - p; 52 | if (Math.abs(z) < 1e-3) { 53 | break; 54 | } 55 | float d = cx + x * (2.0f * bx + 3.0f * ax * x); 56 | x -= z / d; 57 | } 58 | cy = 3.0f * y1; 59 | by = 3.0f * (y2 - y1) - cy; 60 | ay = 1.0f - cy - by; 61 | return x * (cy + x * (by + x * ay)); 62 | } 63 | } 64 | 65 | -------------------------------------------------------------------------------- /Android/src/main/java/com/gaia/MotionCurve/GaiaMotionCurveLinearInterpolator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022, Alibaba Group Holding Limited; 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.gaia.MotionCurve; 18 | 19 | import android.view.animation.Interpolator; 20 | 21 | 22 | public class GaiaMotionCurveLinearInterpolator implements Interpolator { 23 | @Override 24 | public float getInterpolation(float p) { 25 | return p; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Android/src/main/java/com/gaia/MotionCurve/GaiaMotionCurveOvershootInterpolator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022, Alibaba Group Holding Limited; 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.gaia.MotionCurve; 18 | 19 | import android.view.animation.Interpolator; 20 | 21 | 22 | public class GaiaMotionCurveOvershootInterpolator implements Interpolator { 23 | private float d, x1, y1, x2, y2, x3, y3, x4, y4; 24 | 25 | public GaiaMotionCurveOvershootInterpolator() { 26 | d = 1.2f; 27 | x1 = 0.33f; 28 | y1 = 0.0f; 29 | x2 = 0.3f; 30 | y2 = 1.0f; 31 | x3 = 0.33f; 32 | y3 = 0.0f; 33 | x4 = 0.5f; 34 | y4 = 1.0f; 35 | } 36 | 37 | public GaiaMotionCurveOvershootInterpolator(float a_d, float a_x1, float a_y1, float a_x2, float a_y2, float a_x3, float a_y3, float a_x4, float a_y4) { 38 | d = a_d; 39 | x1 = a_x1; 40 | y1 = a_y1; 41 | x2 = a_x2; 42 | y2 = a_y2; 43 | x3 = a_x3; 44 | y3 = a_y3; 45 | x4 = a_x4; 46 | y4 = a_y4; 47 | } 48 | 49 | public GaiaMotionCurveOvershootInterpolator setDamping(float d){ 50 | this.d = d; 51 | return this; 52 | } 53 | 54 | @Override 55 | public float getInterpolation(float p) { 56 | if (p <= 0.5f) { 57 | return d * mcx_standard_curve(p * 2, x1, y1, x2, y2); 58 | } else { 59 | return d * mcx_standard_curve(0.5f * 2.0f, x1, y1, x2, y2) - (d - 1) * mcx_standard_curve((p - 0.5f) * 2.0f, x3, y3, x4, y4); 60 | } 61 | } 62 | 63 | private float mcx_standard_curve(float p, float a_x1, float a_y1, float a_x2, float a_y2) { 64 | float x = p; 65 | float z; 66 | float ax, ay, bx, by, cx, cy; 67 | for (int i = 1; i < 14; i++) { 68 | cx = 3 * a_x1; 69 | bx = 3 * (a_x2 - a_x1) - cx; 70 | ax = 1 - cx - bx; 71 | float b = x * (cx + x * (bx + x * ax)); 72 | z = b - p; 73 | if (Math.abs(z) < 1e-3) { 74 | break; 75 | } 76 | float d = cx + x * (2 * bx + 3 * ax * x); 77 | x -= z / d; 78 | } 79 | cy = 3 * a_y1; 80 | by = 3 * (a_y2 - a_y1) - cy; 81 | ay = 1 - cy - by; 82 | return x * (cy + x * (by + x * ay)); 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /Android/src/main/java/com/gaia/MotionCurve/GaiaMotionCurveSpringInterpolator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022, Alibaba Group Holding Limited; 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.gaia.MotionCurve; 18 | 19 | import android.view.animation.Interpolator; 20 | 21 | 22 | public class GaiaMotionCurveSpringInterpolator implements Interpolator { 23 | private float m, s, d, iv; 24 | // private float t, f, v; 25 | private boolean MassSystem; 26 | 27 | public GaiaMotionCurveSpringInterpolator() { 28 | m = 0.7f; 29 | s = 380.0f; 30 | d = 10.0f; 31 | iv = -2.0f; 32 | // t = 533.0f; 33 | // f = 14.0f; 34 | // v = -2.0f; 35 | MassSystem = true; 36 | } 37 | 38 | public GaiaMotionCurveSpringInterpolator(float a_m, float a_s, float a_d, float a_iv) { 39 | m = a_m; 40 | s = a_s; 41 | d = a_d; 42 | iv = a_iv; 43 | MassSystem = true; 44 | } 45 | 46 | // GaiaMotionCurveSpringInterpolator(float a_t, float a_f, float a_v) { 47 | // t = a_t; 48 | // f = a_f; 49 | // v = a_v; 50 | // } 51 | 52 | @Override 53 | public float getInterpolation(float p) { 54 | float result = 0; 55 | // if (MassSystem) { 56 | float m_w0 = (float) Math.sqrt(s / m); 57 | float m_zeta = (float) (d / (2.0f * Math.sqrt(s * m))); 58 | float m_wd; 59 | float m_A; 60 | float m_B; 61 | if (m_zeta < 1.0f) { 62 | m_wd = (float) (m_w0 * Math.sqrt(1.0f - m_zeta * m_zeta)); 63 | m_A = 1.0f; 64 | m_B = (m_zeta * m_w0 + -iv) / m_wd; 65 | } else { 66 | m_wd = 0.0f; 67 | m_A = 1.0f; 68 | m_B = -iv + m_w0; 69 | } 70 | float t; 71 | if (m_zeta < 1.0f) { 72 | t = (float) (Math.exp(-p * m_zeta * m_w0) * (m_A * Math.cos(m_wd * p) + m_B * Math.sin(m_wd * p))); 73 | } else { 74 | t = (float) ((m_A + m_B * p) * Math.exp(-p * m_w0)); 75 | } 76 | result = 1.0f - t; 77 | // } 78 | return result; 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /Android/src/main/java/com/gaia/MotionCurve/GaiaMotionCurveStandardInterpolator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022, Alibaba Group Holding Limited; 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.gaia.MotionCurve; 18 | 19 | import android.view.animation.Interpolator; 20 | 21 | public class GaiaMotionCurveStandardInterpolator implements Interpolator { 22 | private float x1, y1, x2, y2; 23 | 24 | public GaiaMotionCurveStandardInterpolator() { 25 | x1 = 0.4f; 26 | y1 = 0.0f; 27 | x2 = 0.1f; 28 | y2 = 1.0f; 29 | } 30 | 31 | public GaiaMotionCurveStandardInterpolator(float a_x1, float a_y1, float a_x2, float a_y2) { 32 | x1 = a_x1; 33 | y1 = a_y1; 34 | x2 = a_x2; 35 | y2 = a_y2; 36 | } 37 | 38 | @Override 39 | public float getInterpolation(float p) { 40 | float x = p; 41 | float z; 42 | float ax, ay, bx, by, cx, cy; 43 | for (int i = 1; i < 14; i++) { 44 | cx = 3 * x1; 45 | bx = 3 * (x2 - x1) - cx; 46 | ax = 1 - cx - bx; 47 | float b = x * (cx + x * (bx + x * ax)); 48 | z = b - p; 49 | if (Math.abs(z) < 1e-3) { 50 | break; 51 | } 52 | float d = cx + x * (2 * bx + 3 * ax * x); 53 | x -= z / d; 54 | } 55 | cy = 3 * y1; 56 | by = 3 * (y2 - y1) - cy; 57 | ay = 1 - cy - by; 58 | return x * (cy + x * (by + x * ay)); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /Android/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | GaiaMotionCurve 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 动效曲线 2 | 3 | > [en-US](./README_en.md) 4 | 5 | 动效曲线SDK 由一系列的动效曲线函数构成,为了解决开发动效的成本高、效果和设计的预期不一致的问题,每个动效曲线函数可应用于任意一个可动效的属性上,通过改变动效过程中的速率和方向给用户带来更好的体验,目前包括线性曲线、加速曲线、减速曲线、余弦曲线、过度曲线、预期曲线、标准曲线(三次贝塞尔曲线)、弹跳曲线、弹性曲线等,目前支持 iOS 和 Android; 6 | 7 | [语雀知识库地址](https://www.yuque.com/youku-gaia/gaia-motion-curve) 8 | 9 | `iOS`和`Android`均用同一套动效曲线的算法实现,保证双端的动效的一致性,iOS 上层封装使用的是`Core Animation`,Android 则是使用的`插值器`。 10 | 11 | ## iOS 12 | 13 | #### 安装 14 | 15 | ```ruby 16 | pod 'GaiaMotionCurve', '0.1.0' 17 | ``` 18 | 19 | #### 头文件 20 | 21 | ```objc 22 | #import 23 | ``` 24 | 25 | #### 例子 26 | 27 | ```objc 28 | 29 | #import 30 | 31 | NSMutableArray *animationModels = [[NSMutableArray alloc] init]; 32 | GMCModel *model1 =[GMCModel modelWithKeyPath:@"opacity" 33 | duration:0.2 34 | delay:0 35 | curveType:MCXCurveTypeStandard 36 | fromValue:[NSValue gmc_valueWithCGFloat:0] 37 | toValue:[NSValue gmc_valueWithCGFloat:0.9]]; 38 | [animationModels addObject:model1]; 39 | [_tipsImageView.layer gmc_animateWithAnimationModels:animationModels completion:^(BOOL finished) {}]; 40 | 41 | ``` 42 | 43 | #### [完整iOS Demo 工程](./examples/iOS) 44 | 45 | 46 | ## Android 47 | 48 | #### 安装 49 | 50 | 引入编译的aar文件 51 | 52 | > 目录:src/Android/build/outputs 53 | 54 | #### 包名 55 | 56 | ```java 57 | 58 | import com.gaia.MotionCurve.*; 59 | 60 | ``` 61 | 62 | #### 例子 63 | 64 | ```java 65 | 66 | TranslateAnimation animation = new TranslateAnimation(0, displaySize.x - maxTextWidth - 2 * margin, 0, 0); 67 | animation.setFillAfter(true); 68 | animation.setDuration(ANIMATION_DURATION); 69 | animation.setInterpolator(new MotionCurveXStandardInterpolator()); 70 | view.startAnimation(animation); 71 | 72 | ``` 73 | 74 | #### [完整Android Demo 工程](./examples/Android) 75 | 76 | ## 曲线分类 77 | 78 | * [线性曲线](./docs/zh-CN/linear.md) 79 | * [加速曲线](./docs/zh-CN/accelerate.md) 80 | * [减速曲线](./docs/zh-CN/decelerate.md) 81 | * [标准曲线](./docs/zh-CN/standard.md) 82 | * [预期曲线](./docs/zh-CN/anticipate.md) 83 | * [过度曲线](./docs/zh-CN/overshoot.md) 84 | * [弹性曲线](./docs/zh-CN/spring.md) 85 | * [弹跳曲线](./docs/zh-CN/bounce.md) 86 | * [余弦曲线](./docs/zh-CN/cosine.md) 87 | 88 | # 行为准则 89 | 90 | 请参考[Alibaba Open Source Code of Conduct](https://github.com/AlibabaDR/community/blob/master/CODE_OF_CONDUCT.md) ([中文版](https://github.com/AlibabaDR/community/blob/master/CODE_OF_CONDUCT_zh.md)). 91 | 92 | 93 | # 开源协议 94 | 95 | gaia-motion-curve is licensed under the Apache License, Version 2.0. See LICENSE for the full license text. 96 | 97 | -------------------------------------------------------------------------------- /README_en.md: -------------------------------------------------------------------------------- 1 | # Motion Curve 2 | 3 | The Motion Curve SDK consists of a series of dynamic curve functions. In order to solve the problems of high cost of developing dynamic effects and inconsistent effects and design expectations, each dynamic curve function can be applied to any dynamic attribute. Bring a better experience to users by changing the speed and direction in the animation process, currently including linear curve, acceleration curve, deceleration curve, cosine curve, transition curve, expected curve, standard curve (cubic Bezier curve), bounce Curves, elastic curves, etc., currently support iOS and Android; 4 | 5 | [YuQue](https://www.yuque.com/youku-gaia/gaia-motion-curve) 6 | 7 | Both `iOS` and `Android` are implemented with the same set of motion curve algorithms to ensure the consistency of motion effects at both ends. The upper layer package of iOS uses `Core Animation`, and Android uses `Interpolator`. 8 | 9 | ## iOS 10 | 11 | #### Install 12 | 13 | ```ruby 14 | pod 'GaiaMotionCurve', '0.1.0' 15 | ``` 16 | 17 | #### Header 18 | 19 | ```objc 20 | #import 21 | ``` 22 | 23 | #### Example 24 | 25 | ```objc 26 | #import 27 | 28 | NSMutableArray *animationModels = [[NSMutableArray alloc] init]; 29 | GMCModel *model1 =[GMCModel modelWithKeyPath:@"opacity" 30 | duration:0.2 31 | delay:0 32 | curveType:MCXCurveTypeStandard 33 | fromValue:[NSValue gmc_valueWithCGFloat:0] 34 | toValue:[NSValue gmc_valueWithCGFloat:0.9]]; 35 | [animationModels addObject:model1]; 36 | [_tipsImageView.layer gmc_animateWithAnimationModels:animationModels completion:^(BOOL finished) {}]; 37 | 38 | ``` 39 | 40 | #### [Full iOS Demo Project](./examples/iOS) 41 | 42 | 43 | ## Android 44 | 45 | #### Install 46 | 47 | import compiled aar file 48 | 49 | > Directory:src/Android/build/outputs 50 | 51 | #### Package 52 | 53 | ```java 54 | import com.gaia.MotionCurve.*; 55 | ``` 56 | 57 | #### Example 58 | 59 | ```java 60 | TranslateAnimation animation = new TranslateAnimation(0, displaySize.x - maxTextWidth - 2 * margin, 0, 0); 61 | animation.setFillAfter(true); 62 | animation.setDuration(ANIMATION_DURATION); 63 | animation.setInterpolator(new MotionCurveXStandardInterpolator()); 64 | view.startAnimation(animation); 65 | 66 | ``` 67 | 68 | #### [Full Android Demo Project](./examples/Android) 69 | 70 | ## Motion Curve Categories 71 | 72 | * [Linear](./docs/en-US/linear.md) 73 | * [Accelerate](./docs/en-US/accelerate.md) 74 | * [Decelerate](./docs/en-US/decelerate.md) 75 | * [Standard](./docs/en-US/standard.md) 76 | * [Anticipate](./docs/en-US/anticipate.md) 77 | * [Overshoot](./docs/en-US/overshoot.md) 78 | * [Spring](./docs/en-US/spring.md) 79 | * [Bounce](./docs/en-US/bounce.md) 80 | * [Cosine](./docs/en-US/cosine.md) 81 | 82 | # Code of Conduct 83 | 84 | Please refer to [Alibaba Open Source Code of Conduct](https://github.com/AlibabaDR/community/blob/master/CODE_OF_CONDUCT.md). 85 | 86 | 87 | # LICENCE 88 | 89 | gaia-motion-curve is licensed under the Apache License, Version 2.0. See LICENSE for the full license text. 90 | 91 | -------------------------------------------------------------------------------- /docs/assets/accelerate.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alibaba/gaia-motion-curve/84f3567dd2725efb9e4dd459c3e303591eafcbfd/docs/assets/accelerate.gif -------------------------------------------------------------------------------- /docs/assets/anticipate.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alibaba/gaia-motion-curve/84f3567dd2725efb9e4dd459c3e303591eafcbfd/docs/assets/anticipate.gif -------------------------------------------------------------------------------- /docs/assets/bounce.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alibaba/gaia-motion-curve/84f3567dd2725efb9e4dd459c3e303591eafcbfd/docs/assets/bounce.gif -------------------------------------------------------------------------------- /docs/assets/cosine.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alibaba/gaia-motion-curve/84f3567dd2725efb9e4dd459c3e303591eafcbfd/docs/assets/cosine.gif -------------------------------------------------------------------------------- /docs/assets/decelerate.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alibaba/gaia-motion-curve/84f3567dd2725efb9e4dd459c3e303591eafcbfd/docs/assets/decelerate.gif -------------------------------------------------------------------------------- /docs/assets/linear.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alibaba/gaia-motion-curve/84f3567dd2725efb9e4dd459c3e303591eafcbfd/docs/assets/linear.gif -------------------------------------------------------------------------------- /docs/assets/overshoot.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alibaba/gaia-motion-curve/84f3567dd2725efb9e4dd459c3e303591eafcbfd/docs/assets/overshoot.gif -------------------------------------------------------------------------------- /docs/assets/spring.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alibaba/gaia-motion-curve/84f3567dd2725efb9e4dd459c3e303591eafcbfd/docs/assets/spring.gif -------------------------------------------------------------------------------- /docs/assets/standard.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alibaba/gaia-motion-curve/84f3567dd2725efb9e4dd459c3e303591eafcbfd/docs/assets/standard.gif -------------------------------------------------------------------------------- /docs/en-US/accelerate.md: -------------------------------------------------------------------------------- 1 | # Accelerate 2 | 3 | ## Demo 4 | 5 | 6 | 7 | ## iOS 8 | 9 | Enumerate:GMCCurveTypeAccelerate 10 | 11 | ```objc 12 | #import 13 | 14 | CGFloat right = [[UIScreen mainScreen] bounds].size.width - 80 - 20; 15 | GMCModel *model = [GMCModel modelWithKeyPath:@"position.x" 16 | duration:0.75 17 | delay:0 18 | curveType:GMCCurveTypeAccelerate 19 | fromValue:[NSValue gmc_valueWithCGFloat:_animationView.center.x] 20 | toValue:[NSValue gmc_valueWithCGFloat:right]]; 21 | __weak typeof(self) weakSelf = self; 22 | [_animationView.layer gmc_animateWithAnimationModels:@[model] completion:^(BOOL finished) { 23 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 24 | weakSelf.animationView.layer.frame = CGRectMake(80, 200, 40, 40); 25 | }); 26 | }]; 27 | ``` 28 | 29 | ## Android 30 | 31 | Interpolator:GaiaMotionCurveAccelerateInterpolator 32 | 33 | ```java 34 | import com.gaia.MotionCurve.*; 35 | 36 | View animationView = findViewById(R.id.animation_view); 37 | TranslateAnimation animation = new TranslateAnimation(0, 700, 0, 0); 38 | animation.setFillAfter(true); 39 | animation.setDuration(700); 40 | animation.setInterpolator(new GaiaMotionCurveAccelerateInterpolator()); 41 | animationView.startAnimation(animation); 42 | ``` 43 | 44 | ## Customizable Parameters 45 | 46 | Configurable Parameters: 47 | 48 | ``` 49 | x1: x coordinate of control point x1 50 | y1: y coordinate of control point y1 51 | x2: x coordinate of control point x2 52 | y2: y coordinate of control point y2 53 | ``` 54 | 55 | Default: 56 | 57 | ``` 58 | x1 = 0.4 59 | y1 = 0.0 60 | x2 = 1.0 61 | y2 = 1.0 62 | ``` 63 | 64 | iOS 65 | 66 | ```objective-c 67 | CGFloat right = [[UIScreen mainScreen] bounds].size.width - 80 - 20; 68 | GMCModel *model = [GMCModel modelWithKeyPath:@"position.x" 69 | duration:0.75 70 | delay:0 71 | curveType:GMCCurveTypeAccelerate 72 | customArgs:@{@"x1":@0.4,@"y1":@0.0,@"x2":@1.0,@"y2":@1.0} 73 | fromValue:[NSValue gmc_valueWithCGFloat:_animationView.center.x] 74 | toValue:[NSValue gmc_valueWithCGFloat:right]]; 75 | __weak typeof(self) weakSelf = self; 76 | [_animationView.layer gmc_animateWithAnimationModels:@[model] completion:^(BOOL finished) { 77 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 78 | weakSelf.animationView.layer.frame = CGRectMake(80, 200, 40, 40); 79 | }); 80 | }]; 81 | ``` 82 | 83 | Android 84 | 85 | ```java 86 | View animationView = findViewById(R.id.animation_view); 87 | TranslateAnimation animation = new TranslateAnimation(0, 700, 0, 0); 88 | animation.setFillAfter(true); 89 | animation.setDuration(700); 90 | animation.setInterpolator(new GaiaMotionCurveAccelerateInterpolator(0.4, 0.0, 1.0, 1.0)); 91 | animationView.startAnimation(animation); 92 | ``` 93 | 94 | -------------------------------------------------------------------------------- /docs/en-US/anticipate.md: -------------------------------------------------------------------------------- 1 | # Anticipate 2 | 3 | ## Demo 4 | 5 | 6 | 7 | ## iOS 8 | 9 | Enumerate:GMCCurveTypeAnticipate 10 | 11 | ```objc 12 | #import 13 | 14 | CGFloat right = [[UIScreen mainScreen] bounds].size.width - 80 - 20; 15 | GMCModel *model = [GMCModel modelWithKeyPath:@"position.x" 16 | duration:0.75 17 | delay:0 18 | curveType:GMCCurveTypeAnticipate 19 | fromValue:[NSValue gmc_valueWithCGFloat:_animationView.center.x] 20 | toValue:[NSValue gmc_valueWithCGFloat:right]]; 21 | __weak typeof(self) weakSelf = self; 22 | [_animationView.layer gmc_animateWithAnimationModels:@[model] completion:^(BOOL finished) { 23 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 24 | weakSelf.animationView.layer.frame = CGRectMake(80, 200, 40, 40); 25 | }); 26 | }]; 27 | ``` 28 | 29 | ## Android 30 | 31 | Interpolator:GaiaMotionCurveAnticipateInterpolator 32 | 33 | ```java 34 | import com.gaia.MotionCurve.*; 35 | 36 | View animationView = findViewById(R.id.animation_view); 37 | TranslateAnimation animation = new TranslateAnimation(0, 700, 0, 0); 38 | animation.setFillAfter(true); 39 | animation.setDuration(700); 40 | animation.setInterpolator(new GaiaMotionCurveAnticipateInterpolator()); 41 | animationView.startAnimation(animation); 42 | ``` 43 | 44 | ## Customizable Parameters 45 | 46 | Configurable Parameters: 47 | 48 | ``` 49 | d: damping, controls the height of the highest point 50 | x1: x coordinate of control point x1 51 | y1: y coordinate of control point y1 52 | x2: x coordinate of control point x2 53 | y2: y coordinate of control point y2 54 | x3: x coordinate of control point x3 55 | y3: y coordinate of control point y3 56 | x4: x coordinate of control point x4 57 | y4: y coordinate of control point y4 58 | ``` 59 | 60 | Default: 61 | 62 | ``` 63 | d = 0.2 64 | x1 = 0.33 65 | y1 = 0.0 66 | x2 = 0.67 67 | y2 = 1.0 68 | x3 = 0.33 69 | y3 = 0.0 70 | x4 = 0.2 71 | y4 = 1.0 72 | ``` 73 | 74 | iOS 75 | 76 | ```objective-c 77 | CGFloat right = [[UIScreen mainScreen] bounds].size.width - 80 - 20; 78 | GMCModel *model = [GMCModel modelWithKeyPath:@"position.x" 79 | duration:0.75 80 | delay:0 81 | curveType:GMCCurveTypeAnticipate 82 | customArgs:@{@"d":@0.2,@"x1":@0.33,@"y1":@0.0,@"x2":@0.67,@"y2":@1.0, 83 | @"x3":@0.33,@"y3":@0.0,@"x4":@0.2,@"y4":@1.0} 84 | fromValue:[NSValue gmc_valueWithCGFloat:_animationView.center.x] 85 | toValue:[NSValue gmc_valueWithCGFloat:right]]; 86 | __weak typeof(self) weakSelf = self; 87 | [_animationView.layer gmc_animateWithAnimationModels:@[model] completion:^(BOOL finished) { 88 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 89 | weakSelf.animationView.layer.frame = CGRectMake(80, 200, 40, 40); 90 | }); 91 | }]; 92 | ``` 93 | 94 | Android 95 | 96 | ```java 97 | View animationView = findViewById(R.id.animation_view); 98 | TranslateAnimation animation = new TranslateAnimation(0, 700, 0, 0); 99 | animation.setFillAfter(true); 100 | animation.setDuration(700); 101 | animation.setInterpolator(new GaiaMotionCurveAnticipateInterpolator(0.2,0.33,0.0,0.67,1.0,0.33,0.0,0.2,1.0)); 102 | animationView.startAnimation(animation); 103 | ``` 104 | 105 | -------------------------------------------------------------------------------- /docs/en-US/bounce.md: -------------------------------------------------------------------------------- 1 | # Bounce 2 | 3 | ## Demo 4 | 5 | 6 | 7 | ## iOS 8 | 9 | Enumerate:GMCCurveTypeBounce 10 | 11 | ```objc 12 | #import 13 | 14 | CGFloat right = [[UIScreen mainScreen] bounds].size.width - 80 - 20; 15 | GMCModel *model = [GMCModel modelWithKeyPath:@"position.x" 16 | duration:0.75 17 | delay:0 18 | curveType:GMCCurveTypeBounce 19 | fromValue:[NSValue gmc_valueWithCGFloat:_animationView.center.x] 20 | toValue:[NSValue gmc_valueWithCGFloat:right]]; 21 | __weak typeof(self) weakSelf = self; 22 | [_animationView.layer gmc_animateWithAnimationModels:@[model] completion:^(BOOL finished) { 23 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 24 | weakSelf.animationView.layer.frame = CGRectMake(80, 200, 40, 40); 25 | }); 26 | }]; 27 | ``` 28 | 29 | ## Android 30 | 31 | Interpolator:GaiaMotionCurveBounceInterpolator 32 | 33 | ```java 34 | import com.gaia.MotionCurve.*; 35 | 36 | View animationView = findViewById(R.id.animation_view); 37 | TranslateAnimation animation = new TranslateAnimation(0, 700, 0, 0); 38 | animation.setFillAfter(true); 39 | animation.setDuration(700); 40 | animation.setInterpolator(new GaiaMotionCurveBounceInterpolator()); 41 | animationView.startAnimation(animation); 42 | ``` 43 | 44 | ## Customizable Parameters 45 | 46 | Configurable Parameters: 47 | 48 | ``` 49 | v:velocity 50 | d:damping 51 | ``` 52 | 53 | Default: 54 | 55 | ``` 56 | v = 1.0 57 | d = 1.0 58 | ``` 59 | 60 | iOS 61 | 62 | ```objective-c 63 | CGFloat right = [[UIScreen mainScreen] bounds].size.width - 80 - 20; 64 | GMCModel *model = [GMCModel modelWithKeyPath:@"position.x" 65 | duration:0.75 66 | delay:0 67 | curveType:GMCCurveTypeBounce 68 | customArgs:@{@"v":@1.0,@"d":@1.0} 69 | fromValue:[NSValue gmc_valueWithCGFloat:_animationView.center.x] 70 | toValue:[NSValue gmc_valueWithCGFloat:right]]; 71 | __weak typeof(self) weakSelf = self; 72 | [_animationView.layer gmc_animateWithAnimationModels:@[model] completion:^(BOOL finished) { 73 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 74 | weakSelf.animationView.layer.frame = CGRectMake(80, 200, 40, 40); 75 | }); 76 | }]; 77 | ``` 78 | 79 | Android 80 | 81 | ```java 82 | View animationView = findViewById(R.id.animation_view); 83 | TranslateAnimation animation = new TranslateAnimation(0, 700, 0, 0); 84 | animation.setFillAfter(true); 85 | animation.setDuration(700); 86 | animation.setInterpolator(new GaiaMotionCurveBounceInterpolator(1.0, 1.0)); 87 | animationView.startAnimation(animation); 88 | ``` 89 | 90 | -------------------------------------------------------------------------------- /docs/en-US/cosine.md: -------------------------------------------------------------------------------- 1 | # Cosine 2 | 3 | ## Demo 4 | 5 | 6 | 7 | ## iOS 8 | 9 | Enumerate:GMCCurveTypeCosine 10 | 11 | ```objc 12 | #import 13 | 14 | CGFloat right = [[UIScreen mainScreen] bounds].size.width - 80 - 20; 15 | GMCModel *model = [GMCModel modelWithKeyPath:@"position.x" 16 | duration:0.75 17 | delay:0 18 | curveType:GMCCurveTypeCosine 19 | fromValue:[NSValue gmc_valueWithCGFloat:_animationView.center.x] 20 | toValue:[NSValue gmc_valueWithCGFloat:right]]; 21 | __weak typeof(self) weakSelf = self; 22 | [_animationView.layer gmc_animateWithAnimationModels:@[model] completion:^(BOOL finished) { 23 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 24 | weakSelf.animationView.layer.frame = CGRectMake(80, 200, 40, 40); 25 | }); 26 | }]; 27 | ``` 28 | 29 | ## Android 30 | 31 | Interpolator:GaiaMotionCurveCosineInterpolator 32 | 33 | ```java 34 | import com.gaia.MotionCurve.*; 35 | 36 | View animationView = findViewById(R.id.animation_view); 37 | TranslateAnimation animation = new TranslateAnimation(0, 700, 0, 0); 38 | animation.setFillAfter(true); 39 | animation.setDuration(700); 40 | animation.setInterpolator(new GaiaMotionCurveCosineInterpolator()); 41 | animationView.startAnimation(animation); 42 | ``` 43 | 44 | ## Customizable Parameters 45 | 46 | Configurable Parameters: 47 | 48 | ``` 49 | d:damping 50 | c:cycles, multiples of 0.25 51 | ``` 52 | 53 | Default: 54 | 55 | ``` 56 | d = 1.0 57 | c = 1.0 58 | ``` 59 | 60 | iOS 61 | 62 | ```objective-c 63 | CGFloat right = [[UIScreen mainScreen] bounds].size.width - 80 - 20; 64 | GMCModel *model = [GMCModel modelWithKeyPath:@"position.x" 65 | duration:0.75 66 | delay:0 67 | curveType:GMCCurveTypeCosine 68 | customArgs:@{@"d":@1.0,@"c":@1.0} 69 | fromValue:[NSValue gmc_valueWithCGFloat:_animationView.center.x] 70 | toValue:[NSValue gmc_valueWithCGFloat:right]]; 71 | __weak typeof(self) weakSelf = self; 72 | [_animationView.layer gmc_animateWithAnimationModels:@[model] completion:^(BOOL finished) { 73 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 74 | weakSelf.animationView.layer.frame = CGRectMake(80, 200, 40, 40); 75 | }); 76 | }]; 77 | ``` 78 | 79 | Android 80 | 81 | ```java 82 | View animationView = findViewById(R.id.animation_view); 83 | TranslateAnimation animation = new TranslateAnimation(0, 700, 0, 0); 84 | animation.setFillAfter(true); 85 | animation.setDuration(700); 86 | animation.setInterpolator(new GaiaMotionCurveCosineInterpolator(1.0, 1.0)); 87 | animationView.startAnimation(animation); 88 | ``` 89 | 90 | -------------------------------------------------------------------------------- /docs/en-US/decelerate.md: -------------------------------------------------------------------------------- 1 | # Decelerate 2 | 3 | ## Demo 4 | 5 | 6 | 7 | ## iOS 8 | 9 | Enumerate:GMCCurveTypeDecelerate 10 | 11 | ```objc 12 | #import 13 | 14 | CGFloat right = [[UIScreen mainScreen] bounds].size.width - 80 - 20; 15 | GMCModel *model = [GMCModel modelWithKeyPath:@"position.x" 16 | duration:0.75 17 | delay:0 18 | curveType:GMCCurveTypeDecelerate 19 | fromValue:[NSValue gmc_valueWithCGFloat:_animationView.center.x] 20 | toValue:[NSValue gmc_valueWithCGFloat:right]]; 21 | __weak typeof(self) weakSelf = self; 22 | [_animationView.layer gmc_animateWithAnimationModels:@[model] completion:^(BOOL finished) { 23 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 24 | weakSelf.animationView.layer.frame = CGRectMake(80, 200, 40, 40); 25 | }); 26 | }]; 27 | ``` 28 | 29 | ## Android 30 | 31 | Interpolator:GaiaMotionCurveDecelerateInterpolator 32 | 33 | ```java 34 | import com.gaia.MotionCurve.*; 35 | 36 | View animationView = findViewById(R.id.animation_view); 37 | TranslateAnimation animation = new TranslateAnimation(0, 700, 0, 0); 38 | animation.setFillAfter(true); 39 | animation.setDuration(700); 40 | animation.setInterpolator(new GaiaMotionCurveDecelerateInterpolator()); 41 | animationView.startAnimation(animation); 42 | ``` 43 | 44 | ## Customizable Parameters 45 | 46 | Configurable Parameters: 47 | 48 | ``` 49 | x1: x coordinate of control point x1 50 | y1: y coordinate of control point y1 51 | x2: x coordinate of control point x2 52 | y2: y coordinate of control point y2 53 | ``` 54 | 55 | Default: 56 | 57 | ``` 58 | x1 = 0.0 59 | y1 = 0.0 60 | x2 = 0.1 61 | y2 = 1.0 62 | ``` 63 | 64 | iOS 65 | 66 | ```objective-c 67 | CGFloat right = [[UIScreen mainScreen] bounds].size.width - 80 - 20; 68 | GMCModel *model = [GMCModel modelWithKeyPath:@"position.x" 69 | duration:0.75 70 | delay:0 71 | curveType:GMCCurveTypeDecelerate 72 | customArgs:@{@"x1":@0.0,@"y1":@0.0,@"x2":@0.1,@"y2":@1.0} 73 | fromValue:[NSValue gmc_valueWithCGFloat:_animationView.center.x] 74 | toValue:[NSValue gmc_valueWithCGFloat:right]]; 75 | __weak typeof(self) weakSelf = self; 76 | [_animationView.layer gmc_animateWithAnimationModels:@[model] completion:^(BOOL finished) { 77 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 78 | weakSelf.animationView.layer.frame = CGRectMake(80, 200, 40, 40); 79 | }); 80 | }]; 81 | ``` 82 | 83 | Android 84 | 85 | ```java 86 | View animationView = findViewById(R.id.animation_view); 87 | TranslateAnimation animation = new TranslateAnimation(0, 700, 0, 0); 88 | animation.setFillAfter(true); 89 | animation.setDuration(700); 90 | animation.setInterpolator(new GaiaMotionCurveDecelerateInterpolator(0.0, 0.0, 0.1, 1.0)); 91 | animationView.startAnimation(animation); 92 | ``` 93 | 94 | -------------------------------------------------------------------------------- /docs/en-US/linear.md: -------------------------------------------------------------------------------- 1 | # Linear 2 | 3 | ## Demo 4 | 5 | 6 | 7 | ## iOS 8 | 9 | Enumerate:GMCCurveTypeLinear 10 | 11 | ```objc 12 | #import 13 | 14 | CGFloat right = [[UIScreen mainScreen] bounds].size.width - 80 - 20; 15 | GMCModel *model = [GMCModel modelWithKeyPath:@"position.x" 16 | duration:0.75 17 | delay:0 18 | curveType:GMCCurveTypeLinear 19 | fromValue:[NSValue gmc_valueWithCGFloat:_animationView.center.x] 20 | toValue:[NSValue gmc_valueWithCGFloat:right]]; 21 | __weak typeof(self) weakSelf = self; 22 | [_animationView.layer gmc_animateWithAnimationModels:@[model] completion:^(BOOL finished) { 23 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 24 | weakSelf.animationView.layer.frame = CGRectMake(80, 200, 40, 40); 25 | }); 26 | }]; 27 | ``` 28 | 29 | ## Android 30 | 31 | Interpolator:GaiaMotionCurveLinearInterpolator 32 | 33 | ```java 34 | import com.gaia.MotionCurve.*; 35 | 36 | View animationView = findViewById(R.id.animation_view); 37 | TranslateAnimation animation = new TranslateAnimation(0, 700, 0, 0); 38 | animation.setFillAfter(true); 39 | animation.setDuration(700); 40 | animation.setInterpolator(new GaiaMotionCurveLinearInterpolator()); 41 | animationView.startAnimation(animation); 42 | ``` 43 | 44 | ## Customizable Parameters 45 | 46 | None 47 | -------------------------------------------------------------------------------- /docs/en-US/overshoot.md: -------------------------------------------------------------------------------- 1 | # Overshoot 2 | 3 | ## Demo 4 | 5 | 6 | 7 | 8 | 9 | ## iOS 10 | 11 | Enumerate:GMCCurveTypeOvershoot 12 | 13 | ```objc 14 | #import 15 | 16 | CGFloat right = [[UIScreen mainScreen] bounds].size.width - 80 - 20; 17 | GMCModel *model = [GMCModel modelWithKeyPath:@"position.x" 18 | duration:0.75 19 | delay:0 20 | curveType:GMCCurveTypeOvershoot 21 | fromValue:[NSValue gmc_valueWithCGFloat:_animationView.center.x] 22 | toValue:[NSValue gmc_valueWithCGFloat:right]]; 23 | __weak typeof(self) weakSelf = self; 24 | [_animationView.layer gmc_animateWithAnimationModels:@[model] completion:^(BOOL finished) { 25 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 26 | weakSelf.animationView.layer.frame = CGRectMake(80, 200, 40, 40); 27 | }); 28 | }]; 29 | ``` 30 | 31 | ## Android 32 | 33 | Interpolator:GaiaMotionCurveOvershootInterpolator 34 | 35 | ```java 36 | import com.gaia.MotionCurve.*; 37 | 38 | View animationView = findViewById(R.id.animation_view); 39 | TranslateAnimation animation = new TranslateAnimation(0, 700, 0, 0); 40 | animation.setFillAfter(true); 41 | animation.setDuration(700); 42 | animation.setInterpolator(new GaiaMotionCurveOvershootInterpolator()); 43 | animationView.startAnimation(animation); 44 | ``` 45 | 46 | ## Customizable Parameters 47 | 48 | Configurable Parameters: 49 | 50 | ``` 51 | d: damping, controls the height of the highest point 52 | x1: x coordinate of control point x1 53 | y1: y coordinate of control point y1 54 | x2: x coordinate of control point x2 55 | y2: y coordinate of control point y2 56 | x3: x coordinate of control point x3 57 | y3: y coordinate of control point y3 58 | x4: x coordinate of control point x4 59 | y4: y coordinate of control point y4 60 | ``` 61 | 62 | Default: 63 | 64 | ``` 65 | d = 1.2 66 | x1 = 0.33 67 | y1 = 0.0 68 | x2 = 0.3 69 | y2 = 1.0 70 | x3 = 0.33 71 | y3 = 0.0 72 | x4 = 0.5 73 | y4 = 1.0 74 | ``` 75 | 76 | iOS 77 | 78 | ```objective-c 79 | CGFloat right = [[UIScreen mainScreen] bounds].size.width - 80 - 20; 80 | GMCModel *model = [GMCModel modelWithKeyPath:@"position.x" 81 | duration:0.75 82 | delay:0 83 | curveType:GMCCurveTypeOvershoot 84 | customArgs:@{@"d":@1.2,@"x1":@0.33,@"y1":@0.0,@"x2":@0.3,@"y2":@1.0, 85 | @"x3":@0.33,@"y3":@0.0,@"x4":@0.5,@"y4":@1.0} 86 | fromValue:[NSValue gmc_valueWithCGFloat:_animationView.center.x] 87 | toValue:[NSValue gmc_valueWithCGFloat:right]]; 88 | __weak typeof(self) weakSelf = self; 89 | [_animationView.layer gmc_animateWithAnimationModels:@[model] completion:^(BOOL finished) { 90 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 91 | weakSelf.animationView.layer.frame = CGRectMake(80, 200, 40, 40); 92 | }); 93 | }]; 94 | ``` 95 | 96 | Android 97 | 98 | ```java 99 | View animationView = findViewById(R.id.animation_view); 100 | TranslateAnimation animation = new TranslateAnimation(0, 700, 0, 0); 101 | animation.setFillAfter(true); 102 | animation.setDuration(700); 103 | animation.setInterpolator(new GaiaMotionCurveOvershootInterpolator(1.2,0.33,0.0,0.3,1.0,0.33,0.0,0.5,1.0)); 104 | animationView.startAnimation(animation); 105 | ``` 106 | 107 | -------------------------------------------------------------------------------- /docs/en-US/spring.md: -------------------------------------------------------------------------------- 1 | # Spring 2 | 3 | ## Demo 4 | 5 | 6 | 7 | ## iOS 8 | 9 | Enumerate:GMCCurveTypeSpring 10 | 11 | ```objc 12 | #import 13 | 14 | CGFloat right = [[UIScreen mainScreen] bounds].size.width - 80 - 20; 15 | GMCModel *model = [GMCModel modelWithKeyPath:@"position.x" 16 | duration:0.75 17 | delay:0 18 | curveType:GMCCurveTypeSpring 19 | fromValue:[NSValue gmc_valueWithCGFloat:_animationView.center.x] 20 | toValue:[NSValue gmc_valueWithCGFloat:right]]; 21 | __weak typeof(self) weakSelf = self; 22 | [_animationView.layer gmc_animateWithAnimationModels:@[model] completion:^(BOOL finished) { 23 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 24 | weakSelf.animationView.layer.frame = CGRectMake(80, 200, 40, 40); 25 | }); 26 | }]; 27 | ``` 28 | 29 | ## Android 30 | 31 | Interpolator:GaiaMotionCurveSpringInterpolator 32 | 33 | ```java 34 | import com.gaia.MotionCurve.*; 35 | 36 | View animationView = findViewById(R.id.animation_view); 37 | TranslateAnimation animation = new TranslateAnimation(0, 700, 0, 0); 38 | animation.setFillAfter(true); 39 | animation.setDuration(700); 40 | animation.setInterpolator(new GaiaMotionCurveSpringInterpolator()); 41 | animationView.startAnimation(animation); 42 | ``` 43 | 44 | ## Customizable Parameters 45 | 46 | Configurable Parameters: 47 | 48 | Spring curve supports two parameter systems, Mass and RK4 (Android only supports Mass system temporarily) 49 | 50 | **Mass System:** 51 | 52 | ``` 53 | m: mass 54 | s: stiffness 55 | d: damping 56 | iv:velocity 57 | ``` 58 | 59 | Default: 60 | 61 | ``` 62 | m = 0.7 63 | s = 380.0 64 | d = 10.0 65 | iv = -2.0 66 | ``` 67 | 68 | iOS 69 | 70 | ```objective-c 71 | CGFloat right = [[UIScreen mainScreen] bounds].size.width - 80 - 20; 72 | GMCModel *model = [GMCModel modelWithKeyPath:@"position.x" 73 | duration:0.75 74 | delay:0 75 | curveType:GMCCurveTypeSpring 76 | customArgs:@{@"m":@1.0,@"s":@380.0,@"d":@10.0,@"iv":@-2.0} 77 | fromValue:[NSValue gmc_valueWithCGFloat:_animationView.center.x] 78 | toValue:[NSValue gmc_valueWithCGFloat:right]]; 79 | __weak typeof(self) weakSelf = self; 80 | [_animationView.layer gmc_animateWithAnimationModels:@[model] completion:^(BOOL finished) { 81 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 82 | weakSelf.animationView.layer.frame = CGRectMake(80, 200, 40, 40); 83 | }); 84 | }]; 85 | ``` 86 | 87 | Android 88 | 89 | ```java 90 | View animationView = findViewById(R.id.animation_view); 91 | TranslateAnimation animation = new TranslateAnimation(0, 700, 0, 0); 92 | animation.setFillAfter(true); 93 | animation.setDuration(700); 94 | animation.setInterpolator(new GaiaMotionCurveSpringInterpolator(0.7, 380.0, 10.0, -2.0)); 95 | animationView.startAnimation(animation); 96 | ``` 97 | 98 | **RK4 System:** 99 | 100 | ``` 101 | t: tension 102 | f: friction 103 | v: velocity 104 | ``` 105 | 106 | Default: 107 | 108 | ``` 109 | t = 533.0 110 | f = 14.0 111 | v = -2.0 112 | ``` 113 | 114 | iOS 115 | 116 | ```objective-c 117 | CGFloat right = [[UIScreen mainScreen] bounds].size.width - 80 - 20; 118 | GMCModel *model = [GMCModel modelWithKeyPath:@"position.x" 119 | duration:0.75 120 | delay:0 121 | curveType:GMCCurveTypeSpring 122 | customArgs:@{@"t":@533.0,@"f":@14.0,@"v":@-2.0} 123 | fromValue:[NSValue gmc_valueWithCGFloat:_animationView.center.x] 124 | toValue:[NSValue gmc_valueWithCGFloat:right]]; 125 | __weak typeof(self) weakSelf = self; 126 | [_animationView.layer gmc_animateWithAnimationModels:@[model] completion:^(BOOL finished) { 127 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 128 | weakSelf.animationView.layer.frame = CGRectMake(80, 200, 40, 40); 129 | }); 130 | }]; 131 | ``` 132 | 133 | -------------------------------------------------------------------------------- /docs/en-US/standard.md: -------------------------------------------------------------------------------- 1 | # Standard 2 | 3 | ## Demo 4 | 5 | 6 | 7 | ## iOS 8 | 9 | Enumerate:GMCCurveTypeStandard 10 | 11 | ```objc 12 | #import 13 | 14 | CGFloat right = [[UIScreen mainScreen] bounds].size.width - 80 - 20; 15 | GMCModel *model = [GMCModel modelWithKeyPath:@"position.x" 16 | duration:0.75 17 | delay:0 18 | curveType:GMCCurveTypeStandard 19 | fromValue:[NSValue gmc_valueWithCGFloat:_animationView.center.x] 20 | toValue:[NSValue gmc_valueWithCGFloat:right]]; 21 | __weak typeof(self) weakSelf = self; 22 | [_animationView.layer gmc_animateWithAnimationModels:@[model] completion:^(BOOL finished) { 23 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 24 | weakSelf.animationView.layer.frame = CGRectMake(80, 200, 40, 40); 25 | }); 26 | }]; 27 | ``` 28 | 29 | ## Android 30 | 31 | Interpolator:GaiaMotionCurveStandardInterpolator 32 | 33 | ```java 34 | import com.gaia.MotionCurve.*; 35 | 36 | View animationView = findViewById(R.id.animation_view); 37 | TranslateAnimation animation = new TranslateAnimation(0, 700, 0, 0); 38 | animation.setFillAfter(true); 39 | animation.setDuration(700); 40 | animation.setInterpolator(new GaiaMotionCurveStandardInterpolator()); 41 | animationView.startAnimation(animation); 42 | ``` 43 | 44 | ## Customizable Parameters 45 | 46 | Configurable Parameters: 47 | 48 | ``` 49 | x1: x coordinate of control point x1 50 | y1: y coordinate of control point y1 51 | x2: x coordinate of control point x2 52 | y2: y coordinate of control point y2 53 | ``` 54 | 55 | Default: 56 | 57 | ``` 58 | x1 = 0.4 59 | y1 = 0.0 60 | x2 = 0.1 61 | y2 = 1.0 62 | ``` 63 | 64 | iOS 65 | 66 | ```objective-c 67 | CGFloat right = [[UIScreen mainScreen] bounds].size.width - 80 - 20; 68 | GMCModel *model = [GMCModel modelWithKeyPath:@"position.x" 69 | duration:0.75 70 | delay:0 71 | curveType:GMCCurveTypeStandard 72 | customArgs:@{@"x1":@0.4,@"y1":@0.0,@"x2":@0.1,@"y2":@1.0} 73 | fromValue:[NSValue gmc_valueWithCGFloat:_animationView.center.x] 74 | toValue:[NSValue gmc_valueWithCGFloat:right]]; 75 | __weak typeof(self) weakSelf = self; 76 | [_animationView.layer gmc_animateWithAnimationModels:@[model] completion:^(BOOL finished) { 77 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 78 | weakSelf.animationView.layer.frame = CGRectMake(80, 200, 40, 40); 79 | }); 80 | }]; 81 | ``` 82 | 83 | Android 84 | 85 | ```java 86 | View animationView = findViewById(R.id.animation_view); 87 | TranslateAnimation animation = new TranslateAnimation(0, 700, 0, 0); 88 | animation.setFillAfter(true); 89 | animation.setDuration(700); 90 | animation.setInterpolator(new GaiaMotionCurveStandardInterpolator(0.4, 0.0, 0.1, 1.0)); 91 | animationView.startAnimation(animation); 92 | ``` 93 | 94 | -------------------------------------------------------------------------------- /docs/zh-CN/accelerate.md: -------------------------------------------------------------------------------- 1 | # 加速曲线 2 | 3 | ## 演示 4 | 5 | 6 | 7 | ## iOS 8 | 9 | 枚举:GMCCurveTypeAccelerate 10 | 11 | ```objc 12 | #import 13 | 14 | CGFloat right = [[UIScreen mainScreen] bounds].size.width - 80 - 20; 15 | GMCModel *model = [GMCModel modelWithKeyPath:@"position.x" 16 | duration:0.75 17 | delay:0 18 | curveType:GMCCurveTypeAccelerate 19 | fromValue:[NSValue gmc_valueWithCGFloat:_animationView.center.x] 20 | toValue:[NSValue gmc_valueWithCGFloat:right]]; 21 | __weak typeof(self) weakSelf = self; 22 | [_animationView.layer gmc_animateWithAnimationModels:@[model] completion:^(BOOL finished) { 23 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 24 | weakSelf.animationView.layer.frame = CGRectMake(80, 200, 40, 40); 25 | }); 26 | }]; 27 | ``` 28 | 29 | ## Android 30 | 31 | 差值器:GaiaMotionCurveAccelerateInterpolator 32 | 33 | ```java 34 | import com.gaia.MotionCurve.*; 35 | 36 | View animationView = findViewById(R.id.animation_view); 37 | TranslateAnimation animation = new TranslateAnimation(0, 700, 0, 0); 38 | animation.setFillAfter(true); 39 | animation.setDuration(700); 40 | animation.setInterpolator(new GaiaMotionCurveAccelerateInterpolator()); 41 | animationView.startAnimation(animation); 42 | ``` 43 | 44 | ## 可自定义的参数 45 | 46 | 可配置的参数: 47 | 48 | ``` 49 | x1:控制点1的x坐标 50 | y1:控制点1的y坐标 51 | x2:控制点2的x坐标 52 | y2:控制点2的y坐标 53 | ``` 54 | 55 | 默认值: 56 | 57 | ``` 58 | x1 = 0.4 59 | y1 = 0.0 60 | x2 = 1.0 61 | y2 = 1.0 62 | ``` 63 | 64 | iOS 65 | 66 | ```objective-c 67 | CGFloat right = [[UIScreen mainScreen] bounds].size.width - 80 - 20; 68 | GMCModel *model = [GMCModel modelWithKeyPath:@"position.x" 69 | duration:0.75 70 | delay:0 71 | curveType:GMCCurveTypeAccelerate 72 | customArgs:@{@"x1":@0.4,@"y1":@0.0,@"x2":@1.0,@"y2":@1.0} 73 | fromValue:[NSValue gmc_valueWithCGFloat:_animationView.center.x] 74 | toValue:[NSValue gmc_valueWithCGFloat:right]]; 75 | __weak typeof(self) weakSelf = self; 76 | [_animationView.layer gmc_animateWithAnimationModels:@[model] completion:^(BOOL finished) { 77 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 78 | weakSelf.animationView.layer.frame = CGRectMake(80, 200, 40, 40); 79 | }); 80 | }]; 81 | ``` 82 | 83 | Android 84 | 85 | ```java 86 | View animationView = findViewById(R.id.animation_view); 87 | TranslateAnimation animation = new TranslateAnimation(0, 700, 0, 0); 88 | animation.setFillAfter(true); 89 | animation.setDuration(700); 90 | animation.setInterpolator(new GaiaMotionCurveAccelerateInterpolator(0.4, 0.0, 1.0, 1.0)); 91 | animationView.startAnimation(animation); 92 | ``` 93 | 94 | -------------------------------------------------------------------------------- /docs/zh-CN/anticipate.md: -------------------------------------------------------------------------------- 1 | # 预期曲线 2 | 3 | ## 演示 4 | 5 | 6 | 7 | ## iOS 8 | 9 | 枚举:GMCCurveTypeAnticipate 10 | 11 | ```objc 12 | #import 13 | 14 | CGFloat right = [[UIScreen mainScreen] bounds].size.width - 80 - 20; 15 | GMCModel *model = [GMCModel modelWithKeyPath:@"position.x" 16 | duration:0.75 17 | delay:0 18 | curveType:GMCCurveTypeAnticipate 19 | fromValue:[NSValue gmc_valueWithCGFloat:_animationView.center.x] 20 | toValue:[NSValue gmc_valueWithCGFloat:right]]; 21 | __weak typeof(self) weakSelf = self; 22 | [_animationView.layer gmc_animateWithAnimationModels:@[model] completion:^(BOOL finished) { 23 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 24 | weakSelf.animationView.layer.frame = CGRectMake(80, 200, 40, 40); 25 | }); 26 | }]; 27 | ``` 28 | 29 | ## Android 30 | 31 | 差值器:GaiaMotionCurveAnticipateInterpolator 32 | 33 | ```java 34 | import com.gaia.MotionCurve.*; 35 | 36 | View animationView = findViewById(R.id.animation_view); 37 | TranslateAnimation animation = new TranslateAnimation(0, 700, 0, 0); 38 | animation.setFillAfter(true); 39 | animation.setDuration(700); 40 | animation.setInterpolator(new GaiaMotionCurveAnticipateInterpolator()); 41 | animationView.startAnimation(animation); 42 | ``` 43 | 44 | ## 可自定义的参数 45 | 46 | 可配置的参数: 47 | 48 | ``` 49 | d:damping的缩写,控制的是最低点的高低 50 | x1:控制点1的x坐标 51 | y1:控制点1的y坐标 52 | x2:控制点2的x坐标 53 | y2:控制点2的y坐标 54 | x3:控制点3的x坐标 55 | y3:控制点3的y坐标 56 | x4:控制点4的x坐标 57 | y4:控制点4的y坐标 58 | ``` 59 | 60 | 默认值为: 61 | 62 | ``` 63 | d = 0.2 64 | x1 = 0.33 65 | y1 = 0.0 66 | x2 = 0.67 67 | y2 = 1.0 68 | x3 = 0.33 69 | y3 = 0.0 70 | x4 = 0.2 71 | y4 = 1.0 72 | ``` 73 | 74 | iOS 75 | 76 | ```objective-c 77 | CGFloat right = [[UIScreen mainScreen] bounds].size.width - 80 - 20; 78 | GMCModel *model = [GMCModel modelWithKeyPath:@"position.x" 79 | duration:0.75 80 | delay:0 81 | curveType:GMCCurveTypeAnticipate 82 | customArgs:@{@"d":@0.2,@"x1":@0.33,@"y1":@0.0,@"x2":@0.67,@"y2":@1.0, 83 | @"x3":@0.33,@"y3":@0.0,@"x4":@0.2,@"y4":@1.0} 84 | fromValue:[NSValue gmc_valueWithCGFloat:_animationView.center.x] 85 | toValue:[NSValue gmc_valueWithCGFloat:right]]; 86 | __weak typeof(self) weakSelf = self; 87 | [_animationView.layer gmc_animateWithAnimationModels:@[model] completion:^(BOOL finished) { 88 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 89 | weakSelf.animationView.layer.frame = CGRectMake(80, 200, 40, 40); 90 | }); 91 | }]; 92 | ``` 93 | 94 | Android 95 | 96 | ```java 97 | View animationView = findViewById(R.id.animation_view); 98 | TranslateAnimation animation = new TranslateAnimation(0, 700, 0, 0); 99 | animation.setFillAfter(true); 100 | animation.setDuration(700); 101 | animation.setInterpolator(new GaiaMotionCurveAnticipateInterpolator(0.2,0.33,0.0,0.67,1.0,0.33,0.0,0.2,1.0)); 102 | animationView.startAnimation(animation); 103 | ``` 104 | 105 | -------------------------------------------------------------------------------- /docs/zh-CN/bounce.md: -------------------------------------------------------------------------------- 1 | # 弹跳曲线 2 | 3 | ## 演示 4 | 5 | 6 | 7 | ## iOS 8 | 9 | 枚举:GMCCurveTypeBounce 10 | 11 | ```objc 12 | #import 13 | 14 | CGFloat right = [[UIScreen mainScreen] bounds].size.width - 80 - 20; 15 | GMCModel *model = [GMCModel modelWithKeyPath:@"position.x" 16 | duration:0.75 17 | delay:0 18 | curveType:GMCCurveTypeBounce 19 | fromValue:[NSValue gmc_valueWithCGFloat:_animationView.center.x] 20 | toValue:[NSValue gmc_valueWithCGFloat:right]]; 21 | __weak typeof(self) weakSelf = self; 22 | [_animationView.layer gmc_animateWithAnimationModels:@[model] completion:^(BOOL finished) { 23 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 24 | weakSelf.animationView.layer.frame = CGRectMake(80, 200, 40, 40); 25 | }); 26 | }]; 27 | ``` 28 | 29 | ## Android 30 | 31 | 差值器:GaiaMotionCurveBounceInterpolator 32 | 33 | ```java 34 | import com.gaia.MotionCurve.*; 35 | 36 | View animationView = findViewById(R.id.animation_view); 37 | TranslateAnimation animation = new TranslateAnimation(0, 700, 0, 0); 38 | animation.setFillAfter(true); 39 | animation.setDuration(700); 40 | animation.setInterpolator(new GaiaMotionCurveBounceInterpolator()); 41 | animationView.startAnimation(animation); 42 | ``` 43 | 44 | ## 可自定义的参数 45 | 46 | 可配置的参数: 47 | 48 | ``` 49 | v:velocity的缩写 50 | d:damping的缩写 51 | ``` 52 | 53 | 默认值为: 54 | 55 | ``` 56 | v = 1.0 57 | d = 1.0 58 | ``` 59 | 60 | iOS 61 | 62 | ```objective-c 63 | CGFloat right = [[UIScreen mainScreen] bounds].size.width - 80 - 20; 64 | GMCModel *model = [GMCModel modelWithKeyPath:@"position.x" 65 | duration:0.75 66 | delay:0 67 | curveType:GMCCurveTypeBounce 68 | customArgs:@{@"v":@1.0,@"d":@1.0} 69 | fromValue:[NSValue gmc_valueWithCGFloat:_animationView.center.x] 70 | toValue:[NSValue gmc_valueWithCGFloat:right]]; 71 | __weak typeof(self) weakSelf = self; 72 | [_animationView.layer gmc_animateWithAnimationModels:@[model] completion:^(BOOL finished) { 73 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 74 | weakSelf.animationView.layer.frame = CGRectMake(80, 200, 40, 40); 75 | }); 76 | }]; 77 | ``` 78 | 79 | Android 80 | 81 | ```java 82 | View animationView = findViewById(R.id.animation_view); 83 | TranslateAnimation animation = new TranslateAnimation(0, 700, 0, 0); 84 | animation.setFillAfter(true); 85 | animation.setDuration(700); 86 | animation.setInterpolator(new GaiaMotionCurveBounceInterpolator(1.0, 1.0)); 87 | animationView.startAnimation(animation); 88 | ``` 89 | 90 | -------------------------------------------------------------------------------- /docs/zh-CN/cosine.md: -------------------------------------------------------------------------------- 1 | # 余弦曲线 2 | 3 | ## 演示 4 | 5 | 6 | 7 | ## iOS 8 | 9 | 枚举:GMCCurveTypeCosine 10 | 11 | ```objc 12 | #import 13 | 14 | CGFloat right = [[UIScreen mainScreen] bounds].size.width - 80 - 20; 15 | GMCModel *model = [GMCModel modelWithKeyPath:@"position.x" 16 | duration:0.75 17 | delay:0 18 | curveType:GMCCurveTypeCosine 19 | fromValue:[NSValue gmc_valueWithCGFloat:_animationView.center.x] 20 | toValue:[NSValue gmc_valueWithCGFloat:right]]; 21 | __weak typeof(self) weakSelf = self; 22 | [_animationView.layer gmc_animateWithAnimationModels:@[model] completion:^(BOOL finished) { 23 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 24 | weakSelf.animationView.layer.frame = CGRectMake(80, 200, 40, 40); 25 | }); 26 | }]; 27 | ``` 28 | 29 | ## Android 30 | 31 | 差值器:GaiaMotionCurveCosineInterpolator 32 | 33 | ```java 34 | import com.gaia.MotionCurve.*; 35 | 36 | View animationView = findViewById(R.id.animation_view); 37 | TranslateAnimation animation = new TranslateAnimation(0, 700, 0, 0); 38 | animation.setFillAfter(true); 39 | animation.setDuration(700); 40 | animation.setInterpolator(new GaiaMotionCurveCosineInterpolator()); 41 | animationView.startAnimation(animation); 42 | ``` 43 | 44 | ## 可自定义的参数 45 | 46 | 可配置的参数: 47 | 48 | ``` 49 | d:damping的缩写,控制的是最高点的高低 50 | c:cycles的缩写,周期的次数且是0.25的倍数 51 | ``` 52 | 53 | 默认值为: 54 | 55 | ``` 56 | d = 1.0 57 | c = 1.0 58 | ``` 59 | 60 | iOS 61 | 62 | ```objective-c 63 | CGFloat right = [[UIScreen mainScreen] bounds].size.width - 80 - 20; 64 | GMCModel *model = [GMCModel modelWithKeyPath:@"position.x" 65 | duration:0.75 66 | delay:0 67 | curveType:GMCCurveTypeCosine 68 | customArgs:@{@"d":@1.0,@"c":@1.0} 69 | fromValue:[NSValue gmc_valueWithCGFloat:_animationView.center.x] 70 | toValue:[NSValue gmc_valueWithCGFloat:right]]; 71 | __weak typeof(self) weakSelf = self; 72 | [_animationView.layer gmc_animateWithAnimationModels:@[model] completion:^(BOOL finished) { 73 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 74 | weakSelf.animationView.layer.frame = CGRectMake(80, 200, 40, 40); 75 | }); 76 | }]; 77 | ``` 78 | 79 | Android 80 | 81 | ```java 82 | View animationView = findViewById(R.id.animation_view); 83 | TranslateAnimation animation = new TranslateAnimation(0, 700, 0, 0); 84 | animation.setFillAfter(true); 85 | animation.setDuration(700); 86 | animation.setInterpolator(new GaiaMotionCurveCosineInterpolator(1.0, 1.0)); 87 | animationView.startAnimation(animation); 88 | ``` 89 | 90 | -------------------------------------------------------------------------------- /docs/zh-CN/decelerate.md: -------------------------------------------------------------------------------- 1 | # 减速曲线 2 | 3 | ## 演示 4 | 5 | 6 | 7 | ## iOS 8 | 9 | 枚举:GMCCurveTypeDecelerate 10 | 11 | ```objc 12 | #import 13 | 14 | CGFloat right = [[UIScreen mainScreen] bounds].size.width - 80 - 20; 15 | GMCModel *model = [GMCModel modelWithKeyPath:@"position.x" 16 | duration:0.75 17 | delay:0 18 | curveType:GMCCurveTypeDecelerate 19 | fromValue:[NSValue gmc_valueWithCGFloat:_animationView.center.x] 20 | toValue:[NSValue gmc_valueWithCGFloat:right]]; 21 | __weak typeof(self) weakSelf = self; 22 | [_animationView.layer gmc_animateWithAnimationModels:@[model] completion:^(BOOL finished) { 23 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 24 | weakSelf.animationView.layer.frame = CGRectMake(80, 200, 40, 40); 25 | }); 26 | }]; 27 | ``` 28 | 29 | ## Android 30 | 31 | 差值器:GaiaMotionCurveDecelerateInterpolator 32 | 33 | ```java 34 | import com.gaia.MotionCurve.*; 35 | 36 | View animationView = findViewById(R.id.animation_view); 37 | TranslateAnimation animation = new TranslateAnimation(0, 700, 0, 0); 38 | animation.setFillAfter(true); 39 | animation.setDuration(700); 40 | animation.setInterpolator(new GaiaMotionCurveDecelerateInterpolator()); 41 | animationView.startAnimation(animation); 42 | ``` 43 | 44 | ## 可自定义的参数 45 | 46 | 可配置的参数: 47 | 48 | ``` 49 | x1:控制点1的x坐标 50 | y1:控制点1的y坐标 51 | x2:控制点2的x坐标 52 | y2:控制点2的y坐标 53 | ``` 54 | 55 | 默认值为: 56 | 57 | ``` 58 | x1 = 0.0 59 | y1 = 0.0 60 | x2 = 0.1 61 | y2 = 1.0 62 | ``` 63 | 64 | iOS 65 | 66 | ```objective-c 67 | CGFloat right = [[UIScreen mainScreen] bounds].size.width - 80 - 20; 68 | GMCModel *model = [GMCModel modelWithKeyPath:@"position.x" 69 | duration:0.75 70 | delay:0 71 | curveType:GMCCurveTypeDecelerate 72 | customArgs:@{@"x1":@0.0,@"y1":@0.0,@"x2":@0.1,@"y2":@1.0} 73 | fromValue:[NSValue gmc_valueWithCGFloat:_animationView.center.x] 74 | toValue:[NSValue gmc_valueWithCGFloat:right]]; 75 | __weak typeof(self) weakSelf = self; 76 | [_animationView.layer gmc_animateWithAnimationModels:@[model] completion:^(BOOL finished) { 77 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 78 | weakSelf.animationView.layer.frame = CGRectMake(80, 200, 40, 40); 79 | }); 80 | }]; 81 | ``` 82 | 83 | Android 84 | 85 | ```java 86 | View animationView = findViewById(R.id.animation_view); 87 | TranslateAnimation animation = new TranslateAnimation(0, 700, 0, 0); 88 | animation.setFillAfter(true); 89 | animation.setDuration(700); 90 | animation.setInterpolator(new GaiaMotionCurveDecelerateInterpolator(0.0, 0.0, 0.1, 1.0)); 91 | animationView.startAnimation(animation); 92 | ``` 93 | 94 | -------------------------------------------------------------------------------- /docs/zh-CN/linear.md: -------------------------------------------------------------------------------- 1 | # 线性曲线 2 | 3 | ## 演示 4 | 5 | 6 | 7 | ## iOS 8 | 9 | 枚举:GMCCurveTypeLinear 10 | 11 | ```objc 12 | #import 13 | 14 | CGFloat right = [[UIScreen mainScreen] bounds].size.width - 80 - 20; 15 | GMCModel *model = [GMCModel modelWithKeyPath:@"position.x" 16 | duration:0.75 17 | delay:0 18 | curveType:GMCCurveTypeLinear 19 | fromValue:[NSValue gmc_valueWithCGFloat:_animationView.center.x] 20 | toValue:[NSValue gmc_valueWithCGFloat:right]]; 21 | __weak typeof(self) weakSelf = self; 22 | [_animationView.layer gmc_animateWithAnimationModels:@[model] completion:^(BOOL finished) { 23 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 24 | weakSelf.animationView.layer.frame = CGRectMake(80, 200, 40, 40); 25 | }); 26 | }]; 27 | ``` 28 | 29 | ## Android 30 | 31 | 差值器:GaiaMotionCurveLinearInterpolator 32 | 33 | ```java 34 | import com.gaia.MotionCurve.*; 35 | 36 | View animationView = findViewById(R.id.animation_view); 37 | TranslateAnimation animation = new TranslateAnimation(0, 700, 0, 0); 38 | animation.setFillAfter(true); 39 | animation.setDuration(700); 40 | animation.setInterpolator(new GaiaMotionCurveLinearInterpolator()); 41 | animationView.startAnimation(animation); 42 | ``` 43 | 44 | ## 可自定义的参数 45 | 46 | 无 47 | -------------------------------------------------------------------------------- /docs/zh-CN/overshoot.md: -------------------------------------------------------------------------------- 1 | # 过度曲线 2 | 3 | ## 演示 4 | 5 | 6 | 7 | ## iOS 8 | 9 | 枚举:GMCCurveTypeOvershoot 10 | 11 | ```objc 12 | #import 13 | 14 | CGFloat right = [[UIScreen mainScreen] bounds].size.width - 80 - 20; 15 | GMCModel *model = [GMCModel modelWithKeyPath:@"position.x" 16 | duration:0.75 17 | delay:0 18 | curveType:GMCCurveTypeOvershoot 19 | fromValue:[NSValue gmc_valueWithCGFloat:_animationView.center.x] 20 | toValue:[NSValue gmc_valueWithCGFloat:right]]; 21 | __weak typeof(self) weakSelf = self; 22 | [_animationView.layer gmc_animateWithAnimationModels:@[model] completion:^(BOOL finished) { 23 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 24 | weakSelf.animationView.layer.frame = CGRectMake(80, 200, 40, 40); 25 | }); 26 | }]; 27 | ``` 28 | 29 | ## Android 30 | 31 | 差值器:GaiaMotionCurveOvershootInterpolator 32 | 33 | ```java 34 | import com.gaia.MotionCurve.*; 35 | 36 | View animationView = findViewById(R.id.animation_view); 37 | TranslateAnimation animation = new TranslateAnimation(0, 700, 0, 0); 38 | animation.setFillAfter(true); 39 | animation.setDuration(700); 40 | animation.setInterpolator(new GaiaMotionCurveOvershootInterpolator()); 41 | animationView.startAnimation(animation); 42 | ``` 43 | 44 | ## 可自定义的参数 45 | 46 | 可配置的参数: 47 | 48 | ``` 49 | d:damping的缩写,控制的是最高点的高低 50 | x1:控制点1的x坐标 51 | y1:控制点1的y坐标 52 | x2:控制点2的x坐标 53 | y2:控制点2的y坐标 54 | x3:控制点3的x坐标 55 | y3:控制点3的y坐标 56 | x4:控制点4的x坐标 57 | y4:控制点4的y坐标 58 | ``` 59 | 60 | 默认值为: 61 | 62 | ``` 63 | d = 1.2 64 | x1 = 0.33 65 | y1 = 0.0 66 | x2 = 0.3 67 | y2 = 1.0 68 | x3 = 0.33 69 | y3 = 0.0 70 | x4 = 0.5 71 | y4 = 1.0 72 | ``` 73 | 74 | iOS 75 | 76 | ```objective-c 77 | CGFloat right = [[UIScreen mainScreen] bounds].size.width - 80 - 20; 78 | GMCModel *model = [GMCModel modelWithKeyPath:@"position.x" 79 | duration:0.75 80 | delay:0 81 | curveType:GMCCurveTypeOvershoot 82 | customArgs:@{@"d":@1.2,@"x1":@0.33,@"y1":@0.0,@"x2":@0.3,@"y2":@1.0, 83 | @"x3":@0.33,@"y3":@0.0,@"x4":@0.5,@"y4":@1.0} 84 | fromValue:[NSValue gmc_valueWithCGFloat:_animationView.center.x] 85 | toValue:[NSValue gmc_valueWithCGFloat:right]]; 86 | __weak typeof(self) weakSelf = self; 87 | [_animationView.layer gmc_animateWithAnimationModels:@[model] completion:^(BOOL finished) { 88 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 89 | weakSelf.animationView.layer.frame = CGRectMake(80, 200, 40, 40); 90 | }); 91 | }]; 92 | ``` 93 | 94 | Android 95 | 96 | ```java 97 | View animationView = findViewById(R.id.animation_view); 98 | TranslateAnimation animation = new TranslateAnimation(0, 700, 0, 0); 99 | animation.setFillAfter(true); 100 | animation.setDuration(700); 101 | animation.setInterpolator(new GaiaMotionCurveOvershootInterpolator(1.2,0.33,0.0,0.3,1.0,0.33,0.0,0.5,1.0)); 102 | animationView.startAnimation(animation); 103 | ``` 104 | 105 | -------------------------------------------------------------------------------- /docs/zh-CN/spring.md: -------------------------------------------------------------------------------- 1 | # 弹性曲线 2 | 3 | ## 演示 4 | 5 | 6 | 7 | ## iOS 8 | 9 | 枚举:GMCCurveTypeSpring 10 | 11 | ```objc 12 | #import 13 | 14 | CGFloat right = [[UIScreen mainScreen] bounds].size.width - 80 - 20; 15 | GMCModel *model = [GMCModel modelWithKeyPath:@"position.x" 16 | duration:0.75 17 | delay:0 18 | curveType:GMCCurveTypeSpring 19 | fromValue:[NSValue gmc_valueWithCGFloat:_animationView.center.x] 20 | toValue:[NSValue gmc_valueWithCGFloat:right]]; 21 | __weak typeof(self) weakSelf = self; 22 | [_animationView.layer gmc_animateWithAnimationModels:@[model] completion:^(BOOL finished) { 23 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 24 | weakSelf.animationView.layer.frame = CGRectMake(80, 200, 40, 40); 25 | }); 26 | }]; 27 | ``` 28 | 29 | ## Android 30 | 31 | 差值器:GaiaMotionCurveSpringInterpolator 32 | 33 | ```java 34 | import com.gaia.MotionCurve.*; 35 | 36 | View animationView = findViewById(R.id.animation_view); 37 | TranslateAnimation animation = new TranslateAnimation(0, 700, 0, 0); 38 | animation.setFillAfter(true); 39 | animation.setDuration(700); 40 | animation.setInterpolator(new GaiaMotionCurveSpringInterpolator()); 41 | animationView.startAnimation(animation); 42 | ``` 43 | 44 | ## 可自定义的参数 45 | 46 | 可配置的参数: 47 | 48 | 弹性曲线支持Mass和RK4两套参数系统(Android暂时只支持Mass参数系统) 49 | 50 | **Mass参数系统:** 51 | 52 | ``` 53 | m: mass的缩写 54 | s: stiffness的缩写 55 | d: damping的缩写 56 | iv:velocity的缩写 57 | ``` 58 | 59 | 默认值为: 60 | 61 | ``` 62 | m = 0.7 63 | s = 380.0 64 | d = 10.0 65 | iv = -2.0 66 | ``` 67 | 68 | iOS 69 | 70 | ```objective-c 71 | CGFloat right = [[UIScreen mainScreen] bounds].size.width - 80 - 20; 72 | GMCModel *model = [GMCModel modelWithKeyPath:@"position.x" 73 | duration:0.75 74 | delay:0 75 | curveType:GMCCurveTypeSpring 76 | customArgs:@{@"m":@1.0,@"s":@380.0,@"d":@10.0,@"iv":@-2.0} 77 | fromValue:[NSValue gmc_valueWithCGFloat:_animationView.center.x] 78 | toValue:[NSValue gmc_valueWithCGFloat:right]]; 79 | __weak typeof(self) weakSelf = self; 80 | [_animationView.layer gmc_animateWithAnimationModels:@[model] completion:^(BOOL finished) { 81 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 82 | weakSelf.animationView.layer.frame = CGRectMake(80, 200, 40, 40); 83 | }); 84 | }]; 85 | ``` 86 | 87 | Android 88 | 89 | ```java 90 | View animationView = findViewById(R.id.animation_view); 91 | TranslateAnimation animation = new TranslateAnimation(0, 700, 0, 0); 92 | animation.setFillAfter(true); 93 | animation.setDuration(700); 94 | animation.setInterpolator(new GaiaMotionCurveSpringInterpolator(0.7, 380.0, 10.0, -2.0)); 95 | animationView.startAnimation(animation); 96 | ``` 97 | 98 | **RK4参数系统:** 99 | 100 | ``` 101 | t: tension的缩写 102 | f: friction的缩写 103 | v: velocity的缩写 104 | ``` 105 | 106 | 默认值为: 107 | 108 | ``` 109 | t = 533.0 110 | f = 14.0 111 | v = -2.0 112 | ``` 113 | 114 | iOS 115 | 116 | ```objective-c 117 | CGFloat right = [[UIScreen mainScreen] bounds].size.width - 80 - 20; 118 | GMCModel *model = [GMCModel modelWithKeyPath:@"position.x" 119 | duration:0.75 120 | delay:0 121 | curveType:GMCCurveTypeSpring 122 | customArgs:@{@"t":@533.0,@"f":@14.0,@"v":@-2.0} 123 | fromValue:[NSValue gmc_valueWithCGFloat:_animationView.center.x] 124 | toValue:[NSValue gmc_valueWithCGFloat:right]]; 125 | __weak typeof(self) weakSelf = self; 126 | [_animationView.layer gmc_animateWithAnimationModels:@[model] completion:^(BOOL finished) { 127 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 128 | weakSelf.animationView.layer.frame = CGRectMake(80, 200, 40, 40); 129 | }); 130 | }]; 131 | ``` 132 | 133 | -------------------------------------------------------------------------------- /docs/zh-CN/standard.md: -------------------------------------------------------------------------------- 1 | # 标准曲线 2 | 3 | ## 演示 4 | 5 | 6 | 7 | ## iOS 8 | 9 | 枚举:GMCCurveTypeStandard 10 | 11 | ```objc 12 | #import 13 | 14 | CGFloat right = [[UIScreen mainScreen] bounds].size.width - 80 - 20; 15 | GMCModel *model = [GMCModel modelWithKeyPath:@"position.x" 16 | duration:0.75 17 | delay:0 18 | curveType:GMCCurveTypeStandard 19 | fromValue:[NSValue gmc_valueWithCGFloat:_animationView.center.x] 20 | toValue:[NSValue gmc_valueWithCGFloat:right]]; 21 | __weak typeof(self) weakSelf = self; 22 | [_animationView.layer gmc_animateWithAnimationModels:@[model] completion:^(BOOL finished) { 23 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 24 | weakSelf.animationView.layer.frame = CGRectMake(80, 200, 40, 40); 25 | }); 26 | }]; 27 | ``` 28 | 29 | ## Android 30 | 31 | 差值器:GaiaMotionCurveStandardInterpolator 32 | 33 | ```java 34 | import com.gaia.MotionCurve.*; 35 | 36 | View animationView = findViewById(R.id.animation_view); 37 | TranslateAnimation animation = new TranslateAnimation(0, 700, 0, 0); 38 | animation.setFillAfter(true); 39 | animation.setDuration(700); 40 | animation.setInterpolator(new GaiaMotionCurveStandardInterpolator()); 41 | animationView.startAnimation(animation); 42 | ``` 43 | 44 | ## 可自定义的参数 45 | 46 | 可配置的参数: 47 | 48 | ``` 49 | x1:控制点1的x坐标 50 | y1:控制点1的y坐标 51 | x2:控制点2的x坐标 52 | y2:控制点2的y坐标 53 | ``` 54 | 55 | 默认值为: 56 | 57 | ``` 58 | x1 = 0.4 59 | y1 = 0.0 60 | x2 = 0.1 61 | y2 = 1.0 62 | ``` 63 | 64 | iOS 65 | 66 | ```objective-c 67 | CGFloat right = [[UIScreen mainScreen] bounds].size.width - 80 - 20; 68 | GMCModel *model = [GMCModel modelWithKeyPath:@"position.x" 69 | duration:0.75 70 | delay:0 71 | curveType:GMCCurveTypeStandard 72 | customArgs:@{@"x1":@0.4,@"y1":@0.0,@"x2":@0.1,@"y2":@1.0} 73 | fromValue:[NSValue gmc_valueWithCGFloat:_animationView.center.x] 74 | toValue:[NSValue gmc_valueWithCGFloat:right]]; 75 | __weak typeof(self) weakSelf = self; 76 | [_animationView.layer gmc_animateWithAnimationModels:@[model] completion:^(BOOL finished) { 77 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 78 | weakSelf.animationView.layer.frame = CGRectMake(80, 200, 40, 40); 79 | }); 80 | }]; 81 | ``` 82 | 83 | Android 84 | 85 | ```java 86 | View animationView = findViewById(R.id.animation_view); 87 | TranslateAnimation animation = new TranslateAnimation(0, 700, 0, 0); 88 | animation.setFillAfter(true); 89 | animation.setDuration(700); 90 | animation.setInterpolator(new GaiaMotionCurveStandardInterpolator(0.4, 0.0, 0.1, 1.0)); 91 | animationView.startAnimation(animation); 92 | ``` 93 | 94 | -------------------------------------------------------------------------------- /examples/Android/.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/caches 5 | /.idea/libraries 6 | /.idea/modules.xml 7 | /.idea/workspace.xml 8 | /.idea/navEditor.xml 9 | /.idea/assetWizardSettings.xml 10 | .DS_Store 11 | /build 12 | /captures 13 | .externalNativeBuild 14 | .cxx 15 | local.properties 16 | -------------------------------------------------------------------------------- /examples/Android/app/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /examples/Android/app/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'com.android.application' 3 | } 4 | 5 | android { 6 | compileSdk 32 7 | 8 | defaultConfig { 9 | applicationId "com.gaia.demo" 10 | minSdk 21 11 | targetSdk 32 12 | versionCode 1 13 | versionName "1.0" 14 | 15 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 16 | } 17 | 18 | buildTypes { 19 | release { 20 | minifyEnabled false 21 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' 22 | } 23 | } 24 | compileOptions { 25 | sourceCompatibility JavaVersion.VERSION_1_8 26 | targetCompatibility JavaVersion.VERSION_1_8 27 | } 28 | } 29 | 30 | dependencies { 31 | implementation fileTree(dir:'libs', includes: ['*.aar']) 32 | implementation 'androidx.appcompat:appcompat:1.4.0' 33 | implementation 'com.google.android.material:material:1.4.0' 34 | implementation 'androidx.constraintlayout:constraintlayout:2.1.2' 35 | testImplementation 'junit:junit:4.+' 36 | androidTestImplementation 'androidx.test.ext:junit:1.1.3' 37 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0' 38 | } -------------------------------------------------------------------------------- /examples/Android/app/libs/gaia-motion-curve-0.1.aar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alibaba/gaia-motion-curve/84f3567dd2725efb9e4dd459c3e303591eafcbfd/examples/Android/app/libs/gaia-motion-curve-0.1.aar -------------------------------------------------------------------------------- /examples/Android/app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile -------------------------------------------------------------------------------- /examples/Android/app/src/androidTest/java/com/gaia/demo/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package com.gaia.demo; 2 | 3 | import android.content.Context; 4 | 5 | import androidx.test.platform.app.InstrumentationRegistry; 6 | import androidx.test.ext.junit.runners.AndroidJUnit4; 7 | 8 | import org.junit.Test; 9 | import org.junit.runner.RunWith; 10 | 11 | import static org.junit.Assert.*; 12 | 13 | /** 14 | * Instrumented test, which will execute on an Android device. 15 | * 16 | * @see Testing documentation 17 | */ 18 | @RunWith(AndroidJUnit4.class) 19 | public class ExampleInstrumentedTest { 20 | @Test 21 | public void useAppContext() { 22 | // Context of the app under test. 23 | Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext(); 24 | assertEquals("com.gaia.demo", appContext.getPackageName()); 25 | } 26 | } -------------------------------------------------------------------------------- /examples/Android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 12 | 15 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /examples/Android/app/src/main/java/com/gaia/demo/AnimationActivity.java: -------------------------------------------------------------------------------- 1 | package com.gaia.demo; 2 | 3 | import androidx.appcompat.app.AppCompatActivity; 4 | 5 | import android.animation.ArgbEvaluator; 6 | import android.animation.ValueAnimator; 7 | import android.content.Intent; 8 | import android.os.Bundle; 9 | import android.view.View; 10 | import android.view.animation.AlphaAnimation; 11 | import android.view.animation.Animation; 12 | import android.view.animation.AnimationSet; 13 | import android.view.animation.Interpolator; 14 | import android.view.animation.RotateAnimation; 15 | import android.view.animation.ScaleAnimation; 16 | import android.view.animation.TranslateAnimation; 17 | import android.widget.Button; 18 | 19 | import com.gaia.MotionCurve.*; 20 | 21 | public class AnimationActivity extends AppCompatActivity { 22 | 23 | @Override 24 | protected void onCreate(Bundle savedInstanceState) { 25 | super.onCreate(savedInstanceState); 26 | setContentView(R.layout.activity_animation); 27 | 28 | Intent intent = getIntent(); 29 | String curveType = intent.getStringExtra("curveType"); 30 | 31 | Button positionButton = (Button) findViewById(R.id.animation_position); 32 | positionButton.setOnClickListener(new View.OnClickListener() { 33 | @Override 34 | public void onClick(View view) { 35 | View animationView = findViewById(R.id.animation_view); 36 | TranslateAnimation animation = new TranslateAnimation(0, 700, 0, 0); 37 | animation.setFillAfter(true); 38 | animation.setDuration(700); 39 | try { 40 | animation.setInterpolator((Interpolator)Class.forName("com.gaia.MotionCurve."+curveType).newInstance()); 41 | animationView.startAnimation(animation); 42 | } catch (IllegalAccessException e) { 43 | e.printStackTrace(); 44 | } catch (InstantiationException e) { 45 | e.printStackTrace(); 46 | } catch (ClassNotFoundException e) { 47 | e.printStackTrace(); 48 | } 49 | } 50 | }); 51 | 52 | Button opacityButton = (Button) findViewById(R.id.animation_opacity); 53 | opacityButton.setOnClickListener(new View.OnClickListener() { 54 | @Override 55 | public void onClick(View view) { 56 | View animationView = findViewById(R.id.animation_view); 57 | AlphaAnimation animation = new AlphaAnimation(1, 0); 58 | animation.setFillAfter(true); 59 | animation.setDuration(700); 60 | try { 61 | animation.setInterpolator((Interpolator)Class.forName("com.gaia.MotionCurve."+curveType).newInstance()); 62 | animationView.startAnimation(animation); 63 | } catch (IllegalAccessException e) { 64 | e.printStackTrace(); 65 | } catch (InstantiationException e) { 66 | e.printStackTrace(); 67 | } catch (ClassNotFoundException e) { 68 | e.printStackTrace(); 69 | } 70 | } 71 | }); 72 | 73 | Button colorButton = (Button) findViewById(R.id.animation_color); 74 | colorButton.setOnClickListener(new View.OnClickListener() { 75 | @Override 76 | public void onClick(View view) { 77 | View animationView = findViewById(R.id.animation_view); 78 | 79 | int colorFrom = getResources().getColor(R.color.black); 80 | int colorTo = getResources().getColor(R.color.red); 81 | ValueAnimator animation = ValueAnimator.ofObject(new ArgbEvaluator(), colorFrom, colorTo); 82 | animation.setDuration(700); 83 | try { 84 | animation.setInterpolator((Interpolator)Class.forName("com.gaia.MotionCurve."+curveType).newInstance()); 85 | animation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { 86 | 87 | @Override 88 | public void onAnimationUpdate(ValueAnimator animator) { 89 | animationView.setBackgroundColor((int) animator.getAnimatedValue()); 90 | } 91 | 92 | }); 93 | animation.start(); 94 | } catch (IllegalAccessException e) { 95 | e.printStackTrace(); 96 | } catch (InstantiationException e) { 97 | e.printStackTrace(); 98 | } catch (ClassNotFoundException e) { 99 | e.printStackTrace(); 100 | } 101 | } 102 | }); 103 | 104 | Button scaleButton = (Button) findViewById(R.id.animation_scale); 105 | scaleButton.setOnClickListener(new View.OnClickListener() { 106 | @Override 107 | public void onClick(View view) { 108 | View animationView = findViewById(R.id.animation_view); 109 | ScaleAnimation animation = new ScaleAnimation(1,2,1, 2, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF,0.5f); 110 | animation.setFillAfter(true); 111 | animation.setDuration(700); 112 | try { 113 | animation.setInterpolator((Interpolator)Class.forName("com.gaia.MotionCurve."+curveType).newInstance()); 114 | animationView.startAnimation(animation); 115 | } catch (IllegalAccessException e) { 116 | e.printStackTrace(); 117 | } catch (InstantiationException e) { 118 | e.printStackTrace(); 119 | } catch (ClassNotFoundException e) { 120 | e.printStackTrace(); 121 | } 122 | } 123 | }); 124 | 125 | Button rotationButton = (Button) findViewById(R.id.animation_rotation); 126 | rotationButton.setOnClickListener(new View.OnClickListener() { 127 | @Override 128 | public void onClick(View view) { 129 | View animationView = findViewById(R.id.animation_view); 130 | RotateAnimation animation = new RotateAnimation(0, 360, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF,0.5f); 131 | animation.setFillAfter(true); 132 | animation.setDuration(700); 133 | try { 134 | animation.setInterpolator((Interpolator)Class.forName("com.gaia.MotionCurve."+curveType).newInstance()); 135 | animationView.startAnimation(animation); 136 | } catch (IllegalAccessException e) { 137 | e.printStackTrace(); 138 | } catch (InstantiationException e) { 139 | e.printStackTrace(); 140 | } catch (ClassNotFoundException e) { 141 | e.printStackTrace(); 142 | } 143 | } 144 | }); 145 | 146 | Button combButton = (Button) findViewById(R.id.animation_combination); 147 | combButton.setOnClickListener(new View.OnClickListener() { 148 | @Override 149 | public void onClick(View view) { 150 | View animationView = findViewById(R.id.animation_view); 151 | AnimationSet animationSet = new AnimationSet(false); 152 | 153 | RotateAnimation rotateAnimation= new RotateAnimation(0, 360, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF,0.5f); 154 | animationSet.addAnimation(rotateAnimation); 155 | 156 | ScaleAnimation scaleAnimation = new ScaleAnimation(1,2,1, 2, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF,0.5f); 157 | animationSet.addAnimation(scaleAnimation); 158 | 159 | animationSet.setDuration(700); 160 | try { 161 | animationSet.setInterpolator((Interpolator)Class.forName("com.gaia.MotionCurve."+curveType).newInstance()); 162 | animationView.startAnimation(animationSet); 163 | } catch (IllegalAccessException e) { 164 | e.printStackTrace(); 165 | } catch (InstantiationException e) { 166 | e.printStackTrace(); 167 | } catch (ClassNotFoundException e) { 168 | e.printStackTrace(); 169 | } 170 | } 171 | }); 172 | } 173 | } -------------------------------------------------------------------------------- /examples/Android/app/src/main/java/com/gaia/demo/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.gaia.demo; 2 | 3 | import androidx.appcompat.app.AppCompatActivity; 4 | 5 | import android.content.Intent; 6 | import android.os.Bundle; 7 | import android.view.View; 8 | import android.widget.AdapterView; 9 | import android.widget.ArrayAdapter; 10 | import android.widget.ListView; 11 | 12 | 13 | public class MainActivity extends AppCompatActivity { 14 | 15 | String[] curveTitles = {"线性曲线(Linear)","加速曲线(Accelerate)","减速曲线(Decelerate)", 16 | "标准曲线(Standard)","预期曲线(Anticipate)","过度曲线(Overshoot)", 17 | "弹性曲线(Spring)","弹跳曲线(Bounce)","余弦曲线(Cosine)"}; 18 | 19 | String[] curveTypes = {"GaiaMotionCurveLinearInterpolator","GaiaMotionCurveAccelerateInterpolator","GaiaMotionCurveDecelerateInterpolator", 20 | "GaiaMotionCurveStandardInterpolator","GaiaMotionCurveAnticipateInterpolator","GaiaMotionCurveOvershootInterpolator", 21 | "GaiaMotionCurveSpringInterpolator","GaiaMotionCurveBounceInterpolator","GaiaMotionCurveCosineInterpolator"}; 22 | 23 | @Override 24 | protected void onCreate(Bundle savedInstanceState) { 25 | super.onCreate(savedInstanceState); 26 | setContentView(R.layout.activity_main); 27 | 28 | ArrayAdapter adapter = new ArrayAdapter(this, 29 | R.layout.activity_listview, curveTitles); 30 | 31 | ListView listView = (ListView) findViewById(R.id.gaia_motion_curve_list); 32 | listView.setAdapter(adapter); 33 | 34 | listView.setOnItemClickListener(new AdapterView.OnItemClickListener() { 35 | @Override 36 | public void onItemClick(AdapterView adapterView, View view, int i, long l) { 37 | Intent intent = new Intent(); 38 | intent.setClass(MainActivity.this, AnimationActivity.class); 39 | intent.putExtra("curveType", curveTypes[i]); 40 | startActivity(intent); 41 | } 42 | }); 43 | } 44 | } -------------------------------------------------------------------------------- /examples/Android/app/src/main/res/drawable-v24/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 8 | 9 | 15 | 18 | 21 | 22 | 23 | 24 | 30 | -------------------------------------------------------------------------------- /examples/Android/app/src/main/res/drawable/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 10 | 15 | 20 | 25 | 30 | 35 | 40 | 45 | 50 | 55 | 60 | 65 | 70 | 75 | 80 | 85 | 90 | 95 | 100 | 105 | 110 | 115 | 120 | 125 | 130 | 135 | 140 | 145 | 150 | 155 | 160 | 165 | 170 | 171 | -------------------------------------------------------------------------------- /examples/Android/app/src/main/res/layout/activity_animation.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 18 | 19 | 20 | 26 | 34 | 42 | 43 | 44 | 50 | 58 | 66 | 67 | 68 | 74 | 82 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /examples/Android/app/src/main/res/layout/activity_listview.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /examples/Android/app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 11 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /examples/Android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /examples/Android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /examples/Android/app/src/main/res/mipmap-hdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alibaba/gaia-motion-curve/84f3567dd2725efb9e4dd459c3e303591eafcbfd/examples/Android/app/src/main/res/mipmap-hdpi/ic_launcher.webp -------------------------------------------------------------------------------- /examples/Android/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alibaba/gaia-motion-curve/84f3567dd2725efb9e4dd459c3e303591eafcbfd/examples/Android/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /examples/Android/app/src/main/res/mipmap-mdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alibaba/gaia-motion-curve/84f3567dd2725efb9e4dd459c3e303591eafcbfd/examples/Android/app/src/main/res/mipmap-mdpi/ic_launcher.webp -------------------------------------------------------------------------------- /examples/Android/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alibaba/gaia-motion-curve/84f3567dd2725efb9e4dd459c3e303591eafcbfd/examples/Android/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /examples/Android/app/src/main/res/mipmap-xhdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alibaba/gaia-motion-curve/84f3567dd2725efb9e4dd459c3e303591eafcbfd/examples/Android/app/src/main/res/mipmap-xhdpi/ic_launcher.webp -------------------------------------------------------------------------------- /examples/Android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alibaba/gaia-motion-curve/84f3567dd2725efb9e4dd459c3e303591eafcbfd/examples/Android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /examples/Android/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alibaba/gaia-motion-curve/84f3567dd2725efb9e4dd459c3e303591eafcbfd/examples/Android/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp -------------------------------------------------------------------------------- /examples/Android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alibaba/gaia-motion-curve/84f3567dd2725efb9e4dd459c3e303591eafcbfd/examples/Android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /examples/Android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alibaba/gaia-motion-curve/84f3567dd2725efb9e4dd459c3e303591eafcbfd/examples/Android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp -------------------------------------------------------------------------------- /examples/Android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alibaba/gaia-motion-curve/84f3567dd2725efb9e4dd459c3e303591eafcbfd/examples/Android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /examples/Android/app/src/main/res/values-night/themes.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 16 | -------------------------------------------------------------------------------- /examples/Android/app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #FFBB86FC 4 | #FF6200EE 5 | #FF3700B3 6 | #FF03DAC5 7 | #FF018786 8 | #FF000000 9 | #FFFFFFFF 10 | #0000FF 11 | #FF0000 12 | -------------------------------------------------------------------------------- /examples/Android/app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | Demo 3 | -------------------------------------------------------------------------------- /examples/Android/app/src/main/res/values/themes.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 16 | -------------------------------------------------------------------------------- /examples/Android/app/src/test/java/com/gaia/demo/ExampleUnitTest.java: -------------------------------------------------------------------------------- 1 | package com.gaia.demo; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.*; 6 | 7 | /** 8 | * Example local unit test, which will execute on the development machine (host). 9 | * 10 | * @see Testing documentation 11 | */ 12 | public class ExampleUnitTest { 13 | @Test 14 | public void addition_isCorrect() { 15 | assertEquals(4, 2 + 2); 16 | } 17 | } -------------------------------------------------------------------------------- /examples/Android/build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | buildscript { 3 | repositories { 4 | google() 5 | mavenCentral() 6 | } 7 | dependencies { 8 | classpath "com.android.tools.build:gradle:7.0.4" 9 | 10 | // NOTE: Do not place your application dependencies here; they belong 11 | // in the individual module build.gradle files 12 | } 13 | } 14 | 15 | task clean(type: Delete) { 16 | delete rootProject.buildDir 17 | } -------------------------------------------------------------------------------- /examples/Android/gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | # IDE (e.g. Android Studio) users: 3 | # Gradle settings configured through the IDE *will override* 4 | # any settings specified in this file. 5 | # For more details on how to configure your build environment visit 6 | # http://www.gradle.org/docs/current/userguide/build_environment.html 7 | # Specifies the JVM arguments used for the daemon process. 8 | # The setting is particularly useful for tweaking memory settings. 9 | org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8 10 | # When configured, Gradle will run in incubating parallel mode. 11 | # This option should only be used with decoupled projects. More details, visit 12 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 13 | # org.gradle.parallel=true 14 | # AndroidX package structure to make it clearer which packages are bundled with the 15 | # Android operating system, and which are packaged with your app"s APK 16 | # https://developer.android.com/topic/libraries/support-library/androidx-rn 17 | android.useAndroidX=true 18 | # Automatically convert third-party libraries to use AndroidX 19 | android.enableJetifier=true -------------------------------------------------------------------------------- /examples/Android/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alibaba/gaia-motion-curve/84f3567dd2725efb9e4dd459c3e303591eafcbfd/examples/Android/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /examples/Android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Thu Jan 06 16:17:00 CST 2022 2 | distributionBase=GRADLE_USER_HOME 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-bin.zip 4 | distributionPath=wrapper/dists 5 | zipStorePath=wrapper/dists 6 | zipStoreBase=GRADLE_USER_HOME 7 | -------------------------------------------------------------------------------- /examples/Android/gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # 4 | # Copyright 2015 the original author or authors. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # https://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | 19 | ############################################################################## 20 | ## 21 | ## Gradle start up script for UN*X 22 | ## 23 | ############################################################################## 24 | 25 | # Attempt to set APP_HOME 26 | # Resolve links: $0 may be a link 27 | PRG="$0" 28 | # Need this for relative symlinks. 29 | while [ -h "$PRG" ] ; do 30 | ls=`ls -ld "$PRG"` 31 | link=`expr "$ls" : '.*-> \(.*\)$'` 32 | if expr "$link" : '/.*' > /dev/null; then 33 | PRG="$link" 34 | else 35 | PRG=`dirname "$PRG"`"/$link" 36 | fi 37 | done 38 | SAVED="`pwd`" 39 | cd "`dirname \"$PRG\"`/" >/dev/null 40 | APP_HOME="`pwd -P`" 41 | cd "$SAVED" >/dev/null 42 | 43 | APP_NAME="Gradle" 44 | APP_BASE_NAME=`basename "$0"` 45 | 46 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 47 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' 48 | 49 | # Use the maximum available, or set MAX_FD != -1 to use that value. 50 | MAX_FD="maximum" 51 | 52 | warn () { 53 | echo "$*" 54 | } 55 | 56 | die () { 57 | echo 58 | echo "$*" 59 | echo 60 | exit 1 61 | } 62 | 63 | # OS specific support (must be 'true' or 'false'). 64 | cygwin=false 65 | msys=false 66 | darwin=false 67 | nonstop=false 68 | case "`uname`" in 69 | CYGWIN* ) 70 | cygwin=true 71 | ;; 72 | Darwin* ) 73 | darwin=true 74 | ;; 75 | MINGW* ) 76 | msys=true 77 | ;; 78 | NONSTOP* ) 79 | nonstop=true 80 | ;; 81 | esac 82 | 83 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 84 | 85 | 86 | # Determine the Java command to use to start the JVM. 87 | if [ -n "$JAVA_HOME" ] ; then 88 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 89 | # IBM's JDK on AIX uses strange locations for the executables 90 | JAVACMD="$JAVA_HOME/jre/sh/java" 91 | else 92 | JAVACMD="$JAVA_HOME/bin/java" 93 | fi 94 | if [ ! -x "$JAVACMD" ] ; then 95 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 96 | 97 | Please set the JAVA_HOME variable in your environment to match the 98 | location of your Java installation." 99 | fi 100 | else 101 | JAVACMD="java" 102 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 103 | 104 | Please set the JAVA_HOME variable in your environment to match the 105 | location of your Java installation." 106 | fi 107 | 108 | # Increase the maximum file descriptors if we can. 109 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 110 | MAX_FD_LIMIT=`ulimit -H -n` 111 | if [ $? -eq 0 ] ; then 112 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 113 | MAX_FD="$MAX_FD_LIMIT" 114 | fi 115 | ulimit -n $MAX_FD 116 | if [ $? -ne 0 ] ; then 117 | warn "Could not set maximum file descriptor limit: $MAX_FD" 118 | fi 119 | else 120 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 121 | fi 122 | fi 123 | 124 | # For Darwin, add options to specify how the application appears in the dock 125 | if $darwin; then 126 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 127 | fi 128 | 129 | # For Cygwin or MSYS, switch paths to Windows format before running java 130 | if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then 131 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 132 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 133 | 134 | JAVACMD=`cygpath --unix "$JAVACMD"` 135 | 136 | # We build the pattern for arguments to be converted via cygpath 137 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 138 | SEP="" 139 | for dir in $ROOTDIRSRAW ; do 140 | ROOTDIRS="$ROOTDIRS$SEP$dir" 141 | SEP="|" 142 | done 143 | OURCYGPATTERN="(^($ROOTDIRS))" 144 | # Add a user-defined pattern to the cygpath arguments 145 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 146 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 147 | fi 148 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 149 | i=0 150 | for arg in "$@" ; do 151 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 152 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 153 | 154 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 155 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 156 | else 157 | eval `echo args$i`="\"$arg\"" 158 | fi 159 | i=`expr $i + 1` 160 | done 161 | case $i in 162 | 0) set -- ;; 163 | 1) set -- "$args0" ;; 164 | 2) set -- "$args0" "$args1" ;; 165 | 3) set -- "$args0" "$args1" "$args2" ;; 166 | 4) set -- "$args0" "$args1" "$args2" "$args3" ;; 167 | 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 168 | 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 169 | 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 170 | 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 171 | 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 172 | esac 173 | fi 174 | 175 | # Escape application args 176 | save () { 177 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done 178 | echo " " 179 | } 180 | APP_ARGS=`save "$@"` 181 | 182 | # Collect all arguments for the java command, following the shell quoting and substitution rules 183 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" 184 | 185 | exec "$JAVACMD" "$@" 186 | -------------------------------------------------------------------------------- /examples/Android/gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem https://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | 17 | @if "%DEBUG%" == "" @echo off 18 | @rem ########################################################################## 19 | @rem 20 | @rem Gradle startup script for Windows 21 | @rem 22 | @rem ########################################################################## 23 | 24 | @rem Set local scope for the variables with windows NT shell 25 | if "%OS%"=="Windows_NT" setlocal 26 | 27 | set DIRNAME=%~dp0 28 | if "%DIRNAME%" == "" set DIRNAME=. 29 | set APP_BASE_NAME=%~n0 30 | set APP_HOME=%DIRNAME% 31 | 32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter. 33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi 34 | 35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 37 | 38 | @rem Find java.exe 39 | if defined JAVA_HOME goto findJavaFromJavaHome 40 | 41 | set JAVA_EXE=java.exe 42 | %JAVA_EXE% -version >NUL 2>&1 43 | if "%ERRORLEVEL%" == "0" goto execute 44 | 45 | echo. 46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 47 | echo. 48 | echo Please set the JAVA_HOME variable in your environment to match the 49 | echo location of your Java installation. 50 | 51 | goto fail 52 | 53 | :findJavaFromJavaHome 54 | set JAVA_HOME=%JAVA_HOME:"=% 55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 56 | 57 | if exist "%JAVA_EXE%" goto execute 58 | 59 | echo. 60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 61 | echo. 62 | echo Please set the JAVA_HOME variable in your environment to match the 63 | echo location of your Java installation. 64 | 65 | goto fail 66 | 67 | :execute 68 | @rem Setup the command line 69 | 70 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 71 | 72 | 73 | @rem Execute Gradle 74 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* 75 | 76 | :end 77 | @rem End local scope for the variables with windows NT shell 78 | if "%ERRORLEVEL%"=="0" goto mainEnd 79 | 80 | :fail 81 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 82 | rem the _cmd.exe /c_ return code! 83 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 84 | exit /b 1 85 | 86 | :mainEnd 87 | if "%OS%"=="Windows_NT" endlocal 88 | 89 | :omega 90 | -------------------------------------------------------------------------------- /examples/Android/settings.gradle: -------------------------------------------------------------------------------- 1 | dependencyResolutionManagement { 2 | repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) 3 | repositories { 4 | google() 5 | mavenCentral() 6 | jcenter() // Warning: this repository is going to shut down soon 7 | } 8 | } 9 | rootProject.name = "Demo" 10 | include ':app' 11 | -------------------------------------------------------------------------------- /examples/iOS/GaiaMotionCurveDemo/AnimationViewController.h: -------------------------------------------------------------------------------- 1 | // Copyright 2022 Alibaba Group Holding Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #import 16 | #import 17 | 18 | NS_ASSUME_NONNULL_BEGIN 19 | 20 | @interface AnimationViewController : UIViewController 21 | 22 | @property(nonatomic, assign) GMCCurveType curveType; 23 | 24 | @end 25 | 26 | NS_ASSUME_NONNULL_END 27 | -------------------------------------------------------------------------------- /examples/iOS/GaiaMotionCurveDemo/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // Copyright 2022 Alibaba Group Holding Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #import 16 | 17 | @interface AppDelegate : UIResponder 18 | 19 | @property(strong, nonatomic) UIWindow *window; 20 | @property(strong, nonatomic) UINavigationController *navController; 21 | 22 | @end 23 | 24 | -------------------------------------------------------------------------------- /examples/iOS/GaiaMotionCurveDemo/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // Copyright 2022 Alibaba Group Holding Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #import "AppDelegate.h" 16 | #import "ViewController.h" 17 | 18 | @interface AppDelegate () 19 | 20 | @end 21 | 22 | @implementation AppDelegate 23 | 24 | 25 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 26 | // Override point for customization after application launch. 27 | 28 | 29 | self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; 30 | 31 | self.window.backgroundColor = [UIColor whiteColor]; 32 | 33 | 34 | ViewController *home = [[ViewController alloc] init]; 35 | _navController = [[UINavigationController alloc] initWithRootViewController:home]; 36 | 37 | [self.window setRootViewController:_navController]; 38 | 39 | [self.window makeKeyAndVisible]; 40 | 41 | return YES; 42 | } 43 | 44 | 45 | @end 46 | -------------------------------------------------------------------------------- /examples/iOS/GaiaMotionCurveDemo/Assets.xcassets/AppIcon.appiconset/111.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alibaba/gaia-motion-curve/84f3567dd2725efb9e4dd459c3e303591eafcbfd/examples/iOS/GaiaMotionCurveDemo/Assets.xcassets/AppIcon.appiconset/111.png -------------------------------------------------------------------------------- /examples/iOS/GaiaMotionCurveDemo/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images": [ 3 | { 4 | "idiom": "iphone", 5 | "scale": "2x", 6 | "size": "20x20" 7 | }, 8 | { 9 | "idiom": "iphone", 10 | "scale": "3x", 11 | "size": "20x20" 12 | }, 13 | { 14 | "idiom": "iphone", 15 | "scale": "2x", 16 | "size": "29x29" 17 | }, 18 | { 19 | "idiom": "iphone", 20 | "scale": "3x", 21 | "size": "29x29" 22 | }, 23 | { 24 | "idiom": "iphone", 25 | "scale": "2x", 26 | "size": "40x40" 27 | }, 28 | { 29 | "idiom": "iphone", 30 | "scale": "3x", 31 | "size": "40x40" 32 | }, 33 | { 34 | "filename": "Ico1n.png", 35 | "idiom": "iphone", 36 | "scale": "2x", 37 | "size": "60x60" 38 | }, 39 | { 40 | "filename": "111.png", 41 | "idiom": "iphone", 42 | "scale": "3x", 43 | "size": "60x60" 44 | }, 45 | { 46 | "idiom": "ipad", 47 | "scale": "1x", 48 | "size": "20x20" 49 | }, 50 | { 51 | "idiom": "ipad", 52 | "scale": "2x", 53 | "size": "20x20" 54 | }, 55 | { 56 | "idiom": "ipad", 57 | "scale": "1x", 58 | "size": "29x29" 59 | }, 60 | { 61 | "idiom": "ipad", 62 | "scale": "2x", 63 | "size": "29x29" 64 | }, 65 | { 66 | "idiom": "ipad", 67 | "scale": "1x", 68 | "size": "40x40" 69 | }, 70 | { 71 | "idiom": "ipad", 72 | "scale": "2x", 73 | "size": "40x40" 74 | }, 75 | { 76 | "idiom": "ipad", 77 | "scale": "1x", 78 | "size": "76x76" 79 | }, 80 | { 81 | "idiom": "ipad", 82 | "scale": "2x", 83 | "size": "76x76" 84 | }, 85 | { 86 | "idiom": "ipad", 87 | "scale": "2x", 88 | "size": "83.5x83.5" 89 | }, 90 | { 91 | "idiom": "ios-marketing", 92 | "scale": "1x", 93 | "size": "1024x1024" 94 | } 95 | ], 96 | "info": { 97 | "author": "xcode", 98 | "version": 1 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /examples/iOS/GaiaMotionCurveDemo/Assets.xcassets/AppIcon.appiconset/Ico1n.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alibaba/gaia-motion-curve/84f3567dd2725efb9e4dd459c3e303591eafcbfd/examples/iOS/GaiaMotionCurveDemo/Assets.xcassets/AppIcon.appiconset/Ico1n.png -------------------------------------------------------------------------------- /examples/iOS/GaiaMotionCurveDemo/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info": { 3 | "author": "xcode", 4 | "version": 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /examples/iOS/GaiaMotionCurveDemo/Assets.xcassets/LaunchImage.launchimage/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images": [ 3 | { 4 | "extent": "full-screen", 5 | "idiom": "iphone", 6 | "minimum-system-version": "12.0", 7 | "orientation": "portrait", 8 | "scale": "3x", 9 | "subtype": "2688h" 10 | }, 11 | { 12 | "extent": "full-screen", 13 | "idiom": "iphone", 14 | "minimum-system-version": "12.0", 15 | "orientation": "landscape", 16 | "scale": "3x", 17 | "subtype": "2688h" 18 | }, 19 | { 20 | "extent": "full-screen", 21 | "idiom": "iphone", 22 | "minimum-system-version": "12.0", 23 | "orientation": "portrait", 24 | "scale": "2x", 25 | "subtype": "1792h" 26 | }, 27 | { 28 | "extent": "full-screen", 29 | "idiom": "iphone", 30 | "minimum-system-version": "12.0", 31 | "orientation": "landscape", 32 | "scale": "2x", 33 | "subtype": "1792h" 34 | }, 35 | { 36 | "extent": "full-screen", 37 | "idiom": "iphone", 38 | "minimum-system-version": "11.0", 39 | "orientation": "portrait", 40 | "scale": "3x", 41 | "subtype": "2436h" 42 | }, 43 | { 44 | "extent": "full-screen", 45 | "idiom": "iphone", 46 | "minimum-system-version": "11.0", 47 | "orientation": "landscape", 48 | "scale": "3x", 49 | "subtype": "2436h" 50 | }, 51 | { 52 | "extent": "full-screen", 53 | "idiom": "iphone", 54 | "minimum-system-version": "8.0", 55 | "orientation": "portrait", 56 | "scale": "3x", 57 | "subtype": "736h" 58 | }, 59 | { 60 | "extent": "full-screen", 61 | "idiom": "iphone", 62 | "minimum-system-version": "8.0", 63 | "orientation": "landscape", 64 | "scale": "3x", 65 | "subtype": "736h" 66 | }, 67 | { 68 | "extent": "full-screen", 69 | "filename": "画板@2x.png", 70 | "idiom": "iphone", 71 | "minimum-system-version": "8.0", 72 | "orientation": "portrait", 73 | "scale": "2x", 74 | "subtype": "667h" 75 | }, 76 | { 77 | "extent": "full-screen", 78 | "idiom": "iphone", 79 | "minimum-system-version": "7.0", 80 | "orientation": "portrait", 81 | "scale": "2x" 82 | }, 83 | { 84 | "extent": "full-screen", 85 | "idiom": "iphone", 86 | "minimum-system-version": "7.0", 87 | "orientation": "portrait", 88 | "scale": "2x", 89 | "subtype": "retina4" 90 | }, 91 | { 92 | "extent": "full-screen", 93 | "idiom": "iphone", 94 | "orientation": "portrait", 95 | "scale": "1x" 96 | }, 97 | { 98 | "extent": "full-screen", 99 | "idiom": "iphone", 100 | "orientation": "portrait", 101 | "scale": "2x" 102 | }, 103 | { 104 | "extent": "full-screen", 105 | "idiom": "iphone", 106 | "orientation": "portrait", 107 | "scale": "2x", 108 | "subtype": "retina4" 109 | } 110 | ], 111 | "info": { 112 | "author": "xcode", 113 | "version": 1 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /examples/iOS/GaiaMotionCurveDemo/Assets.xcassets/LaunchImage.launchimage/画板@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alibaba/gaia-motion-curve/84f3567dd2725efb9e4dd459c3e303591eafcbfd/examples/iOS/GaiaMotionCurveDemo/Assets.xcassets/LaunchImage.launchimage/画板@2x.png -------------------------------------------------------------------------------- /examples/iOS/GaiaMotionCurveDemo/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | $(PRODUCT_BUNDLE_PACKAGE_TYPE) 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | UILaunchStoryboardName 24 | LaunchImage 25 | UIRequiredDeviceCapabilities 26 | 27 | armv7 28 | 29 | UISupportedInterfaceOrientations 30 | 31 | UIInterfaceOrientationPortrait 32 | UIInterfaceOrientationLandscapeLeft 33 | UIInterfaceOrientationLandscapeRight 34 | 35 | UISupportedInterfaceOrientations~ipad 36 | 37 | UIInterfaceOrientationPortrait 38 | UIInterfaceOrientationPortraitUpsideDown 39 | UIInterfaceOrientationLandscapeLeft 40 | UIInterfaceOrientationLandscapeRight 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /examples/iOS/GaiaMotionCurveDemo/ViewController.h: -------------------------------------------------------------------------------- 1 | // Copyright 2022 Alibaba Group Holding Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #import 16 | 17 | @interface ViewController : UIViewController 18 | 19 | 20 | @end 21 | 22 | -------------------------------------------------------------------------------- /examples/iOS/GaiaMotionCurveDemo/ViewController.m: -------------------------------------------------------------------------------- 1 | // Copyright 2022 Alibaba Group Holding Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #import "ViewController.h" 16 | #import "AnimationViewController.h" 17 | 18 | @interface ViewController () 19 | 20 | @property(nonatomic, strong) UITableView *tableView; 21 | @property(nonatomic, strong) NSArray *dataArray; 22 | @property(nonatomic, strong) NSArray *curveTypeArray; 23 | 24 | @end 25 | 26 | @implementation ViewController 27 | 28 | - (void)viewDidLoad { 29 | [super viewDidLoad]; 30 | // Do any additional setup after loading the view. 31 | 32 | _tableView = [[UITableView alloc] initWithFrame:self.view.bounds style:UITableViewStyleGrouped]; 33 | _tableView.delegate = self; 34 | _tableView.dataSource = self; 35 | 36 | self.title = @"动效曲线"; 37 | 38 | 39 | _dataArray = @[@"线性曲线(Linear)", @"加速曲线(Accelerate)", @"减速曲线(Decelerate)", @"标准曲线(Standard)", @"预期曲线(Anticipate)", @"过度曲线(Overshoot)", @"弹性曲线(Spring)", @"弹跳曲线(Bounce)", @"余弦曲线(Cosine)"]; 40 | _curveTypeArray = @[@(GMCCurveTypeLinear), @(GMCCurveTypeAccelerate), @(GMCCurveTypeDecelerate), @(GMCCurveTypeStandard), @(GMCCurveTypeAnticipate), @(GMCCurveTypeOvershoot), @(GMCCurveTypeSpring), @(GMCCurveTypeBounce), @(GMCCurveTypeCosine)]; 41 | 42 | [self.view addSubview:_tableView]; 43 | } 44 | 45 | - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { 46 | return _dataArray.count; 47 | } 48 | 49 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { 50 | return 1; 51 | } 52 | 53 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 54 | static NSString *cellIdentifier = @"UITableViewCell"; 55 | UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier]; 56 | if (cell == nil) { 57 | cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:cellIdentifier]; 58 | } 59 | cell.textLabel.text = _dataArray[indexPath.section]; 60 | cell.accessoryType = UITableViewRowAnimationRight; 61 | return cell; 62 | } 63 | 64 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { 65 | [tableView deselectRowAtIndexPath:indexPath animated:NO]; 66 | AnimationViewController *controller = [[AnimationViewController alloc] initWithNibName:nil bundle:nil]; 67 | controller.curveType = [_curveTypeArray[indexPath.section] integerValue]; 68 | controller.title = _dataArray[indexPath.section]; 69 | [self.navigationController pushViewController:controller animated:YES]; 70 | } 71 | 72 | @end 73 | -------------------------------------------------------------------------------- /examples/iOS/GaiaMotionCurveDemo/main.m: -------------------------------------------------------------------------------- 1 | // Copyright 2022 Alibaba Group Holding Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #import 16 | #import "AppDelegate.h" 17 | 18 | int main(int argc, char *argv[]) { 19 | NSString *appDelegateClassName; 20 | @autoreleasepool { 21 | // Setup code that might create autoreleased objects goes here. 22 | appDelegateClassName = NSStringFromClass([AppDelegate class]); 23 | } 24 | return UIApplicationMain(argc, argv, nil, appDelegateClassName); 25 | } 26 | -------------------------------------------------------------------------------- /examples/iOS/Podfile: -------------------------------------------------------------------------------- 1 | # Uncomment the next line to define a global platform for your project 2 | # platform :ios, '9.0' 3 | source 'https://github.com/CocoaPods/Specs.git' 4 | 5 | target 'GaiaMotionCurveDemo' do 6 | # Comment the next line if you don't want to use dynamic frameworks 7 | use_frameworks! 8 | 9 | pod "GaiaMotionCurve", "0.1.0" 10 | 11 | end 12 | -------------------------------------------------------------------------------- /examples/iOS/Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - GaiaMotionCurve (0.1.0) 3 | 4 | DEPENDENCIES: 5 | - GaiaMotionCurve (= 0.1.0) 6 | 7 | SPEC REPOS: 8 | https://github.com/CocoaPods/Specs.git: 9 | - GaiaMotionCurve 10 | 11 | SPEC CHECKSUMS: 12 | GaiaMotionCurve: ece6f75d77f6aa8df28804416da467db64d224be 13 | 14 | PODFILE CHECKSUM: f1f14cba75d0390a6e6710446f6090cd2ea1de10 15 | 16 | COCOAPODS: 1.11.2 17 | -------------------------------------------------------------------------------- /iOS/GaiaMotionCurve.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | 3 | s.name = "GaiaMotionCurve" 4 | s.version = "0.1.1" 5 | s.summary = "a library to solve the problems of high cost of developing dynamic effects and inconsistent effects and design expectations" 6 | s.license = { :type => 'Apache License, Version 2.0' } 7 | s.homepage = "https://github.com/alibaba/gaia-motion-curve" 8 | 9 | s.author = { "ronghui.zrh" => "ronghui.zrh@alibaba-inc.com" } 10 | s.platform = :ios, "9.0" 11 | s.source = { :git => "https://github.com/alibaba/gaia-motion-curve.git", :tag => s.version } 12 | 13 | 14 | s.source_files = 'iOS/GaiaMotionCurve/**/*.{h,m,mm,c}' 15 | s.xcconfig = { "ENABLE_BITCODE" => "NO" } 16 | s.requires_arc = true 17 | end 18 | -------------------------------------------------------------------------------- /iOS/GaiaMotionCurve/CALayer+GaiaMotionCurve.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022, Alibaba Group Holding Limited; 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #import 16 | #import "GMCModel.h" 17 | #import "NSValue+GMCCGFloat.h" 18 | #import "NSValue+GMCUIColor.h" 19 | 20 | NS_ASSUME_NONNULL_BEGIN 21 | 22 | @interface CALayer (GaiaMotionCurve) 23 | 24 | /** 25 | when finished,will auto set toValue to layer,do not need set in completion block again 26 | @param models animation models array 27 | @param completion finished block 28 | @return animation unique id 29 | */ 30 | - (NSString *)gmc_animateWithGMCModels:(NSArray *)models 31 | completion:(GMCCompletionBlock)completion; 32 | 33 | 34 | //serial animation 35 | - (NSString *)gmc_serialAnimationWithGMCModels:(NSArray *)models 36 | completion:(GMCCompletionBlock)completion; 37 | 38 | /** 39 | cancel animation with animationID 40 | @param animationID animation unique id 41 | */ 42 | - (void)gmc_cancelAnimationWithID:(NSString *)animationID; 43 | 44 | // cancel all animations 45 | - (void)gmc_cancelAllAnimations; 46 | 47 | 48 | @property(nonatomic, strong) NSMutableDictionary *gmc_animationKeys; 49 | 50 | 51 | @end 52 | 53 | NS_ASSUME_NONNULL_END 54 | -------------------------------------------------------------------------------- /iOS/GaiaMotionCurve/GMCDefines.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022, Alibaba Group Holding Limited; 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #ifndef GMCDefines_h 16 | #define GMCDefines_h 17 | 18 | #import 19 | 20 | typedef NS_ENUM(NSInteger, GMCCurveType) { 21 | GMCCurveTypeLinear, 22 | GMCCurveTypeCosine, 23 | GMCCurveTypeAccelerate, 24 | GMCCurveTypeDecelerate, 25 | GMCCurveTypeStandard, 26 | GMCCurveTypeCubicBezier = GMCCurveTypeStandard, 27 | GMCCurveTypeAnticipate, 28 | GMCCurveTypeOvershoot, 29 | GMCCurveTypeBounce, 30 | GMCCurveTypeSpring, 31 | }; 32 | 33 | typedef void (^GMCCompletionBlock)(BOOL finished); 34 | 35 | #define GMCWeakSelf(type) __weak typeof(type) weak##type = type; 36 | #define GMCStrongSelf(type) __strong typeof(type) type = weak##type; 37 | 38 | #endif /* GMCDefines_h */ 39 | -------------------------------------------------------------------------------- /iOS/GaiaMotionCurve/GMCFunctions.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022, Alibaba Group Holding Limited; 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | 16 | #import 17 | #import 18 | 19 | 20 | #ifndef GMCFunctions_h 21 | #define GMCFunctions_h 22 | 23 | CGFloat gmc_linear_curve(CGFloat p); 24 | 25 | CGFloat gmc_cosine_curve(CGFloat p, CGFloat d, CGFloat c); 26 | 27 | CGFloat gmc_decelerate_curve(CGFloat p, CGFloat x1, CGFloat y1, CGFloat x2, 28 | CGFloat y2); 29 | 30 | CGFloat gmc_accelerate_curve(CGFloat p, CGFloat x1, CGFloat y1, CGFloat x2, 31 | CGFloat y2); 32 | 33 | CGFloat gmc_standard_curve(CGFloat p, CGFloat x1, CGFloat y1, CGFloat x2, 34 | CGFloat y2); 35 | 36 | CGFloat gmc_anticipate_curve(CGFloat p, CGFloat d, CGFloat x1, CGFloat y1, 37 | CGFloat x2, CGFloat y2, CGFloat x3, CGFloat y3, 38 | CGFloat x4, CGFloat y4); 39 | 40 | CGFloat gmc_overshoot_curve(CGFloat p, CGFloat d, CGFloat x1, CGFloat y1, 41 | CGFloat x2, CGFloat y2, CGFloat x3, CGFloat y3, 42 | CGFloat x4, CGFloat y4); 43 | 44 | CGFloat gmc_bounce_curve(CGFloat p, CGFloat v, CGFloat d); 45 | 46 | CGFloat gmc_spring_motion_curve(CGFloat p, CGFloat m, CGFloat s, CGFloat d, 47 | CGFloat iv); 48 | 49 | CGFloat gmc_spring_rk4_motion_curve(CGFloat p, CGFloat *lastValue, 50 | CGFloat t, CGFloat f, 51 | CGFloat *v); 52 | 53 | #endif /* GMCFunctions_h */ 54 | -------------------------------------------------------------------------------- /iOS/GaiaMotionCurve/GMCFunctions.m: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022, Alibaba Group Holding Limited; 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #import "GMCFunctions.h" 16 | 17 | CGFloat gmc_linear_curve(CGFloat p) { 18 | return p; 19 | } 20 | 21 | CGFloat gmc_cosine_curve(CGFloat p, CGFloat d, CGFloat c) { 22 | return d * 0.5 * (1 - cos(p * 2 * c * M_PI)); 23 | } 24 | 25 | CGFloat gmc_decelerate_curve(CGFloat p, CGFloat x1, CGFloat y1, CGFloat x2, 26 | CGFloat y2) { 27 | return gmc_standard_curve(p, x1, y1, x2, y2); 28 | } 29 | 30 | CGFloat gmc_accelerate_curve(CGFloat p, CGFloat x1, CGFloat y1, CGFloat x2, 31 | CGFloat y2) { 32 | return gmc_standard_curve(p, x1, y1, x2, y2); 33 | } 34 | 35 | CGFloat gmc_standard_curve(CGFloat p, CGFloat x1, CGFloat y1, CGFloat x2, 36 | CGFloat y2) { 37 | CGFloat x = p; 38 | CGFloat z; 39 | CGFloat ax, ay, bx, by, cx, cy; 40 | for (int i = 1; i < 14; i++) { 41 | cx = 3.0f * x1; 42 | bx = 3.0f * (x2 - x1) - cx; 43 | ax = 1.0f - cx - bx; 44 | CGFloat b = x * (cx + x * (bx + x * ax)); 45 | z = b - p; 46 | if (fabs(z) < 1e-3) { 47 | break; 48 | } 49 | CGFloat d = cx + x * (2.0f * bx + 3.0f * ax * x); 50 | x -= z / d; 51 | } 52 | cy = 3.0f * y1; 53 | by = 3.0f * (y2 - y1) - cy; 54 | ay = 1.0f - cy - by; 55 | return x * (cy + x * (by + x * ay)); 56 | } 57 | 58 | CGFloat gmc_anticipate_curve(CGFloat p, CGFloat d, CGFloat x1, CGFloat y1, CGFloat x2, 59 | CGFloat y2, CGFloat x3, CGFloat y3, CGFloat x4, 60 | CGFloat y4) { 61 | // Anticipate (0.33,0,0.67,1 )time:0.3 (0.33,0,0.2,1 ) 62 | if (p <= 0.3f) { 63 | return -d * gmc_standard_curve(p * 3.33, x1, y1, x2, y2); 64 | } else { 65 | return -d * gmc_standard_curve(0.3 * 3.33, x1, y1, x2, y2) + (1 + d) * gmc_standard_curve((p - 0.3) * 1.42, x3, y3, x4, y4); 66 | } 67 | } 68 | 69 | CGFloat gmc_bounce_curve(CGFloat p, CGFloat v, CGFloat d) { 70 | CGFloat tp = p; 71 | CGFloat b = 2.75 * v; 72 | if (tp < (1 / b)) { 73 | return pow(b, 2) * tp * tp; 74 | } else if (tp < (2 / b)) { 75 | return pow(b * d, 2) * (tp - 1.5 / b) * (tp - 1.5 / b) + (1 - pow(b * d, 2) * (1 / b - 1.5 / b) * (1 / b - 1.5 / b)); 76 | } else if (tp < (2.5 / b)) { 77 | return pow(b * d, 2) * (tp - 2.25 / b) * (tp - 2.25 / b) + (1 - pow(b * d, 2) * (2 / b - 2.25 / b) * (2 / b - 2.25 / b)); 78 | } else { 79 | return MIN(1.0f, pow(b * d, 2) * (tp - 2.625 / b) * (tp - 2.625 / b) + (1 - pow(b * d, 2) * (2.5 / b - 2.625 / b) * (2.5 / b - 2.625 / b))); 80 | } 81 | } 82 | 83 | CGFloat gmc_overshoot_curve(CGFloat p, CGFloat d, CGFloat x1, CGFloat y1, CGFloat x2, 84 | CGFloat y2, CGFloat x3, CGFloat y3, CGFloat x4, 85 | CGFloat y4) { 86 | //Overshoot (0.33,0,0.3,1 )time:0.5 (0.33,0,0.5,1 ) 87 | if (p <= 0.5f) { 88 | return d * gmc_standard_curve(p * 2, x1, y1, x2, y2); 89 | } else { 90 | return d * gmc_standard_curve(0.5 * 2, x1, y1, x2, y2) - (d - 1) * gmc_standard_curve((p - 0.5) * 2, x3, y3, x4, y4); 91 | } 92 | } 93 | 94 | CGFloat gmc_spring_motion_curve(CGFloat p, CGFloat m, CGFloat s, CGFloat d, 95 | CGFloat iv) { 96 | CGFloat m_w0 = sqrt(s / m); 97 | CGFloat m_zeta = d / (2.0f * sqrt(s * m)); 98 | CGFloat m_wd; 99 | CGFloat m_A; 100 | CGFloat m_B; 101 | if (m_zeta < 1.0f) { 102 | m_wd = m_w0 * sqrt(1.0f - m_zeta * m_zeta); 103 | m_A = 1.0f; 104 | m_B = (m_zeta * m_w0 + -iv) / m_wd; 105 | } else { 106 | m_wd = 0.0f; 107 | m_A = 1.0f; 108 | m_B = -iv + m_w0; 109 | } 110 | CGFloat t; 111 | if (m_zeta < 1.0f) { 112 | t = exp(-p * m_zeta * m_w0) * (m_A * cos(m_wd * p) + m_B * sin(m_wd * p)); 113 | } else { 114 | t = (m_A + m_B * p) * exp(-p * m_w0); 115 | } 116 | return 1.0f - t; 117 | } 118 | 119 | typedef struct { 120 | CGFloat x; 121 | CGFloat v; 122 | CGFloat tension; 123 | CGFloat friction; 124 | } GMCSpringState; 125 | 126 | typedef struct { 127 | CGFloat dx; 128 | CGFloat dv; 129 | } GMCSpringDerivative; 130 | 131 | CGFloat normalizeSpringValue(CGFloat value) { 132 | if (isnan(value)) { 133 | return 0; 134 | } else if (isinf(value)) { 135 | return 0; 136 | } else { 137 | return value; 138 | } 139 | } 140 | 141 | CGFloat springAccelerationForState(GMCSpringState state) { 142 | return -state.tension * state.x - state.friction * state.v; 143 | } 144 | 145 | GMCSpringDerivative springEvaluateState(GMCSpringState initialState) { 146 | GMCSpringDerivative output; 147 | output.dx = initialState.v; 148 | output.dv = springAccelerationForState(initialState); 149 | return output; 150 | } 151 | 152 | GMCSpringDerivative springEvaluateStateWithDerivative(GMCSpringState initialState, CGFloat dt, GMCSpringDerivative derivative) { 153 | 154 | GMCSpringState state; 155 | state.x = initialState.x + derivative.dx * dt; 156 | state.v = initialState.v + derivative.dv * dt; 157 | state.tension = initialState.tension; 158 | state.friction = initialState.friction; 159 | 160 | GMCSpringDerivative output; 161 | output.dx = state.v; 162 | output.dv = springAccelerationForState(state); 163 | 164 | return output; 165 | } 166 | 167 | GMCSpringState springIntegrateState(GMCSpringState state, CGFloat speed) { 168 | GMCSpringDerivative a = springEvaluateState(state); 169 | GMCSpringDerivative b = springEvaluateStateWithDerivative(state, speed * 0.5, a); 170 | GMCSpringDerivative c = springEvaluateStateWithDerivative(state, speed * 0.5, b); 171 | GMCSpringDerivative d = springEvaluateStateWithDerivative(state, speed, c); 172 | 173 | CGFloat tx = (a.dx + 2.0 * (b.dx + c.dx) + d.dx); 174 | CGFloat ty = (a.dv + 2.0 * (b.dv + c.dv) + d.dv); 175 | 176 | CGFloat dxdt = 1.0 / 6.0 * tx; 177 | CGFloat dvdt = 1.0 / 6.0 * ty; 178 | 179 | GMCSpringState output = state; 180 | 181 | output.x = state.x + dxdt * speed; 182 | output.v = state.v + dvdt * speed; 183 | 184 | return output; 185 | } 186 | 187 | CGFloat gmc_spring_rk4_motion_curve(CGFloat p, CGFloat *lastValue, CGFloat t, CGFloat f, CGFloat *v) { 188 | CGFloat result; 189 | if (p == 0.0f) { 190 | result = 0.0f; 191 | } else { 192 | GMCSpringState before; 193 | before.x = *lastValue - 1.0f; 194 | before.v = *v; 195 | before.tension = t; 196 | before.friction = f; 197 | 198 | GMCSpringState after = springIntegrateState(before, 1 / 60.0f); 199 | *lastValue = 1 + after.x; 200 | *v = after.v; 201 | 202 | *lastValue = normalizeSpringValue(*lastValue); 203 | *v = normalizeSpringValue(*v); 204 | 205 | result = *lastValue; 206 | } 207 | return result; 208 | } 209 | -------------------------------------------------------------------------------- /iOS/GaiaMotionCurve/GMCHelper.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022, Alibaba Group Holding Limited; 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | 16 | #import 17 | #import 18 | 19 | @class GMCModel; 20 | 21 | NS_ASSUME_NONNULL_BEGIN 22 | 23 | @interface GMCHelper : NSObject 24 | 25 | 26 | + (NSArray *)valuesByCurveModel:(GMCModel *)model; 27 | 28 | /* 29 | count > 1 30 | */ 31 | + (NSArray *)valuesByCurveModel:(GMCModel *)model valueCount:(NSInteger)count; 32 | 33 | 34 | /* 35 | 0 < percent <= 1 36 | */ 37 | + (NSValue *)valueByCurveModel:(GMCModel *)model progressPercent:(CGFloat)percent; 38 | 39 | 40 | @end 41 | 42 | NS_ASSUME_NONNULL_END 43 | -------------------------------------------------------------------------------- /iOS/GaiaMotionCurve/GMCModel+Internal.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022, Alibaba Group Holding Limited; 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | 16 | #import "GMCModel.h" 17 | 18 | NS_ASSUME_NONNULL_BEGIN 19 | 20 | @interface GMCBaseArgsModel : NSObject 21 | 22 | @end 23 | 24 | @interface GMCStandardArgsModel : GMCBaseArgsModel 25 | 26 | @property(nonatomic, assign) CGFloat x1; 27 | @property(nonatomic, assign) CGFloat y1; 28 | @property(nonatomic, assign) CGFloat x2; 29 | @property(nonatomic, assign) CGFloat y2; 30 | 31 | @end 32 | 33 | @interface GMCAccelerateArgsModel : GMCStandardArgsModel 34 | 35 | @end 36 | 37 | @interface GMCDecelerateArgsModel : GMCStandardArgsModel 38 | 39 | @end 40 | 41 | @interface GMCAnticipateArgsModel : GMCBaseArgsModel 42 | 43 | @property(nonatomic, assign) CGFloat d; 44 | @property(nonatomic, assign) CGFloat x1; 45 | @property(nonatomic, assign) CGFloat y1; 46 | @property(nonatomic, assign) CGFloat x2; 47 | @property(nonatomic, assign) CGFloat y2; 48 | @property(nonatomic, assign) CGFloat x3; 49 | @property(nonatomic, assign) CGFloat y3; 50 | @property(nonatomic, assign) CGFloat x4; 51 | @property(nonatomic, assign) CGFloat y4; 52 | 53 | @end 54 | 55 | @interface GMCOvershootArgsModel : GMCAnticipateArgsModel 56 | 57 | @end 58 | 59 | @interface GMCBounceArgsModel : GMCBaseArgsModel 60 | 61 | @property(nonatomic, assign) CGFloat v; 62 | @property(nonatomic, assign) CGFloat d; 63 | 64 | @end 65 | 66 | @interface GMCDefaultSpringArgsModel : GMCBaseArgsModel 67 | 68 | @property(nonatomic, assign) CGFloat mass; 69 | @property(nonatomic, assign) CGFloat stiffness; 70 | @property(nonatomic, assign) CGFloat damping; 71 | @property(nonatomic, assign) CGFloat velocity; 72 | 73 | @end 74 | 75 | @interface GMCRK4SpringArgsModel : GMCBaseArgsModel 76 | 77 | @property(nonatomic, assign) CGFloat tension; 78 | @property(nonatomic, assign) CGFloat friction; 79 | @property(nonatomic, assign) CGFloat velocity; 80 | 81 | @end 82 | 83 | @interface GMCCosineArgsModel : GMCBaseArgsModel 84 | 85 | @property(nonatomic, assign) CGFloat d; 86 | @property(nonatomic, assign) CGFloat c; 87 | 88 | @end 89 | 90 | 91 | @interface GMCModel (Internal) 92 | 93 | @property(nonatomic, strong) GMCBaseArgsModel *argsModel; 94 | 95 | + (GMCModel *)modelWithKeyPath:(NSString *)keyPath 96 | duration:(CFTimeInterval)duration 97 | delay:(CFTimeInterval)delay 98 | curveType:(GMCCurveType)curveType 99 | argsModel:(nullable GMCBaseArgsModel *)argsModel 100 | fromValue:(NSValue *)fromValue 101 | toValue:(NSValue *)toValue; 102 | 103 | @end 104 | 105 | NS_ASSUME_NONNULL_END 106 | -------------------------------------------------------------------------------- /iOS/GaiaMotionCurve/GMCModel+Internal.m: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022, Alibaba Group Holding Limited; 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #import "GMCModel+Internal.h" 16 | #import 17 | 18 | @implementation GMCBaseArgsModel 19 | @end 20 | 21 | @implementation GMCStandardArgsModel 22 | @end 23 | 24 | @implementation GMCAccelerateArgsModel 25 | @end 26 | 27 | @implementation GMCDecelerateArgsModel 28 | @end 29 | 30 | @implementation GMCAnticipateArgsModel 31 | @end 32 | 33 | @implementation GMCOvershootArgsModel 34 | @end 35 | 36 | @implementation GMCBounceArgsModel 37 | @end 38 | 39 | @implementation GMCDefaultSpringArgsModel 40 | @end 41 | 42 | @implementation GMCRK4SpringArgsModel 43 | @end 44 | 45 | @implementation GMCCosineArgsModel 46 | @end 47 | 48 | 49 | @implementation GMCModel (Internal) 50 | 51 | static NSString *kGMCModelArgsModelKey = @"kGMCModelArgsModelKey"; 52 | 53 | - (void)setArgsModel:(GMCBaseArgsModel *)argsModel { 54 | objc_setAssociatedObject(self, &kGMCModelArgsModelKey, argsModel, 55 | OBJC_ASSOCIATION_RETAIN); 56 | } 57 | 58 | - (GMCBaseArgsModel *)argsModel { 59 | return objc_getAssociatedObject(self, &kGMCModelArgsModelKey); 60 | } 61 | 62 | + (GMCModel *)modelWithKeyPath:(NSString *)keyPath 63 | duration:(CFTimeInterval)duration 64 | delay:(CFTimeInterval)delay 65 | curveType:(GMCCurveType)curveType 66 | argsModel:(nullable GMCBaseArgsModel *)argsModel 67 | fromValue:(NSValue *)fromValue 68 | toValue:(NSValue *)toValue { 69 | GMCModel *model = [GMCModel modelWithKeyPath:keyPath 70 | duration:duration 71 | delay:delay 72 | curveType:curveType 73 | fromValue:fromValue 74 | toValue:toValue]; 75 | model.argsModel = argsModel; 76 | return model; 77 | } 78 | 79 | @end 80 | -------------------------------------------------------------------------------- /iOS/GaiaMotionCurve/GMCModel.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022, Alibaba Group Holding Limited; 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | 16 | #import 17 | #import 18 | #import "GMCDefines.h" 19 | #import "NSValue+GMCCGFloat.h" 20 | #import "NSValue+GMCUIColor.h" 21 | 22 | NS_ASSUME_NONNULL_BEGIN 23 | 24 | @interface GMCModel : NSObject 25 | 26 | //default 0 27 | @property(nonatomic, assign) NSInteger repeatCount; 28 | 29 | //default NO 30 | @property(nonatomic, assign) BOOL autoReverse; 31 | 32 | //animation key path 33 | @property(nonatomic, strong) NSString *keyPath; 34 | 35 | //second 36 | @property(nonatomic, assign) CFTimeInterval duration; 37 | 38 | //second 39 | @property(nonatomic, assign) CFTimeInterval delay; 40 | 41 | //motion curve type 42 | @property(nonatomic, assign) GMCCurveType curveType; 43 | 44 | @property(nonatomic, strong) NSValue *fromValue; 45 | 46 | @property(nonatomic, strong) NSValue *toValue; 47 | 48 | 49 | + (GMCModel *)modelWithKeyPath:(NSString *)keyPath 50 | duration:(CFTimeInterval)duration 51 | delay:(CFTimeInterval)delay 52 | curveType:(GMCCurveType)curveType 53 | fromValue:(NSValue *)fromValue 54 | toValue:(NSValue *)toValue; 55 | 56 | 57 | + (GMCModel *)modelWithKeyPath:(NSString *)keyPath 58 | duration:(CFTimeInterval)duration 59 | delay:(CFTimeInterval)delay 60 | curveType:(GMCCurveType)curveType 61 | customArgs:(nullable NSDictionary *)customArgs 62 | fromValue:(NSValue *)fromValue 63 | toValue:(NSValue *)toValue; 64 | 65 | 66 | + (GMCModel *)modelWithKeyPath:(NSString *)keyPath 67 | duration:(CFTimeInterval)duration 68 | delay:(CFTimeInterval)delay 69 | repeatCount:(NSInteger)repeatCount 70 | autoReverse:(BOOL)autoReverse 71 | curveType:(GMCCurveType)curveType 72 | fromValue:(NSValue *)fromValue 73 | toValue:(NSValue *)toValue; 74 | 75 | 76 | + (GMCModel *)modelWithKeyPath:(NSString *)keyPath 77 | duration:(CFTimeInterval)duration 78 | delay:(CFTimeInterval)delay 79 | repeatCount:(NSInteger)repeatCount 80 | autoReverse:(BOOL)autoReverse 81 | curveType:(GMCCurveType)curveType 82 | customArgs:(nullable NSDictionary *)customArgs 83 | fromValue:(NSValue *)fromValue 84 | toValue:(NSValue *)toValue; 85 | 86 | @end 87 | 88 | NS_ASSUME_NONNULL_END 89 | -------------------------------------------------------------------------------- /iOS/GaiaMotionCurve/GMCModel.m: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022, Alibaba Group Holding Limited; 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | 16 | #import "GMCModel.h" 17 | #import "GMCModel+Internal.h" 18 | 19 | @implementation GMCModel 20 | 21 | + (GMCModel *)modelWithKeyPath:(NSString *)keyPath 22 | duration:(CFTimeInterval)duration 23 | delay:(CFTimeInterval)delay 24 | curveType:(GMCCurveType)curveType 25 | fromValue:(NSValue *)fromValue 26 | toValue:(NSValue *)toValue { 27 | return [GMCModel modelWithKeyPath:keyPath 28 | duration:duration 29 | delay:delay 30 | curveType:curveType 31 | customArgs:nil 32 | fromValue:fromValue 33 | toValue:toValue]; 34 | } 35 | 36 | + (GMCModel *)modelWithKeyPath:(NSString *)keyPath 37 | duration:(CFTimeInterval)duration 38 | delay:(CFTimeInterval)delay 39 | curveType:(GMCCurveType)curveType 40 | customArgs:(nullable NSDictionary *)customArgs 41 | fromValue:(NSValue *)fromValue 42 | toValue:(NSValue *)toValue { 43 | return [GMCModel modelWithKeyPath:keyPath 44 | duration:duration 45 | delay:delay 46 | repeatCount:0 47 | autoReverse:NO 48 | curveType:curveType 49 | customArgs:customArgs 50 | fromValue:fromValue 51 | toValue:toValue]; 52 | 53 | } 54 | 55 | 56 | + (GMCModel *)modelWithKeyPath:(NSString *)keyPath 57 | duration:(CFTimeInterval)duration 58 | delay:(CFTimeInterval)delay 59 | repeatCount:(NSInteger)repeatCount 60 | autoReverse:(BOOL)autoReverse 61 | curveType:(GMCCurveType)curveType 62 | fromValue:(NSValue *)fromValue 63 | toValue:(NSValue *)toValue { 64 | return [GMCModel modelWithKeyPath:keyPath 65 | duration:duration 66 | delay:delay 67 | repeatCount:repeatCount 68 | autoReverse:autoReverse 69 | curveType:curveType 70 | customArgs:nil 71 | fromValue:fromValue 72 | toValue:toValue]; 73 | } 74 | 75 | 76 | + (GMCModel *)modelWithKeyPath:(NSString *)keyPath 77 | duration:(CFTimeInterval)duration 78 | delay:(CFTimeInterval)delay 79 | repeatCount:(NSInteger)repeatCount 80 | autoReverse:(BOOL)autoReverse 81 | curveType:(GMCCurveType)curveType 82 | customArgs:(nullable NSDictionary *)customArgs 83 | fromValue:(NSValue *)fromValue 84 | toValue:(NSValue *)toValue { 85 | GMCModel *model = [[GMCModel alloc] init]; 86 | model.keyPath = keyPath; 87 | model.duration = duration; 88 | model.delay = delay; 89 | model.repeatCount = repeatCount; 90 | model.autoReverse = autoReverse; 91 | model.curveType = curveType; 92 | model.fromValue = fromValue; 93 | model.toValue = toValue; 94 | if (curveType == GMCCurveTypeCosine) { 95 | GMCCosineArgsModel *argsModel = [[GMCCosineArgsModel alloc] init]; 96 | argsModel.d = customArgs[@"d"] != nil ? [customArgs[@"d"] floatValue] : 1.0f; 97 | argsModel.c = customArgs[@"c"] != nil ? [customArgs[@"c"] floatValue] : 1.0f; 98 | model.argsModel = argsModel; 99 | } else if (curveType == GMCCurveTypeBounce) { 100 | GMCBounceArgsModel *argsModel = [[GMCBounceArgsModel alloc] init]; 101 | argsModel.v = customArgs[@"v"] != nil ? [customArgs[@"v"] floatValue] : 1.0f; 102 | argsModel.d = customArgs[@"d"] != nil ? [customArgs[@"d"] floatValue] : 1.0f; 103 | model.argsModel = argsModel; 104 | } else if (curveType == GMCCurveTypeAccelerate) { 105 | GMCAccelerateArgsModel *argsModel = [[GMCAccelerateArgsModel alloc] init]; 106 | argsModel.x1 = customArgs[@"x1"] != nil ? [customArgs[@"x1"] floatValue] : 0.4f; 107 | argsModel.y1 = customArgs[@"y1"] != nil ? [customArgs[@"y1"] floatValue] : 0.0f; 108 | argsModel.x2 = customArgs[@"x2"] != nil ? [customArgs[@"x2"] floatValue] : 1.0f; 109 | argsModel.y2 = customArgs[@"y2"] != nil ? [customArgs[@"y2"] floatValue] : 1.0f; 110 | model.argsModel = argsModel; 111 | } else if (curveType == GMCCurveTypeDecelerate) { 112 | GMCDecelerateArgsModel *argsModel = [[GMCDecelerateArgsModel alloc] init]; 113 | argsModel.x1 = customArgs[@"x1"] != nil ? [customArgs[@"x1"] floatValue] : 0.0f; 114 | argsModel.y1 = customArgs[@"y1"] != nil ? [customArgs[@"y1"] floatValue] : 0.0f; 115 | argsModel.x2 = customArgs[@"x2"] != nil ? [customArgs[@"x2"] floatValue] : 0.1f; 116 | argsModel.y2 = customArgs[@"y2"] != nil ? [customArgs[@"y2"] floatValue] : 1.0f; 117 | model.argsModel = argsModel; 118 | } else if (curveType == GMCCurveTypeStandard) { 119 | GMCStandardArgsModel *argsModel = [[GMCStandardArgsModel alloc] init]; 120 | argsModel.x1 = customArgs[@"x1"] != nil ? [customArgs[@"x1"] floatValue] : 0.4f; 121 | argsModel.y1 = customArgs[@"y1"] != nil ? [customArgs[@"y1"] floatValue] : 0.0f; 122 | argsModel.x2 = customArgs[@"x2"] != nil ? [customArgs[@"x2"] floatValue] : 0.1f; 123 | argsModel.y2 = customArgs[@"y2"] != nil ? [customArgs[@"y2"] floatValue] : 1.0f; 124 | model.argsModel = argsModel; 125 | } else if (curveType == GMCCurveTypeOvershoot) { 126 | GMCOvershootArgsModel *argsModel = [[GMCOvershootArgsModel alloc] init]; 127 | argsModel.d = customArgs[@"d"] != nil ? [customArgs[@"d"] floatValue] : 1.2f; 128 | argsModel.x1 = customArgs[@"x1"] != nil ? [customArgs[@"x1"] floatValue] : 0.33f; 129 | argsModel.y1 = customArgs[@"y1"] != nil ? [customArgs[@"y1"] floatValue] : 0.0f; 130 | argsModel.x2 = customArgs[@"x2"] != nil ? [customArgs[@"x2"] floatValue] : 0.3f; 131 | argsModel.y2 = customArgs[@"y2"] != nil ? [customArgs[@"y2"] floatValue] : 1.0f; 132 | argsModel.x3 = customArgs[@"x3"] != nil ? [customArgs[@"x3"] floatValue] : 0.33f; 133 | argsModel.y3 = customArgs[@"y3"] != nil ? [customArgs[@"y3"] floatValue] : 0.0f; 134 | argsModel.x4 = customArgs[@"x4"] != nil ? [customArgs[@"x4"] floatValue] : 0.5f; 135 | argsModel.y4 = customArgs[@"y4"] != nil ? [customArgs[@"y4"] floatValue] : 1.0f; 136 | model.argsModel = argsModel; 137 | } else if (curveType == GMCCurveTypeAnticipate) { 138 | GMCAnticipateArgsModel *argsModel = [[GMCAnticipateArgsModel alloc] init]; 139 | argsModel.d = customArgs[@"d"] != nil ? [customArgs[@"d"] floatValue] : 0.2f; 140 | argsModel.x1 = customArgs[@"x1"] != nil ? [customArgs[@"x1"] floatValue] : 0.33f; 141 | argsModel.y1 = customArgs[@"y1"] != nil ? [customArgs[@"y1"] floatValue] : 0.0f; 142 | argsModel.x2 = customArgs[@"x2"] != nil ? [customArgs[@"x2"] floatValue] : 0.67f; 143 | argsModel.y2 = customArgs[@"y2"] != nil ? [customArgs[@"y2"] floatValue] : 1.0f; 144 | argsModel.x3 = customArgs[@"x3"] != nil ? [customArgs[@"x3"] floatValue] : 0.33f; 145 | argsModel.y3 = customArgs[@"y3"] != nil ? [customArgs[@"y3"] floatValue] : 0.0f; 146 | argsModel.x4 = customArgs[@"x4"] != nil ? [customArgs[@"x4"] floatValue] : 0.2f; 147 | argsModel.y4 = customArgs[@"y4"] != nil ? [customArgs[@"y4"] floatValue] : 1.0f; 148 | model.argsModel = argsModel; 149 | } else if (curveType == GMCCurveTypeSpring) { 150 | if (customArgs[@"m"] != nil || customArgs[@"s"] != nil || customArgs[@"d"] != nil || customArgs[@"iv"] != nil) { 151 | GMCDefaultSpringArgsModel *argsModel = [[GMCDefaultSpringArgsModel alloc] init]; 152 | argsModel.mass = customArgs[@"m"] != nil ? [customArgs[@"m"] floatValue] : 0.7f; 153 | argsModel.stiffness = customArgs[@"s"] != nil ? [customArgs[@"s"] floatValue] : 380.0f; 154 | argsModel.damping = customArgs[@"d"] != nil ? [customArgs[@"d"] floatValue] : 10.0f; 155 | argsModel.velocity = customArgs[@"iv"] != nil ? [customArgs[@"iv"] floatValue] : -2.0f; 156 | model.argsModel = argsModel; 157 | } else { 158 | GMCRK4SpringArgsModel *argsModel = [[GMCRK4SpringArgsModel alloc] init]; 159 | argsModel.tension = customArgs[@"t"] != nil ? [customArgs[@"t"] floatValue] : 533.0f; 160 | argsModel.friction = customArgs[@"f"] != nil ? [customArgs[@"f"] floatValue] : 14.0f; 161 | argsModel.velocity = customArgs[@"v"] != nil ? [customArgs[@"v"] floatValue] : -2.0f; 162 | model.argsModel = argsModel; 163 | } 164 | } 165 | return model; 166 | } 167 | 168 | 169 | @end 170 | -------------------------------------------------------------------------------- /iOS/GaiaMotionCurve/GaiaMotionCurve.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022, Alibaba Group Holding Limited; 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #import 16 | 17 | //! Project version number for GaiaMotionCurve. 18 | FOUNDATION_EXPORT double GaiaMotionCurveVersionNumber; 19 | 20 | //! Project version string for GaiaMotionCurve. 21 | FOUNDATION_EXPORT const unsigned char GaiaMotionCurveVersionString[]; 22 | 23 | // In this header, you should import all the public headers of your framework using statements like #import 24 | 25 | 26 | #import 27 | #import 28 | #import 29 | #import 30 | #import 31 | #import 32 | #import -------------------------------------------------------------------------------- /iOS/GaiaMotionCurve/NSValue+GMCCGFloat.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022, Alibaba Group Holding Limited; 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #import 16 | #import 17 | 18 | NS_ASSUME_NONNULL_BEGIN 19 | 20 | @interface NSValue (GMCCGFloat) 21 | 22 | - (CGFloat)gmc_CGFloatValue; 23 | 24 | + (NSValue *)gmc_valueWithCGFloat:(CGFloat)floatValue; 25 | 26 | 27 | @end 28 | 29 | NS_ASSUME_NONNULL_END 30 | -------------------------------------------------------------------------------- /iOS/GaiaMotionCurve/NSValue+GMCCGFloat.m: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022, Alibaba Group Holding Limited; 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | 16 | #import "NSValue+GMCCGFloat.h" 17 | 18 | @implementation NSValue (GMCCGFloat) 19 | 20 | - (CGFloat)gmc_CGFloatValue { 21 | CGFloat floatValue; 22 | [self getValue:&floatValue]; 23 | return floatValue; 24 | } 25 | 26 | + (NSValue *)gmc_valueWithCGFloat:(CGFloat)floatValue { 27 | NSValue *returnValue = [NSValue valueWithBytes:&floatValue 28 | objCType:@encode(CGFloat)]; 29 | return returnValue; 30 | } 31 | 32 | 33 | @end 34 | -------------------------------------------------------------------------------- /iOS/GaiaMotionCurve/NSValue+GMCUIColor.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022, Alibaba Group Holding Limited; 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | 16 | #import 17 | #import 18 | 19 | @class UIColor; 20 | 21 | NS_ASSUME_NONNULL_BEGIN 22 | 23 | @interface NSValue (GMCUIColor) 24 | 25 | 26 | - (CGColorRef)gmc_CGColorValue; 27 | 28 | + (NSValue *)gmc_valueWithCGColor:(CGColorRef)color; 29 | 30 | @end 31 | 32 | NS_ASSUME_NONNULL_END 33 | -------------------------------------------------------------------------------- /iOS/GaiaMotionCurve/NSValue+GMCUIColor.m: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022, Alibaba Group Holding Limited; 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | 16 | #import "NSValue+GMCUIColor.h" 17 | 18 | @implementation NSValue (GMCUIColor) 19 | 20 | + (NSValue *)gmc_valueWithCGColor:(CGColorRef)color { 21 | return [NSValue valueWithBytes:&color objCType:@encode(CGColorRef)]; 22 | } 23 | 24 | - (CGColorRef)gmc_CGColorValue { 25 | CGColorRef color; 26 | [self getValue:&color]; 27 | return color; 28 | } 29 | 30 | @end 31 | -------------------------------------------------------------------------------- /iOS/GaiaMotionCurveTests/GaiaMotionCurveTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // GaiaMotionCurveTests.m 3 | // GaiaMotionCurveTests 4 | // 5 | // Created by 周荣慧 on 2022/1/4. 6 | // 7 | 8 | #import 9 | 10 | @interface GaiaMotionCurveTests : XCTestCase 11 | 12 | @end 13 | 14 | @implementation GaiaMotionCurveTests 15 | 16 | - (void)setUp { 17 | // Put setup code here. This method is called before the invocation of each test method in the class. 18 | } 19 | 20 | - (void)tearDown { 21 | // Put teardown code here. This method is called after the invocation of each test method in the class. 22 | } 23 | 24 | - (void)testExample { 25 | // This is an example of a functional test case. 26 | // Use XCTAssert and related functions to verify your tests produce the correct results. 27 | } 28 | 29 | - (void)testPerformanceExample { 30 | // This is an example of a performance test case. 31 | [self measureBlock:^{ 32 | // Put the code you want to measure the time of here. 33 | }]; 34 | } 35 | 36 | @end 37 | -------------------------------------------------------------------------------- /iOS/Podfile: -------------------------------------------------------------------------------- 1 | 2 | target 'GaiaMotionCurve' do 3 | platform :ios, '9.0' 4 | # Uncomment the next line if you're using Swift or would like to use dynamic frameworks 5 | # use_frameworks! 6 | 7 | end 8 | --------------------------------------------------------------------------------