commit 76a52b4dd8458b7244c9a08042da09215118d43a Author: 刘洪超 <943480861@qq.com> Date: Tue Aug 15 10:34:08 2023 +0800 海信大屏项目提交 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ebdd23d --- /dev/null +++ b/.gitignore @@ -0,0 +1,14 @@ +*.iml +.gradle +/local.properties +/.idea/caches +/.idea/libraries +/.idea/modules.xml +/.idea/workspace.xml +/.idea/navEditor.xml +/.idea/assetWizardSettings.xml +.DS_Store +/build +/captures +.externalNativeBuild +.cxx diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..3543521 --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..6e8ac24 --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,29 @@ +apply plugin: 'com.android.application' + +android { + compileSdkVersion 29 + buildToolsVersion "29.0.2" + defaultConfig { + applicationId "com.hisensehitachi.himitboard" + minSdkVersion 19 + targetSdkVersion 29 + versionCode 1 + versionName "1.0" + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + } + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } +} + +dependencies { + implementation fileTree(dir: 'libs', include: ['*.jar']) + implementation 'androidx.appcompat:appcompat:1.2.0' + implementation 'androidx.constraintlayout:constraintlayout:2.0.1' + testImplementation 'junit:junit:4.12' + androidTestImplementation 'androidx.test:runner:1.3.0' + androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0' +} diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..6e7ffa9 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile diff --git a/app/release/output.json b/app/release/output.json new file mode 100644 index 0000000..9f0c959 --- /dev/null +++ b/app/release/output.json @@ -0,0 +1 @@ +[{"outputType":{"type":"APK"},"apkInfo":{"type":"MAIN","splits":[],"versionCode":1,"versionName":"1.0","enabled":true,"outputFile":"app-release.apk","fullName":"release","baseName":"release"},"path":"app-release.apk","properties":{}}] \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..c3afd7c --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + diff --git a/app/src/main/assets/Fonts/FZLTCXHJW--GB1-0.TTF b/app/src/main/assets/Fonts/FZLTCXHJW--GB1-0.TTF new file mode 100644 index 0000000..7d09ff7 Binary files /dev/null and b/app/src/main/assets/Fonts/FZLTCXHJW--GB1-0.TTF differ diff --git a/app/src/main/assets/Fonts/FZLTCXHJW--GB1-1.TTF b/app/src/main/assets/Fonts/FZLTCXHJW--GB1-1.TTF new file mode 100644 index 0000000..cd19908 Binary files /dev/null and b/app/src/main/assets/Fonts/FZLTCXHJW--GB1-1.TTF differ diff --git a/app/src/main/assets/img/bk_00.jpg b/app/src/main/assets/img/bk_00.jpg new file mode 100644 index 0000000..124cb3b Binary files /dev/null and b/app/src/main/assets/img/bk_00.jpg differ diff --git a/app/src/main/assets/img/bk_01.jpg b/app/src/main/assets/img/bk_01.jpg new file mode 100644 index 0000000..93798ce Binary files /dev/null and b/app/src/main/assets/img/bk_01.jpg differ diff --git a/app/src/main/assets/img/bk_02.jpg b/app/src/main/assets/img/bk_02.jpg new file mode 100644 index 0000000..25da6f2 Binary files /dev/null and b/app/src/main/assets/img/bk_02.jpg differ diff --git a/app/src/main/assets/img/bk_03.jpg b/app/src/main/assets/img/bk_03.jpg new file mode 100644 index 0000000..decc48a Binary files /dev/null and b/app/src/main/assets/img/bk_03.jpg differ diff --git a/app/src/main/assets/img/bk_04.jpg b/app/src/main/assets/img/bk_04.jpg new file mode 100644 index 0000000..2a133e9 Binary files /dev/null and b/app/src/main/assets/img/bk_04.jpg differ diff --git a/app/src/main/assets/img/bk_05.jpg b/app/src/main/assets/img/bk_05.jpg new file mode 100644 index 0000000..8872340 Binary files /dev/null and b/app/src/main/assets/img/bk_05.jpg differ diff --git a/app/src/main/assets/img/bk_06.jpg b/app/src/main/assets/img/bk_06.jpg new file mode 100644 index 0000000..f30c87d Binary files /dev/null and b/app/src/main/assets/img/bk_06.jpg differ diff --git a/app/src/main/assets/img/bk_07.jpg b/app/src/main/assets/img/bk_07.jpg new file mode 100644 index 0000000..b886f76 Binary files /dev/null and b/app/src/main/assets/img/bk_07.jpg differ diff --git a/app/src/main/assets/img/bk_08.jpg b/app/src/main/assets/img/bk_08.jpg new file mode 100644 index 0000000..b886f76 Binary files /dev/null and b/app/src/main/assets/img/bk_08.jpg differ diff --git a/app/src/main/assets/img/bk_09.jpg b/app/src/main/assets/img/bk_09.jpg new file mode 100644 index 0000000..9d94ae5 Binary files /dev/null and b/app/src/main/assets/img/bk_09.jpg differ diff --git a/app/src/main/assets/img/bk_10.jpg b/app/src/main/assets/img/bk_10.jpg new file mode 100644 index 0000000..99f7f07 Binary files /dev/null and b/app/src/main/assets/img/bk_10.jpg differ diff --git a/app/src/main/assets/img/bk_11.jpg b/app/src/main/assets/img/bk_11.jpg new file mode 100644 index 0000000..ca88e3a Binary files /dev/null and b/app/src/main/assets/img/bk_11.jpg differ diff --git a/app/src/main/assets/img/bk_12.jpg b/app/src/main/assets/img/bk_12.jpg new file mode 100644 index 0000000..7d6ab76 Binary files /dev/null and b/app/src/main/assets/img/bk_12.jpg differ diff --git a/app/src/main/assets/img/bk_13.jpg b/app/src/main/assets/img/bk_13.jpg new file mode 100644 index 0000000..6d90e03 Binary files /dev/null and b/app/src/main/assets/img/bk_13.jpg differ diff --git a/app/src/main/assets/img/bk_14.jpg b/app/src/main/assets/img/bk_14.jpg new file mode 100644 index 0000000..a9e7927 Binary files /dev/null and b/app/src/main/assets/img/bk_14.jpg differ diff --git a/app/src/main/assets/img/bk_15.jpg b/app/src/main/assets/img/bk_15.jpg new file mode 100644 index 0000000..be6d0e2 Binary files /dev/null and b/app/src/main/assets/img/bk_15.jpg differ diff --git a/app/src/main/assets/img/bk_16.jpg b/app/src/main/assets/img/bk_16.jpg new file mode 100644 index 0000000..909bc44 Binary files /dev/null and b/app/src/main/assets/img/bk_16.jpg differ diff --git a/app/src/main/assets/img/bk_17.jpg b/app/src/main/assets/img/bk_17.jpg new file mode 100644 index 0000000..bd83d1c Binary files /dev/null and b/app/src/main/assets/img/bk_17.jpg differ diff --git a/app/src/main/assets/img/bk_18.jpg b/app/src/main/assets/img/bk_18.jpg new file mode 100644 index 0000000..41cc17b Binary files /dev/null and b/app/src/main/assets/img/bk_18.jpg differ diff --git a/app/src/main/assets/img/bk_19.jpg b/app/src/main/assets/img/bk_19.jpg new file mode 100644 index 0000000..9c451d5 Binary files /dev/null and b/app/src/main/assets/img/bk_19.jpg differ diff --git a/app/src/main/assets/img/bk_20.jpg b/app/src/main/assets/img/bk_20.jpg new file mode 100644 index 0000000..90bab6c Binary files /dev/null and b/app/src/main/assets/img/bk_20.jpg differ diff --git a/app/src/main/assets/img/bk_21.jpg b/app/src/main/assets/img/bk_21.jpg new file mode 100644 index 0000000..92cb860 Binary files /dev/null and b/app/src/main/assets/img/bk_21.jpg differ diff --git a/app/src/main/assets/img/bk_22.jpg b/app/src/main/assets/img/bk_22.jpg new file mode 100644 index 0000000..52efa7e Binary files /dev/null and b/app/src/main/assets/img/bk_22.jpg differ diff --git a/app/src/main/assets/img/bk_23.jpg b/app/src/main/assets/img/bk_23.jpg new file mode 100644 index 0000000..6c51b01 Binary files /dev/null and b/app/src/main/assets/img/bk_23.jpg differ diff --git a/app/src/main/assets/img/bk_24.jpg b/app/src/main/assets/img/bk_24.jpg new file mode 100644 index 0000000..50eacde Binary files /dev/null and b/app/src/main/assets/img/bk_24.jpg differ diff --git a/app/src/main/assets/img/bk_25.jpg b/app/src/main/assets/img/bk_25.jpg new file mode 100644 index 0000000..5e85ddd Binary files /dev/null and b/app/src/main/assets/img/bk_25.jpg differ diff --git a/app/src/main/assets/img/bk_26.jpg b/app/src/main/assets/img/bk_26.jpg new file mode 100644 index 0000000..597ef31 Binary files /dev/null and b/app/src/main/assets/img/bk_26.jpg differ diff --git a/app/src/main/assets/img/bk_27.jpg b/app/src/main/assets/img/bk_27.jpg new file mode 100644 index 0000000..a31474a Binary files /dev/null and b/app/src/main/assets/img/bk_27.jpg differ diff --git a/app/src/main/assets/img/bk_28.jpg b/app/src/main/assets/img/bk_28.jpg new file mode 100644 index 0000000..eb952c1 Binary files /dev/null and b/app/src/main/assets/img/bk_28.jpg differ diff --git a/app/src/main/assets/img/bk_29.jpg b/app/src/main/assets/img/bk_29.jpg new file mode 100644 index 0000000..c239be4 Binary files /dev/null and b/app/src/main/assets/img/bk_29.jpg differ diff --git a/app/src/main/assets/img/bk_30.jpg b/app/src/main/assets/img/bk_30.jpg new file mode 100644 index 0000000..a6a6906 Binary files /dev/null and b/app/src/main/assets/img/bk_30.jpg differ diff --git a/app/src/main/assets/img/bk_31.jpg b/app/src/main/assets/img/bk_31.jpg new file mode 100644 index 0000000..dce9587 Binary files /dev/null and b/app/src/main/assets/img/bk_31.jpg differ diff --git a/app/src/main/assets/img/bk_32.jpg b/app/src/main/assets/img/bk_32.jpg new file mode 100644 index 0000000..41cc17b Binary files /dev/null and b/app/src/main/assets/img/bk_32.jpg differ diff --git a/app/src/main/assets/img/bk_33.jpg b/app/src/main/assets/img/bk_33.jpg new file mode 100644 index 0000000..7fcb7e0 Binary files /dev/null and b/app/src/main/assets/img/bk_33.jpg differ diff --git a/app/src/main/assets/img/bk_49.jpg b/app/src/main/assets/img/bk_49.jpg new file mode 100644 index 0000000..41cc17b Binary files /dev/null and b/app/src/main/assets/img/bk_49.jpg differ diff --git a/app/src/main/assets/img/bk_53.jpg b/app/src/main/assets/img/bk_53.jpg new file mode 100644 index 0000000..fc89adc Binary files /dev/null and b/app/src/main/assets/img/bk_53.jpg differ diff --git a/app/src/main/assets/img/bk_54.jpg b/app/src/main/assets/img/bk_54.jpg new file mode 100644 index 0000000..ce18e21 Binary files /dev/null and b/app/src/main/assets/img/bk_54.jpg differ diff --git a/app/src/main/assets/img/bk_55.jpg b/app/src/main/assets/img/bk_55.jpg new file mode 100644 index 0000000..39f6a8b Binary files /dev/null and b/app/src/main/assets/img/bk_55.jpg differ diff --git a/app/src/main/assets/img/bk_56.jpg b/app/src/main/assets/img/bk_56.jpg new file mode 100644 index 0000000..f3a6d28 Binary files /dev/null and b/app/src/main/assets/img/bk_56.jpg differ diff --git a/app/src/main/assets/img/bk_57.jpg b/app/src/main/assets/img/bk_57.jpg new file mode 100644 index 0000000..41cc17b Binary files /dev/null and b/app/src/main/assets/img/bk_57.jpg differ diff --git a/app/src/main/assets/img/bk_58.jpg b/app/src/main/assets/img/bk_58.jpg new file mode 100644 index 0000000..41cc17b Binary files /dev/null and b/app/src/main/assets/img/bk_58.jpg differ diff --git a/app/src/main/assets/img/bk_99.jpg b/app/src/main/assets/img/bk_99.jpg new file mode 100644 index 0000000..4eed61e Binary files /dev/null and b/app/src/main/assets/img/bk_99.jpg differ diff --git a/app/src/main/assets/img/bottombar.png b/app/src/main/assets/img/bottombar.png new file mode 100644 index 0000000..acc22ee Binary files /dev/null and b/app/src/main/assets/img/bottombar.png differ diff --git a/app/src/main/assets/img/circle/bg-circle.png b/app/src/main/assets/img/circle/bg-circle.png new file mode 100644 index 0000000..20d166b Binary files /dev/null and b/app/src/main/assets/img/circle/bg-circle.png differ diff --git a/app/src/main/assets/img/circle/sm-circle.png b/app/src/main/assets/img/circle/sm-circle.png new file mode 100644 index 0000000..17ecac8 Binary files /dev/null and b/app/src/main/assets/img/circle/sm-circle.png differ diff --git a/app/src/main/assets/img/cloud/cloud_one.png b/app/src/main/assets/img/cloud/cloud_one.png new file mode 100644 index 0000000..57ee20d Binary files /dev/null and b/app/src/main/assets/img/cloud/cloud_one.png differ diff --git a/app/src/main/assets/img/cloud/cloud_three.png b/app/src/main/assets/img/cloud/cloud_three.png new file mode 100644 index 0000000..fedc05d Binary files /dev/null and b/app/src/main/assets/img/cloud/cloud_three.png differ diff --git a/app/src/main/assets/img/cloud/cloud_two.png b/app/src/main/assets/img/cloud/cloud_two.png new file mode 100644 index 0000000..16e18b3 Binary files /dev/null and b/app/src/main/assets/img/cloud/cloud_two.png differ diff --git a/app/src/main/assets/img/icon/iuOnOff_0.png b/app/src/main/assets/img/icon/iuOnOff_0.png new file mode 100644 index 0000000..6abcc2e Binary files /dev/null and b/app/src/main/assets/img/icon/iuOnOff_0.png differ diff --git a/app/src/main/assets/img/icon/iuOnOff_1.png b/app/src/main/assets/img/icon/iuOnOff_1.png new file mode 100644 index 0000000..cd83053 Binary files /dev/null and b/app/src/main/assets/img/icon/iuOnOff_1.png differ diff --git a/app/src/main/assets/img/icon/mode_0.png b/app/src/main/assets/img/icon/mode_0.png new file mode 100644 index 0000000..1c56102 Binary files /dev/null and b/app/src/main/assets/img/icon/mode_0.png differ diff --git a/app/src/main/assets/img/icon/mode_1.png b/app/src/main/assets/img/icon/mode_1.png new file mode 100644 index 0000000..4a009bd Binary files /dev/null and b/app/src/main/assets/img/icon/mode_1.png differ diff --git a/app/src/main/assets/img/icon/mode_10.png b/app/src/main/assets/img/icon/mode_10.png new file mode 100644 index 0000000..99863a4 Binary files /dev/null and b/app/src/main/assets/img/icon/mode_10.png differ diff --git a/app/src/main/assets/img/icon/mode_2.png b/app/src/main/assets/img/icon/mode_2.png new file mode 100644 index 0000000..4af4ff0 Binary files /dev/null and b/app/src/main/assets/img/icon/mode_2.png differ diff --git a/app/src/main/assets/img/icon/mode_3.png b/app/src/main/assets/img/icon/mode_3.png new file mode 100644 index 0000000..ec9c4e4 Binary files /dev/null and b/app/src/main/assets/img/icon/mode_3.png differ diff --git a/app/src/main/assets/img/icon/mode_4.png b/app/src/main/assets/img/icon/mode_4.png new file mode 100644 index 0000000..99863a4 Binary files /dev/null and b/app/src/main/assets/img/icon/mode_4.png differ diff --git a/app/src/main/assets/img/icon/mode_5.png b/app/src/main/assets/img/icon/mode_5.png new file mode 100644 index 0000000..4af4ff0 Binary files /dev/null and b/app/src/main/assets/img/icon/mode_5.png differ diff --git a/app/src/main/assets/img/icon/mode_6.png b/app/src/main/assets/img/icon/mode_6.png new file mode 100644 index 0000000..4af4ff0 Binary files /dev/null and b/app/src/main/assets/img/icon/mode_6.png differ diff --git a/app/src/main/assets/img/icon/mode_7.png b/app/src/main/assets/img/icon/mode_7.png new file mode 100644 index 0000000..4af4ff0 Binary files /dev/null and b/app/src/main/assets/img/icon/mode_7.png differ diff --git a/app/src/main/assets/img/icon/mode_8.png b/app/src/main/assets/img/icon/mode_8.png new file mode 100644 index 0000000..4af4ff0 Binary files /dev/null and b/app/src/main/assets/img/icon/mode_8.png differ diff --git a/app/src/main/assets/img/icon/mode_9.png b/app/src/main/assets/img/icon/mode_9.png new file mode 100644 index 0000000..4af4ff0 Binary files /dev/null and b/app/src/main/assets/img/icon/mode_9.png differ diff --git a/app/src/main/assets/img/icon/wind_0.png b/app/src/main/assets/img/icon/wind_0.png new file mode 100644 index 0000000..5f41d0a Binary files /dev/null and b/app/src/main/assets/img/icon/wind_0.png differ diff --git a/app/src/main/assets/img/icon/wind_1.png b/app/src/main/assets/img/icon/wind_1.png new file mode 100644 index 0000000..c521237 Binary files /dev/null and b/app/src/main/assets/img/icon/wind_1.png differ diff --git a/app/src/main/assets/img/icon/wind_2.png b/app/src/main/assets/img/icon/wind_2.png new file mode 100644 index 0000000..befbe10 Binary files /dev/null and b/app/src/main/assets/img/icon/wind_2.png differ diff --git a/app/src/main/assets/img/icon/wind_3.png b/app/src/main/assets/img/icon/wind_3.png new file mode 100644 index 0000000..4766107 Binary files /dev/null and b/app/src/main/assets/img/icon/wind_3.png differ diff --git a/app/src/main/assets/img/icon/wind_4.png b/app/src/main/assets/img/icon/wind_4.png new file mode 100644 index 0000000..c521237 Binary files /dev/null and b/app/src/main/assets/img/icon/wind_4.png differ diff --git a/app/src/main/assets/img/icon/wind_5.png b/app/src/main/assets/img/icon/wind_5.png new file mode 100644 index 0000000..de78146 Binary files /dev/null and b/app/src/main/assets/img/icon/wind_5.png differ diff --git a/app/src/main/assets/img/icon/wind_6.png b/app/src/main/assets/img/icon/wind_6.png new file mode 100644 index 0000000..4766107 Binary files /dev/null and b/app/src/main/assets/img/icon/wind_6.png differ diff --git a/app/src/main/assets/img/icon/wind_7.png b/app/src/main/assets/img/icon/wind_7.png new file mode 100644 index 0000000..4766107 Binary files /dev/null and b/app/src/main/assets/img/icon/wind_7.png differ diff --git a/app/src/main/assets/img/icon_00.png b/app/src/main/assets/img/icon_00.png new file mode 100644 index 0000000..880df66 Binary files /dev/null and b/app/src/main/assets/img/icon_00.png differ diff --git a/app/src/main/assets/img/icon_01.png b/app/src/main/assets/img/icon_01.png new file mode 100644 index 0000000..df47e50 Binary files /dev/null and b/app/src/main/assets/img/icon_01.png differ diff --git a/app/src/main/assets/img/icon_02.png b/app/src/main/assets/img/icon_02.png new file mode 100644 index 0000000..7efe5de Binary files /dev/null and b/app/src/main/assets/img/icon_02.png differ diff --git a/app/src/main/assets/img/icon_03.png b/app/src/main/assets/img/icon_03.png new file mode 100644 index 0000000..6c9636c Binary files /dev/null and b/app/src/main/assets/img/icon_03.png differ diff --git a/app/src/main/assets/img/icon_04.png b/app/src/main/assets/img/icon_04.png new file mode 100644 index 0000000..961d8ab Binary files /dev/null and b/app/src/main/assets/img/icon_04.png differ diff --git a/app/src/main/assets/img/icon_05.png b/app/src/main/assets/img/icon_05.png new file mode 100644 index 0000000..961d8ab Binary files /dev/null and b/app/src/main/assets/img/icon_05.png differ diff --git a/app/src/main/assets/img/icon_06.png b/app/src/main/assets/img/icon_06.png new file mode 100644 index 0000000..7089e0f Binary files /dev/null and b/app/src/main/assets/img/icon_06.png differ diff --git a/app/src/main/assets/img/icon_07.png b/app/src/main/assets/img/icon_07.png new file mode 100644 index 0000000..f0543fe Binary files /dev/null and b/app/src/main/assets/img/icon_07.png differ diff --git a/app/src/main/assets/img/icon_08.png b/app/src/main/assets/img/icon_08.png new file mode 100644 index 0000000..dc347c7 Binary files /dev/null and b/app/src/main/assets/img/icon_08.png differ diff --git a/app/src/main/assets/img/icon_09.png b/app/src/main/assets/img/icon_09.png new file mode 100644 index 0000000..b9f008b Binary files /dev/null and b/app/src/main/assets/img/icon_09.png differ diff --git a/app/src/main/assets/img/icon_10.png b/app/src/main/assets/img/icon_10.png new file mode 100644 index 0000000..6adb292 Binary files /dev/null and b/app/src/main/assets/img/icon_10.png differ diff --git a/app/src/main/assets/img/icon_11.png b/app/src/main/assets/img/icon_11.png new file mode 100644 index 0000000..6adb292 Binary files /dev/null and b/app/src/main/assets/img/icon_11.png differ diff --git a/app/src/main/assets/img/icon_12.png b/app/src/main/assets/img/icon_12.png new file mode 100644 index 0000000..6adb292 Binary files /dev/null and b/app/src/main/assets/img/icon_12.png differ diff --git a/app/src/main/assets/img/icon_13.png b/app/src/main/assets/img/icon_13.png new file mode 100644 index 0000000..482cdb8 Binary files /dev/null and b/app/src/main/assets/img/icon_13.png differ diff --git a/app/src/main/assets/img/icon_14.png b/app/src/main/assets/img/icon_14.png new file mode 100644 index 0000000..d237f2a Binary files /dev/null and b/app/src/main/assets/img/icon_14.png differ diff --git a/app/src/main/assets/img/icon_15.png b/app/src/main/assets/img/icon_15.png new file mode 100644 index 0000000..482cdb8 Binary files /dev/null and b/app/src/main/assets/img/icon_15.png differ diff --git a/app/src/main/assets/img/icon_16.png b/app/src/main/assets/img/icon_16.png new file mode 100644 index 0000000..5eac54d Binary files /dev/null and b/app/src/main/assets/img/icon_16.png differ diff --git a/app/src/main/assets/img/icon_17.png b/app/src/main/assets/img/icon_17.png new file mode 100644 index 0000000..5eac54d Binary files /dev/null and b/app/src/main/assets/img/icon_17.png differ diff --git a/app/src/main/assets/img/icon_18.png b/app/src/main/assets/img/icon_18.png new file mode 100644 index 0000000..8ad6e70 Binary files /dev/null and b/app/src/main/assets/img/icon_18.png differ diff --git a/app/src/main/assets/img/icon_19.png b/app/src/main/assets/img/icon_19.png new file mode 100644 index 0000000..6adb292 Binary files /dev/null and b/app/src/main/assets/img/icon_19.png differ diff --git a/app/src/main/assets/img/icon_20.png b/app/src/main/assets/img/icon_20.png new file mode 100644 index 0000000..7dbc630 Binary files /dev/null and b/app/src/main/assets/img/icon_20.png differ diff --git a/app/src/main/assets/img/icon_21.png b/app/src/main/assets/img/icon_21.png new file mode 100644 index 0000000..6c9636c Binary files /dev/null and b/app/src/main/assets/img/icon_21.png differ diff --git a/app/src/main/assets/img/icon_22.png b/app/src/main/assets/img/icon_22.png new file mode 100644 index 0000000..b9f008b Binary files /dev/null and b/app/src/main/assets/img/icon_22.png differ diff --git a/app/src/main/assets/img/icon_23.png b/app/src/main/assets/img/icon_23.png new file mode 100644 index 0000000..6adb292 Binary files /dev/null and b/app/src/main/assets/img/icon_23.png differ diff --git a/app/src/main/assets/img/icon_24.png b/app/src/main/assets/img/icon_24.png new file mode 100644 index 0000000..6adb292 Binary files /dev/null and b/app/src/main/assets/img/icon_24.png differ diff --git a/app/src/main/assets/img/icon_25.png b/app/src/main/assets/img/icon_25.png new file mode 100644 index 0000000..6adb292 Binary files /dev/null and b/app/src/main/assets/img/icon_25.png differ diff --git a/app/src/main/assets/img/icon_26.png b/app/src/main/assets/img/icon_26.png new file mode 100644 index 0000000..482cdb8 Binary files /dev/null and b/app/src/main/assets/img/icon_26.png differ diff --git a/app/src/main/assets/img/icon_27.png b/app/src/main/assets/img/icon_27.png new file mode 100644 index 0000000..5eac54d Binary files /dev/null and b/app/src/main/assets/img/icon_27.png differ diff --git a/app/src/main/assets/img/icon_28.png b/app/src/main/assets/img/icon_28.png new file mode 100644 index 0000000..5eac54d Binary files /dev/null and b/app/src/main/assets/img/icon_28.png differ diff --git a/app/src/main/assets/img/icon_29.png b/app/src/main/assets/img/icon_29.png new file mode 100644 index 0000000..3411fe0 Binary files /dev/null and b/app/src/main/assets/img/icon_29.png differ diff --git a/app/src/main/assets/img/icon_30.png b/app/src/main/assets/img/icon_30.png new file mode 100644 index 0000000..0628064 Binary files /dev/null and b/app/src/main/assets/img/icon_30.png differ diff --git a/app/src/main/assets/img/icon_31.png b/app/src/main/assets/img/icon_31.png new file mode 100644 index 0000000..4a00cd2 Binary files /dev/null and b/app/src/main/assets/img/icon_31.png differ diff --git a/app/src/main/assets/img/icon_32.png b/app/src/main/assets/img/icon_32.png new file mode 100644 index 0000000..8ad6e70 Binary files /dev/null and b/app/src/main/assets/img/icon_32.png differ diff --git a/app/src/main/assets/img/icon_33.png b/app/src/main/assets/img/icon_33.png new file mode 100644 index 0000000..482cdb8 Binary files /dev/null and b/app/src/main/assets/img/icon_33.png differ diff --git a/app/src/main/assets/img/icon_49.png b/app/src/main/assets/img/icon_49.png new file mode 100644 index 0000000..8ad6e70 Binary files /dev/null and b/app/src/main/assets/img/icon_49.png differ diff --git a/app/src/main/assets/img/icon_53.png b/app/src/main/assets/img/icon_53.png new file mode 100644 index 0000000..2e3faa6 Binary files /dev/null and b/app/src/main/assets/img/icon_53.png differ diff --git a/app/src/main/assets/img/icon_54.png b/app/src/main/assets/img/icon_54.png new file mode 100644 index 0000000..41f7ccd Binary files /dev/null and b/app/src/main/assets/img/icon_54.png differ diff --git a/app/src/main/assets/img/icon_55.png b/app/src/main/assets/img/icon_55.png new file mode 100644 index 0000000..e03f495 Binary files /dev/null and b/app/src/main/assets/img/icon_55.png differ diff --git a/app/src/main/assets/img/icon_56.png b/app/src/main/assets/img/icon_56.png new file mode 100644 index 0000000..75071d5 Binary files /dev/null and b/app/src/main/assets/img/icon_56.png differ diff --git a/app/src/main/assets/img/icon_57.png b/app/src/main/assets/img/icon_57.png new file mode 100644 index 0000000..8ad6e70 Binary files /dev/null and b/app/src/main/assets/img/icon_57.png differ diff --git a/app/src/main/assets/img/icon_58.png b/app/src/main/assets/img/icon_58.png new file mode 100644 index 0000000..8ad6e70 Binary files /dev/null and b/app/src/main/assets/img/icon_58.png differ diff --git a/app/src/main/assets/img/icon_99.png b/app/src/main/assets/img/icon_99.png new file mode 100644 index 0000000..880df66 Binary files /dev/null and b/app/src/main/assets/img/icon_99.png differ diff --git a/app/src/main/assets/img/layer_00.png b/app/src/main/assets/img/layer_00.png new file mode 100644 index 0000000..7f2a3ad Binary files /dev/null and b/app/src/main/assets/img/layer_00.png differ diff --git a/app/src/main/assets/img/layer_01.png b/app/src/main/assets/img/layer_01.png new file mode 100644 index 0000000..f7af866 Binary files /dev/null and b/app/src/main/assets/img/layer_01.png differ diff --git a/app/src/main/assets/img/layer_02.png b/app/src/main/assets/img/layer_02.png new file mode 100644 index 0000000..f7af866 Binary files /dev/null and b/app/src/main/assets/img/layer_02.png differ diff --git a/app/src/main/assets/img/layer_03.png b/app/src/main/assets/img/layer_03.png new file mode 100644 index 0000000..7d9608a Binary files /dev/null and b/app/src/main/assets/img/layer_03.png differ diff --git a/app/src/main/assets/img/layer_04.png b/app/src/main/assets/img/layer_04.png new file mode 100644 index 0000000..8d42b94 Binary files /dev/null and b/app/src/main/assets/img/layer_04.png differ diff --git a/app/src/main/assets/img/layer_05.png b/app/src/main/assets/img/layer_05.png new file mode 100644 index 0000000..8d42b94 Binary files /dev/null and b/app/src/main/assets/img/layer_05.png differ diff --git a/app/src/main/assets/img/layer_06.png b/app/src/main/assets/img/layer_06.png new file mode 100644 index 0000000..e6ed587 Binary files /dev/null and b/app/src/main/assets/img/layer_06.png differ diff --git a/app/src/main/assets/img/layer_07.png b/app/src/main/assets/img/layer_07.png new file mode 100644 index 0000000..7d9608a Binary files /dev/null and b/app/src/main/assets/img/layer_07.png differ diff --git a/app/src/main/assets/img/layer_08.png b/app/src/main/assets/img/layer_08.png new file mode 100644 index 0000000..7d9608a Binary files /dev/null and b/app/src/main/assets/img/layer_08.png differ diff --git a/app/src/main/assets/img/layer_09.png b/app/src/main/assets/img/layer_09.png new file mode 100644 index 0000000..7d9608a Binary files /dev/null and b/app/src/main/assets/img/layer_09.png differ diff --git a/app/src/main/assets/img/layer_10.png b/app/src/main/assets/img/layer_10.png new file mode 100644 index 0000000..7d9608a Binary files /dev/null and b/app/src/main/assets/img/layer_10.png differ diff --git a/app/src/main/assets/img/layer_11.png b/app/src/main/assets/img/layer_11.png new file mode 100644 index 0000000..7d9608a Binary files /dev/null and b/app/src/main/assets/img/layer_11.png differ diff --git a/app/src/main/assets/img/layer_12.png b/app/src/main/assets/img/layer_12.png new file mode 100644 index 0000000..7d9608a Binary files /dev/null and b/app/src/main/assets/img/layer_12.png differ diff --git a/app/src/main/assets/img/layer_13.png b/app/src/main/assets/img/layer_13.png new file mode 100644 index 0000000..e6ed587 Binary files /dev/null and b/app/src/main/assets/img/layer_13.png differ diff --git a/app/src/main/assets/img/layer_14.png b/app/src/main/assets/img/layer_14.png new file mode 100644 index 0000000..e6ed587 Binary files /dev/null and b/app/src/main/assets/img/layer_14.png differ diff --git a/app/src/main/assets/img/layer_15.png b/app/src/main/assets/img/layer_15.png new file mode 100644 index 0000000..e6ed587 Binary files /dev/null and b/app/src/main/assets/img/layer_15.png differ diff --git a/app/src/main/assets/img/layer_16.png b/app/src/main/assets/img/layer_16.png new file mode 100644 index 0000000..e6ed587 Binary files /dev/null and b/app/src/main/assets/img/layer_16.png differ diff --git a/app/src/main/assets/img/layer_17.png b/app/src/main/assets/img/layer_17.png new file mode 100644 index 0000000..e6ed587 Binary files /dev/null and b/app/src/main/assets/img/layer_17.png differ diff --git a/app/src/main/assets/img/layer_18.png b/app/src/main/assets/img/layer_18.png new file mode 100644 index 0000000..ce251cb Binary files /dev/null and b/app/src/main/assets/img/layer_18.png differ diff --git a/app/src/main/assets/img/layer_19.png b/app/src/main/assets/img/layer_19.png new file mode 100644 index 0000000..7d9608a Binary files /dev/null and b/app/src/main/assets/img/layer_19.png differ diff --git a/app/src/main/assets/img/layer_20.png b/app/src/main/assets/img/layer_20.png new file mode 100644 index 0000000..5425087 Binary files /dev/null and b/app/src/main/assets/img/layer_20.png differ diff --git a/app/src/main/assets/img/layer_21.png b/app/src/main/assets/img/layer_21.png new file mode 100644 index 0000000..7d9608a Binary files /dev/null and b/app/src/main/assets/img/layer_21.png differ diff --git a/app/src/main/assets/img/layer_22.png b/app/src/main/assets/img/layer_22.png new file mode 100644 index 0000000..7d9608a Binary files /dev/null and b/app/src/main/assets/img/layer_22.png differ diff --git a/app/src/main/assets/img/layer_23.png b/app/src/main/assets/img/layer_23.png new file mode 100644 index 0000000..7d9608a Binary files /dev/null and b/app/src/main/assets/img/layer_23.png differ diff --git a/app/src/main/assets/img/layer_24.png b/app/src/main/assets/img/layer_24.png new file mode 100644 index 0000000..7d9608a Binary files /dev/null and b/app/src/main/assets/img/layer_24.png differ diff --git a/app/src/main/assets/img/layer_25.png b/app/src/main/assets/img/layer_25.png new file mode 100644 index 0000000..7d9608a Binary files /dev/null and b/app/src/main/assets/img/layer_25.png differ diff --git a/app/src/main/assets/img/layer_26.png b/app/src/main/assets/img/layer_26.png new file mode 100644 index 0000000..e6ed587 Binary files /dev/null and b/app/src/main/assets/img/layer_26.png differ diff --git a/app/src/main/assets/img/layer_27.png b/app/src/main/assets/img/layer_27.png new file mode 100644 index 0000000..e6ed587 Binary files /dev/null and b/app/src/main/assets/img/layer_27.png differ diff --git a/app/src/main/assets/img/layer_28.png b/app/src/main/assets/img/layer_28.png new file mode 100644 index 0000000..e6ed587 Binary files /dev/null and b/app/src/main/assets/img/layer_28.png differ diff --git a/app/src/main/assets/img/layer_29.png b/app/src/main/assets/img/layer_29.png new file mode 100644 index 0000000..5425087 Binary files /dev/null and b/app/src/main/assets/img/layer_29.png differ diff --git a/app/src/main/assets/img/layer_30.png b/app/src/main/assets/img/layer_30.png new file mode 100644 index 0000000..5425087 Binary files /dev/null and b/app/src/main/assets/img/layer_30.png differ diff --git a/app/src/main/assets/img/layer_31.png b/app/src/main/assets/img/layer_31.png new file mode 100644 index 0000000..8e96782 Binary files /dev/null and b/app/src/main/assets/img/layer_31.png differ diff --git a/app/src/main/assets/img/layer_32.png b/app/src/main/assets/img/layer_32.png new file mode 100644 index 0000000..ce251cb Binary files /dev/null and b/app/src/main/assets/img/layer_32.png differ diff --git a/app/src/main/assets/img/layer_33.png b/app/src/main/assets/img/layer_33.png new file mode 100644 index 0000000..e6ed587 Binary files /dev/null and b/app/src/main/assets/img/layer_33.png differ diff --git a/app/src/main/assets/img/layer_49.png b/app/src/main/assets/img/layer_49.png new file mode 100644 index 0000000..ce251cb Binary files /dev/null and b/app/src/main/assets/img/layer_49.png differ diff --git a/app/src/main/assets/img/layer_53.png b/app/src/main/assets/img/layer_53.png new file mode 100644 index 0000000..f057480 Binary files /dev/null and b/app/src/main/assets/img/layer_53.png differ diff --git a/app/src/main/assets/img/layer_54.png b/app/src/main/assets/img/layer_54.png new file mode 100644 index 0000000..f057480 Binary files /dev/null and b/app/src/main/assets/img/layer_54.png differ diff --git a/app/src/main/assets/img/layer_55.png b/app/src/main/assets/img/layer_55.png new file mode 100644 index 0000000..f057480 Binary files /dev/null and b/app/src/main/assets/img/layer_55.png differ diff --git a/app/src/main/assets/img/layer_56.png b/app/src/main/assets/img/layer_56.png new file mode 100644 index 0000000..f057480 Binary files /dev/null and b/app/src/main/assets/img/layer_56.png differ diff --git a/app/src/main/assets/img/layer_57.png b/app/src/main/assets/img/layer_57.png new file mode 100644 index 0000000..ce251cb Binary files /dev/null and b/app/src/main/assets/img/layer_57.png differ diff --git a/app/src/main/assets/img/layer_58.png b/app/src/main/assets/img/layer_58.png new file mode 100644 index 0000000..ce251cb Binary files /dev/null and b/app/src/main/assets/img/layer_58.png differ diff --git a/app/src/main/assets/img/layer_99.png b/app/src/main/assets/img/layer_99.png new file mode 100644 index 0000000..7f2a3ad Binary files /dev/null and b/app/src/main/assets/img/layer_99.png differ diff --git a/app/src/main/assets/img/login/bk.jpg b/app/src/main/assets/img/login/bk.jpg new file mode 100644 index 0000000..73e0f94 Binary files /dev/null and b/app/src/main/assets/img/login/bk.jpg differ diff --git a/app/src/main/assets/img/login/button.png b/app/src/main/assets/img/login/button.png new file mode 100644 index 0000000..4a189f5 Binary files /dev/null and b/app/src/main/assets/img/login/button.png differ diff --git a/app/src/main/assets/img/login/checkbox-0.png b/app/src/main/assets/img/login/checkbox-0.png new file mode 100644 index 0000000..e6468ba Binary files /dev/null and b/app/src/main/assets/img/login/checkbox-0.png differ diff --git a/app/src/main/assets/img/login/checkbox-1.png b/app/src/main/assets/img/login/checkbox-1.png new file mode 100644 index 0000000..3e2dca3 Binary files /dev/null and b/app/src/main/assets/img/login/checkbox-1.png differ diff --git a/app/src/main/assets/img/login/help.png b/app/src/main/assets/img/login/help.png new file mode 100644 index 0000000..a3ffc94 Binary files /dev/null and b/app/src/main/assets/img/login/help.png differ diff --git a/app/src/main/assets/img/login/hikari.png b/app/src/main/assets/img/login/hikari.png new file mode 100644 index 0000000..9b97a8b Binary files /dev/null and b/app/src/main/assets/img/login/hikari.png differ diff --git a/app/src/main/assets/img/login/inputbox-bk.png b/app/src/main/assets/img/login/inputbox-bk.png new file mode 100644 index 0000000..6d18f4c Binary files /dev/null and b/app/src/main/assets/img/login/inputbox-bk.png differ diff --git a/app/src/main/assets/img/login/left.png b/app/src/main/assets/img/login/left.png new file mode 100644 index 0000000..74d5b39 Binary files /dev/null and b/app/src/main/assets/img/login/left.png differ diff --git a/app/src/main/assets/img/login/login-box.png b/app/src/main/assets/img/login/login-box.png new file mode 100644 index 0000000..771626f Binary files /dev/null and b/app/src/main/assets/img/login/login-box.png differ diff --git a/app/src/main/assets/img/login/logo.png b/app/src/main/assets/img/login/logo.png new file mode 100644 index 0000000..1f2858b Binary files /dev/null and b/app/src/main/assets/img/login/logo.png differ diff --git a/app/src/main/assets/img/login/password-bk.png b/app/src/main/assets/img/login/password-bk.png new file mode 100644 index 0000000..075b6c6 Binary files /dev/null and b/app/src/main/assets/img/login/password-bk.png differ diff --git a/app/src/main/assets/img/login/password.png b/app/src/main/assets/img/login/password.png new file mode 100644 index 0000000..7239282 Binary files /dev/null and b/app/src/main/assets/img/login/password.png differ diff --git a/app/src/main/assets/img/login/right.png b/app/src/main/assets/img/login/right.png new file mode 100644 index 0000000..4444d90 Binary files /dev/null and b/app/src/main/assets/img/login/right.png differ diff --git a/app/src/main/assets/img/login/user-bk.png b/app/src/main/assets/img/login/user-bk.png new file mode 100644 index 0000000..9ef5c9b Binary files /dev/null and b/app/src/main/assets/img/login/user-bk.png differ diff --git a/app/src/main/assets/img/login/user.png b/app/src/main/assets/img/login/user.png new file mode 100644 index 0000000..bd97a12 Binary files /dev/null and b/app/src/main/assets/img/login/user.png differ diff --git a/app/src/main/assets/img/mark/aqi_0.png b/app/src/main/assets/img/mark/aqi_0.png new file mode 100644 index 0000000..dd5bd79 Binary files /dev/null and b/app/src/main/assets/img/mark/aqi_0.png differ diff --git a/app/src/main/assets/img/mark/aqi_1.png b/app/src/main/assets/img/mark/aqi_1.png new file mode 100644 index 0000000..c325ec9 Binary files /dev/null and b/app/src/main/assets/img/mark/aqi_1.png differ diff --git a/app/src/main/assets/img/mark/aqi_2.png b/app/src/main/assets/img/mark/aqi_2.png new file mode 100644 index 0000000..b7f8424 Binary files /dev/null and b/app/src/main/assets/img/mark/aqi_2.png differ diff --git a/app/src/main/assets/img/mark/aqi_3.png b/app/src/main/assets/img/mark/aqi_3.png new file mode 100644 index 0000000..5a0a92a Binary files /dev/null and b/app/src/main/assets/img/mark/aqi_3.png differ diff --git a/app/src/main/assets/img/mark/aqi_4.png b/app/src/main/assets/img/mark/aqi_4.png new file mode 100644 index 0000000..ff0342f Binary files /dev/null and b/app/src/main/assets/img/mark/aqi_4.png differ diff --git a/app/src/main/assets/img/mark/aqi_5.png b/app/src/main/assets/img/mark/aqi_5.png new file mode 100644 index 0000000..eeebd2e Binary files /dev/null and b/app/src/main/assets/img/mark/aqi_5.png differ diff --git a/app/src/main/assets/img/mark/indoor.png b/app/src/main/assets/img/mark/indoor.png new file mode 100644 index 0000000..24182af Binary files /dev/null and b/app/src/main/assets/img/mark/indoor.png differ diff --git a/app/src/main/assets/img/mark/outdoor.png b/app/src/main/assets/img/mark/outdoor.png new file mode 100644 index 0000000..4249430 Binary files /dev/null and b/app/src/main/assets/img/mark/outdoor.png differ diff --git a/app/src/main/assets/img/menu/icon.png b/app/src/main/assets/img/menu/icon.png new file mode 100644 index 0000000..64e41b4 Binary files /dev/null and b/app/src/main/assets/img/menu/icon.png differ diff --git a/app/src/main/assets/img/menu/line.png b/app/src/main/assets/img/menu/line.png new file mode 100644 index 0000000..a9d116d Binary files /dev/null and b/app/src/main/assets/img/menu/line.png differ diff --git a/app/src/main/assets/img/menu/line_sel.png b/app/src/main/assets/img/menu/line_sel.png new file mode 100644 index 0000000..9d93c9e Binary files /dev/null and b/app/src/main/assets/img/menu/line_sel.png differ diff --git a/app/src/main/assets/img/menu/menu.png b/app/src/main/assets/img/menu/menu.png new file mode 100644 index 0000000..c3afa83 Binary files /dev/null and b/app/src/main/assets/img/menu/menu.png differ diff --git a/app/src/main/assets/img/menu/right.png b/app/src/main/assets/img/menu/right.png new file mode 100644 index 0000000..5663189 Binary files /dev/null and b/app/src/main/assets/img/menu/right.png differ diff --git a/app/src/main/assets/img/snow/sn.png b/app/src/main/assets/img/snow/sn.png new file mode 100644 index 0000000..dfd2f69 Binary files /dev/null and b/app/src/main/assets/img/snow/sn.png differ diff --git a/app/src/main/assets/js/XeZBab.js b/app/src/main/assets/js/XeZBab.js new file mode 100644 index 0000000..f8e89e4 --- /dev/null +++ b/app/src/main/assets/js/XeZBab.js @@ -0,0 +1,1758 @@ +const { + E, LN10, LN2, LOG10E, LOG2E, PI, SQRT1_2, SQRT2, + abs, acos, acosh, asin, asinh, atan, atan2, atanh, cbrt, ceil, clz32, + cosh, exp, expm1, floor, fround, hypot, imul, log, log10, log1p, log2, max, + min, pow, /* random, */ round, sign, sinh, sqrt, tan, tanh, trunc +} = Math; + +let _codepenIDRegex = /codepen\.io\/[^/]+\/(?:pen|debug|fullpage|fullembedgrid)\/([^?#]+)/; + +// Why not? +const ZERO = 0.0; +const ONE = 1.0; +const TWO = 2.0; +const THREE = 3.0; +const FOUR = 4.0; +const FIVE = 5.0; +const SIX = 6.0; +const SEVEN = 7.0; +const EIGHT = 8.0; +const NINE = 9.0; +const TEN = 10.0; +const ELEVEN = 11.0; +const TWELVE = 12.0; +const SIXTEEN = 16.0; +const THIRTY = 30.0; +const THIRTY_TWO = 32.0; +const SIXTY = 60.0; +const HUNDRED = 100.0; +const THOUSAND = 1000.0; + +const HALF = ONE / TWO; +const THIRD = ONE / THREE; +const TWO_THIRDS = THIRD * TWO; +const QUARTER = ONE / FOUR; +const THREE_QUARTER = QUARTER * THREE; +const FIFTH = ONE / FIVE; +const SIXTH = ONE / SIX; +const SEVENTH = ONE / SEVEN; +const EIGHTH = ONE / EIGHT; +const TWELFTH = ONE / TWELVE; +const SIXTEENTH = ONE / SIXTEEN; +const ONE_THIRTIETH = ONE / THIRTY; +const THIRTY_SECONDTH = ONE / THIRTY_TWO; +const SIXTIETH = ONE / SIXTY; + +const TENTH = 1e-1; +const HUNDREDTH = 1e-2; +const THOUSANDTH = 1e-3; +const TEN_THOUSANDTH = 1e-4; +const HUNDRED_THOUSANDTH = 1e-5; +const MILLIONTH = 1e-6; +const TEN_MILLIONTH = 1e-7; +const HUNDRED_MILLIONTH = 1e-8; +const BILLIONTH = 1e-9; +const TEN_BILLIONTH = 1e-10; +const HUNDRED_BILLIONTH = 1e-11; + +const HALF_PI = PI * HALF; +const THIRD_PI = PI * THIRD; +const THREE_QUARTER_PI = PI * THREE_QUARTER; +const QUARTER_PI = PI * QUARTER; +const FIFTH_PI = PI * FIFTH; +const SIXTH_PI = PI * SIXTH; +const SEVENTH_PI = PI * SEVENTH; +const EIGHTH_PI = PI * EIGHTH; +const TWELFTH_PI = PI * TWELFTH; +const SIXTEENTH_PI = PI * SIXTEENTH; +const THIRTY_SECONDTH_PI = PI * THIRTY_SECONDTH; +const TAU = PI * TWO; +const TWO_TAU = TAU * TWO; +const HALF_TAU = PI; +const THIRD_TAU = TAU * THIRD; +const QUARTER_TAU = HALF_PI; +const FIFTH_TAU = TAU * FIFTH; +const SIXTH_TAU = THIRD_PI; +const EIGHTH_TAU = QUARTER_PI; +const TWELFTH_TAU = SIXTH_PI; +const SIXTEENTH_TAU = EIGHTH_PI; +const THIRTY_SECONDTH_TAU = SIXTEENTH_PI; + +const SQRT_3 = sqrt(THREE); +const SQRT_4 = sqrt(FOUR); +const SQRT_5 = sqrt(FIVE); + +const PHI = (1 + sqrt(5)) * 0.5; +const GOLDEN_ANGLE = 1 / (PHI * PHI); + +const COLOR_BLACK = hsl(0, 0, 0); +const COLOR_WHITE = hsl(0, 0, 100); +const COLOR_RED = hsl(0, 100, 50); +const COLOR_ORANGE = hsl(30, 100, 50); +const COLOR_YELLOW = hsl(60, 100, 50); +const COLOR_GREEN = hsl(120, 100, 50); +const COLOR_CYAN = hsl(180, 100, 50); +const COLOR_BLUE = hsl(240, 100, 50); +const COLOR_PURPLE = hsl(280, 100, 50); +const COLOR_MAGENTA = hsl(300, 100, 50); + +const TEXTALIGN_LEFT = 'left'; +const TEXTALIGN_CENTER = 'center'; +const TEXTALIGN_RIGHT = 'right'; +const TEXTBASELINE_TOP = 'top'; +const TEXTBASELINE_MIDDLE = 'middle'; +const TEXTBASELINE_BOTTOM = 'bottom'; + +let _defaulCanvasOptions = { + autoClear: false, + autoCompensate: true, + autoPushPop: false, + canvas: true, + centered: false, + desynchronized: false, + drawAndStop: false, + width: null, + height: null + }; +let _canvasOptions = {}; +let canvas;// = document.getElementById('canvas'); +// if(canvas === null) { +// canvas = document.createElement('canvas'); +// canvas.id = 'canvas'; +// //document.body.appendChild(canvas); +// $(".main").prepend(canvas); +// } +let ctx ; +//canvas.getContext('2d', { +// desynchronized: window.canvasOptions && window.canvasOptions.desynchronized !== undefined ? +// window.canvasOptions.desynchronized : _defaulCanvasOptions.desynchronized +// // preserveDrawingBuffer: true // WebGL +// }); +var _originalCtx = ctx; +let _anim, _lastCanvasTime, canvasFrameRate, frameCount, width, height, width_half, height_half, width_quarter, height_quarter; +let _canvasCurrentlyCentered = false; +let mouseUpdate = -Infinity, mouseIn = false, mouseDown = false, mouseMove = null, mousePos = null, mousePosPrev = null; +function initsnow(){ + canvas = document.getElementById('canvas'); + if(canvas === null) { + canvas = document.createElement('canvas'); + canvas.id = 'canvas'; + canvas.setAttribute("style", "z-index:-2; width:1920px; height:1080px;"); + //document.body.appendChild(canvas); + var mainDiv = document.getElementById('mainDiv'); + mainDiv.appendChild(canvas); + } + ctx = canvas.getContext('2d', { + desynchronized: window.canvasOptions && window.canvasOptions.desynchronized !== undefined ? + window.canvasOptions.desynchronized : _defaulCanvasOptions.desynchronized + // preserveDrawingBuffer: true // WebGL + }); + _originalCtx = ctx; + + +// canvas.addEventListener('mouseenter', e => (updateMouse(e), mouseIn = true)); +// canvas.addEventListener('mouseleave', e => (updateMouse(e), mouseIn = false, mouseDown = false)); +// canvas.addEventListener('mousemove', e => (updateMouse(e), mouseIn = true, mouseMove = e.timeStamp)); +// canvas.addEventListener('mousedown', e => (updateMouse(e), mouseIn = true, mouseDown = true)); +// canvas.addEventListener('mouseup', e => (updateMouse(e), mouseDown = false)); +// canvas.addEventListener('touchstart', e => (updateMouse(e), mouseIn = true)); +// canvas.addEventListener('touchend', e => (updateMouse(e), mouseIn = false, mouseDown = false)); +// canvas.addEventListener('touchcancel', e => (updateMouse(e), mouseIn = false, mouseDown = false)); +// canvas.addEventListener('touchmove', e => (updateMouse(e), mouseIn = true)); +// window.removeEventListener('resize', _resizeCanvas); + +// window.addEventListener('resize', _resizeCanvas); +// window.addEventListener('load', () => { +// mousePos = createVector(); +// mousePosPrev = createVector(); +// Object.assign( +// _canvasOptions, +// _defaulCanvasOptions, +// 'canvasOptions' in window ? window.canvasOptions : {} +// ); +// if(_canvasOptions.canvas === false) { +// document.body.removeChild(canvas); +// } +// _resizeCanvas(); +// if('setup' in window) { +// //window.setup(); +// } +// frameCount = 0; +// _anim = requestAnimationFrame(_draw); +// }); + + + mousePos = createVector(); + mousePosPrev = createVector(); + Object.assign( + _canvasOptions, + _defaulCanvasOptions, + 'canvasOptions' in window ? window.canvasOptions : {} + ); + // if(_canvasOptions.canvas === false) { + // document.body.removeChild(canvas); + // } + _resizeCanvas(); + if('setup' in window) { + //window.setup(); + } + frameCount = 0; + _anim = requestAnimationFrame(_draw); +} + +function updateMouse(e) { // Modified from p5.js + if(e && !e.clientX) { + e = e.touches ? e.touches[0] : (e.changedTouches ? e.changedTouches[0] : e); + } + mouseUpdate = e.timeStamp === undefined ? performance.now() : e.timeStamp; + let rect = canvas.getBoundingClientRect(); + let sx = canvas.scrollWidth / width; + let sy = canvas.scrollHeight / height; + let x = (e.clientX - rect.left) / sx; + let y = (e.clientY - rect.top) / sy; + if(x < 0) x = 0; + else if(x > width) x = width; + if(y < 0) y = 0; + else if(y > height) y = height; + if(mousePos) { + mousePosPrev.set(mousePos); + mousePos.set(x, y); + } + // return { x, y, winX: e.clientX, winY: e.clientY, id: e.identifier }; +} + +// let mouseIn = false, mouseDown = false, mouseMove = null, mousePos = { x: 0, y: 0 }; +// function updateMouse(e) { +// if(e && !e.clientX) { +// e = e.touches ? e.touches[0] : (e.changedTouches ? e.changedTouches[0] : e); +// } +// const { innerWidth: width, innerHeight: height } = window; +// uniforms.mouse.value.set(e.clientX / width, 1 - e.clientY / height); +// } + +// [ +// [ 'mouseenter', e => mouseIn = true ], +// [ 'mouseleave', e => (mouseIn = false, mouseDown = false) ], +// [ 'mousemove', e => (mouseIn = true, mouseMove = e.timeStamp) ], +// [ 'mousedown', e => (mouseIn = true, mouseDown = true) ], +// [ 'mouseup', e => mouseDown = false ], +// [ 'touchstart', e => mouseIn = true ], +// [ 'touchend', e => (mouseIn = false, mouseDown = false) ], +// [ 'touchcancel', e => (mouseIn = false, mouseDown = false) ], +// [ 'touchmove', e => (mouseIn = true, mouseMove = e.timeStamp) ] +// ].forEach(([ eventName, cb ]) => document.body.addEventListener(eventName, e => { +// updateMouse(e); +// cb(e); +// })); + + + +function _draw(timestamp) { + frameCount++; + canvasFrameRate = 1000.0 / (timestamp - _lastCanvasTime); + _lastCanvasTime = timestamp; + ctx = _originalCtx; + _canvasOptions.autoClear && clear(null); + if(_canvasOptions.autoPushPop) { + push(); + _canvasOptions.centered && (_canvasCurrentlyCentered = true) && translateCenter(); + _canvasOptions.autoCompensate && compensateCanvas(); + } + 'draw' in window && window.draw(timestamp); + _canvasOptions.autoPushPop && pop(); + _canvasCurrentlyCentered = false; + if(_canvasOptions.drawAndStop) { + return; + } + _anim = requestAnimationFrame(_draw); +} + +function _resizeCanvas(specificCanvas) { + width = canvas.width = _canvasOptions.width !== null ? _canvasOptions.width : window.innerWidth; + height = canvas.height = _canvasOptions.height !== null ? _canvasOptions.height : window.innerHeight; + width_quarter = (width_half = width * HALF) * HALF; + height_quarter = (height_half = height * HALF) * HALF; + ctx.fillStyle = 'hsl(0, 0%, 100%)'; + ctx.strokeStyle = 'hsl(0, 0%, 100%)'; + if('onResize' in window) { + window.onResize(); + } +} + +function clear(x, y, w, h) { + if(x !== undefined && typeof x === 'number') { + ctx.clearRect(x, y, w, h); + } + else if(_canvasOptions.centered && _canvasCurrentlyCentered/* && x !== null */) { + ctx.clearRect(-width_half, -height_half, width, height); + } + else { + ctx.clearRect(0, 0, width, height); + } +} + +function background(a) { + push(); + if(typeof a !== 'number') { + fillStyle(a); + } + if(_canvasOptions.centered && _canvasCurrentlyCentered) { + ctx.fillRect(-width_half, -height_half, width, height); + } + else { + ctx.fillRect(0, 0, width, height); + } + pop(); +} + +function globalAlpha(alpha = ctx.globalAlpha) { + return ctx.globalAlpha = alpha; +} + +function fillStyle(...args) { + if(args.length === 1) { + let a = args[0]; + if(typeof a === 'string' || a instanceof CanvasGradient || a instanceof CanvasPattern) { + ctx.fillStyle = args[0]; + } + } + return ctx.fillStyle; +} + +function lineWidth(w) { + if(typeof w === 'number') { + ctx.lineWidth = w; + } + return ctx.lineWidth; +} + +// "butt" || "round" || "square"; +function lineCap(style = 'butt') { + ctx.lineCap = style; +} + +// "bevel" || "round" || "miter" +function lineJoin(style) { + ctx.lineJoin = style; +} + +function miterLimit(value = 10) { + ctx.miterLimit = value; +} + +function strokeStyle(...args) { + if(args.length === 1) { + let a = args[0]; + if(typeof a === 'string' || a instanceof CanvasGradient) { + ctx.strokeStyle = a; + } + } + else if(args.length === 2) { + strokeStyle(args[0]); + lineWidth(args[1]); + } + return ctx.strokeStyle; +} + +function lerpRGB(...args) { + let r1 = 255; + let b1 = 255; + let g1 = 255; + let a1 = 1; + let r2 = 0; + let g2 = 0; + let b2 = 0; + let a2 = 1; + let t = 0.5; + if(args.length === 3) { + if(Array.isArray(args[0]) && Array.isArray(args[1])) { + return lerpRGB(...args[0], ...args[1], args[2]); + } + [ + { r: r1 = 255, b: b1 = 255, g: g1 = 255, a: a1 = 1 }, + { r: r2 = 0, b: b2 = 0, g: g2 = 0, a: a2 = 1 }, + t + ] = args; + } + else if(args.length === 7) { + [ + r1, g1, b1, + r2, g2, b2, + t + ] = args; + } + else if(args.length === 9) { + [ + r1, g1, b1, a1, + r2, g2, b2, a2, + t + ] = args; + } + else if(args.length === 2 && Array.isArray(args[0])) { + if(args[0].length === 2) { + return lerpRGB(...args[0], args[1]); + } + // TODO: Allow (possibly weighted) lerping between n-count RGBs at specified positions + } + else { + return { r: 127.5, g: 127.5, b: 127.5, a: 1 }; + } + let r = lerp(r1, r2, t); + let g = lerp(g1, g2, t); + let b = lerp(b1, b2, t); + let a = lerp(a1, a2, t); + return { r, g, b, a }; +} + +function hsl(hue, sat, light, alpha = 1) { + if(typeof hue !== 'number') { + if(Array.isArray(hue)) { + [ hue, sat, light, alpha = alpha ] = hue; + } + else if('h' in hue) { + ({ h: hue, s: sat, l: light, a: alpha = alpha } = hue); + } + } + hue = hue % 360; + if(hue < 0) { + hue += 360; + } + return `hsl(${hue} ${sat}% ${light}% / ${alpha})`; +} + +function parseHSL(input) { + if(typeof input !== 'string') { + return input; + } + let result = input.match(/hsla?\(([\d.]+)\s*,?\s*([\d.]+)%\s*,?\s*([\d.]+)%\s*[/,]?\s*([\d.]*)?\)/); + if(result) { + let [ i, h, s, l, a ] = result; + return { input, h, s, l, a }; + } + return null; +} + +function setHueHSL(input, val) { + if(val === undefined) return input; + let p = parseHSL(input); + p.h = val; + return hsl(p); +} + +function rotateHSL(input, amt = 90) { + if(amt === 0) return input; + let p = parseHSL(input); + p.h += amt; + return hsl(p); +} + +function saturateHSL(input, amt = 0.1) { + if(amt === 0) return input; + let p = parseHSL(input); + p.s *= 1 + amt; + return hsl(p); +} + +function lightenHSL(input, amt = 0.1) { + if(amt === 0) return input; + let p = parseHSL(input); + p.l *= 1 + amt; + return hsl(p); +} + +function rgb(r = 255, g = 255, b = 255, a = 1) { + if(typeof r !== 'number' && 'r' in r) { + ({ r = 255, g = 255, b = 255, a = 1 } = r); + } + return `rgba(${r}, ${g}, ${b}, ${a})`; +} + +function fill(...args) { + if(args.length) { + fillStyle(...args); + } + ctx.fill(); +} + +function stroke(...args) { + if(args.length) { + strokeStyle(...args); + } + ctx.stroke(); +} + +function clip() { + ctx.clip(); +} + +function createLinearGradient(x1 = -100, y1 = -100, x2 = 100, y2 = 100) { +// if(typeof x1 !== 'number') { +// if('x' in x1) { + +// } +// } + return ctx.createLinearGradient(x1, y1, x2, y2); +} + +function createRadialGradient(x1 = 0, y1 = 0, r1 = 0, x2 = 0, y2 = 0, r2 = 200) { + return ctx.createRadialGradient(x1, y1, r1, x2, y2, r2); +} + +function drawImage(img, x = 0, y = 0, ...args) { + ctx.drawImage(img, x, y, ...args); +} + +function strokeText(str = 'Hello world', x = 0, y = 0) { + ctx.strokeText(str, x, y); +} + +function fillText(str = 'Hello world', x = 0, y = 0) { + ctx.fillText(str, x, y); +} + +function strokeFillText(str = 'Hello world', x = 0, y = 0) { + strokeText(str, x, y); + fillText(str, x, y); +} + +function fillStrokeText(str = 'Hello world', x = 0, y = 0) { + fillText(str, x, y); + strokeText(str, x, y); +} + +function measureText(...args) { + return ctx.measureText(...args); +} + +// ctx.textAlign = "left" || "right" || "center" || "start" || "end"; +function textAlign(str = 'left') { + ctx.textAlign = str; +} + +// ctx.textBaseline = "top" || "hanging" || "middle" || "alphabetic" || "ideographic" || "bottom"; +function textBaseline(str = 'left') { + if(str === 'center') str = 'middle'; + ctx.textBaseline = str; +} + +function push() { + ctx.save(); +} + +function pop() { + ctx.restore(); +} + +function resetTransform() { + ctx.resetTransform(); +} + +function translate(x = 0, y = 0) { + if(typeof x === 'number') { + ctx.translate(x, y); + } + else if('x' in x) { + ctx.translate(x.x, x.y); + } +} + +function translateCenter(x = 0, y = 0) { + ctx.translate(width_half + x, height_half + y); +} + +function rotate(rot, offsetX, offsetY) { + rot = rot % TAU; + if(offsetX === undefined) { + ctx.rotate(rot); + } + else if(typeof offsetX !== 'number') { + if('x' in offsetX) { + ctx.translate(offsetX.x, offsetX.y); + ctx.rotate(rot); + ctx.translate(-offsetX.x, -offsetX.y); + } + } + else { + ctx.translate(offsetX, offsetY); + ctx.rotate(rot); + ctx.translate(-offsetX, -offsetY); + } +} + +function scale(x = 1, y = x) { + ctx.scale(x, y); +} + +function shearX(rad) { + ctx.transform(1, 0, tan(rad), 1, 0, 0); +} + +function shearY(rad) { + ctx.transform(1, tan(rad), 0, 1, 0, 0); +} + +function compensateCanvas() { + let offX = 0; + let offY = 0; + if(width % 2) offX += 0.5; + if(height % 2) offY += 0.5; + if(offX || offY) { + translate(offX, offY); + } +} + +const compOper = { + default: 'source-over', sourceOver: 'source-over', sourceIn: 'source-in', + sourceOut: 'source-out', sourceAtop: 'source-atop', destinationOver: 'destination-over', + destinationIn: 'destination-in', destinationOut: 'destination-out', destinationAtop: 'destination-atop', + lighter: 'lighter', copy: 'copy', xor: 'xor', + multiply: 'multiply', screen: 'screen', overlay: 'overlay', + darken: 'darken', lighten: 'lighten', colorDodge: 'color-dodge', + colorBurn: 'color-burn', hardLight: 'hard-light', softLight: 'soft-light', + difference: 'difference', exclusion: 'exclusion', hue: 'hue', + saturation: 'saturation', color: 'color', luminosity: 'luminosity', + source: { + over: 'source-over', in: 'source-in', out: 'source-out', + atop: 'source-atop' + }, + destination: { + over: 'destination-over', in: 'destination-in', out: 'destination-out', + atop: 'destination-atop' + }, + light: { + hard: 'hard-light', soft: 'soft-light' + } + }; + + +function compositeOperation(type = compOper.default) { // https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/globalCompositeOperation + ctx.globalCompositeOperation = type; +} + +// const filters = [ +// [ 'url', [ 'url' ] ], +// [ 'blur', [ 'length' ] ], +// [ 'brightness', [ 'percentage' ] ], +// [ 'contrast', [ 'percentage' ] ] +// ]; + +function filter(filterFuncs = 'none') { + ctx.filter = filterFuncs; +} + +function beginPath() { + ctx.beginPath(); +} + +function moveTo(x, y) { + if(typeof x === 'number') { + ctx.moveTo(x, y); + } + else if('x' in x) { + ctx.moveTo(x.x, x.y); + } +} + +function lineTo(x, y) { + if(typeof x === 'number') { + ctx.lineTo(x, y); + } + else if('x' in x) { + ctx.lineTo(x.x, x.y); + } +} + +function quadraticCurveTo(cpX, cpY, x, y) { + // ctx.quadraticCurveTo(cpX, cpY, x, y); + let a = []; + let b = []; + if(typeof cpX === 'number') { + a = [ cpX, cpY ]; + if(typeof x === 'number') { + b = [ x, y ]; + } + else if('x' in x) { + b = x.xy; + } + } + else if('x' in cpX) { + a = cpX.xy; + if(typeof cpY === 'number') { + b = [ cpY, x ]; + } + else if('x' in cpY) { + b = cpY.xy; + } + } + ctx.quadraticCurveTo(a[0], a[1], b[0], b[1]); +} + +function bezierCurveTo(cp1X, cp1Y, cp2X, cp2Y, x, y) { + let a = []; + let b = []; + let c = []; + if(typeof cp1X === 'number') { + a = [ cp1X, cp1Y ]; + if(typeof cp2X === 'number') { + b = [ cp2X, cp2Y ]; + if(typeof x === 'number') { + c = [ x, y ]; + } + else if('x' in x) { + c = x.xy; + } + } + else if('x' in cp2X) { + b = cp2X.xy; + if(typeof cp2Y === 'number') { + c = [ cp2Y, x ]; + } + else if('x' in cp2Y) { + c = cp2Y.xy; + } + } + } + else if('x' in cp1X) { + a = cp1X.xy; + if(typeof cp1Y === 'number') { + b = [ cp1Y, cp2X ]; + if(typeof cp2Y === 'number') { + c = [ cp2Y, x ]; + } + else if('x' in cp2Y) { + c = cp2Y.xy; + } + } + else if('x' in cp1Y) { + b = cp1Y.xy; + if(typeof cp2X === 'number') { + c = [ cp2X, cp2Y ]; + } + else if('x' in cp2X) { + c = cp2X.xy; + } + } + } + ctx.bezierCurveTo(a[0], a[1], b[0], b[1], c[0], c[1]); +} + +function closePath() { + ctx.closePath(); +} + +function point(x = 0, y = 0, r = 0, g = 0, b = 0, a = 255, doPut_ = true) { + // let imgData = ctx.createImageData(1, 1); + // imgData.data[0] = r; + // imgData.data[1] = g; + // imgData.data[2] = b; + // imgData.data[3] = a; + // if(doPut_) { + // ctx.putImageData(imgData, x, y); + // } + // return imgData; +} + +function line(x = 0, y = 0, x_ = 0, y_ = 0) { + if(typeof x === 'number') { + moveTo(x, y); + lineTo(x_, y_); + } + else if('x' in x) { + moveTo(x); + lineTo(y, x_); + } +} + +function vertices(...verts) { + if(verts.length === 0) return; + else if(verts.length === 1 && Array.isArray(verts[0])) { + verts = verts[0]; + } + for(let i = 0; i < verts.length; i++) { + let n = verts[i]; + let x = 0; + let y = 0; + if(Array.isArray(n)) { + ([ x, y ] = n); + } + else if(n instanceof Vector || ('x' in n && 'y' in n)) { + ({ x, y } = n); + } + lineTo(x, y); + } +} + +function arcTo(x1 = 0, y1 = 0, x2 = 0, y2 = 0, radius = 50) { + ctx.arcTo(x1, y1, x2, y2, radius); +} + +function rect(x = 0, y = 0, w = 10, h = w, r = 0) { + if(r > 0) { + moveTo(x + r, y); + arcTo(x + w, y, x + w, y + h, r); + arcTo(x + w, y + h, x, y + h, r); + arcTo(x, y + h, x, y, r); + arcTo(x, y, x + w, y, r); + closePath(); + } + else { + ctx.rect(x, y, w, h); + } +} + +function arc(x = 0, y = 0, radius = 50, startAngle = 0, endAngle = Math.PI * 2, anticlockwise = false) { + if(radius < 0) radius = 0; + ctx.arc(x, y, radius, startAngle, endAngle, anticlockwise); +} + +function circle(x = 0, y = undefined, rX = 20, rY = undefined) { + if(typeof x !== 'number' && 'x' in x) { + if(y !== undefined) { + rX = y; + } + y = x.y; + x = x.x; + } + else if(y === undefined) { + y = 0; + } + if(typeof rX !== 'number' && 'x' in rX) { + rY = rX.y; + rX = rX.x; + } + ctx.moveTo(x + rX, y); + if(rY !== undefined) { + ellipse(x, y, rX, rY); + } + else { + if(rX < 0) rX = 0; + ctx.arc(x, y, rX, 0, TAU); + } +} + +function ellipse(x = 0, y = 0, rX = 50, rY = 50, rot = 0, angStart = 0, angEnd = Math.PI * 2, antiCw = false) { + if(rX < 0) rX = 0; + if(rY < 0) rY = 0; + ctx.ellipse(x, y, rX, rY, rot, angStart, angEnd, antiCw); +} + +function regularPolygon(sides, radius = 50, rotation = 0) { + let circumference = TAU * radius; + let count = min(sides, circumference); + for(let i = 0; i < count; i++) { + let t = i / count * TAU + rotation; + let x = cos(t) * radius; + let y = sin(t) * radius; + if(i === 0) { + ctx.moveTo(x, y); + } + else { + ctx.lineTo(x, y); + } + } + ctx.closePath(); +} + +function genRegularPolygon(sides = 3, radius = 50, rotation = 0) { + let iSizes = 1 / sides * TAU; + let data = { + sides, + radius, + rotation, + points: [] + }; + for(let i = 0; i < sides; i++) { + let t = i * iSizes + rotation; + let x = cos(t) * radius; + let y = sin(t) * radius; + let point = createVector(x, y); + Object.assign(point, { i, t }); + data.points.push(point); + } + return data; +} + +function getCodePenID() { + if(_codepenIDRegex.test(window.location.href)) { + return _codepenIDRegex.exec(window.location.href)[1]; + } + else { + let metas = document.getElementsByTagName('link'); + for(let i = 0; i < metas.length; i++) { + let m = metas[i]; + if(m.getAttribute('rel') == 'canonical') { + let id = _codepenIDRegex.exec(m.getAttribute('href')); + if(id) { + return id[1]; + } + } + } + } +} + +function isPreviewEmbed() { + return location.href.includes('/fullcpgrid/'); +} + +function loadImage(url) { + return new Promise((resolve, reject) => { + let img = new Image(); + img.crossOrigin = 'Anonymous'; + img.onload = () => resolve(img); + img.src = url; + }); +} + +loadImage.alca = function(urlPart) { + return loadImage('https://alca.tv/static/' + urlPart); + }; + +loadImage.alca.pen = function(urlPart) { + return loadImage.alca('codepen/' + urlPart); + }; + +loadImage.alca.pen._ = function(urlPart) { + return loadImage.alca.pen(`pens/${getCodePenID()}/${urlPart}`); + }; + +function loadVideo(url) { + return new Promise((resolve, reject) => { + let vid = document.createElement('video'); + vid.crossOrigin = 'anonymous'; + vid.onloadeddata = () => resolve(vid); + vid.preload = true; + vid.muted = true; + vid.src = url; + vid.load(); + }); +} + +loadVideo.alca = function(urlPart) { + return loadVideo('https://alca.tv/static/' + urlPart); + }; + +loadVideo.alca.pen = function(urlPart) { + return loadVideo.alca('codepen/' + urlPart); + }; + +loadVideo.alca.pen._ = function(urlPart) { + return loadVideo.alca.pen(`pens/${getCodePenID()}/${urlPart}`); + }; + +function loadData(url) { + return fetch(url); +} + +loadData.alca = function(urlPart) { + return loadData('https://alca.tv/static/' + urlPart); + }; + +function loadText(url) { + return loadData(url) + .then(res => res.text()); +} + +loadText.alca = function(urlPart) { + return loadText('https://alca.tv/static/' + urlPart); + }; + +function loadJSON(url) { + return loadData(url) + .then(res => res.json()); +} + +loadJSON.alca = function(urlPart) { + return loadJSON('https://alca.tv/static/' + urlPart); + }; + +function getImageData(img, ...args) { + if(img instanceof Image) { + let canvas = document.createElement('canvas'); + let ctx = canvas.getContext('2d'); + Object.assign(canvas, { width: img.width, height: img.height }); + ctx.drawImage(img, 0, 0); + let data; + if(args.length) { + data = ctx.getImageData(...args); + } + else { + data = ctx.getImageData(0, 0, img.width, img.height); + } + return Object.assign(data, { canvas, ctx }); + } + else { + return ctx.getImageData(img, ...args); + } +} + +function xyToI(x, y, w, h) { + if(typeof x !== 'number' && 'x' in x) { + h = w; + w = y; + ({ x, y } = x); + } + if(w === undefined) w = 1; + // if(h === undefined) h = Infinity; + return x + w * y; +} + +function iToXY(i, w, h) { + return createVector(i % w, floor(i / w)); +} + +function random(low = 1, high = null) { + if(Array.isArray(low)) { + return low[floor(Math.random() * low.length)]; + } + if(high === null) { + return Math.random() * low; + } + return Math.random() * (high - low) + low; +} + +let _randomGaussianPrevious = false; +let _randomGaussianY2 = 0; + +// https://github.com/processing/p5.js/blob/5a46133fdc3e8c42fda1c1888864cf499940d86d/src/math/random.js#L166 +// Offset, deviation +function randomGaussian(mean = 0, sd = 1) { + let y1, x1, x2, w; + if(_randomGaussianPrevious) { + y1 = _randomGaussianY2; + _randomGaussianPrevious = false; + } + else { + do { + x1 = random(2) - 1; + x2 = random(2) - 1; + w = x1 * x1 + x2 * x2; + } while (w >= 1); + w = sqrt(-2 * log(w) / w); + y1 = x1 * w; + _randomGaussianY2 = x2 * w; + _randomGaussianPrevious = true; + } + return y1 * (sd || 1) + mean; +} + +function map(n, a, b, c, d) { + return (n - a) * (d - c) / (b - a) + c; +} + +function constrain(n, mn, mx) { + return max(mn, min(mx, n)); +} + +function lerp(start, stop, amt = 0.5) { + if(typeof start !== 'number') { + return Vector.lerp(start, stop, amt); + } + return amt * (stop - start) + start; +} + +function _distSq(x1, y1, x2, y2) { + let _x = x2 - x1; + let _y = y2 - y1; + return _x * _x + _y * _y; +} + +function distSq(x1, y1, x2, y2) { + if(x1 === undefined || y1 === undefined || x2 === undefined || y2 === undefined) { + return 0; + } + else if(typeof x1 === 'number') { + if(x1 === x1) { + return _distSq(x1, y1, x2, y2); + } + return 0; + } + else if('x' in x1) { + return _distSq(x1.x, x1.y, y1.x, y1.y); + } + return 0; +} + +function dist(x1, y1, x2, y2) { + let d = distSq(x1, y1, x2, y2); + if(d === 0) { + return 0; + } + return sqrt(d); +} + +function cos(input, mult = null) { + let c = Math.cos(input % TAU); + if(mult === null) { + return c; + } + return c * mult; +} + +function sin(input, mult = null) { + let s = Math.sin(input % TAU); + if(mult === null) { + return s; + } + return s * mult; +} + + +function createVector(x, y, z) { + return new Vector(x, y, z); +} + +class Vector { + constructor(x = 0, y = 0, z = 0) { + this.x = x; + this.y = y; + this.z = z; + } + toString() { + let { x, y, z } = this; + return `{ x: ${x}, y: ${y}, z: ${z} }`; + } + + static center() { + return createVector(width_half, height_half); + } + + static from(v, ...args) { + if(v === undefined) { + return createVector(); + } + else if(Array.isArray(v)) { + return createVector(...v); + } + else if(typeof v === 'object') { + return createVector(v.x, v.y, v.z); + } + else if(typeof v === 'number') { + return createVector(v, ...args); + } + } + + static fromAngle(angle, mult = 1) { + let v = createVector(cos(angle), sin(angle)); + if(mult !== 1) v.mult(mult); + return v; + } + + static random2D(angle = true, mult = 1) { + let v; + if(angle === true) { + v = Vector.fromAngle(random(TAU)); + } + else { + v = createVector(random(-1, 1), random(-1, 1)); + } + if(typeof angle === 'number') { + v.mult(angle); + } + else if(mult !== 1) { + v.mult(mult); + } + return v; + } + + static lerp(start, stop, amt = 0.5, apply = false) { + let x = start.x === stop.x ? start.x : lerp(start.x, stop.x, amt); + let y = start.y === stop.y ? start.y : lerp(start.y, stop.y, amt); + let z = start.z === undefined ? stop.z === undefined ? 0 : stop.z : start.z === stop.z ? start.z : lerp(start.z, stop.z, amt); + if(apply) { + return start.set(x, y, z); + } + return createVector(x, y, z); + } + + get xy() { return [ this.x, this.y ]; } + get yx() { return [ this.y, this.x ]; } + get xz() { return [ this.x, this.z ]; } + get zx() { return [ this.z, this.x ]; } + get yz() { return [ this.y, this.z ]; } + get zy() { return [ this.z, this.y ]; } + get xyz() { return [ this.x, this.y, this.z ]; } + get xzy() { return [ this.x, this.z, this.y ]; } + get yxz() { return [ this.y, this.x, this.z ]; } + get yzx() { return [ this.y, this.z, this.x ]; } + get zyx() { return [ this.z, this.y, this.x ]; } + get zxy() { return [ this.z, this.x, this.y ]; } + + get xyObject() { return { x: this.x, y: this.y }; } + get xzObject() { return { x: this.x, z: this.z }; } + get yzObject() { return { y: this.y, z: this.z }; } + get xyzObject() { return { x: this.x, y: this.y, z: this.z }; } + + copy() { + return createVector(this.x, this.y, this.z); + } + + get _() { + return this.copy(); + } + + equals(vec) { + return this.x === vec.x && this.y === vec.y; + } + + equals3D(vec = {}) { + return this.x === vec.x && this.y === vec.y && this.z === vec.z; + } + + draw() { + point(this.x, this.y); + } + + set(x = this.x, y = this.y, z = this.z) { + if(x instanceof Vector) { + this.x = x.x; + this.y = x.y; + this.z = x.z; + return this; + } + this.x = x; + this.y = y; + this.z = z; + return this; + } + setX(x = this.x) { + if(x instanceof Vector) { + this.x = x.x; + return this; + } + this.x = x; + return this; + } + setY(y = this.y) { + if(y instanceof Vector) { + this.y = y.y; + return this; + } + this.y = y; + return this; + } + setZ(z = this.z) { + if(z instanceof Vector) { + this.z = z.z; + return this; + } + this.z = z; + return this; + } + setXY(x = this.x, y = this.y) { + if(x instanceof Vector) { + this.x = x.x; + this.y = x.y; + return this; + } + this.x = x; + this.y = y; + return this; + } + setYZ(y = this.y, z = this.z) { + if(y instanceof Vector) { + this.y = y.y; + this.z = y.z; + return this; + } + this.y = y; + this.z = z; + return this; + } + setXZ(x = this.x, z = this.y) { + if(x instanceof Vector) { + this.x = x.x; + this.z = x.z; + return this; + } + this.x = x; + this.z = z; + return this; + } + setZX(...args) { + return this.setXZ(...args); + } + + add(x = 0, y = undefined, z = undefined) { + if(y === undefined) { + y = x; + z = x; + } + else if(z === undefined) { + z = 0; + } + if(x instanceof Vector) { + this.x += x.x; + this.y += x.y; + this.z += x.z; + return this; + } + this.x += x; + this.y += y; + this.z += z; + return this; + } + addX(n = 0) { + if(n instanceof Vector) { + this.x += n.x; + return this; + } + this.x += n; + return this; + } + addY(n = 0) { + if(n instanceof Vector) { + this.y += n.y; + return this; + } + this.y += n; + return this; + } + addZ(n = 0) { + if(n instanceof Vector) { + this.z += n.z; + return this; + } + this.z += n; + return this; + } + sub(x = 0, y = undefined, z = undefined) { + if(y === undefined) { + y = x; + z = x; + } + else if(z === undefined) { + z = 0; + } + if(x instanceof Vector) { + this.x -= x.x; + this.y -= x.y; + this.z -= x.z; + return this; + } + this.x -= x; + this.y -= y; + this.z -= z; + return this; + } + subX(n = 0) { + if(n instanceof Vector) { + this.x -= n.x; + return this; + } + this.x -= n; + return this; + } + subY(n = 0) { + if(n instanceof Vector) { + this.y -= n.y; + return this; + } + this.y -= n; + return this; + } + subZ(n = 0) { + if(n instanceof Vector) { + this.z -= n.z; + return this; + } + this.z -= n; + return this; + } + mult(x = 1, y = x, z = x) { + if(x instanceof Vector) { + this.x *= x.x; + this.y *= x.y; + this.z *= x.z; + return this; + } + this.x *= x; + this.y *= y; + this.z *= z; + return this; + } + multX(n = 1) { + if(n instanceof Vector) { + this.x *= n.x; + return this; + } + this.x *= n; + return this; + } + multY(n = 1) { + if(n instanceof Vector) { + this.y *= n.y; + return this; + } + this.y *= n; + return this; + } + multZ(n = 1) { + if(n instanceof Vector) { + this.z *= n.z; + return this; + } + this.z *= n; + return this; + } + div(x = 1, y = x, z = x) { + if(x instanceof Vector) { + this.x /= x.x; + this.y /= x.y; + this.z /= x.z; + return this; + } + this.x /= x; + this.y /= y; + this.z /= z; + return this; + } + divX(n = 1) { + if(n instanceof Vector) { + this.x /= n.x; + return this; + } + this.x /= n; + return this; + } + divY(n = 1) { + if(n instanceof Vector) { + this.y /= n.y; + return this; + } + this.y /= n; + return this; + } + divZ(n = 1) { + if(n instanceof Vector) { + this.z /= n.z; + return this; + } + this.z /= n; + return this; + } + + mod(x, y, z) { + if(x === undefined) return this; + else if(x instanceof Vector) { + this.x %= x.x; + this.y %= x.y; + this.z %= x.z; + return this; + } + this.x %= x; + this.y %= y === undefined ? x : y; + this.z %= z === undefined ? x : y; + return this; + } + // TODO: modX, modY, modZ + + min(mX = this.x, mY = this.y, mZ = this.z) { + if(mX instanceof Vector) { + this.x = min(this.x, mX.x); + this.y = min(this.y, mX.y); + this.z = min(this.z, mX.z); + return this; + } + this.x = min(this.x, mX); + this.y = min(this.y, mY); + this.z = min(this.z, mZ); + return this; + } + max(mX = this.x, mY = this.y, mZ = this.z) { + if(mX instanceof Vector) { + this.x = max(this.x, mX.x); + this.y = max(this.y, mX.y); + this.z = max(this.z, mX.z); + return this; + } + this.x = max(this.x, mX); + this.y = max(this.y, mY); + this.z = max(this.z, mZ); + return this; + } + minX(n) { + this.x = min(this.x, n instanceof Vector ? n.x : n); + return this; + } + minY(n) { + this.y = min(this.y, n instanceof Vector ? n.y : n); + return this; + } + minZ(n) { + this.z = min(this.z, n instanceof Vector ? n.z : n); + return this; + } + maxX(n) { + this.x = max(this.x, n instanceof Vector ? n.x : n); + return this; + } + maxY(n) { + this.y = max(this.y, n instanceof Vector ? n.y : n); + return this; + } + maxZ(n) { + this.z = max(this.z, n instanceof Vector ? n.z : n); + return this; + } + + heading() { + return atan2(this.y, this.x); + } + rotate(a = 0) { + // if(a === 0) { + // return this; + // } + // let newHeading = this.heading() + a; + // let mag = this.mag(); + // return this.set(cos(newHeading), sin(newHeading)).mult(mag); + if(!a) { + return this; + } + const c = cos(a); + const s = sin(a); + const { x, y } = this; + this.x = x * c - y * s; + this.y = x * s + y * c; + return this; + } + rotateXY(a) { + let v = new Vector(this.x, this.y).rotate(a); + this.x = v.x; + this.y = v.y; + return this; + } + rotateYZ(a) { + let v = new Vector(this.y, this.z).rotate(a); + this.y = v.x; + this.z = v.y; + return this; + } + rotateZX(a) { + let v = new Vector(this.z, this.x).rotate(a); + this.z = v.x; + this.x = v.y; + return this; + } + magSq() { + return this.x * this.x + this.y * this.y; + } + magSq3D() { + return this.x * this.x + this.y * this.y + this.z * this.z; + } + mag() { + return Math.sqrt(this.magSq()); + // return hypot(this.x, this.y); + } + mag3D() { + return Math.sqrt(this.magSq3D()); + // return hypot(this.x, this.y); + } + normalize(mag = this.mag()) { + return mag === 0 ? this : this.div(mag); + } + normalize3D(mag = this.mag3D()) { + return mag === 0 ? this : this.div(mag); + } + setMag(mag) { + return this.normalize().mult(mag); + } + setMag3D(mag) { + return this.normalize3D().mult(mag); + } + limit(max) { + const magSq = this.magSq(); + if(magSq > max * max) { + this.div(sqrt(magSq)); + this.mult(max); + } + return this; + } + limit3D(max) { + const magSq = this.magSq3D(); + if(magSq > max * max) { + this.div(sqrt(magSq)); + this.mult(max); + } + return this; + } + dot(x = 0, y = 0) { + if(x instanceof Vector) { + return this.dot(x.x, x.y); + } + return this.x * x + this.y * y; + } + dot3D(x = 0, y = 0, z = 0) { + if(x instanceof Vector) { + return this.dot(x.x, x.y, x.z); + } + return this.x * x + this.y * y + this.z * z; + } + dist(x, y) { + if(x instanceof Vector) { + return x.copy().sub(this).mag(); + } + else if(typeof x === 'object' && 'x' in x) { + ({ x, y } = x); + } + return dist(this.x, this.y, x, y); + } + dist3D(v) { + return v.copy().sub(this).mag3D(); + } + lerp(stop, amt) { + return Vector.lerp(this, stop, amt, true); + } + round() { + this.x = round(this.x); + this.y = round(this.y); + this.z = round(this.z); + return this; + } + floor() { + this.x = floor(this.x); + this.y = floor(this.y); + this.z = floor(this.z); + return this; + } + fastFloor() { + this.x = ~~this.x; + this.y = ~~this.y; + this.z = ~~this.z; + return this; + } + ceil() { + this.x = ceil(this.x); + this.y = ceil(this.y); + this.z = ceil(this.z); + return this; + } +} + + +// Robert Penner - http://gizma.com/easing/ +// t: Current time +// b: Start value +// c: Change in value +// d: Duration + +function linearTween /* simple linear tweening */ (t = 0.5, b = 0, c = 1, d = 1) { return c * t / d + b; } +function easeInQuad /* quadratic easing in */ (t = 0.5, b = 0, c = 1, d = 1) { t /= d; return c * t * t + b; } +function easeOutQuad /* quadratic easing out */ (t = 0.5, b = 0, c = 1, d = 1) { t /= d; return -c * t * (t - 2) + b; } +function easeInOutQuad /* quadratic easing in/out */ (t = 0.5, b = 0, c = 1, d = 1) { t /= d * 0.5; if(t < 1) return c * 0.5 * t * t + b; t--; return -c * 0.5 * (t * (t - 2) - 1) + b; } +function easeInCubic /* cubic easing in */ (t = 0.5, b = 0, c = 1, d = 1) { t /= d; return c * t * t * t + b; } +function easeOutCubic /* cubic easing out */ (t = 0.5, b = 0, c = 1, d = 1) { t /= d; t--; return c * (t * t * t + 1) + b; } +function easeInOutCubic /* cubic easing in/out */ (t = 0.5, b = 0, c = 1, d = 1) { t /= d * 0.5; if(t < 1) return c * 0.5 * t * t * t + b; t -= 2; return c * 0.5 * (t * t * t + 2) + b; } +function easeInQuart /* quartic easing in */ (t = 0.5, b = 0, c = 1, d = 1) { t /= d; return c * t * t * t * t + b; } +function easeOutQuart /* quartic easing out */ (t = 0.5, b = 0, c = 1, d = 1) { t /= d; t--; return -c * (t * t * t * t - 1) + b; } +function easeInOutQuart /* quartic easing in/out */ (t = 0.5, b = 0, c = 1, d = 1) { t /= d * 0.5; if(t < 1) return c * 0.5 * t * t * t * t + b; t -= 2; return -c * 0.5 * (t * t * t * t - 2) + b; } +function easeInQuint /* quintic easing in */ (t = 0.5, b = 0, c = 1, d = 1) { t /= d; return c * t * t * t * t * t + b; } +function easeOutQuint /* quintic easing out */ (t = 0.5, b = 0, c = 1, d = 1) { t /= d; t--; return c * (t * t * t * t * t + 1) + b; } +function easeInOutQuint /* quintic easing in/out */ (t = 0.5, b = 0, c = 1, d = 1) { t /= d * 0.5; if(t < 1) return c * 0.5 * t * t * t * t * t + b; t -= 2; return c * 0.5 * (t * t * t * t * t + 2) + b; } +function easeInSine /* sinusoidal easing in */ (t = 0.5, b = 0, c = 1, d = 1) { return -c * cos(t / d * HALF_PI) + c + b; } +function easeOutSine /* sinusoidal easing out */ (t = 0.5, b = 0, c = 1, d = 1) { return c * sin(t / d * HALF_PI) + b; } +function easeInOutSine /* sinusoidal easing in/out */ (t = 0.5, b = 0, c = 1, d = 1) { return -c * 0.5 * (cos(PI * t / d) - 1) + b; } +function easeInExpo /* exponential easing in */ (t = 0.5, b = 0, c = 1, d = 1) { return c * pow(2, 10 * (t / d - 1)) + b; } +function easeOutExpo /* exponential easing out */ (t = 0.5, b = 0, c = 1, d = 1) { return c * (-pow(2, -10 * t / d ) + 1) + b; } +function easeInOutExpo /* exponential easing in/out */ (t = 0.5, b = 0, c = 1, d = 1) { t /= d * 0.5; if(t < 1) return c * 0.5 * pow(2, 10 * (t - 1)) + b; t--; return c * 0.5 * (-pow(2, -10 * t) + 2) + b; } +function easeInCirc /* circular easing in */ (t = 0.5, b = 0, c = 1, d = 1) { t /= d; return -c * (sqrt(1 - t * t) - 1) + b; } +function easeOutCirc /* circular easing out */ (t = 0.5, b = 0, c = 1, d = 1) { t /= d; t--; return c * sqrt(1 - t * t) + b; } +function easeInOutCirc /* circular easing in/out */ (t = 0.5, b = 0, c = 1, d = 1) { t /= d * 0.5; if(t < 1) return -c * 0.5 * (sqrt(1 - t * t) - 1) + b; t -= 2; return c * 0.5 * (sqrt(1 - t * t) + 1) + b; } + +const ease = { + linearTween, + easeInQuad, easeOutQuad, easeInOutQuad, + easeInCubic, easeOutCubic, easeInOutCubic, + easeInQuart, easeOutQuart, easeInOutQuart, + easeInQuint, easeOutQuint, easeInOutQuint, + easeInSine, easeOutSine, easeInOutSine, + easeInExpo, easeOutExpo, easeInOutExpo, + easeInCirc, easeOutCirc, easeInOutCirc, + in: { linear: linearTween, quad: easeInQuad, cubic: easeInCubic, quart: easeInQuart, quint: easeInQuint, sine: easeInSine, expo: easeInExpo, circ: easeInCirc }, + out: { linear: linearTween, quad: easeOutQuad, cubic: easeOutCubic, quart: easeOutQuart, quint: easeOutQuint, sine: easeOutSine, expo: easeOutExpo, circ: easeOutCirc }, + inOut: { linear: linearTween, quad: easeInOutQuad, cubic: easeInOutCubic, quart: easeInOutQuart, quint: easeInOutQuint, sine: easeInOutSine, expo: easeInOutExpo, circ: easeInOutCirc }, + linear: Object.assign(linearTween, + { in: linearTween, out: linearTween, inOut: linearTween }), + quad: { in: easeInQuad, out: easeOutQuad, inOut: easeInOutQuad }, + cubic: { in: easeInCubic, out: easeOutCubic, inOut: easeInOutCubic }, + quart: { in: easeInQuart, out: easeOutQuart, inOut: easeInOutQuart }, + quint: { in: easeInQuint, out: easeOutQuint, inOut: easeInOutQuint }, + sine: { in: easeInSine, out: easeOutSine, inOut: easeInOutSine }, + expo: { in: easeInExpo, out: easeOutExpo, inOut: easeInOutExpo }, + circ: { in: easeInCirc, out: easeOutCirc, inOut: easeInOutCirc } + }; + +function getTimeArray(timestamp = null) { + if(timestamp === null) { + timestamp = new Date(); + } + else if(typeof timestamp === 'string' || typeof timestamp === 'number') { + let parsedTimestamp = Date.parse(timestamp); + if(!isNaN(parsedTimestamp)) { + timestamp = new Date(parsedTimestamp); + } + else { + throw new RangeError('Invalid Date'); + } + } + else if(!(timestamp instanceof Date)) { + throw new TypeError('Unsupported timestamp'); + } + let arr = [ + timestamp.getHours(), + timestamp.getMinutes(), + timestamp.getSeconds(), + timestamp.getMilliseconds() + ]; + return arr; +} + +function getTimeArrayPadded(...opts) { + return getTimeArray(...opts).map(n => `0${n}`.slice(-2)); +} + +function getTimeArraySmooth(...opts) { + let arr = getTimeArray(...opts); + let milliseconds = arr[3] / 1000; + let seconds = (arr[2] + milliseconds) / 60; + let minutes = (arr[1] + seconds) / 60; + let hours = ((arr[0] % 12 || 12) + minutes) / 12; + return [ hours, minutes, seconds, milliseconds ]; +} + +function loadWebFont(fontName) { + if('WebFont' in window === false) { + return Promise.reject('WebFont not available. Load using this script: https://cdnjs.cloudflare.com/ajax/libs/webfont/1.6.28/webfontloader.js'); + } + if(fontName === '') { + return Promise.resolve(); + } + return new Promise((resolve, reject) => { + let options = { fontactive: resolve }; + let providers = {}; + if(typeof fontName === 'string') { + providers = { google: { families: [ fontName ] } }; + } + else if(Array.isArray(fontName)) { + providers = { google: { families: fontName } }; + } + else { + providers = fontName; + } + Object.assign(options, providers); + WebFont.load(options); + }); +} + +function isFontDefault() { + return ctx.font === '10px sans-serif'; +} + +function font(fontStr, fallbackIfDefault) { + if(fontStr !== undefined) { + ctx.font = fontStr; + if(fallbackIfDefault !== undefined && isFontDefault()) { + ctx.font = fallbackIfDefault; + } + } + return ctx.font; +} \ No newline at end of file diff --git a/app/src/main/assets/js/circle-progress.js b/app/src/main/assets/js/circle-progress.js new file mode 100644 index 0000000..ab8ac24 --- /dev/null +++ b/app/src/main/assets/js/circle-progress.js @@ -0,0 +1,412 @@ +/* +jquery-circle-progress - jQuery Plugin to draw animated circular progress bars + +URL: http://kottenator.github.io/jquery-circle-progress/ +Author: Rostyslav Bryzgunov +Version: 1.1.2 +License: MIT +*/ +export const circle_progress = (function($) { + function CircleProgress(config) { + this.init(config); + } + + CircleProgress.prototype = { + //----------------------------------------------- public options ----------------------------------------------- + /** + * This is the only required option. It should be from 0.0 to 1.0 + * @type {number} + */ + value: 0.0, + + /** + * Size of the circle / canvas in pixels + * @type {number} + */ + size: 100.0, + + /** + * Initial angle for 0.0 value in radians + * @type {number} + */ + startAngle: -Math.PI, + + /** + * Width of the arc. By default it's auto-calculated as 1/14 of size, but you may set it explicitly in pixels + * @type {number|string} + */ + thickness: 'auto', + + /** + * Fill of the arc. You may set it to: + * - solid color: + * - { color: '#3aeabb' } + * - { color: 'rgba(255, 255, 255, .3)' } + * - linear gradient (left to right): + * - { gradient: ['#3aeabb', '#fdd250'], gradientAngle: Math.PI / 4 } + * - { gradient: ['red', 'green', 'blue'], gradientDirection: [x0, y0, x1, y1] } + * - image: + * - { image: 'http://i.imgur.com/pT0i89v.png' } + * - { image: imageObject } + * - { color: 'lime', image: 'http://i.imgur.com/pT0i89v.png' } - color displayed until the image is loaded + */ + fill: { + gradient: ['#3aeabb', '#fdd250'] + }, + + /** + * Color of the "empty" arc. Only a color fill supported by now + * @type {string} + */ + emptyFill: 'rgba(0, 0, 0, .1)', + + /** + * Animation config (see jQuery animations: http://api.jquery.com/animate/) + */ + animation: { + duration: 1200, + easing: 'circleProgressEasing' + }, + + /** + * Default animation starts at 0.0 and ends at specified `value`. Let's call this direct animation. + * If you want to make reversed animation then you should set `animationStartValue` to 1.0. + * Also you may specify any other value from 0.0 to 1.0 + * @type {number} + */ + animationStartValue: 0.0, + + /** + * Reverse animation and arc draw + * @type {boolean} + */ + reverse: false, + + /** + * Arc line cap ('butt' (default), 'round' and 'square') + * Read more: https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D.lineCap + * @type {string} + */ + lineCap: 'butt', + + //-------------------------------------- protected properties and methods -------------------------------------- + /** + * @protected + */ + constructor: CircleProgress, + + /** + * Container element. Should be passed into constructor config + * @protected + * @type {jQuery} + */ + el: null, + + /** + * Canvas element. Automatically generated and prepended to the {@link CircleProgress.el container} + * @protected + * @type {HTMLCanvasElement} + */ + canvas: null, + + /** + * 2D-context of the {@link CircleProgress.canvas canvas} + * @protected + * @type {CanvasRenderingContext2D} + */ + ctx: null, + + /** + * Radius of the outer circle. Automatically calculated as {@link CircleProgress.size} / 2 + * @protected + * @type {number} + */ + radius: 0.0, + + /** + * Fill of the main arc. Automatically calculated, depending on {@link CircleProgress.fill} option + * @protected + * @type {string|CanvasGradient|CanvasPattern} + */ + arcFill: null, + + /** + * Last rendered frame value + * @protected + * @type {number} + */ + lastFrameValue: 0.0, + + /** + * Init/re-init the widget + * @param {object} config Config + */ + init: function(config) { + $.extend(this, config); + this.radius = this.size / 2; + this.initWidget(); + this.initFill(); + this.draw(); + }, + + /** + * @protected + */ + initWidget: function() { + var canvas = this.canvas = this.canvas || $('').prependTo(this.el)[0]; + canvas.width = this.size; + canvas.height = this.size; + this.ctx = canvas.getContext('2d'); + }, + + /** + * This method sets {@link CircleProgress.arcFill} + * It could do this async (on image load) + * @protected + */ + initFill: function() { + var self = this, + fill = this.fill, + ctx = this.ctx, + size = this.size; + + if (!fill) + throw Error("The fill is not specified!"); + + if (fill.color) + this.arcFill = fill.color; + + if (fill.gradient) { + var gr = fill.gradient; + + if (gr.length == 1) { + this.arcFill = gr[0]; + } else if (gr.length > 1) { + var ga = fill.gradientAngle || 0, // gradient direction angle; 0 by default + gd = fill.gradientDirection || [ + size / 2 * (1 - Math.cos(ga)), // x0 + size / 2 * (1 + Math.sin(ga)), // y0 + size / 2 * (1 + Math.cos(ga)), // x1 + size / 2 * (1 - Math.sin(ga)) // y1 + ]; + + var lg = ctx.createLinearGradient.apply(ctx, gd); + + for (var i = 0; i < gr.length; i++) { + var color = gr[i], + pos = i / (gr.length - 1); + + if ($.isArray(color)) { + pos = color[1]; + color = color[0]; + } + + lg.addColorStop(pos, color); + } + + this.arcFill = lg; + } + } + + if (fill.image) { + var img; + + if (fill.image instanceof Image) { + img = fill.image; + } else { + img = new Image(); + img.src = fill.image; + } + + if (img.complete) + setImageFill(); + else + img.onload = setImageFill; + } + + function setImageFill() { + var bg = $('')[0]; + bg.width = self.size; + bg.height = self.size; + bg.getContext('2d').drawImage(img, 0, 0, size, size); + self.arcFill = self.ctx.createPattern(bg, 'no-repeat'); + self.drawFrame(self.lastFrameValue); + } + }, + + draw: function() { + if (this.animation) + this.drawAnimated(this.value); + else + this.drawFrame(this.value); + }, + + /** + * @protected + * @param {number} v Frame value + */ + drawFrame: function(v) { + this.lastFrameValue = v; + this.ctx.clearRect(0, 0, this.size, this.size); + this.drawEmptyArc(v); + this.drawArc(v); + }, + + /** + * @protected + * @param {number} v Frame value + */ + drawArc: function(v) { + var ctx = this.ctx, + r = this.radius, + t = this.getThickness(), + a = this.startAngle; + + ctx.save(); + ctx.beginPath(); + + if (!this.reverse) { + ctx.arc(r, r, r - t / 2, a, a + Math.PI * 2 * v); + } else { + ctx.arc(r, r, r - t / 2, a - Math.PI * 2 * v, a); + } + + ctx.lineWidth = t; + ctx.lineCap = this.lineCap; + ctx.strokeStyle = this.arcFill; + ctx.stroke(); + ctx.restore(); + }, + + /** + * @protected + * @param {number} v Frame value + */ + drawEmptyArc: function(v) { + var ctx = this.ctx, + r = this.radius, + t = this.getThickness(), + a = this.startAngle; + + if (v < 1) { + ctx.save(); + ctx.beginPath(); + + if (v <= 0) { + ctx.arc(r, r, r - t / 2, 0, Math.PI * 2); + } else { + if (!this.reverse) { + ctx.arc(r, r, r - t / 2, a + Math.PI * 2 * v, a); + } else { + ctx.arc(r, r, r - t / 2, a, a - Math.PI * 2 * v); + } + } + + ctx.lineWidth = t; + ctx.strokeStyle = this.emptyFill; + ctx.stroke(); + ctx.restore(); + ctx.closePath(); + + ctx.save(); + //背景黑 + ctx.beginPath();//开始绘制 + ctx.arc(r,r,r-t,0,2*Math.PI);//arc 的意思是“弧” + ctx.fillStyle="#000";//设置填充颜色 + ctx.closePath(); + ctx.fill();//开始填充 + //ctx.strokeStyle="blue";//将线条颜色设置为蓝色 + ctx.stroke();//stroke() 方法默认颜色是黑色(如果没有上面一行,则会是黑色)。 + } + }, + + /** + * @protected + * @param {number} v Value + */ + drawAnimated: function(v) { + var self = this, + el = this.el; + + el.trigger('circle-animation-start'); + + $(this.canvas) + .stop(true, true) + .css({ animationProgress: 0 }) + .animate({ animationProgress: 1 }, $.extend({}, this.animation, { + step: function(animationProgress) { + var stepValue = self.animationStartValue * (1 - animationProgress) + v * animationProgress; + self.drawFrame(stepValue); + el.trigger('circle-animation-progress', [animationProgress, stepValue]); + }, + complete: function() { + el.trigger('circle-animation-end'); + } + })); + + + }, + + /** + * @protected + * @returns {number} + */ + getThickness: function() { + return $.isNumeric(this.thickness) ? this.thickness : this.size / 14; + } + }; + + //-------------------------------------------- Initiating jQuery plugin -------------------------------------------- + $.circleProgress = { + // Default options (you may override them) + defaults: CircleProgress.prototype + }; + + // ease-in-out-cubic + $.easing.circleProgressEasing = function(x, t, b, c, d) { + if ((t /= d / 2) < 1) + return c / 2 * t * t * t + b; + return c / 2 * ((t -= 2) * t * t + 2) + b; + }; + + /** + * Draw animated circular progress bar. + * + * Appends to the element or updates already appended one. + * + * If animated, throws 3 events: + * + * - circle-animation-start(jqEvent) + * - circle-animation-progress(jqEvent, animationProgress, stepValue) - multiple event; + * animationProgress: from 0.0 to 1.0; + * stepValue: from 0.0 to value + * - circle-animation-end(jqEvent) + * + * @param config Example: { value: 0.75, size: 50, animation: false }; + * you may set any of public options; + * `animation` may be set to false; + * you may also use .circleProgress('widget') to get the canvas + */ + $.fn.circleProgress = function(config) { + var dataName = 'circle-progress'; + + if (config == 'widget') { + var data = this.data(dataName); + return data && data.canvas; + } + + return this.each(function() { + var el = $(this), + instance = el.data(dataName), + cfg = $.isPlainObject(config) ? config : {}; + + if (instance) { + instance.init(cfg); + } else { + cfg.el = el; + instance = new CircleProgress(cfg); + el.data(dataName, instance); + } + }); + }; +})(jQuery); diff --git a/app/src/main/assets/js/rainyday.js b/app/src/main/assets/js/rainyday.js new file mode 100644 index 0000000..198fc6a --- /dev/null +++ b/app/src/main/assets/js/rainyday.js @@ -0,0 +1,1066 @@ +/** + * Defines a new instance of the rainyday.js. + * @param options options element with script parameters + * @param canvas to be used (if not defined a new one will be created) + * https://github.com/iefreer/rainyday.js + */ + +function RainyDay(options, canvas) { + + if (this === window) { //if *this* is the window object, start over with a *new* object + return new RainyDay(options, canvas); + } + + this.img = options.image; + var defaults = { + opacity: 1, + blur: 10, + crop: [0, 0, this.img.naturalWidth, this.img.naturalHeight], + enableSizeChange: true, + parentElement: document.getElementsByTagName('body')[0], + fps: 30, + fillStyle: '#8ED6FF', + enableCollisions: true, + gravityThreshold: 3, + gravityAngle: Math.PI / 2, + gravityAngleVariance: 0, + reflectionScaledownFactor: 5, + reflectionDropMappingWidth: 200, + reflectionDropMappingHeight: 200, + width: this.img.clientWidth, + height: this.img.clientHeight, + position: 'absolute', + top: 0, + left: 0 + }; + + // add the defaults to options + for (var option in defaults) { + if (typeof options[option] === 'undefined') { + options[option] = defaults[option]; + } + } + this.options = options; + + this.drops = []; + + // prepare canvas elements + this.canvas = canvas || this.prepareCanvas(); + if(this.canvas.width == 0) { + return null; + } + this.prepareBackground(); + this.prepareGlass(); + + // assume defaults + this.reflection = this.REFLECTION_MINIATURE; + this.trail = this.TRAIL_DROPS; + this.gravity = this.GRAVITY_REAL; + this.collision = this.COLLISION_SIMPLE; + + // set polyfill of requestAnimationFrame + this.setRequestAnimFrame(); +} + +/** + * Create the main canvas over a given element + * @returns HTMLElement the canvas + */ +RainyDay.prototype.prepareCanvas = function() { + var canvas = document.createElement('canvas'); + canvas.style.position = this.options.position; + canvas.style.zIndex = -2; + canvas.id = "rain_canvas"; + canvas.style.top = this.options.top; + canvas.style.left = this.options.left; + canvas.width = this.options.width; + canvas.height = this.options.height; + this.options.parentElement.appendChild(canvas); + if (this.options.enableSizeChange) { + this.setResizeHandler(); + } + return canvas; +}; + +RainyDay.prototype.setResizeHandler = function() { + // use setInterval if oneresize event already use by other. + if (window.onresize !== null) { + window.setInterval(this.checkSize.bind(this), 100); + } else { + window.onresize = this.checkSize.bind(this); + window.onorientationchange = this.checkSize.bind(this); + } +}; + +/** + * Periodically check the size of the underlying element + */ +RainyDay.prototype.checkSize = function() { + var clientWidth = this.img.clientWidth; + var clientHeight = this.img.clientHeight; + var clientOffsetLeft = this.img.offsetLeft; + var clientOffsetTop = this.img.offsetTop; + var canvasWidth = this.canvas.width; + var canvasHeight = this.canvas.height; + var canvasOffsetLeft = this.canvas.offsetLeft; + var canvasOffsetTop = this.canvas.offsetTop; + + if (canvasWidth !== clientWidth || canvasHeight !== clientHeight) { + this.canvas.width = clientWidth; + this.canvas.height = clientHeight; + this.prepareBackground(); + this.glass.width = this.canvas.width; + this.glass.height = this.canvas.height; + this.prepareReflections(); + } + if (canvasOffsetLeft !== clientOffsetLeft || canvasOffsetTop !== clientOffsetTop) { + this.canvas.offsetLeft = clientOffsetLeft; + this.canvas.offsetTop = clientOffsetTop; + } +}; + +/** + * Start animation loop + */ +RainyDay.prototype.animateDrops = function() { + if (this.addDropCallback) { + if(this.canvas.width == 0 || this.canvas.height == 0){ + console.info("animateDrops canvas size empty."); + return; + } + this.addDropCallback(); + } + // |this.drops| array may be changed as we iterate over drops + var dropsClone = this.drops.slice(); + var newDrops = []; + for (var i = 0; i < dropsClone.length; ++i) { + if (dropsClone[i].animate()) { + newDrops.push(dropsClone[i]); + } + } + this.drops = newDrops; + window.requestAnimFrame(this.animateDrops.bind(this)); +}; + +/** + * Polyfill for requestAnimationFrame + */ +RainyDay.prototype.setRequestAnimFrame = function() { + var fps = this.options.fps; + window.requestAnimFrame = (function() { + return window.requestAnimationFrame || + window.webkitRequestAnimationFrame || + window.mozRequestAnimationFrame || + function(callback) { + window.setTimeout(callback, 1000 / fps); + }; + })(); +}; + +/** + * Create the helper canvas for rendering raindrop reflections. + */ +RainyDay.prototype.prepareReflections = function() { + this.reflected = document.createElement('canvas'); + this.reflected.width = this.canvas.width / this.options.reflectionScaledownFactor; + this.reflected.height = this.canvas.height / this.options.reflectionScaledownFactor; + var ctx = this.reflected.getContext('2d'); + ctx.drawImage(this.img, this.options.crop[0], this.options.crop[1], this.options.crop[2], this.options.crop[3], 0, 0, this.reflected.width, this.reflected.height); +}; + +/** + * Create the glass canvas. + */ +RainyDay.prototype.prepareGlass = function() { + this.glass = document.createElement('canvas'); + this.glass.width = this.canvas.width; + this.glass.height = this.canvas.height; + this.context = this.glass.getContext('2d'); +}; + +/** + * Main function for starting rain rendering. + * @param presets list of presets to be applied + * @param speed speed of the animation (if not provided or 0 static image will be generated) + */ +RainyDay.prototype.rain = function(presets, speed) { + // prepare canvas for drop reflections + if (this.reflection !== this.REFLECTION_NONE) { + this.prepareReflections(); + } + + this.animateDrops(); + + // animation + this.presets = presets; + + this.PRIVATE_GRAVITY_FORCE_FACTOR_Y = (this.options.fps * 0.001) / 25; + this.PRIVATE_BASE_FRICTION = 6; //base friction + this.PRIVATE_GRAVITY_FORCE_FACTOR_X = ((Math.PI / 2) - this.options.gravityAngle) * (this.options.fps * 0.001) / 50; + + // prepare gravity matrix + if (this.options.enableCollisions) { + + // calculate max radius of a drop to establish gravity matrix resolution + var maxDropRadius = 0; + for (var i = 0; i < presets.length; i++) { + if (presets[i][0] + presets[i][1] > maxDropRadius) { + maxDropRadius = Math.floor(presets[i][0] + presets[i][1]); + } + } + + if (maxDropRadius > 0) { + // initialize the gravity matrix + var mwi = Math.ceil(this.canvas.width / maxDropRadius); + var mhi = Math.ceil(this.canvas.height / maxDropRadius); + this.matrix = new CollisionMatrix(mwi, mhi, maxDropRadius); + } else { + this.options.enableCollisions = false; + } + } + + for (var i = 0; i < presets.length; i++) { + if (!presets[i][3]) { + presets[i][3] = -1; + } + } + + var lastExecutionTime = 0; + this.addDropCallback = function() { + if(this.canvas.width==0 || this.canvas.height==0){ + console.info("addDropCallback canvas size empty."); + return; + } + var timestamp = new Date().getTime(); + if (timestamp - lastExecutionTime < speed) { + return; + } + lastExecutionTime = timestamp; + var context = this.canvas.getContext('2d'); + context.clearRect(0, 0, this.canvas.width, this.canvas.height); + context.drawImage(this.background, 0, 0, this.canvas.width, this.canvas.height); + // select matching preset + var preset; + for (var i = 0; i < presets.length; i++) { + if (presets[i][2] > 1 || presets[i][3] === -1) { + if (presets[i][3] !== 0) { + presets[i][3]--; + for (var y = 0; y < presets[i][2]; ++y) { + this.putDrop(new Drop(this, Math.random() * this.canvas.width, Math.random() * this.canvas.height, presets[i][0], presets[i][1])); + } + } + } else if (Math.random() < presets[i][2]) { + preset = presets[i]; + break; + } + } + if (preset) { + this.putDrop(new Drop(this, Math.random() * this.canvas.width, Math.random() * this.canvas.height, preset[0], preset[1])); + } + context.save(); + context.globalAlpha = this.options.opacity; + context.drawImage(this.glass, 0, 0, this.canvas.width, this.canvas.height); + context.restore(); + } + .bind(this); +}; + +/** + * Adds a new raindrop to the animation. + * @param drop drop object to be added to the animation + */ +RainyDay.prototype.putDrop = function(drop) { + drop.draw(); + if (this.gravity && drop.r > this.options.gravityThreshold) { + if (this.options.enableCollisions) { + this.matrix.update(drop); + } + this.drops.push(drop); + } +}; + +/** + * Clear the drop and remove from the list if applicable. + * @drop to be cleared + * @force force removal from the list + * result if true animation of this drop should be stopped + */ +RainyDay.prototype.clearDrop = function(drop, force) { + var result = drop.clear(force); + if (result) { + var index = this.drops.indexOf(drop); + if (index >= 0) { + this.drops.splice(index, 1); + } + } + return result; +}; + +/** + * Defines a new raindrop object. + * @param rainyday reference to the parent object + * @param centerX x position of the center of this drop + * @param centerY y position of the center of this drop + * @param min minimum size of a drop + * @param base base value for randomizing drop size + */ + +function Drop(rainyday, centerX, centerY, min, base) { + this.x = Math.floor(centerX); + this.y = Math.floor(centerY); + this.r = (Math.random() * base) + min; + this.rainyday = rainyday; + this.context = rainyday.context; + this.reflection = rainyday.reflected; +} + +/** + * Draws a raindrop on canvas at the current position. + */ +Drop.prototype.draw = function() { + this.context.save(); + this.context.beginPath(); + + var orgR = this.r; + this.r = 0.95 * this.r; + if (this.r < 3) { + this.context.arc(this.x, this.y, this.r, 0, Math.PI * 2, true); + this.context.closePath(); + } else if (this.colliding || this.yspeed > 2) { + if (this.colliding) { + var collider = this.colliding; + this.r = 1.001 * (this.r > collider.r ? this.r : collider.r); + this.x += (collider.x - this.x); + this.colliding = null; + } + + var yr = 1 + 0.1 * this.yspeed; + this.context.moveTo(this.x - this.r / yr, this.y); + this.context.bezierCurveTo(this.x - this.r, this.y - this.r * 2, this.x + this.r, this.y - this.r * 2, this.x + this.r / yr, this.y); + this.context.bezierCurveTo(this.x + this.r, this.y + yr * this.r, this.x - this.r, this.y + yr * this.r, this.x - this.r / yr, this.y); + } else { + this.context.arc(this.x, this.y, this.r * 0.9, 0, Math.PI * 2, true); + this.context.closePath(); + } + + this.context.clip(); + + this.r = orgR; + + if (this.rainyday.reflection) { + this.rainyday.reflection(this); + } + + this.context.restore(); +}; + +/** + * Clears the raindrop region. + * @param force force stop + * @returns Boolean true if the animation is stopped + */ +Drop.prototype.clear = function(force) { + this.context.clearRect(this.x - this.r - 1, this.y - this.r - 2, 2 * this.r + 2, 2 * this.r + 2); + if (force) { + this.terminate = true; + return true; + } + if ((this.y - this.r > this.rainyday.canvas.height) || (this.x - this.r > this.rainyday.canvas.width) || (this.x + this.r < 0)) { + // over edge so stop this drop + return true; + } + return false; +}; + +/** + * Moves the raindrop to a new position according to the gravity. + */ +Drop.prototype.animate = function() { + if (this.terminate) { + return false; + } + var stopped = this.rainyday.gravity(this); + if (!stopped && this.rainyday.trail) { + this.rainyday.trail(this); + } + if (this.rainyday.options.enableCollisions) { + var collisions = this.rainyday.matrix.update(this, stopped); + if (collisions) { + this.rainyday.collision(this, collisions); + } + } + return !stopped || this.terminate; +}; + +/** + * TRAIL function: no trail at all + */ +RainyDay.prototype.TRAIL_NONE = function() { + // nothing going on here +}; + +/** + * TRAIL function: trail of small drops (default) + * @param drop raindrop object + */ +RainyDay.prototype.TRAIL_DROPS = function(drop) { + if (!drop.trailY || drop.y - drop.trailY >= Math.random() * 100 * drop.r) { + drop.trailY = drop.y; + var nDrop = new Drop(this, drop.x + (Math.random() * 2 - 1) * Math.random(), drop.y - drop.r - 5, Math.ceil(drop.r / 5), 0); + this.putDrop(nDrop); + //reduce the original drop area + drop.r = Math.sqrt(drop.r*drop.r - nDrop.r*nDrop.r); + } +}; + +/** + * TRAIL function: trail of unblurred image + * @param drop raindrop object + */ +RainyDay.prototype.TRAIL_SMUDGE = function(drop) { + var y = drop.y - drop.r - 3; + var x = drop.x - drop.r / 2 + (Math.random() * 2); + if (y < 0 || x < 0) { + return; + } + this.context.drawImage(this.clearbackground, x, y, drop.r, 2, x, y, drop.r, 2); +}; + +/** + * GRAVITY function: no gravity at all + * @returns Boolean true if the animation is stopped + */ +RainyDay.prototype.GRAVITY_NONE = function() { + return true; +}; + +/** + * GRAVITY function: linear gravity + * @param drop raindrop object + * @returns Boolean true if the animation is stopped + */ +RainyDay.prototype.GRAVITY_LINEAR = function(drop) { + if (this.clearDrop(drop)) { + return true; + } + + if (drop.yspeed) { + drop.yspeed += this.PRIVATE_GRAVITY_FORCE_FACTOR_Y * Math.floor(drop.r); + drop.xspeed += this.PRIVATE_GRAVITY_FORCE_FACTOR_X * Math.floor(drop.r); + } else { + drop.yspeed = this.PRIVATE_GRAVITY_FORCE_FACTOR_Y; + drop.xspeed = this.PRIVATE_GRAVITY_FORCE_FACTOR_X; + } + + drop.y += drop.yspeed; + drop.draw(); + return false; +}; + +/** + * GRAVITY function: real gravity + * @param drop raindrop object + * @returns Boolean true if the animation is stopped + */ +RainyDay.prototype.GRAVITY_REAL = function(drop) { + if (this.clearDrop(drop)) { + return true; + } + + if (drop.yspeed) { + friction = this.PRIVATE_BASE_FRICTION + Math.ceil(Math.random() * 9.8) / (Math.floor(drop.r) - this.presets[0][0] + 1); + drop.yspeed += Math.floor(9.8 - friction)/30; + if(drop.yspeed < 0) drop.yspeed = 0; + drop.xspeed += Math.floor(drop.r); + } else { + drop.yspeed = 0.01; + drop.xspeed = 0; + } + + drop.y += drop.yspeed; + drop.draw(); + return false; +}; + +/** + * GRAVITY function: non-linear gravity (default) + * @param drop raindrop object + * @returns Boolean true if the animation is stopped + */ +RainyDay.prototype.GRAVITY_NON_LINEAR = function(drop) { + if (this.clearDrop(drop)) { + return true; + } + + if (drop.collided) { + drop.collided = false; + drop.seed = Math.floor(drop.r * Math.random() * this.options.fps); + drop.skipping = false; + drop.slowing = false; + } else if (!drop.seed || drop.seed < 0) { + drop.seed = Math.floor(drop.r * Math.random() * this.options.fps); + drop.skipping = drop.skipping === false ? true : false; + drop.slowing = true; + } + + drop.seed--; + + if (drop.yspeed) { + if (drop.slowing) { + drop.yspeed /= 1.1; + drop.xspeed /= 1.1; + if (drop.yspeed < this.PRIVATE_GRAVITY_FORCE_FACTOR_Y) { + drop.slowing = false; + } + + } else if (drop.skipping) { + drop.yspeed = this.PRIVATE_GRAVITY_FORCE_FACTOR_Y; + drop.xspeed = this.PRIVATE_GRAVITY_FORCE_FACTOR_X; + } else { + drop.yspeed += 1 * this.PRIVATE_GRAVITY_FORCE_FACTOR_Y * Math.floor(drop.r); + drop.xspeed += 1 * this.PRIVATE_GRAVITY_FORCE_FACTOR_X * Math.floor(drop.r); + } + } else { + drop.yspeed = this.PRIVATE_GRAVITY_FORCE_FACTOR_Y; + drop.xspeed = this.PRIVATE_GRAVITY_FORCE_FACTOR_X; + } + + if (this.options.gravityAngleVariance !== 0) { + drop.xspeed += ((Math.random() * 2 - 1) * drop.yspeed * this.options.gravityAngleVariance); + } + + drop.y += drop.yspeed; + drop.x += drop.xspeed; + + drop.draw(); + return false; +}; + +/** + * Utility function to return positive min value + * @param val1 first number + * @param val2 second number + */ +RainyDay.prototype.positiveMin = function(val1, val2) { + var result = 0; + if (val1 < val2) { + if (val1 <= 0) { + result = val2; + } else { + result = val1; + } + } else { + if (val2 <= 0) { + result = val1; + } else { + result = val2; + } + } + return result <= 0 ? 1 : result; +}; + +/** + * REFLECTION function: no reflection at all + */ +RainyDay.prototype.REFLECTION_NONE = function() { + this.context.fillStyle = this.options.fillStyle; + this.context.fill(); +}; + +/** + * REFLECTION function: miniature reflection (default) + * @param drop raindrop object + */ +RainyDay.prototype.REFLECTION_MINIATURE = function(drop) { + var sx = Math.max((drop.x - this.options.reflectionDropMappingWidth) / this.options.reflectionScaledownFactor, 0); + var sy = Math.max((drop.y - this.options.reflectionDropMappingHeight) / this.options.reflectionScaledownFactor, 0); + var sw = this.positiveMin(this.options.reflectionDropMappingWidth * 2 / this.options.reflectionScaledownFactor, this.reflected.width - sx); + var sh = this.positiveMin(this.options.reflectionDropMappingHeight * 2 / this.options.reflectionScaledownFactor, this.reflected.height - sy); + var dx = Math.max(drop.x - 1.1 * drop.r, 0); + var dy = Math.max(drop.y - 1.1 * drop.r, 0); + this.context.drawImage(this.reflected, sx, sy, sw, sh, dx, dy, drop.r * 2, drop.r * 2); +}; + +/** + * COLLISION function: default collision implementation + * @param drop one of the drops colliding + * @param collisions list of potential collisions + */ +RainyDay.prototype.COLLISION_SIMPLE = function(drop, collisions) { + var item = collisions; + var drop2; + while (item != null) { + var p = item.drop; + var radiusSum = drop.r + p.r; + var dx = drop.x - p.x; + var dy = drop.y - p.y; + if(Math.abs(dx) < radiusSum) { + if(Math.abs(dy) < radiusSum) { + if (Math.sqrt(Math.pow(drop.x - p.x, 2) + Math.pow(drop.y - p.y, 2)) < (drop.r + p.r)) { + drop2 = p; + break; + } + } + } + item = item.next; + } + + if (!drop2) { + return; + } + + // rename so that we're dealing with low/high drops + var higher, + lower; + if (drop.y > drop2.y) { + higher = drop; + lower = drop2; + } else { + higher = drop2; + lower = drop; + } + + this.clearDrop(lower); + // force stopping the second drop + this.clearDrop(higher, true); + this.matrix.remove(higher); + lower.r = Math.sqrt(higher.r*higher.r + lower.r*lower.r);//merge drops' area + lower.draw(); + + lower.colliding = higher; + lower.collided = true; +}; + +/** + * Resizes canvas, draws original image and applies blurring algorithm. + */ +RainyDay.prototype.prepareBackground = function() { + this.background = document.createElement('canvas'); + this.background.width = this.canvas.width; + this.background.height = this.canvas.height; + + this.clearbackground = document.createElement('canvas'); + this.clearbackground.width = this.canvas.width; + this.clearbackground.height = this.canvas.height; + + var context = this.background.getContext('2d'); + context.clearRect(0, 0, this.canvas.width, this.canvas.height); + + context.drawImage(this.img, this.options.crop[0], this.options.crop[1], this.options.crop[2], this.options.crop[3], 0, 0, this.canvas.width, this.canvas.height); + + context = this.clearbackground.getContext('2d'); + context.clearRect(0, 0, this.canvas.width, this.canvas.height); + context.drawImage(this.img, this.options.crop[0], this.options.crop[1], this.options.crop[2], this.options.crop[3], 0, 0, this.canvas.width, this.canvas.height); + + if (!isNaN(this.options.blur) && this.options.blur >= 1) { + this.stackBlurCanvasRGB(this.canvas.width, this.canvas.height, this.options.blur); + } +}; + +/** + * Implements the Stack Blur Algorithm (@see http://www.quasimondo.com/StackBlurForCanvas/StackBlurDemo.html). + * @param width width of the canvas + * @param height height of the canvas + * @param radius blur radius + */ +RainyDay.prototype.stackBlurCanvasRGB = function(width, height, radius) { + + if(width == 0 || height == 0){ + console.info("canvas size empty."); + return; + } + var shgTable = [ + [0, 9], + [1, 11], + [2, 12], + [3, 13], + [5, 14], + [7, 15], + [11, 16], + [15, 17], + [22, 18], + [31, 19], + [45, 20], + [63, 21], + [90, 22], + [127, 23], + [181, 24] + ]; + + var mulTable = [ + 512, 512, 456, 512, 328, 456, 335, 512, 405, 328, 271, 456, 388, 335, 292, 512, + 454, 405, 364, 328, 298, 271, 496, 456, 420, 388, 360, 335, 312, 292, 273, 512, + 482, 454, 428, 405, 383, 364, 345, 328, 312, 298, 284, 271, 259, 496, 475, 456, + 437, 420, 404, 388, 374, 360, 347, 335, 323, 312, 302, 292, 282, 273, 265, 512, + 497, 482, 468, 454, 441, 428, 417, 405, 394, 383, 373, 364, 354, 345, 337, 328, + 320, 312, 305, 298, 291, 284, 278, 271, 265, 259, 507, 496, 485, 475, 465, 456, + 446, 437, 428, 420, 412, 404, 396, 388, 381, 374, 367, 360, 354, 347, 341, 335, + 329, 323, 318, 312, 307, 302, 297, 292, 287, 282, 278, 273, 269, 265, 261, 512, + 505, 497, 489, 482, 475, 468, 461, 454, 447, 441, 435, 428, 422, 417, 411, 405, + 399, 394, 389, 383, 378, 373, 368, 364, 359, 354, 350, 345, 341, 337, 332, 328, + 324, 320, 316, 312, 309, 305, 301, 298, 294, 291, 287, 284, 281, 278, 274, 271, + 268, 265, 262, 259, 257, 507, 501, 496, 491, 485, 480, 475, 470, 465, 460, 456, + 451, 446, 442, 437, 433, 428, 424, 420, 416, 412, 408, 404, 400, 396, 392, 388, + 385, 381, 377, 374, 370, 367, 363, 360, 357, 354, 350, 347, 344, 341, 338, 335, + 332, 329, 326, 323, 320, 318, 315, 312, 310, 307, 304, 302, 299, 297, 294, 292, + 289, 287, 285, 282, 280, 278, 275, 273, 271, 269, 267, 265, 263, 261, 259 + ]; + + radius |= 0; + + var context = this.background.getContext('2d'); + var imageData = context.getImageData(0, 0, width, height); + var pixels = imageData.data; + var x, + y, + i, + p, + yp, + yi, + yw, + rSum, + gSum, + bSum, + rOutSum, + gOutSum, + bOutSum, + rInSum, + gInSum, + bInSum, + pr, + pg, + pb, + rbs; + var radiusPlus1 = radius + 1; + var sumFactor = radiusPlus1 * (radiusPlus1 + 1) / 2; + + var stackStart = new BlurStack(); + var stackEnd = new BlurStack(); + var stack = stackStart; + for (i = 1; i < 2 * radius + 1; i++) { + stack = stack.next = new BlurStack(); + if (i === radiusPlus1) { + stackEnd = stack; + } + } + stack.next = stackStart; + var stackIn = null; + var stackOut = null; + + yw = yi = 0; + + var mulSum = mulTable[radius]; + var shgSum; + for (var ssi = 0; ssi < shgTable.length; ++ssi) { + if (radius <= shgTable[ssi][0]) { + shgSum = shgTable[ssi - 1][1]; + break; + } + } + + for (y = 0; y < height; y++) { + rInSum = gInSum = bInSum = rSum = gSum = bSum = 0; + + rOutSum = radiusPlus1 * (pr = pixels[yi]); + gOutSum = radiusPlus1 * (pg = pixels[yi + 1]); + bOutSum = radiusPlus1 * (pb = pixels[yi + 2]); + + rSum += sumFactor * pr; + gSum += sumFactor * pg; + bSum += sumFactor * pb; + + stack = stackStart; + + for (i = 0; i < radiusPlus1; i++) { + stack.r = pr; + stack.g = pg; + stack.b = pb; + stack = stack.next; + } + + for (i = 1; i < radiusPlus1; i++) { + p = yi + ((width - 1 < i ? width - 1 : i) << 2); + rSum += (stack.r = (pr = pixels[p])) * (rbs = radiusPlus1 - i); + gSum += (stack.g = (pg = pixels[p + 1])) * rbs; + bSum += (stack.b = (pb = pixels[p + 2])) * rbs; + + rInSum += pr; + gInSum += pg; + bInSum += pb; + + stack = stack.next; + } + + stackIn = stackStart; + stackOut = stackEnd; + for (x = 0; x < width; x++) { + pixels[yi] = (rSum * mulSum) >> shgSum; + pixels[yi + 1] = (gSum * mulSum) >> shgSum; + pixels[yi + 2] = (bSum * mulSum) >> shgSum; + + rSum -= rOutSum; + gSum -= gOutSum; + bSum -= bOutSum; + + rOutSum -= stackIn.r; + gOutSum -= stackIn.g; + bOutSum -= stackIn.b; + + p = (yw + ((p = x + radius + 1) < (width - 1) ? p : (width - 1))) << 2; + + rInSum += (stackIn.r = pixels[p]); + gInSum += (stackIn.g = pixels[p + 1]); + bInSum += (stackIn.b = pixels[p + 2]); + + rSum += rInSum; + gSum += gInSum; + bSum += bInSum; + + stackIn = stackIn.next; + + rOutSum += (pr = stackOut.r); + gOutSum += (pg = stackOut.g); + bOutSum += (pb = stackOut.b); + + rInSum -= pr; + gInSum -= pg; + bInSum -= pb; + + stackOut = stackOut.next; + + yi += 4; + } + yw += width; + } + + for (x = 0; x < width; x++) { + gInSum = bInSum = rInSum = gSum = bSum = rSum = 0; + + yi = x << 2; + rOutSum = radiusPlus1 * (pr = pixels[yi]); + gOutSum = radiusPlus1 * (pg = pixels[yi + 1]); + bOutSum = radiusPlus1 * (pb = pixels[yi + 2]); + + rSum += sumFactor * pr; + gSum += sumFactor * pg; + bSum += sumFactor * pb; + + stack = stackStart; + + for (i = 0; i < radiusPlus1; i++) { + stack.r = pr; + stack.g = pg; + stack.b = pb; + stack = stack.next; + } + + yp = width; + + for (i = 1; i < radiusPlus1; i++) { + yi = (yp + x) << 2; + + rSum += (stack.r = (pr = pixels[yi])) * (rbs = radiusPlus1 - i); + gSum += (stack.g = (pg = pixels[yi + 1])) * rbs; + bSum += (stack.b = (pb = pixels[yi + 2])) * rbs; + + rInSum += pr; + gInSum += pg; + bInSum += pb; + + stack = stack.next; + + if (i < (height - 1)) { + yp += width; + } + } + + yi = x; + stackIn = stackStart; + stackOut = stackEnd; + for (y = 0; y < height; y++) { + p = yi << 2; + pixels[p] = (rSum * mulSum) >> shgSum; + pixels[p + 1] = (gSum * mulSum) >> shgSum; + pixels[p + 2] = (bSum * mulSum) >> shgSum; + + rSum -= rOutSum; + gSum -= gOutSum; + bSum -= bOutSum; + + rOutSum -= stackIn.r; + gOutSum -= stackIn.g; + bOutSum -= stackIn.b; + + p = (x + (((p = y + radiusPlus1) < (height - 1) ? p : (height - 1)) * width)) << 2; + + rSum += (rInSum += (stackIn.r = pixels[p])); + gSum += (gInSum += (stackIn.g = pixels[p + 1])); + bSum += (bInSum += (stackIn.b = pixels[p + 2])); + + stackIn = stackIn.next; + + rOutSum += (pr = stackOut.r); + gOutSum += (pg = stackOut.g); + bOutSum += (pb = stackOut.b); + + rInSum -= pr; + gInSum -= pg; + bInSum -= pb; + + stackOut = stackOut.next; + + yi += width; + } + } + + context.putImageData(imageData, 0, 0); + +}; + +/** + * Defines a new helper object for Stack Blur Algorithm. + */ +function BlurStack() { + this.r = 0; + this.g = 0; + this.b = 0; + this.next = null; +} + +/** + * Defines a gravity matrix object which handles collision detection. + * @param x number of columns in the matrix + * @param y number of rows in the matrix + * @param r grid size + */ +function CollisionMatrix(x, y, r) { + this.resolution = r; + this.xc = x; + this.yc = y; + this.matrix = new Array(x); + for (var i = 0; i <= (x + 5); i++) { + this.matrix[i] = new Array(y); + for (var j = 0; j <= (y + 5); ++j) { + this.matrix[i][j] = new DropItem(null); + } + } +} + +/** + * Updates position of the given drop on the collision matrix. + * @param drop raindrop to be positioned/repositioned + * @param forceDelete if true the raindrop will be removed from the matrix + * @returns collisions if any + */ +CollisionMatrix.prototype.update = function(drop, forceDelete) { + if (drop.gid) { + if (!this.matrix[drop.gmx] || !this.matrix[drop.gmx][drop.gmy]) { + return null; + } + this.matrix[drop.gmx][drop.gmy].remove(drop); + if (forceDelete) { + return null; + } + + drop.gmx = Math.floor(drop.x / this.resolution); + drop.gmy = Math.floor(drop.y / this.resolution); + if (!this.matrix[drop.gmx] || !this.matrix[drop.gmx][drop.gmy]) { + return null; + } + this.matrix[drop.gmx][drop.gmy].add(drop); + + var collisions = this.collisions(drop); + if (collisions && collisions.next != null) { + return collisions.next; + } + } else { + drop.gid = Math.random().toString(36).substr(2, 9); + drop.gmx = Math.floor(drop.x / this.resolution); + drop.gmy = Math.floor(drop.y / this.resolution); + if (!this.matrix[drop.gmx] || !this.matrix[drop.gmx][drop.gmy]) { + return null; + } + + this.matrix[drop.gmx][drop.gmy].add(drop); + } + return null; +}; + +/** + * Looks for collisions with the given raindrop. + * @param drop raindrop to be checked + * @returns DropItem list of drops that collide with it + */ +CollisionMatrix.prototype.collisions = function(drop) { + var item = new DropItem(null); + var first = item; + + item = this.addAll(item, drop.gmx - 1, drop.gmy + 1); + item = this.addAll(item, drop.gmx, drop.gmy + 1); + item = this.addAll(item, drop.gmx + 1, drop.gmy + 1); + + return first; +}; + +/** + * Appends all found drop at a given location to the given item. + * @param to item to which the results will be appended to + * @param x x position in the matrix + * @param y y position in the matrix + * @returns last discovered item on the list + */ +CollisionMatrix.prototype.addAll = function(to, x, y) { + if (x > 0 && y > 0 && x < this.xc && y < this.yc) { + var items = this.matrix[x][y]; + while (items.next != null) { + items = items.next; + to.next = new DropItem(items.drop); + to = to.next; + } + } + return to; +}; + +/** + * Removed the drop from its current position + * @param drop to be removed + */ +CollisionMatrix.prototype.remove = function(drop) { + this.matrix[drop.gmx][drop.gmy].remove(drop); +}; + +/** + * Defines a linked list item. + */ +function DropItem(drop) { + this.drop = drop; + this.next = null; +} + +/** + * Adds the raindrop to the end of the list. + * @param drop raindrop to be added + */ +DropItem.prototype.add = function(drop) { + var item = this; + while (item.next != null) { + item = item.next; + } + item.next = new DropItem(drop); +}; + +/** + * Removes the raindrop from the list. + * @param drop raindrop to be removed + */ +DropItem.prototype.remove = function(drop) { + var item = this; + var prevItem = null; + while (item.next != null) { + prevItem = item; + item = item.next; + if (item.drop.gid === drop.gid) { + prevItem.next = item.next; + } + } +}; diff --git a/app/src/main/assets/js/rainyday.min.js b/app/src/main/assets/js/rainyday.min.js new file mode 100644 index 0000000..dbc7eb0 --- /dev/null +++ b/app/src/main/assets/js/rainyday.min.js @@ -0,0 +1,888 @@ +/** + * Defines a new instance of the rainyday.js. + * @param canvasid DOM id of the canvas used for rendering + * @param sourceid DOM id of the image element used as background image + * @param width width of the rendering + * @param height height of the rendering + * @param opacity opacity attribute value of the glass canvas (default: 1) + * @param blur blur radius (default: 20) + */ + +function RainyDay(canvasid, sourceid, width, height, opacity, blur) { + this.canvasid = canvasid; + this.canvas = document.getElementById(canvasid); + + this.sourceid = sourceid; + this.img = document.getElementById(sourceid); + + // draw and blur the backgroiund image + this.prepareBackground(blur ? blur : 20, width, height); + this.w = this.canvas.width; + this.h = this.canvas.height; + + // create the glass canvas + this.prepareGlass(opacity ? opacity : 1); + + // assume default reflection mechanism + this.reflection = this.REFLECTION_MINIATURE; + + // assume default trail mechanism + this.trail = this.TRAIL_DROPS; + + // assume default gravity + this.gravity = this.GRAVITY_NON_LINEAR; + + // drop size threshold for the gravity algorhitm + this.VARIABLE_GRAVITY_THRESHOLD = 3; + + // gravity angle + this.VARIABLE_GRAVITY_ANGLE = Math.PI / 2; + + // frames per second animation speed + this.VARIABLE_FPS = 25; + + // context fill style when no REFLECTION_NONE is used + this.VARIABLE_FILL_STYLE = '#8ED6FF'; + + // collisions enabled by default + this.VARIABLE_COLLISIONS = false; + + // assume default collision algorhitm + this.collision = this.COLLISION_SIMPLE; +} + +/** + * Create the helper canvas for rendering raindrop reflections. + */ +RainyDay.prototype.prepareReflections = function() { + // new canvas + this.reflected = document.createElement('canvas'); + this.reflected.width = this.canvas.width; + this.reflected.height = this.canvas.height; + + var ctx = this.reflected.getContext('2d'); + + // rotate by 180 degress + ctx.translate(this.reflected.width / 2, this.reflected.height / 2); + ctx.rotate(Math.PI); + + ctx.drawImage(this.img, -this.reflected.width / 2, -this.reflected.height / 2, this.reflected.width, this.reflected.height); +}; + +/** + * Create the glass canvas and position it directly over the main one. + * @param opacity opacity attribute value of the glass canvas + */ +RainyDay.prototype.prepareGlass = function(opacity) { + this.glass = document.createElement('canvas'); + this.glass.width = this.canvas.width; + this.glass.height = this.canvas.height; + this.glass.style.position = "absolute"; + this.glass.style.top = this.canvas.offsetTop; + this.glass.style.left = this.canvas.offsetLeft; + this.glass.style.zIndex = this.canvas.style.zIndex + 100; + this.canvas.parentNode.appendChild(this.glass); + this.context = this.glass.getContext('2d'); + this.glass.style.opacity = opacity; +}; + +/** + * Creates a new preset object with given attributes. + * @param min minimum size of a drop + * @param base base value for randomizing drop size + * @param quan probability of selecting this preset (must be between 0 and 1) + * @returns present object with given attributes + */ +RainyDay.prototype.preset = function(min, base, quan) { + return { + "min": min, + "base": base, + "quan": quan + } +}; + +/** + * Main function for starting rain rendering. + * @param presets list of presets to be applied + * @param speed speed of the animation (if not provided or 0 static image will be generated) + */ +RainyDay.prototype.rain = function(presets, speed) { + // prepare canvas for drop reflections + if (this.reflection != this.REFLECTION_NONE) { + this.prepareReflections(); + } + + if (speed > 0) { + // animation + this.presets = presets; + + this.PRIVATE_GRAVITY_FORCE_FACTOR_Y = (this.VARIABLE_FPS * 0.005) / 25; + this.PRIVATE_GRAVITY_FORCE_FACTOR_X = ((Math.PI / 2) - this.VARIABLE_GRAVITY_ANGLE) * (this.VARIABLE_FPS * 0.005) / 50; + + // prepare gravity matrix + if (this.VARIABLE_COLLISIONS) { + + // calculate max radius of a drop to establish gravity matrix resolution + var maxDropRadius = 0; + for (var i = 0; i < presets.length; i++) { + if (presets[i].base + presets[i].min > maxDropRadius) { + maxDropRadius = Math.floor(presets[i].base + presets[i].min); + } + } + + if (maxDropRadius > 0) { + // initialize the gravity matrix + var mwi = Math.ceil(this.w / maxDropRadius); + var mhi = Math.ceil(this.h / maxDropRadius); + this.matrix = new CollisionMatrix(mwi, mhi, maxDropRadius); + } else { + this.VARIABLE_COLLISIONS = false; + } + } + + setInterval( + (function(self) { + return function() { + var random = Math.random(); + // select matching preset + var preset; + for (var i = 0; i < presets.length; i++) { + if (random < presets[i].quan) { + preset = presets[i]; + break; + } + } + if (preset) { + self.putDrop(new Drop(self, Math.random() * self.w, Math.random() * self.h, preset.min, preset.base)); + } + } + })(this), + speed + ); + } else { + // static picture + for (var i = 0; i < presets.length; i++) { + var preset = presets[i]; + for (var c = 0; c < preset.quan; ++c) { + this.putDrop(new Drop(this, Math.random() * this.w, Math.random() * this.h, preset.min, preset.base)); + } + } + } +}; +/** + * Adds a new raindrop to the animation. + * @param drop drop object to be added to the animation + */ +RainyDay.prototype.putDrop = function(drop) { + drop.draw(); + if (this.gravity && drop.r1 > this.VARIABLE_GRAVITY_THRESHOLD) { + + if (this.VARIABLE_COLLISIONS) { + // put on the gravity matrix + this.matrix.update(drop); + } + + drop.animate(); + } +}; +/** + * Imperfectly approximates shape of a circle. + * @param iterations number of iterations applied to the size approximation algorithm + * @returns list of points approximating a circle shape + */ +RainyDay.prototype.getLinepoints = function(iterations) { + var pointList = {}; + pointList.first = { + x: 0, + y: 1 + }; + var lastPoint = { + x: 1, + y: 1 + } + var minY = 1; + var maxY = 1; + var point; + var nextPoint; + var dx, newX, newY; + + pointList.first.next = lastPoint; + for (var i = 0; i < iterations; i++) { + point = pointList.first; + while (point.next != null) { + nextPoint = point.next; + + dx = nextPoint.x - point.x; + newX = 0.5 * (point.x + nextPoint.x); + newY = 0.5 * (point.y + nextPoint.y); + newY += dx * (Math.random() * 2 - 1); + + var newPoint = { + x: newX, + y: newY + }; + + //min, max + if (newY < minY) { + minY = newY; + } else if (newY > maxY) { + maxY = newY; + } + + //put between points + newPoint.next = nextPoint; + point.next = newPoint; + + point = nextPoint; + } + } + + //normalize to values between 0 and 1 + if (maxY != minY) { + var normalizeRate = 1 / (maxY - minY); + point = pointList.first; + while (point != null) { + point.y = normalizeRate * (point.y - minY); + point = point.next; + } + } else { + point = pointList.first; + while (point != null) { + point.y = 1; + point = point.next; + } + } + + return pointList; +}; + +/** + * Defines a new raindrop object. + * @param rainyday reference to the parent object + * @param centerX x position of the center of this drop + * @param centerY y position of the center of this drop + * @param min minimum size of a drop + * @param base base value for randomizing drop size + */ + +function Drop(rainyday, centerX, centerY, min, base) { + this.x = Math.floor(centerX); + this.y = Math.floor(centerY); + this.r1 = (Math.random() * base) + min; + this.rainyday = rainyday; + var iterations = 4; + this.r2 = 0.8 * this.r1; + this.linepoints = rainyday.getLinepoints(iterations); + this.context = rainyday.context; + this.reflection = rainyday.reflected; +} + +/** + * Draws a raindrop on canvas at the current position. + */ +Drop.prototype.draw = function() { + var phase = 0; + var point; + var rad, theta; + var x0, y0; + + this.context.save(); + this.context.beginPath(); + point = this.linepoints.first; + theta = phase; + rad = this.r2 + 0.5 * Math.random() * (this.r2 - this.r1); + x0 = this.x + rad * Math.cos(theta); + y0 = this.y + rad * Math.sin(theta); + this.context.lineTo(x0, y0); + while (point.next != null) { + point = point.next; + theta = (Math.PI * 2 * point.x) + phase; + rad = this.r2 + 0.5 * Math.random() * (this.r2 - this.r1); + x0 = this.x + rad * Math.cos(theta); + y0 = this.y + rad * Math.sin(theta); + this.context.lineTo(x0, y0); + } + + this.context.clip(); + + if (this.rainyday.reflection) { + this.rainyday.reflection(this); + } + + this.context.restore(); +}; + +/** + * Clears the raindrop region. + * @param force force stop + * @returns true if the animation is stopped + */ +Drop.prototype.clear = function(force) { + this.context.clearRect(this.x - this.r1 - 1, this.y - this.r1 - 1, 2 * this.r1 + 2, 2 * this.r1 + 2); + if (force) { + // forced + clearInterval(this.intid); + return true; + } + if (this.y - this.r1 > this.rainyday.h) { + // over the bottom edge, stop the thread + clearInterval(this.intid); + return true; + } + if ((this.x - this.r1 > this.rainyday.w) || (this.x + this.r1 < 0)) { + // over the right or left edge, stop the thread + clearInterval(this.intid); + return true; + } + return false; +}; + +/** + * Moves the raindrop to a new position according to the gravity. + */ +Drop.prototype.animate = function() { + this.intid = setInterval( + (function(self) { + return function() { + var stopped = self.rainyday.gravity(self); + if (!stopped && self.rainyday.trail) { + self.rainyday.trail(self); + } + if (self.rainyday.VARIABLE_COLLISIONS) { + var collision = self.rainyday.matrix.update(self, stopped); + if (collision) { + self.rainyday.collision(self, collision.drop); + } + } + } + })(this), + Math.floor(1000 / this.rainyday.VARIABLE_FPS) + ); +}; + +/** + * TRAIL function: no trail at all + * @param drop raindrop object + */ +RainyDay.prototype.TRAIL_NONE = function(drop) { + // nothing going on here +}; + +/** + * TRAIL function: trail of small drops (default) + * @param drop raindrop object + */ +RainyDay.prototype.TRAIL_DROPS = function(drop) { + if (!drop.trail_y || drop.y - drop.trail_y >= Math.random() * 10 * drop.r1) { + drop.trail_y = drop.y; + this.putDrop(new Drop(this, drop.x, drop.y - drop.r1 - 5, 0, Math.ceil(drop.r1 / 5))); + } +}; +/** + * GRAVITY function: no gravity at all + * @param drop raindrop object + * @returns true if the animation is stopped + */ +RainyDay.prototype.GRAVITY_NONE = function(drop) { + return true; +}; + +/** + * GRAVITY function: linear gravity + * @param drop raindrop object + * @returns true if the animation is stopped + */ +RainyDay.prototype.GRAVITY_LINEAR = function(drop) { + if (drop.clear()) { + return true; + } + + if (drop.yspeed) { + drop.yspeed += this.PRIVATE_GRAVITY_FORCE_FACTOR_Y * Math.floor(drop.r1); + drop.xspeed += this.PRIVATE_GRAVITY_FORCE_FACTOR_X * Math.floor(drop.r1); + } else { + drop.yspeed = this.PRIVATE_GRAVITY_FORCE_FACTOR_Y; + drop.xspeed = this.PRIVATE_GRAVITY_FORCE_FACTOR_X; + } + + drop.y += drop.yspeed; + drop.draw(); + return false; +}; + +/** + * GRAVITY function: non-linear gravity (default) + * @param drop raindrop object + * @returns true if the animation is stopped + */ +RainyDay.prototype.GRAVITY_NON_LINEAR = function(drop) { + if (drop.clear()) { + return true; + } + + if (!drop.seed || drop.seed < 0) { + drop.seed = Math.floor(Math.random() * this.VARIABLE_FPS); + drop.skipping = drop.skipping == false ? true : false; + drop.slowing = true; + } + + drop.seed--; + + if (drop.yspeed) { + if (drop.slowing) { + drop.yspeed /= 1.1; + drop.xspeed /= 1.1; + if (drop.yspeed < this.PRIVATE_GRAVITY_FORCE_FACTOR_Y) { + drop.slowing = false; + } + } else if (drop.skipping) { + drop.yspeed = this.PRIVATE_GRAVITY_FORCE_FACTOR_Y; + drop.xspeed = this.PRIVATE_GRAVITY_FORCE_FACTOR_X; + } else { + drop.yspeed += 10 * this.PRIVATE_GRAVITY_FORCE_FACTOR_Y * Math.floor(drop.r1); + drop.xspeed += 10 * this.PRIVATE_GRAVITY_FORCE_FACTOR_X * Math.floor(drop.r1); + } + } else { + drop.yspeed = this.PRIVATE_GRAVITY_FORCE_FACTOR_Y; + drop.xspeed = this.PRIVATE_GRAVITY_FORCE_FACTOR_X; + } + + drop.y += drop.yspeed; + drop.x += drop.xspeed; + + drop.draw(); + return false; +}; +/** + * REFLECTION function: no reflection at all + * @param drop raindrop object + */ +RainyDay.prototype.REFLECTION_NONE = function(drop) { + this.context.fillStyle = this.VARIABLE_FILL_STYLE; + this.context.fill(); +}; + +/** + * REFLECTION function: miniature reflection (default) + * @param drop raindrop object + */ +RainyDay.prototype.REFLECTION_MINIATURE = function(drop) { + this.context.drawImage(this.reflected, drop.x - drop.r1, drop.y - drop.r1, drop.r1 * 2, drop.r1 * 2); +}; + +/** + * COLLISION function: default collision implementation + * @param drop1 one of the drops colliding + * @param drop2 the other one + */ +RainyDay.prototype.COLLISION_SIMPLE = function(drop1, drop2) { + drop1.clear(); + // force stopping the second drop + drop2.clear(true); + + drop1.x = (drop1.x + drop2.x) / 2; + drop1.y = (drop1.y + drop2.y) / 2; +}; + +var mul_table = [ + 512, 512, 456, 512, 328, 456, 335, 512, 405, 328, 271, 456, 388, 335, 292, 512, + 454, 405, 364, 328, 298, 271, 496, 456, 420, 388, 360, 335, 312, 292, 273, 512, + 482, 454, 428, 405, 383, 364, 345, 328, 312, 298, 284, 271, 259, 496, 475, 456, + 437, 420, 404, 388, 374, 360, 347, 335, 323, 312, 302, 292, 282, 273, 265, 512, + 497, 482, 468, 454, 441, 428, 417, 405, 394, 383, 373, 364, 354, 345, 337, 328, + 320, 312, 305, 298, 291, 284, 278, 271, 265, 259, 507, 496, 485, 475, 465, 456, + 446, 437, 428, 420, 412, 404, 396, 388, 381, 374, 367, 360, 354, 347, 341, 335, + 329, 323, 318, 312, 307, 302, 297, 292, 287, 282, 278, 273, 269, 265, 261, 512, + 505, 497, 489, 482, 475, 468, 461, 454, 447, 441, 435, 428, 422, 417, 411, 405, + 399, 394, 389, 383, 378, 373, 368, 364, 359, 354, 350, 345, 341, 337, 332, 328, + 324, 320, 316, 312, 309, 305, 301, 298, 294, 291, 287, 284, 281, 278, 274, 271, + 268, 265, 262, 259, 257, 507, 501, 496, 491, 485, 480, 475, 470, 465, 460, 456, + 451, 446, 442, 437, 433, 428, 424, 420, 416, 412, 408, 404, 400, 396, 392, 388, + 385, 381, 377, 374, 370, 367, 363, 360, 357, 354, 350, 347, 344, 341, 338, 335, + 332, 329, 326, 323, 320, 318, 315, 312, 310, 307, 304, 302, 299, 297, 294, 292, + 289, 287, 285, 282, 280, 278, 275, 273, 271, 269, 267, 265, 263, 261, 259 +]; + +var shg_table = [ + 9, 11, 12, 13, 13, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 17, + 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 18, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24 +]; + +/** + * Resizes canvas, draws original image and applies bluring algorithm. + * @param radius blur radius to be applied + * @param width width of the canvas + * @param height height of the canvas + */ +RainyDay.prototype.prepareBackground = function(radius, width, height) { + if (width && height) { + this.canvas.style.width = width + "px"; + this.canvas.style.height = height + "px"; + this.canvas.width = width; + this.canvas.height = height; + } else { + width = this.canvas.width; + height = this.canvas.height; + } + + var context = this.canvas.getContext("2d"); + context.clearRect(0, 0, width, height); + context.drawImage(this.img, 0, 0, width, height); + + if (isNaN(radius) || radius < 1) return; + + this.stackBlurCanvasRGB(0, 0, width, height, radius); +}; + +/** + * Implements the Stack Blur Algorithm (@see http://www.quasimondo.com/StackBlurForCanvas/StackBlurDemo.html). + * @param top_x x of top-left corner of the blurred rectangle + * @param top_y y of top-left corner of the blurred rectangle + * @param width width of the canvas + * @param height height of the canvas + * @param radius blur radius + */ +RainyDay.prototype.stackBlurCanvasRGB = function(top_x, top_y, width, height, radius) { + radius |= 0; + + var context = this.canvas.getContext("2d"); + var imageData = context.getImageData(top_x, top_y, width, height); + + var pixels = imageData.data; + + var x, y, i, p, yp, yi, yw, r_sum, g_sum, b_sum, + r_out_sum, g_out_sum, b_out_sum, + r_in_sum, g_in_sum, b_in_sum, + pr, pg, pb, rbs; + + var div = radius + radius + 1; + var w4 = width << 2; + var widthMinus1 = width - 1; + var heightMinus1 = height - 1; + var radiusPlus1 = radius + 1; + var sumFactor = radiusPlus1 * (radiusPlus1 + 1) / 2; + + var stackStart = new BlurStack(); + var stack = stackStart; + for (i = 1; i < div; i++) { + stack = stack.next = new BlurStack(); + if (i == radiusPlus1) var stackEnd = stack; + } + stack.next = stackStart; + var stackIn = null; + var stackOut = null; + + yw = yi = 0; + + var mul_sum = mul_table[radius]; + var shg_sum = shg_table[radius]; + + for (y = 0; y < height; y++) { + r_in_sum = g_in_sum = b_in_sum = r_sum = g_sum = b_sum = 0; + + r_out_sum = radiusPlus1 * (pr = pixels[yi]); + g_out_sum = radiusPlus1 * (pg = pixels[yi + 1]); + b_out_sum = radiusPlus1 * (pb = pixels[yi + 2]); + + r_sum += sumFactor * pr; + g_sum += sumFactor * pg; + b_sum += sumFactor * pb; + + stack = stackStart; + + for (i = 0; i < radiusPlus1; i++) { + stack.r = pr; + stack.g = pg; + stack.b = pb; + stack = stack.next; + } + + for (i = 1; i < radiusPlus1; i++) { + p = yi + ((widthMinus1 < i ? widthMinus1 : i) << 2); + r_sum += (stack.r = (pr = pixels[p])) * (rbs = radiusPlus1 - i); + g_sum += (stack.g = (pg = pixels[p + 1])) * rbs; + b_sum += (stack.b = (pb = pixels[p + 2])) * rbs; + + r_in_sum += pr; + g_in_sum += pg; + b_in_sum += pb; + + stack = stack.next; + } + + stackIn = stackStart; + stackOut = stackEnd; + for (x = 0; x < width; x++) { + pixels[yi] = (r_sum * mul_sum) >> shg_sum; + pixels[yi + 1] = (g_sum * mul_sum) >> shg_sum; + pixels[yi + 2] = (b_sum * mul_sum) >> shg_sum; + + r_sum -= r_out_sum; + g_sum -= g_out_sum; + b_sum -= b_out_sum; + + r_out_sum -= stackIn.r; + g_out_sum -= stackIn.g; + b_out_sum -= stackIn.b; + + p = (yw + ((p = x + radius + 1) < widthMinus1 ? p : widthMinus1)) << 2; + + r_in_sum += (stackIn.r = pixels[p]); + g_in_sum += (stackIn.g = pixels[p + 1]); + b_in_sum += (stackIn.b = pixels[p + 2]); + + r_sum += r_in_sum; + g_sum += g_in_sum; + b_sum += b_in_sum; + + stackIn = stackIn.next; + + r_out_sum += (pr = stackOut.r); + g_out_sum += (pg = stackOut.g); + b_out_sum += (pb = stackOut.b); + + r_in_sum -= pr; + g_in_sum -= pg; + b_in_sum -= pb; + + stackOut = stackOut.next; + + yi += 4; + } + yw += width; + } + + + for (x = 0; x < width; x++) { + g_in_sum = b_in_sum = r_in_sum = g_sum = b_sum = r_sum = 0; + + yi = x << 2; + r_out_sum = radiusPlus1 * (pr = pixels[yi]); + g_out_sum = radiusPlus1 * (pg = pixels[yi + 1]); + b_out_sum = radiusPlus1 * (pb = pixels[yi + 2]); + + r_sum += sumFactor * pr; + g_sum += sumFactor * pg; + b_sum += sumFactor * pb; + + stack = stackStart; + + for (i = 0; i < radiusPlus1; i++) { + stack.r = pr; + stack.g = pg; + stack.b = pb; + stack = stack.next; + } + + yp = width; + + for (i = 1; i <= radius; i++) { + yi = (yp + x) << 2; + + r_sum += (stack.r = (pr = pixels[yi])) * (rbs = radiusPlus1 - i); + g_sum += (stack.g = (pg = pixels[yi + 1])) * rbs; + b_sum += (stack.b = (pb = pixels[yi + 2])) * rbs; + + r_in_sum += pr; + g_in_sum += pg; + b_in_sum += pb; + + stack = stack.next; + + if (i < heightMinus1) { + yp += width; + } + } + + yi = x; + stackIn = stackStart; + stackOut = stackEnd; + for (y = 0; y < height; y++) { + p = yi << 2; + pixels[p] = (r_sum * mul_sum) >> shg_sum; + pixels[p + 1] = (g_sum * mul_sum) >> shg_sum; + pixels[p + 2] = (b_sum * mul_sum) >> shg_sum; + + r_sum -= r_out_sum; + g_sum -= g_out_sum; + b_sum -= b_out_sum; + + r_out_sum -= stackIn.r; + g_out_sum -= stackIn.g; + b_out_sum -= stackIn.b; + + p = (x + (((p = y + radiusPlus1) < heightMinus1 ? p : heightMinus1) * width)) << 2; + + r_sum += (r_in_sum += (stackIn.r = pixels[p])); + g_sum += (g_in_sum += (stackIn.g = pixels[p + 1])); + b_sum += (b_in_sum += (stackIn.b = pixels[p + 2])); + + stackIn = stackIn.next; + + r_out_sum += (pr = stackOut.r); + g_out_sum += (pg = stackOut.g); + b_out_sum += (pb = stackOut.b); + + r_in_sum -= pr; + g_in_sum -= pg; + b_in_sum -= pb; + + stackOut = stackOut.next; + + yi += width; + } + } + + context.putImageData(imageData, top_x, top_y); + +}; + +/** + * Defines a new helper object for Stack Blur Algorithm. + */ + +function BlurStack() { + this.r = 0; + this.g = 0; + this.b = 0; + this.a = 0; + this.next = null; +} + +/** + * Defines a gravity matrix object which handles collision detection. + * @param x number of columns in the matrix + * @param y number of rows in the matrix + * @param r grid size + */ + +function CollisionMatrix(x, y, r) { + this.resolution = r; + this.xc = x; + this.yc = y; + this.matrix = new Array(x); + for (var i = 0; i <= (x + 5); i++) { + this.matrix[i] = Array(y); + for (var j = 0; j <= (y + 5); ++j) { + this.matrix[i][j] = new DropItem(null); + } + } +} + +/** + * Updates position of the given drop on the collision matrix. + * @param drop raindrop to be positioned/repositioned + * @forceDelete if true the raindrop will be removed from the matrix + * @returns collisions if any + */ +CollisionMatrix.prototype.update = function(drop, forceDelete) { + if (drop.gid) { + this.matrix[drop.gmx][drop.gmy].remove(drop); + if (forceDelete) { + return null; + } + + drop.gmx = Math.floor(drop.x / this.resolution); + drop.gmy = Math.floor(drop.y / this.resolution); + this.matrix[drop.gmx][drop.gmy].add(drop); + + var collisions = this.collisions(drop); + if (collisions && collisions.next != null) { + return collisions.next; + } + } else { + drop.gid = Math.random().toString(36).substr(2, 9); + drop.gmx = Math.floor(drop.x / this.resolution); + drop.gmy = Math.floor(drop.y / this.resolution); + this.matrix[drop.gmx][drop.gmy].add(drop); + } + return null; +}; + +/** + * Looks for collisions with the given raindrop. + * @param drop raindrop to be checked + * @returns list of drops that collide with it + */ +CollisionMatrix.prototype.collisions = function(drop) { + var item = new DropItem(null); + var first = item; + + item = this.addAll(item, drop.gmx - 1, drop.gmy); + item = this.addAll(item, drop.gmx - 1, drop.gmy + 1); + item = this.addAll(item, drop.gmx, drop.gmy + 1); + item = this.addAll(item, drop.gmx + 1, drop.gmy + 1); + item = this.addAll(item, drop.gmx + 1, drop.gmy); + + return first; +}; + +/** + * Appends all found drop at a given location to the given item. + * @param to item to which the results will be appended to + * @param x x position in the matrix + * @param y y position in the matrix + * @returns last discovered item on the list + */ +CollisionMatrix.prototype.addAll = function(to, x, y) { + if (x > 0 && y > 0 && x < this.xc && y < this.yc) { + var items = this.matrix[x][y]; + while (items.next != null) { + items = items.next; + to.next = new DropItem(items.drop); + to = to.next; + } + } + return to; +}; + +/** + * Defines a linked list item. + */ + +function DropItem(drop) { + this.drop = drop; + this.next = null; +} + +/** + * Adds the raindrop to the end of the list. + * @param drop raindrop to be added + */ +DropItem.prototype.add = function(drop) { + var item = this; + while (item.next != null) { + item = item.next; + } + item.next = new DropItem(drop); +}; + +/** + * Removes the raindrop from the list. + * @param drop raindrop to be removed + */ +DropItem.prototype.remove = function(drop) { + var item = this; + var prevItem = null; + while (item.next != null) { + prevItem = item; + item = item.next; + if (item.drop.gid == drop.gid) { + prevItem.next = item.next; + } + } +}; diff --git a/app/src/main/assets/js/script.js b/app/src/main/assets/js/script.js new file mode 100644 index 0000000..a8a3941 --- /dev/null +++ b/app/src/main/assets/js/script.js @@ -0,0 +1,192 @@ +!function(){"use strict";var r=.5*(Math.sqrt(3)-1),e=(3-Math.sqrt(3))/6,t=1/6,a=(Math.sqrt(5)-1)/4,o=(5-Math.sqrt(5))/20;function i(r){var e;e="function"==typeof r?r:r?function(){var r=0,e=0,t=0,a=1,o=(i=4022871197,function(r){r=r.toString();for(var e=0;e>>0,i=(t*=i)>>>0,i+=4294967296*(t-=i)}return 2.3283064365386963e-10*(i>>>0)});var i;r=o(" "),e=o(" "),t=o(" ");for(var n=0;nc?(o=1,i=0):(o=0,i=1);var y=m-o+e,w=c-i+e,g=m-1+2*e,A=c-1+2*e,x=255&d,q=255&p,D=.5-m*m-c*c;if(D>=0){var S=3*n[x+f[q]];v=(D*=D)*D*(s[S]*m+s[S+1]*c)}var U=.5-y*y-w*w;if(U>=0){var b=3*n[x+o+f[q+i]];h=(U*=U)*U*(s[b]*y+s[b+1]*w)}var F=.5-g*g-A*A;if(F>=0){var N=3*n[x+1+f[q+1]];l=(F*=F)*F*(s[N]*g+s[N+1]*A)}return 70*(v+h+l)},noise3D:function(r,e,a){var o,i,n,f,s,v,h,l,u,d,p=this.permMod12,M=this.perm,m=this.grad3,c=(r+e+a)*(1/3),y=Math.floor(r+c),w=Math.floor(e+c),g=Math.floor(a+c),A=(y+w+g)*t,x=r-(y-A),q=e-(w-A),D=a-(g-A);x>=q?q>=D?(s=1,v=0,h=0,l=1,u=1,d=0):x>=D?(s=1,v=0,h=0,l=1,u=0,d=1):(s=0,v=0,h=1,l=1,u=0,d=1):qT?k++:z++,P>_?k++:B++,P>j?k++:E++,T>_?z++:B++,T>j?z++:E++,_>j?B++:E++;var G=P-(l=k>=3?1:0)+o,H=T-(u=z>=3?1:0)+o,I=_-(d=B>=3?1:0)+o,J=j-(p=E>=3?1:0)+o,K=P-(M=k>=2?1:0)+2*o,L=T-(m=z>=2?1:0)+2*o,O=_-(c=B>=2?1:0)+2*o,Q=j-(y=E>=2?1:0)+2*o,R=P-(w=k>=1?1:0)+3*o,V=T-(g=z>=1?1:0)+3*o,W=_-(A=B>=1?1:0)+3*o,X=j-(x=E>=1?1:0)+3*o,Y=P-1+4*o,Z=T-1+4*o,$=_-1+4*o,rr=j-1+4*o,er=255&U,tr=255&b,ar=255&F,or=255&N,ir=.6-P*P-T*T-_*_-j*j;if(ir<0)n=0;else{var nr=q[er+q[tr+q[ar+q[or]]]]%32*4;n=(ir*=ir)*ir*(D[nr]*P+D[nr+1]*T+D[nr+2]*_+D[nr+3]*j)}var fr=.6-G*G-H*H-I*I-J*J;if(fr<0)f=0;else{var sr=q[er+l+q[tr+u+q[ar+d+q[or+p]]]]%32*4;f=(fr*=fr)*fr*(D[sr]*G+D[sr+1]*H+D[sr+2]*I+D[sr+3]*J)}var vr=.6-K*K-L*L-O*O-Q*Q;if(vr<0)s=0;else{var hr=q[er+M+q[tr+m+q[ar+c+q[or+y]]]]%32*4;s=(vr*=vr)*vr*(D[hr]*K+D[hr+1]*L+D[hr+2]*O+D[hr+3]*Q)}var lr=.6-R*R-V*V-W*W-X*X;if(lr<0)v=0;else{var ur=q[er+w+q[tr+g+q[ar+A+q[or+x]]]]%32*4;v=(lr*=lr)*lr*(D[ur]*R+D[ur+1]*V+D[ur+2]*W+D[ur+3]*X)}var dr=.6-Y*Y-Z*Z-$*$-rr*rr;if(dr<0)h=0;else{var pr=q[er+1+q[tr+1+q[ar+1+q[or+1]]]]%32*4;h=(dr*=dr)*dr*(D[pr]*Y+D[pr+1]*Z+D[pr+2]*$+D[pr+3]*rr)}return 27*(n+f+s+v+h)}},i._buildPermutationTable=n,"undefined"!=typeof define&&define.amd&&define(function(){return i}),"undefined"!=typeof exports?exports.SimplexNoise=i:"undefined"!=typeof window&&(window.SimplexNoise=i),"undefined"!=typeof module&&(module.exports=i)}(); + +window.canvasOptions = { + autoClear: true, + autoCompensate: false, + autoPushPop: true, + canvas: true, + //- centered: true, + desynchronized: false, + width: null, + height: null +}; +function _defineProperty(obj, key, value) {if (key in obj) {Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true });} else {obj[key] = value;}return obj;} // Options editor: https://codepen.io/Alca/pen/MWYwxoN + +const SPRITE_SIZE = 32; + +let flakes = []; +let spritesheet; +let SPRITE_SCALE = 1; +let MAX_FLAKES = 100; +let WIND_SCALE = 1; +let WIND_DENSITY = 1; +let GRAVITY = 1; + +let GRAVITY_BASE = 1.5; +let GRAVITY_SPEED = 1.5; + +const simplex = new SimplexNoise(); + +function draw(e) { + if (!spritesheet) { + return; + } + // if(flakes.length < MAX_FLAKES) { + // const f = new Snowflake(); + // f._pos.set(random(-SPRITE_SIZE, width), -SPRITE_SIZE); + // flakes.push(f); + // } + const time = e * 0.001; + const windTime = time * 0.1 * WIND_DENSITY; + beginPath(); + for (let i = flakes.length - 1; i >= 0; i--) { + const f = flakes[i]; + f.update(time, windTime); + f.draw(time); + if ( + GRAVITY >= 0 && f.pos.y > height + SPRITE_SIZE || + GRAVITY < 0 && f.pos.y < -SPRITE_SIZE) + { + // flakes.splice(i, 1); + f.randomize(); + } + } + stroke(hsl(0, 0, 100)); +} + +const sclRngs = [ +[0.12, 0.2], [0.25, 0.4], [0.5, 0.7], [0.8, 1]]; + + +const scales = [ +sclRngs[0], sclRngs[0], sclRngs[0], +sclRngs[1], sclRngs[1], sclRngs[1], sclRngs[1], +sclRngs[2], sclRngs[2], sclRngs[2], sclRngs[2], +sclRngs[3], sclRngs[3]]; + + +class Snowflake { + + + // scale; img; offset; rot; + constructor() {_defineProperty(this, "_pos", new Vector());_defineProperty(this, "pos", new Vector()); + this.randomize(); + } + randomize() { + this._pos.set(random(-SPRITE_SIZE, width), -SPRITE_SIZE); + this.scale = SPRITE_SCALE * random(...random(scales)); + this.img = [random([0, 1, 2, 3]), random([0, 1, 2, 3])]; + this.offset = random(10000000); + this.rot = random(0.1, 1) * PI * random([-1, 1]); + } + update(e = performance.now(), windTime) { + const { _pos, pos, scale, offset } = this; + let wind = 0; + if (WIND_SCALE) { + wind = WIND_SCALE * simplex.noise3D( + ..._pos._.mult(WIND_DENSITY * 0.0002 * (1 - scale * 0.5)).xy, + windTime); + + } + _pos.add( + wind, + ease.expo.inOut(scale, GRAVITY_BASE, GRAVITY_SPEED, 1)); + + pos.set(_pos). + add( + sin(offset + e * scale) * (scale + 1) * 10, + 0); + + } + draw(e = performance.now()) { + const { pos, vel, scale: flakeScale, img, offset, rot } = this; + const size = SPRITE_SIZE * flakeScale; + push(); + translate(pos); + rotate(offset * flakeScale + rot * e); + const r = 0; + rotate(r); + scale(sin((e + offset) * rot), 1); + rotate(-r); + drawImage( + spritesheet, + img[0] * SPRITE_SIZE, img[1] * SPRITE_SIZE, + SPRITE_SIZE, SPRITE_SIZE, + -size * 0.5, -size * 0.5, + size, size); + + pop(); + }} + + + function setup() { + loadImage('/static/img/snow/sn.png'). + then(img => spritesheet = img); + + // ?sprite_scale=1.0&max_flakes=100&wind_scale=1&wind_density=1 + const _qs = new URLSearchParams(location.search); + const qs = new URLSearchParams(); + for (const [key, value] of _qs.entries()) { + qs.append(key.toLowerCase(), value); + } + if (qs.has('sprite_scale')) { + const _val = qs.get('sprite_scale'); + if (_val) { + const val = parseFloat(_val, 10); + if (!isNaN(val) && val > 0) { + SPRITE_SCALE = val; + } + } + } + if (qs.has('max_flakes')) { + const _val = qs.get('max_flakes'); + if (_val) { + const val = parseFloat(_val, 10); + if (!isNaN(val) && val >= 0) { + MAX_FLAKES = val; + } + } + } + if (qs.has('gravity')) { + const _val = qs.get('gravity'); + if (_val) { + const val = parseFloat(_val, 10); + if (!isNaN(val)) { + GRAVITY = val; + } + } + } + GRAVITY_BASE *= GRAVITY; + GRAVITY_SPEED *= GRAVITY; + if (qs.has('wind_scale')) { + const _val = qs.get('wind_scale'); + if (_val) { + const val = parseFloat(_val, 10); + if (!isNaN(val)) { + WIND_SCALE = val; + } + } + } + if (qs.has('wind_density')) { + const _val = qs.get('wind_density'); + if (_val) { + const val = parseFloat(_val, 10); + if (!isNaN(val)) { + WIND_DENSITY = val; + } + } + } + if (qs.has('hide_overlay')) { + const ele = document.querySelector('.overlay'); + ele.remove(); + } + + for (let i = 0; i < MAX_FLAKES; i++) { + const f = new Snowflake(); + f._pos.setY( + // random(-SPRITE_SIZE, width), + random(-SPRITE_SIZE, height)); + + flakes.push(f); + } +} \ No newline at end of file diff --git a/app/src/main/assets/js/simplex-noise.min.js b/app/src/main/assets/js/simplex-noise.min.js new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/assets/js/weatherConst.json b/app/src/main/assets/js/weatherConst.json new file mode 100644 index 0000000..6246c49 --- /dev/null +++ b/app/src/main/assets/js/weatherConst.json @@ -0,0 +1,46 @@ +{ + "weatherConst": { + "00": "晴", + "01": "多云", + "02": "阴", + "03": "阵雨", + "04": "雷阵雨", + "05": "雷阵雨伴有冰雹", + "06": "雨夹雪", + "07": "小雨", + "08": "中雨", + "09": "大雨", + "10": "暴雨", + "11": "大暴雨", + "12": "特大暴雨", + "13": "阵雪", + "14": "小雪", + "15": "中雪", + "16": "大雪", + "17": "暴雪", + "18": "雾", + "19": "冻雨", + "20": "沙尘暴", + "21": "小到中雨", + "22": "中到大雨", + "23": "大到暴雨", + "24": "暴雨到大暴雨", + "25": "大暴雨到特大暴雨", + "26": "小到中雪", + "27": "中到大雪", + "28": "大到暴雪", + "29": "浮尘", + "30": "扬沙", + "31": "强沙尘暴", + "32": "浓雾", + "33": "雪", + "49": "强浓雾", + "53": "霾", + "54": "中度霾", + "55": "重度霾", + "56": "严重霾", + "57": "大雾", + "58": "特强浓雾", + "99": "无" + } +} \ No newline at end of file diff --git a/app/src/main/java/com/hisensehitachi/himitboard/MainActivity.java b/app/src/main/java/com/hisensehitachi/himitboard/MainActivity.java new file mode 100644 index 0000000..7d79f98 --- /dev/null +++ b/app/src/main/java/com/hisensehitachi/himitboard/MainActivity.java @@ -0,0 +1,287 @@ +package com.hisensehitachi.himitboard; + +import android.annotation.SuppressLint; +import android.app.AlertDialog; +import android.content.res.AssetManager; +import android.graphics.Bitmap; +import android.net.Uri; +import android.os.Build; +import android.text.TextUtils; +import android.util.Log; +import android.view.KeyEvent; +import android.view.View; +import android.webkit.*; +import android.widget.ProgressBar; + +import androidx.annotation.RequiresApi; +import androidx.appcompat.app.AppCompatActivity; + +import android.os.Bundle; + +import java.io.*; +import java.util.HashMap; +import java.util.Map; + +public class MainActivity extends AppCompatActivity { + private WebView webView; + private ProgressBar progressBar; + + @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN) + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_main); + + progressBar = findViewById(R.id.progressbar);//进度条 + webView = findViewById(R.id.webview); + + //webView.loadUrl("https://1.hicloud.hisensehitachi.com:32199/");//测试环境加载url + // webView.loadUrl("http://47.110.57.25:32081/"); // 生产环境 + // webView.loadUrl("https://1.hicloud.hisensehitachi.com:32703/login"); // 生产环境 + webView.loadUrl("http://192.168.2.56:8080"); // 生产环境 + //webView.loadUrl("http://192.168.3.103:8080/");//加载url + //runWebView("http://192.168.3.103:8080/"); + webView.addJavascriptInterface(this, "android");//添加js监听 这样html就能调用客户端 + webView.setWebChromeClient(webChromeClient); + webView.setWebViewClient(webViewClient); + + WebSettings webSettings = webView.getSettings(); + + /** + * LOAD_CACHE_ONLY: 不使用网络,只读取本地缓存数据 + * LOAD_DEFAULT: (默认)根据cache-control决定是否从网络上取数据。 + * LOAD_NO_CACHE: 不使用缓存,只从网络获取数据. + * LOAD_CACHE_ELSE_NETWORK,只要本地有,无论是否过期,或者no-cache,都使用缓存中的数据。 + */ + webSettings.setCacheMode(WebSettings.LOAD_DEFAULT);//不使用缓存,只从网络获取数据. + webSettings.setTextZoom(100); + webSettings.setJavaScriptCanOpenWindowsAutomatically(true);//设置js可以直接打开窗口,如window.open(),默认为false + webSettings.setJavaScriptEnabled(true);//是否允许执行js,默认为false。设置true时,会提醒可能造成XSS漏洞 + webSettings.setSupportZoom(false);//是否可以缩放,默认true + webSettings.setBuiltInZoomControls(false);//是否显示缩放按钮,默认false + webSettings.setUseWideViewPort(true);//设置此属性,可任意比例缩放。大视图模式 + webSettings.setLoadWithOverviewMode(true);//和setUseWideViewPort(true)一起解决网页自适应问题 + webSettings.setAppCacheEnabled(true);//是否使用缓存 + webSettings.setDomStorageEnabled(true);//DOM Storage + webSettings.setDisplayZoomControls(true); //隐藏webview缩放按钮 + //允许webview对文件的操作 + webSettings.setAllowUniversalAccessFromFileURLs(true); + webSettings.setAllowFileAccess(true); + webSettings.setAllowFileAccessFromFileURLs(true); + + +// DisplayMetrics metric = new DisplayMetrics(); +// getWindowManager().getDefaultDisplay().getMetrics(metric); +// // 屏幕宽度(像素) +// int width = metric.widthPixels; +// // 屏幕高度(像素) +// int height = metric.heightPixels; +// // 屏幕密度(1.0 / 1.5 / 2.0) +// float density = metric.density; +// // 屏幕密度DPI(160 / 240 / 320) +// int densityDpi = metric.densityDpi; +// String info = "机顶盒型号: " + Build.MODEL + ",\nSDK版本:" +// + Build.VERSION.SDK + ",\n系统版本:" +// + Build.VERSION.RELEASE + "\n屏幕宽度(像素): " +width + "\n屏幕高度(像素): " + height + "\n屏幕密度: " +density+"\n屏幕密度DPI: "+densityDpi; +// Log.d("System INFO", info); + } + + //WebViewClient主要帮助WebView处理各种通知、请求事件 + private WebViewClient webViewClient = new WebViewClient() { + @Override + public void onPageFinished(WebView view, String url) {//页面加载完成 + progressBar.setVisibility(View.GONE); + } + + @Override + public void onPageStarted(WebView view, String url, Bitmap favicon) {//页面开始加载 + progressBar.setVisibility(View.VISIBLE); + } + + @SuppressLint("NewApi") + @Override + public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) { + //Log.i("ansen","拦截url:"+request.getUrl()); + return super.shouldOverrideUrlLoading(view, request); + } + + @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) + @Override + public WebResourceResponse shouldInterceptRequest(WebView view, String url) { + Uri uri = Uri.parse(url); + if (interceptRequest(uri) != null) { + return interceptRequest(uri); + } + return super.shouldInterceptRequest(view, url); + } + + @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) + @Override + public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) { + Uri uri = request.getUrl(); + if (interceptRequest(uri) != null) { + return interceptRequest(uri); + } + return super.shouldInterceptRequest(view, request); + } + + /** + * 拦截url 判断本地是否有缓存资源文件 + * @param uri + * @return + */ + @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) + private WebResourceResponse interceptRequest(Uri uri) { + WebResourceResponse resourceResponse = null; + //判断是否要加载本地资源 + if (uri.getPath().contains("/static/")) { + try { + //加载资源类型 + String mimeType = ""; + if (uri.getPath().contains(".js")) { + mimeType = "text/javascript"; + } else { + mimeType = MimeTypeMapUtils.getMimeTypeFromUrl(uri.toString()); + } + AssetManager am = getAssets(); + + InputStream is = am.open(uri.getPath().replaceAll("/static/", "")); + + //@SuppressLint({"NewApi", "LocalSuppress"}) + //Uri uriraw = Uri.parse("android.resource://com.example.myapplication/raw/"); + //String path = "file:///android_asset/"+ uri.getPath().replaceAll("/static/", ""); + + if (!TextUtils.isEmpty(mimeType)) { + Map header = new HashMap(); + header.put("Access-Control-Allow-Origin", "*"); + header.put("Access-Control-Allow-Headers", "Content-Type"); + resourceResponse = new WebResourceResponse(mimeType, "", 200, "ok", header, is); + return resourceResponse; + } + } catch (FileNotFoundException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + } + return resourceResponse; + } + }; + + + //WebChromeClient主要辅助WebView处理Javascript的对话框、网站图标、网站title、加载进度等 + private WebChromeClient webChromeClient = new WebChromeClient() { + //不支持js的alert弹窗,需要自己监听然后通过dialog弹窗 + @Override + public boolean onJsAlert(WebView webView, String url, String message, JsResult result) { + AlertDialog.Builder localBuilder = new AlertDialog.Builder(webView.getContext()); + localBuilder.setMessage(message).setPositiveButton("确定", null); + localBuilder.setCancelable(false); + localBuilder.create().show(); + + //注意: + //必须要这一句代码:result.confirm()表示: + //处理结果为确定状态同时唤醒WebCore线程 + //否则不能继续点击按钮 + result.confirm(); + return true; + } + + //获取网页标题 + @Override + public void onReceivedTitle(WebView view, String title) { + super.onReceivedTitle(view, title); + Log.i("ansen", "网页标题:" + title); + } + + //加载进度回调 +// @Override +// public void onProgressChanged(WebView view, int newProgress) { +// +// } + + @Override + public void onProgressChanged(WebView view, int newProgress) { +// if(newProgress==100){ +// //页面加载完成执行的操作 +// String path= "file:///"+ getFilesDir()+ File.separator+"/img/"; +// String action="javascript:replaceLocalPath('"+path+"')"; +// new AlertDialog.Builder(MainActivity.this) +// .setMessage(action) +// .show(); +// runWebView(action); +// } + progressBar.setProgress(newProgress); + //super.onProgressChanged(view, newProgress); + } + +// private void runWebView(final String url){ +// runOnUiThread(new Runnable() { +// @Override +// public void run() { +// webView.loadUrl(url); +// } +// }); +// } + + }; + + @SuppressLint("NewApi") + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + +// if(keyCode != KeyEvent.KEYCODE_DPAD_LEFT && keyCode != KeyEvent.KEYCODE_DPAD_UP +// && keyCode != KeyEvent.KEYCODE_DPAD_RIGHT && keyCode != KeyEvent.KEYCODE_DPAD_DOWN +// && keyCode != KeyEvent.KEYCODE_ENTER && keyCode != KeyEvent.KEYCODE_DPAD_CENTER +// && keyCode != KeyEvent.KEYCODE_MENU && keyCode != KeyEvent.KEYCODE_BACK +// ) { +// +// new AlertDialog.Builder(MainActivity.this) +// .setMessage("KeyCode:" + keyCode) +// .show(); +// } + + Log.i("ansen", "是否有上一个页面:" + webView.canGoBack()); + if (webView.canGoBack() && keyCode == KeyEvent.KEYCODE_BACK) {//点击返回按钮的时候判断有没有上一页 +// String action="GoBack button pressed."; +// new AlertDialog.Builder(MainActivity.this) +// .setMessage(action) +// .show(); + webView.goBack(); // goBack()表示返回webView的上一页面 + return true; + } + if (keyCode == KeyEvent.KEYCODE_MENU) {//点击返回按钮的时候判断有没有上一页 +// String action="KEYCODE_MENU button pressed."; +// new AlertDialog.Builder(MainActivity.this) +// .setMessage(action) +// .show(); + webView.evaluateJavascript("javascript:open()", new ValueCallback() { + @Override + public void onReceiveValue(String s) { + } + }); + return true; + } + return super.onKeyDown(keyCode, event); + } + + /** + * JS调用android的方法 + * + * @param str + * @return + */ + @JavascriptInterface //仍然必不可少 + public void getClient(String str) { + Log.i("ansen", "html调用客户端:" + str); + } + + @Override + protected void onDestroy() { + super.onDestroy(); + + //释放资源 + webView.destroy(); + webView = null; + } +} diff --git a/app/src/main/java/com/hisensehitachi/himitboard/MimeTypeMapUtils.java b/app/src/main/java/com/hisensehitachi/himitboard/MimeTypeMapUtils.java new file mode 100644 index 0000000..af5685f --- /dev/null +++ b/app/src/main/java/com/hisensehitachi/himitboard/MimeTypeMapUtils.java @@ -0,0 +1,43 @@ +package com.hisensehitachi.himitboard; + +import android.text.TextUtils; +import android.webkit.MimeTypeMap; + +public class MimeTypeMapUtils { + + public static String getFileExtensionFromUrl(String url) { + url = url.toLowerCase(); + if (!TextUtils.isEmpty(url)) { + int fragment = url.lastIndexOf('#'); + if (fragment > 0) { + url = url.substring(0, fragment); + } + + int query = url.lastIndexOf('?'); + if (query > 0) { + url = url.substring(0, query); + } + + int filenamePos = url.lastIndexOf('/'); + String filename = + 0 <= filenamePos ? url.substring(filenamePos + 1) : url; + + // if the filename contains special characters, we don't + // consider it valid for our matching purposes: + if (!filename.isEmpty()) { + int dotPos = filename.lastIndexOf('.'); + if (0 <= dotPos) { + return filename.substring(dotPos + 1); + } + } + } + + return ""; + } + public static String getMimeTypeFromUrl(String url) { + return MimeTypeMap.getSingleton().getMimeTypeFromExtension(getFileExtensionFromUrl(url)); + } + public static String getMimeTypeFromExtension(String extension) { + return MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension); + } +} diff --git a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000..d828d65 --- /dev/null +++ b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000..f5769eb --- /dev/null +++ b/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,74 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml new file mode 100644 index 0000000..48efbaa --- /dev/null +++ b/app/src/main/res/layout/activity_main.xml @@ -0,0 +1,19 @@ + + + + + + diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml new file mode 100644 index 0000000..3f3c50b --- /dev/null +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml new file mode 100644 index 0000000..3f3c50b --- /dev/null +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher.png b/app/src/main/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 0000000..898f3ed Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/ic_launcher.png differ diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher_round.png b/app/src/main/res/mipmap-hdpi/ic_launcher_round.png new file mode 100644 index 0000000..dffca36 Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/ic_launcher_round.png differ diff --git a/app/src/main/res/mipmap-hdpi/icon.png b/app/src/main/res/mipmap-hdpi/icon.png new file mode 100644 index 0000000..38fd6f5 Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/icon.png differ diff --git a/app/src/main/res/mipmap-ldpi/icon.png b/app/src/main/res/mipmap-ldpi/icon.png new file mode 100644 index 0000000..cd0fac1 Binary files /dev/null and b/app/src/main/res/mipmap-ldpi/icon.png differ diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher.png b/app/src/main/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 0000000..64ba76f Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/ic_launcher.png differ diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher_round.png b/app/src/main/res/mipmap-mdpi/ic_launcher_round.png new file mode 100644 index 0000000..dae5e08 Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/ic_launcher_round.png differ diff --git a/app/src/main/res/mipmap-mdpi/icon.png b/app/src/main/res/mipmap-mdpi/icon.png new file mode 100644 index 0000000..288349d Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/icon.png differ diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/app/src/main/res/mipmap-xhdpi/ic_launcher.png new file mode 100644 index 0000000..e5ed465 Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png new file mode 100644 index 0000000..14ed0af Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png differ diff --git a/app/src/main/res/mipmap-xhdpi/icon.png b/app/src/main/res/mipmap-xhdpi/icon.png new file mode 100644 index 0000000..9830cd4 Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/icon.png differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/app/src/main/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 0000000..b0907ca Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png new file mode 100644 index 0000000..d8ae031 Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png differ diff --git a/app/src/main/res/mipmap-xxhdpi/icon.png b/app/src/main/res/mipmap-xxhdpi/icon.png new file mode 100644 index 0000000..79c8f62 Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/icon.png differ diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 0000000..2c18de9 Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png new file mode 100644 index 0000000..beed3cd Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png differ diff --git a/app/src/main/res/mipmap-xxxhdpi/icon.png b/app/src/main/res/mipmap-xxxhdpi/icon.png new file mode 100644 index 0000000..01d3a64 Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/icon.png differ diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml new file mode 100644 index 0000000..6b3f6ab --- /dev/null +++ b/app/src/main/res/values/colors.xml @@ -0,0 +1,6 @@ + + + #008577 + #00574B + #D81B60 + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml new file mode 100644 index 0000000..f8450a6 --- /dev/null +++ b/app/src/main/res/values/strings.xml @@ -0,0 +1,3 @@ + + 海信Ai享家 + diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml new file mode 100644 index 0000000..6f19b47 --- /dev/null +++ b/app/src/main/res/values/styles.xml @@ -0,0 +1,11 @@ + + + + + + diff --git a/app/src/test/java/com/hisensehitachi/himitboard/ExampleUnitTest.java b/app/src/test/java/com/hisensehitachi/himitboard/ExampleUnitTest.java new file mode 100644 index 0000000..a292dc5 --- /dev/null +++ b/app/src/test/java/com/hisensehitachi/himitboard/ExampleUnitTest.java @@ -0,0 +1,17 @@ +package com.hisensehitachi.himitboard; + +import org.junit.Test; + +import static org.junit.Assert.*; + +/** + * Example local unit test, which will execute on the development machine (host). + * + * @see Testing documentation + */ +public class ExampleUnitTest { + @Test + public void addition_isCorrect() { + assertEquals(4, 2 + 2); + } +} diff --git a/build.gradle b/build.gradle new file mode 100644 index 0000000..17b10e0 --- /dev/null +++ b/build.gradle @@ -0,0 +1,37 @@ +// Top-level build file where you can add configuration options common to all sub-projects/modules. + +buildscript { + repositories { + maven { url 'https://jitpack.io' } + maven { url 'https://maven.aliyun.com/repository/public' } + maven { url 'https://maven.aliyun.com/repository/central' } + maven { url 'https://maven.aliyun.com/repository/google' } + maven { url 'https://maven.aliyun.com/repository/public' } + maven { url 'https://maven.aliyun.com/repository/gradle-plugin' } + google() + jcenter() + } + dependencies { + classpath 'com.android.tools.build:gradle:3.3.0' + + // NOTE: Do not place your application dependencies here; they belong + // in the individual module build.gradle files + } +} + +allprojects { + repositories { + maven { url 'https://jitpack.io' } + maven { url 'https://maven.aliyun.com/repository/public' } + maven { url 'https://maven.aliyun.com/repository/central' } + maven { url 'https://maven.aliyun.com/repository/google' } + maven { url 'https://maven.aliyun.com/repository/public' } + maven { url 'https://maven.aliyun.com/repository/gradle-plugin' } + google() + jcenter() + } +} + +task clean(type: Delete) { + delete rootProject.buildDir +} diff --git a/gradle.properties b/gradle.properties new file mode 100644 index 0000000..55f37b3 --- /dev/null +++ b/gradle.properties @@ -0,0 +1,20 @@ +# Project-wide Gradle settings. +# IDE (e.g. Android Studio) users: +# Gradle settings configured through the IDE *will override* +# any settings specified in this file. +# For more details on how to configure your build environment visit +# http://www.gradle.org/docs/current/userguide/build_environment.html +# Specifies the JVM arguments used for the daemon process. +# The setting is particularly useful for tweaking memory settings. +org.gradle.jvmargs=-Xmx1536m +# When configured, Gradle will run in incubating parallel mode. +# This option should only be used with decoupled projects. More details, visit +# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects +# org.gradle.parallel=true +# AndroidX package structure to make it clearer which packages are bundled with the +# Android operating system, and which are packaged with your app's APK +# https://developer.android.com/topic/libraries/support-library/androidx-rn +android.useAndroidX=true +# Automatically convert third-party libraries to use AndroidX +android.enableJetifier=true + diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000..f6b961f Binary files /dev/null and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..b01aecc --- /dev/null +++ b/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Tue Sep 01 08:49:29 CST 2020 +distributionBase=GRADLE_USER_HOME +distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.2-all.zip +distributionPath=wrapper/dists +zipStorePath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME diff --git a/gradlew b/gradlew new file mode 100644 index 0000000..518efff --- /dev/null +++ b/gradlew @@ -0,0 +1,172 @@ +#!/usr/bin/env sh + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS="" + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn () { + echo "$*" +} + +die () { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; + NONSTOP* ) + nonstop=true + ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin, switch paths to Windows format before running java +if $cygwin ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=$((i+1)) + done + case $i in + (0) set -- ;; + (1) set -- "$args0" ;; + (2) set -- "$args0" "$args1" ;; + (3) set -- "$args0" "$args1" "$args2" ;; + (4) set -- "$args0" "$args1" "$args2" "$args3" ;; + (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " +} +APP_ARGS=$(save "$@") + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong +if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then + cd "$(dirname "$0")" +fi + +exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat new file mode 100644 index 0000000..e95643d --- /dev/null +++ b/gradlew.bat @@ -0,0 +1,84 @@ +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS= + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto init + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto init + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:init +@rem Get command-line arguments, handling Windows variants + +if not "%OS%" == "Windows_NT" goto win9xME_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/settings.gradle b/settings.gradle new file mode 100644 index 0000000..d3db109 --- /dev/null +++ b/settings.gradle @@ -0,0 +1 @@ +include ':app'