From ac0cbe9f5b2e5d77cdc22dbf2efe58ebf522a066 Mon Sep 17 00:00:00 2001 From: Juli Date: Sat, 14 Sep 2024 12:29:32 +0300 Subject: [PATCH] init --- feed.xml | 12 + index.html | 90 ++ pages/contact/index.html | 69 ++ pages/feed/index.html | 66 ++ pages/license/index.html | 69 ++ posts.html | 77 ++ posts/pmosphone/index.html | 75 ++ static/animal.js | 17 + static/buttons/boykiss.gif | Bin 0 -> 3939 bytes static/buttons/boykisser.gif | Bin 0 -> 485 bytes static/buttons/csshard.gif | Bin 0 -> 495 bytes static/buttons/cutie.gif | Bin 0 -> 2436 bytes static/buttons/fediverse.gif | Bin 0 -> 1079 bytes static/buttons/flag-pan.gif | Bin 0 -> 267 bytes static/buttons/gayweb.gif | Bin 0 -> 1329 bytes static/buttons/juli.gif | Bin 0 -> 2121 bytes static/buttons/linux.gif | Bin 0 -> 3978 bytes static/buttons/madeonlinux.png | Bin 0 -> 456 bytes static/buttons/neofox.gif | Bin 0 -> 1654 bytes static/buttons/paws.gif | Bin 0 -> 885 bytes static/buttons/php.gif | Bin 0 -> 1441 bytes static/buttons/powered_linux.gif | Bin 0 -> 1052 bytes static/buttons/support.gif | Bin 0 -> 3477 bytes static/buttons/transrights.gif | Bin 0 -> 471 bytes static/buttons/ubuntu.gif | Bin 0 -> 1716 bytes static/icons/fediverse.svg | 37 + static/icons/git.svg | 1 + static/icons/github.svg | 1 + static/icons/itch.svg | 1 + static/icons/lastfm.svg | 1 + static/icons/lemmy.svg | 1 + static/icons/mastodon.svg | 47 + static/icons/reddit.svg | 3 + static/icons/replit.svg | 1 + static/icons/steam.svg | 1 + static/icons/twitter.svg | 47 + static/icons/twitter_better.svg | 1 + static/icons/youtube.svg | 1 + static/oneko.gif | Bin 0 -> 3316 bytes static/oneko.js | 282 ++++++ static/particles.js | 1546 ++++++++++++++++++++++++++++++ static/particles.json | 110 +++ static/style.css | 109 +++ tags/linux/index.html | 77 ++ tags/mobile/index.html | 77 ++ 45 files changed, 2819 insertions(+) create mode 100644 feed.xml create mode 100644 index.html create mode 100644 pages/contact/index.html create mode 100644 pages/feed/index.html create mode 100644 pages/license/index.html create mode 100644 posts.html create mode 100644 posts/pmosphone/index.html create mode 100644 static/animal.js create mode 100644 static/buttons/boykiss.gif create mode 100644 static/buttons/boykisser.gif create mode 100644 static/buttons/csshard.gif create mode 100644 static/buttons/cutie.gif create mode 100644 static/buttons/fediverse.gif create mode 100644 static/buttons/flag-pan.gif create mode 100644 static/buttons/gayweb.gif create mode 100644 static/buttons/juli.gif create mode 100644 static/buttons/linux.gif create mode 100644 static/buttons/madeonlinux.png create mode 100644 static/buttons/neofox.gif create mode 100644 static/buttons/paws.gif create mode 100644 static/buttons/php.gif create mode 100644 static/buttons/powered_linux.gif create mode 100644 static/buttons/support.gif create mode 100644 static/buttons/transrights.gif create mode 100644 static/buttons/ubuntu.gif create mode 100644 static/icons/fediverse.svg create mode 100644 static/icons/git.svg create mode 100644 static/icons/github.svg create mode 100644 static/icons/itch.svg create mode 100644 static/icons/lastfm.svg create mode 100644 static/icons/lemmy.svg create mode 100644 static/icons/mastodon.svg create mode 100644 static/icons/reddit.svg create mode 100644 static/icons/replit.svg create mode 100644 static/icons/steam.svg create mode 100644 static/icons/twitter.svg create mode 100644 static/icons/twitter_better.svg create mode 100644 static/icons/youtube.svg create mode 100644 static/oneko.gif create mode 100644 static/oneko.js create mode 100644 static/particles.js create mode 100644 static/particles.json create mode 100644 static/style.css create mode 100644 tags/linux/index.html create mode 100644 tags/mobile/index.html diff --git a/feed.xml b/feed.xml new file mode 100644 index 0000000..f550897 --- /dev/null +++ b/feed.xml @@ -0,0 +1,12 @@ + + + Juli's site + http://127.0.0.1:8000 + 2024-02-19 + + I installed linux on my phone + + 2024-02-19 + + + diff --git a/index.html b/index.html new file mode 100644 index 0000000..ddbba77 --- /dev/null +++ b/index.html @@ -0,0 +1,90 @@ + + + + Juli's silly website + + + + + + + + + + + + + + + + + +
+
+
+ + +

Juli's silly website

+

I am Juli, a Finnish pansexual furry of some gender from '09(thats 15 years old). I go by Juli or Julimiro, any pronouns are fine.

+

I have a few coding projects which are on my git(and still a bit on my github)

+
+ Fediverse + Lemmy + Last.fm + Youtube +
+ + + + + + +
+ + +
+ + + \ No newline at end of file diff --git a/pages/contact/index.html b/pages/contact/index.html new file mode 100644 index 0000000..fd64da9 --- /dev/null +++ b/pages/contact/index.html @@ -0,0 +1,69 @@ + + + + Contact + + + + + + + + + + + + + + + + + +
+
+
+ + +

Discord : @julimiro

+

Email : juli@julimiro.eu

+

Matrix : @juli:arcticfoxes.net

+

XMPP : juli@404.city

+ + + + + +
+ + +
+ + + \ No newline at end of file diff --git a/pages/feed/index.html b/pages/feed/index.html new file mode 100644 index 0000000..b2d339b --- /dev/null +++ b/pages/feed/index.html @@ -0,0 +1,66 @@ + + + + Feed + + + + + + + + + + + + + + + + + +
+
+
+ + +

A feed for posts can be found at /feed.xml

+ + + + + +
+ + +
+ + + \ No newline at end of file diff --git a/pages/license/index.html b/pages/license/index.html new file mode 100644 index 0000000..bf86f34 --- /dev/null +++ b/pages/license/index.html @@ -0,0 +1,69 @@ + + + + License info + + + + + + + + + + + + + + + + + +
+
+
+ + +

This website uses particles.js (License)

+

This website uses the Atkinson Hyperlegible font (License)

+

This website uses the Roboto Mono font (License)

+

This website uses oneko.js (License)

+ + + + + +
+ + +
+ + + \ No newline at end of file diff --git a/posts.html b/posts.html new file mode 100644 index 0000000..3caa549 --- /dev/null +++ b/posts.html @@ -0,0 +1,77 @@ + + + + Posts - Juli's site + + + + + + + + + + + + + + + + + +
+
+
+ + + + +

Posts - Juli's site

+ +
+

+ I installed linux on my phone +

+
Mon 19 Feb 2024
+

+ +

+
+
+ + + +
+ + +
+ + + \ No newline at end of file diff --git a/posts/pmosphone/index.html b/posts/pmosphone/index.html new file mode 100644 index 0000000..90698d6 --- /dev/null +++ b/posts/pmosphone/index.html @@ -0,0 +1,75 @@ + + + + I installed linux on my phone + + + + + + + + + + + + + + + + + +
+
+
+ +

I installed linux on my phone

+
Mon 19 Feb 2024
+ +

Tags:

+ + + + + + +
+ + +
+ + + \ No newline at end of file diff --git a/static/animal.js b/static/animal.js new file mode 100644 index 0000000..2ac0d43 --- /dev/null +++ b/static/animal.js @@ -0,0 +1,17 @@ +function getRandomInt(max) { + return Math.floor(Math.random() * max); +} + +function load_animal() { + images = ["https://api.tinyfox.dev/img?animal=caracal","https://api.tinyfox.dev/img?animal=chee","https://api.tinyfox.dev/img?animal=yote","https://api.tinyfox.dev/img?animal=dook","https://api.tinyfox.dev/img?animal=fox","https://api.tinyfox.dev/img?animal=mane","https://api.tinyfox.dev/img?animal=ott","https://api.tinyfox.dev/img?animal=marten","https://api.tinyfox.dev/img?animal=wah","https://api.tinyfox.dev/img?animal=serval","https://api.tinyfox.dev/img?animal=woof","https://api.tinyfox.dev/img?animal=yeen"] + names = ["caracal", "cheetah","cayote","ferret","fox","maned wolf","otter","marten","red panda","serval","wolf","hyena"] + number = getRandomInt(images.length) + document.getElementById('animal_subtitle').innerText = "Current animal is "+names[number]+"." + document.getElementById('animal_img').alt = "A "+names[number] + document.getElementById('animal_img').title = "A "+names[number] + document.getElementById("animal_img").src = images[number]; +} + +window.addEventListener('load', function () { + load_animal() + }) \ No newline at end of file diff --git a/static/buttons/boykiss.gif b/static/buttons/boykiss.gif new file mode 100644 index 0000000000000000000000000000000000000000..4325539c7c977c0717e4a450359dd592c257cd49 GIT binary patch literal 3939 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 literal 0 HcmV?d00001 diff --git a/static/buttons/boykisser.gif b/static/buttons/boykisser.gif new file mode 100644 index 0000000000000000000000000000000000000000..94ed3197626bb0012000de62f86c0b7141400171 GIT binary patch literal 485 zcmVOY{s_9<{xHf(tGzgD z7L@p4D2`-loGhgbDzzl8t4E0z#o00yT~cor?(q<&Pm0fUAa-{EZh?m=gLhF#dyalbkyw$9 zWNCyvjAUbiR#icraG+ZXe5PEde5I-YK%1_RZ(*>rv2}Q>Y=x{bNgi{Sud-9MaYna= zxv0E&Lcf)ik6~tgWq?-9ySk>OYrlx#X{g%EIpyEs>4J7UJ-VgNtw(36^N)P4`Sk$< z`GN`r00gWMaG;)Nr(ogRmvGWONB)2aoOq$&u6Pk4VxhK<4x2tb4ug3~M$!kyNgF|O zj2N=z$`%sLDRP9cBgdD3ZmI;S@EsIW>uP=+iZbU;qSvrZz&ApZ&7(yv&GV-*DKVTn_1nDNJQN1Q=BMu=@dtJlg_zJY%*qCMIHALHzWyXYVnY00GNS)tHOPhlEOBe^) bwaQW{Ud*_$%MR- z&$J5wsiNNK$=g#SPr?9u9g+2&>iYeW{-_fV4(W+DI-i$V(_F?Il zARdfFwdfg?5+;f%bKLql3^z(v$4aG`>Jb7|Q6jTN2U4m`$q?9zgvE>rnns|Ga?(vvBcvef8P+enaf!qOaQ%_IRc zTA6Zn>XqFZR#?(DW#VX^TXk>=$X!eK<=t1?vTB{nqwe3gfw2$}z__vF$B-MpJVLp$ lWgvMEYu=3U!;R0NLyI0wy0q!js7s$n&APSg*QX-@06Q*%>?;5O literal 0 HcmV?d00001 diff --git a/static/buttons/cutie.gif b/static/buttons/cutie.gif new file mode 100644 index 0000000000000000000000000000000000000000..f271daacda1d40b69141d45e9da6a8a4a57fe3c5 GIT binary patch literal 2436 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 MGV6s@BrAh80Bz8hi~s-t literal 0 HcmV?d00001 diff --git a/static/buttons/flag-pan.gif b/static/buttons/flag-pan.gif new file mode 100644 index 0000000000000000000000000000000000000000..49d06681066a11afc4910d450fe23c8c0d8cbd82 GIT binary patch literal 267 zcmZ?wbhEHbj9`#w_{6~Q|NnmmAgS2%{|1BNMi3hU6o0aS8H)e8J#!P&Q+*TDGn2D< z(-U)Z6KxIjOiWEoO&N4RN^0{1EA+0dd-q>ouD~N^YnR6&gOgWuX9wIg_VWG6c4JN1>9w4F$-?Vh&=56z~Zr`<9clW+IHadq6A31vL_=%IJPM=^n NbN<4`OQ$&*tN|6CeBb~8 literal 0 HcmV?d00001 diff --git a/static/buttons/gayweb.gif b/static/buttons/gayweb.gif new file mode 100644 index 0000000000000000000000000000000000000000..7bfa0682ee7aef00dda1b336521cf8daedec999a GIT binary patch literal 1329 zcmZ?wbhEHbj9`#w_#({kpMl}ke+EWIhW|MXAn;#Eh~d8nL&X0&h7Ulw|5^-;3~~(r z^%;X085q9(XW#(}vH>yU{|OBD{xhfmnQ}lyPTv_8zhjvDjbYJShB?u!<^LI0{Qv*| z+_`g#|GE8KLxPXBfGgPO1##3&AjpE_{_~!`{nyA<~(jWo^I^#E7pJ4YR4bm z=T7^7WLEmW+gzR2SXUmy>+(YA3i$GzrW5rR`$|UQL(>bS5Is(%r1X%o>lHs z4a1KO1s)9yPG-Hc-4;gK8~$Zj#=N0%!4m!tH7##8Zb+Qa?kw_A@^<+}U$>H1GXfu# z8FZRYmJfJ$LGq*Alupr~kpjZ3kL|N>++tkWxkT~Y9BW0PK+iypKux#AQ#^;JbOg)U zEcN?3Gk@06)xic#A`>p8MNO!GJGbHB=_H*;a3>fXujj zfq|ve;Do1k?%7u-cik7B)+iQS8)Y_$k)cE?XJrmIOPcJZ$I$0fq{Y6 zt*R+=_?)-MGzw*|eep$gv-i5KrCi-B>~$<&XTI0F_C88dHf+w5Pjj4)JbqeY7;2oX z9u;U=;nS+xZlqAJlH2cHIdwXpm>|?8!1M@r33D;Wt~)u$PKK_U%kB2YYj@C=!UKgN zLa#bfDjDKtZ|uH#W5XQH#h=y4ZQu<}W9+W|(W3 zWoe$5JNG(b#vRk1JMU&4YCe4RO-S+9zaEnf3tVbt>$N1xWm4On3w!%nCQf4E#NrOt zY6XS96i=rKEBpLkuT!3N=vnZ-EUU{7B3rcx6W4G_^RU zIv1N~C3<$mOf{YEWYBL?J3qQ}>2e`8MJ(=NDHQ<5knhP?osbv`0>x0nB5(|?WAr}E~3`q*0#!w$sVu*>4lffDQ%C$>D literal 0 HcmV?d00001 diff --git a/static/buttons/juli.gif b/static/buttons/juli.gif new file mode 100644 index 0000000000000000000000000000000000000000..4ff0364bedd46536fa42d190347940e477b64a94 GIT binary patch literal 2121 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 Z_E3ofTmT0T__UhUD>B-p!N&ld{{cn`nHvBA literal 0 HcmV?d00001 diff --git a/static/buttons/madeonlinux.png b/static/buttons/madeonlinux.png new file mode 100644 index 0000000000000000000000000000000000000000..f756052d820a8eaeb1b5b473f415ce861f37c5fd GIT binary patch literal 456 zcmV;(0XP1MP)@%t2RYDb6WAi;8k9d*v&0Fws} zu)M;8mN%RB_;{5${AE^@jVa8~iaAWxD#95Y;K`r&3bR-4z{L*;-g3Vh=IMO`TnU4F zY#ElozFiBuyL6a)hvWPcmzd^HB1~XNn6~8*hJzGV`2U0<6&c{55|#;U)gubX2<+nR7=1D!SGj$8NP=1@n5W+603uc yQ&Fp`J^=Vuy?OWRjZAc0=bdDn5kBH2OB+Zv><;&yy z)wL5&PONUzG1r3(hon%H^DW{z?(uZ)>VLT3?)}5-*Z1?h-_QHa@nAcSUQr4Zf zLPBO{#Ll7HN# zB*0#B%BdpQsUghu?l*_p&VBvXmG$2F$osE7nxokdV(1TJ8C`MA$H|`W>E3HceBb(< zSoJ(U&pWx|8{Cu3R;6$U(>>LhUJHR?D<{LBN5qWBCohFY&BY`wMJ3FpTwaPxE4_C4 zcj2)q(XmmX?{qG2zQBLEC}6EPaJxKcTY9>$Jbm<%a4|DqBoY-C7M5QZ7Kw|>%F3#$ zs(!35zuzQnYHGYEyVu^{F7K8<%PV{#%zKrcKYhJqpj0v?seG4rWAj1j)9TvEx+X=( z_v5mbq3%axKX;9Ec5ghcogC<1?~|=P>r^Nd1AYC20|N^az00o#_V)HZm-9dV+XQfb zfj=AAe&VN109tzh0)pnY)F?$-1~$R{6rAV^+|skMQ>(p* z;3nk|kU*iuJfUHWIod|(x95?dVl0!LeNz*8Y4*8t80QE~i(l@lS5#F-q<|fU^ePw& zPo)kgE)JuBm>thoixc6u+hI;)o$B0m2`Lyw0n|I>`QPpkQ=$zi|!p`dgCA%*s{BE)fIh07Wjk4Q|^rE%=*}DZ|a8IWev=pzHqBv z+W_4tU9a^of-GCK#=>f_9Vu@FFo-p1BnM(=dUu^+ei5zCX2&TG_FoVol~~wfND7}D z4YWKl4iSij898d2(x@#LL_>YNMG0XKE%5W9RyDIMwsobmDluFtEruK@bHs7+$YBhe z_{Z!mec~YYg%MD*!N>ev3+J%iWxV|TR)+B!X~+Ft`pt+9Jg&J_gMtaQrhPT%Vg5*& zrIQ1K&~&RcTT5WQ7+MeKfLy?lP!99CP|{Xt9wd<~L0n5Te7z6q0Sl`yicFjT5@5hP zG{IVD=S~_U3>B<+YMDxHW<770kMVI;sSK=E_*}%Z+PxMP_FXNnAM0Nu=0gL9@iSOi zMj9S$Jk629(5YK2DC(iO2Wks%(?Fc@src61eP@D+Yw#^rBOO0Jz1`FnAO9q`&tjPm zwTpDP1M!1-a&WBn0*0RZ{GA>|hHSXm_q7JCveEleZB9mz7O|oWJr~NTN3{wV`~9R? zPV?{s=^HE|NtVqfU+J#r$Ov;L#`@NDB{F@TbtTi#=3iYOEW0Od5S8z$Dhfj zAb~)Z!YGt>Oj+(}X2HUKdC3CR4f%PGPng_902(fo;@-J@%b^?{Ag)F-lMbrpo8rJN zBMZ{|EE?n?-R$B^i$_W}szGwPE1-Jx-$Ru#QIpFpD)R11`^1Ia)y{X#yKC}oaykug F`v+DdF^d2I literal 0 HcmV?d00001 diff --git a/static/buttons/paws.gif b/static/buttons/paws.gif new file mode 100644 index 0000000000000000000000000000000000000000..b58580086879477ba809f5e25c8a3302622cbbdb GIT binary patch literal 885 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 literal 0 HcmV?d00001 diff --git a/static/buttons/support.gif b/static/buttons/support.gif new file mode 100644 index 0000000000000000000000000000000000000000..f5791f627ed5fa5ebc81e56fe0722a1d478b982c GIT binary patch literal 3477 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 I0s->*A9AWwegFUf literal 0 HcmV?d00001 diff --git a/static/icons/fediverse.svg b/static/icons/fediverse.svg new file mode 100644 index 0000000..11874d2 --- /dev/null +++ b/static/icons/fediverse.svg @@ -0,0 +1,37 @@ + + + + + + diff --git a/static/icons/git.svg b/static/icons/git.svg new file mode 100644 index 0000000..13af359 --- /dev/null +++ b/static/icons/git.svg @@ -0,0 +1 @@ +Git \ No newline at end of file diff --git a/static/icons/github.svg b/static/icons/github.svg new file mode 100644 index 0000000..538ec5b --- /dev/null +++ b/static/icons/github.svg @@ -0,0 +1 @@ +GitHub \ No newline at end of file diff --git a/static/icons/itch.svg b/static/icons/itch.svg new file mode 100644 index 0000000..cc67541 --- /dev/null +++ b/static/icons/itch.svg @@ -0,0 +1 @@ +Itch.io \ No newline at end of file diff --git a/static/icons/lastfm.svg b/static/icons/lastfm.svg new file mode 100644 index 0000000..e75fbec --- /dev/null +++ b/static/icons/lastfm.svg @@ -0,0 +1 @@ +Last.fm \ No newline at end of file diff --git a/static/icons/lemmy.svg b/static/icons/lemmy.svg new file mode 100644 index 0000000..9557954 --- /dev/null +++ b/static/icons/lemmy.svg @@ -0,0 +1 @@ +Lemmy \ No newline at end of file diff --git a/static/icons/mastodon.svg b/static/icons/mastodon.svg new file mode 100644 index 0000000..4e41bca --- /dev/null +++ b/static/icons/mastodon.svg @@ -0,0 +1,47 @@ + + + + + Mastodon + + + diff --git a/static/icons/reddit.svg b/static/icons/reddit.svg new file mode 100644 index 0000000..a9927f9 --- /dev/null +++ b/static/icons/reddit.svg @@ -0,0 +1,3 @@ + \ No newline at end of file diff --git a/static/icons/replit.svg b/static/icons/replit.svg new file mode 100644 index 0000000..21b7620 --- /dev/null +++ b/static/icons/replit.svg @@ -0,0 +1 @@ +Replit \ No newline at end of file diff --git a/static/icons/steam.svg b/static/icons/steam.svg new file mode 100644 index 0000000..affefa5 --- /dev/null +++ b/static/icons/steam.svg @@ -0,0 +1 @@ +Steam \ No newline at end of file diff --git a/static/icons/twitter.svg b/static/icons/twitter.svg new file mode 100644 index 0000000..b072f10 --- /dev/null +++ b/static/icons/twitter.svg @@ -0,0 +1,47 @@ + + + + + X + + + diff --git a/static/icons/twitter_better.svg b/static/icons/twitter_better.svg new file mode 100644 index 0000000..c5a5eb2 --- /dev/null +++ b/static/icons/twitter_better.svg @@ -0,0 +1 @@ +Twitter \ No newline at end of file diff --git a/static/icons/youtube.svg b/static/icons/youtube.svg new file mode 100644 index 0000000..0492366 --- /dev/null +++ b/static/icons/youtube.svg @@ -0,0 +1 @@ +YouTube \ No newline at end of file diff --git a/static/oneko.gif b/static/oneko.gif new file mode 100644 index 0000000000000000000000000000000000000000..a009c2cc19c96b001ac76e96f27e5fa1a9e56577 GIT binary patch literal 3316 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 yo73M10028!@k;#w literal 0 HcmV?d00001 diff --git a/static/oneko.js b/static/oneko.js new file mode 100644 index 0000000..3200f62 --- /dev/null +++ b/static/oneko.js @@ -0,0 +1,282 @@ +// oneko.js: https://github.com/adryd325/oneko.js + +(function oneko() { + const isReducedMotion = + window.matchMedia(`(prefers-reduced-motion: reduce)`) === true || + window.matchMedia(`(prefers-reduced-motion: reduce)`).matches === true; + + if (isReducedMotion) return; + + const nekoEl = document.createElement("div"); + + let nekoPosX = 32; + let nekoPosY = 32; + + let mousePosX = 0; + let mousePosY = 0; + + let frameCount = 0; + let idleTime = 0; + let idleAnimation = null; + let idleAnimationFrame = 0; + + const nekoSpeed = 10; + const spriteSets = { + idle: [[-3, -3]], + alert: [[-7, -3]], + scratchSelf: [ + [-5, 0], + [-6, 0], + [-7, 0], + ], + scratchWallN: [ + [0, 0], + [0, -1], + ], + scratchWallS: [ + [-7, -1], + [-6, -2], + ], + scratchWallE: [ + [-2, -2], + [-2, -3], + ], + scratchWallW: [ + [-4, 0], + [-4, -1], + ], + tired: [[-3, -2]], + sleeping: [ + [-2, 0], + [-2, -1], + ], + N: [ + [-1, -2], + [-1, -3], + ], + NE: [ + [0, -2], + [0, -3], + ], + E: [ + [-3, 0], + [-3, -1], + ], + SE: [ + [-5, -1], + [-5, -2], + ], + S: [ + [-6, -3], + [-7, -2], + ], + SW: [ + [-5, -3], + [-6, -1], + ], + W: [ + [-4, -2], + [-4, -3], + ], + NW: [ + [-1, 0], + [-1, -1], + ], + }; + + function init() { + nekoEl.id = "oneko"; + nekoEl.ariaHidden = true; + nekoEl.style.width = "32px"; + nekoEl.style.height = "32px"; + nekoEl.style.position = "fixed"; + nekoEl.style.pointerEvents = "auto"; + nekoEl.style.imageRendering = "pixelated"; + nekoEl.style.left = `${nekoPosX - 16}px`; + nekoEl.style.top = `${nekoPosY - 16}px`; + nekoEl.style.zIndex = Number.MAX_VALUE; + + let nekoFile = "/static/oneko.gif" + const curScript = document.currentScript + if (curScript && curScript.dataset.cat) { + nekoFile = curScript.dataset.cat + } + nekoEl.style.backgroundImage = `url(${nekoFile})`; + + document.body.appendChild(nekoEl); + + document.addEventListener("mousemove", function (event) { + mousePosX = event.clientX; + mousePosY = event.clientY; + }); + + window.requestAnimationFrame(onAnimationFrame); + } + + let lastFrameTimestamp; + + function onAnimationFrame(timestamp) { + // Stops execution if the neko element is removed from DOM + if (!nekoEl.isConnected) { + return; + } + if (!lastFrameTimestamp) { + lastFrameTimestamp = timestamp; + } + if (timestamp - lastFrameTimestamp > 100) { + lastFrameTimestamp = timestamp + frame() + } + window.requestAnimationFrame(onAnimationFrame); + } + + function setSprite(name, frame) { + const sprite = spriteSets[name][frame % spriteSets[name].length]; + nekoEl.style.backgroundPosition = `${sprite[0] * 32}px ${sprite[1] * 32}px`; + } + + function resetIdleAnimation() { + idleAnimation = null; + idleAnimationFrame = 0; + } + + function idle() { + idleTime += 1; + + // every ~ 20 seconds + if ( + idleTime > 10 && + Math.floor(Math.random() * 200) == 0 && + idleAnimation == null + ) { + let avalibleIdleAnimations = ["sleeping", "scratchSelf"]; + if (nekoPosX < 32) { + avalibleIdleAnimations.push("scratchWallW"); + } + if (nekoPosY < 32) { + avalibleIdleAnimations.push("scratchWallN"); + } + if (nekoPosX > window.innerWidth - 32) { + avalibleIdleAnimations.push("scratchWallE"); + } + if (nekoPosY > window.innerHeight - 32) { + avalibleIdleAnimations.push("scratchWallS"); + } + idleAnimation = + avalibleIdleAnimations[ + Math.floor(Math.random() * avalibleIdleAnimations.length) + ]; + } + + switch (idleAnimation) { + case "sleeping": + if (idleAnimationFrame < 8) { + setSprite("tired", 0); + break; + } + setSprite("sleeping", Math.floor(idleAnimationFrame / 4)); + if (idleAnimationFrame > 192) { + resetIdleAnimation(); + } + break; + case "scratchWallN": + case "scratchWallS": + case "scratchWallE": + case "scratchWallW": + case "scratchSelf": + setSprite(idleAnimation, idleAnimationFrame); + if (idleAnimationFrame > 9) { + resetIdleAnimation(); + } + break; + default: + setSprite("idle", 0); + return; + } + idleAnimationFrame += 1; + } + + function explodeHearts() { + const parent = nekoEl.parentElement; + const rect = nekoEl.getBoundingClientRect(); + const scrollLeft = window.scrollX || document.documentElement.scrollLeft; + const scrollTop = window.scrollY || document.documentElement.scrollTop; + const centerX = rect.left + rect.width / 2 + scrollLeft; + const centerY = rect.top + rect.height / 2 + scrollTop; + + for (let i = 0; i < 10; i++) { + const heart = document.createElement('div'); + heart.className = 'heart'; + heart.textContent = '❤'; + const offsetX = (Math.random() - 0.5) * 50; + const offsetY = (Math.random() - 0.5) * 50; + heart.style.left = `${centerX + offsetX - 16}px`; + heart.style.top = `${centerY + offsetY - 16}px`; + heart.style.transform = `translate(-50%, -50%) rotate(${Math.random() * 360}deg)`; + parent.appendChild(heart); + + setTimeout(() => { + parent.removeChild(heart); + }, 1000); + } + } + + const style = document.createElement('style'); + style.innerHTML = ` + @keyframes heartBurst { + 0% { transform: scale(0); opacity: 1; } + 100% { transform: scale(1); opacity: 0; } + } + .heart { + position: absolute; + font-size: 2em; + animation: heartBurst 1s ease-out; + animation-fill-mode: forwards; + color: #ab9df2; + } + `; + + document.head.appendChild(style); + nekoEl.addEventListener('click', explodeHearts); + + function frame() { + frameCount += 1; + const diffX = nekoPosX - mousePosX; + const diffY = nekoPosY - mousePosY; + const distance = Math.sqrt(diffX ** 2 + diffY ** 2); + + if (distance < nekoSpeed || distance < 48) { + idle(); + return; + } + + idleAnimation = null; + idleAnimationFrame = 0; + + if (idleTime > 1) { + setSprite("alert", 0); + // count down after being alerted before moving + idleTime = Math.min(idleTime, 7); + idleTime -= 1; + return; + } + + let direction; + direction = diffY / distance > 0.5 ? "N" : ""; + direction += diffY / distance < -0.5 ? "S" : ""; + direction += diffX / distance > 0.5 ? "W" : ""; + direction += diffX / distance < -0.5 ? "E" : ""; + setSprite(direction, frameCount); + + nekoPosX -= (diffX / distance) * nekoSpeed; + nekoPosY -= (diffY / distance) * nekoSpeed; + + nekoPosX = Math.min(Math.max(16, nekoPosX), window.innerWidth - 16); + nekoPosY = Math.min(Math.max(16, nekoPosY), window.innerHeight - 16); + + nekoEl.style.left = `${nekoPosX - 16}px`; + nekoEl.style.top = `${nekoPosY - 16}px`; + } + + init(); +})(); \ No newline at end of file diff --git a/static/particles.js b/static/particles.js new file mode 100644 index 0000000..66404f3 --- /dev/null +++ b/static/particles.js @@ -0,0 +1,1546 @@ +/* ----------------------------------------------- +/* Author : Vincent Garreau - vincentgarreau.com +/* MIT license: http://opensource.org/licenses/MIT +/* Demo / Generator : vincentgarreau.com/particles.js +/* GitHub : github.com/VincentGarreau/particles.js +/* How to use? : Check the GitHub README +/* v2.0.0 +/* ----------------------------------------------- */ + +var pJS = function(tag_id, params){ + + var canvas_el = document.querySelector('#'+tag_id+' > .particles-js-canvas-el'); + + /* particles.js variables with default values */ + this.pJS = { + canvas: { + el: canvas_el, + w: canvas_el.offsetWidth, + h: canvas_el.offsetHeight + }, + particles: { + number: { + value: 400, + density: { + enable: true, + value_area: 800 + } + }, + color: { + value: '#fff' + }, + shape: { + type: 'circle', + stroke: { + width: 0, + color: '#ff0000' + }, + polygon: { + nb_sides: 5 + }, + image: { + src: '', + width: 100, + height: 100 + } + }, + opacity: { + value: 1, + random: false, + anim: { + enable: false, + speed: 2, + opacity_min: 0, + sync: false + } + }, + size: { + value: 20, + random: false, + anim: { + enable: false, + speed: 20, + size_min: 0, + sync: false + } + }, + line_linked: { + enable: true, + distance: 100, + color: '#fff', + opacity: 1, + width: 1 + }, + move: { + enable: true, + speed: 2, + direction: 'none', + random: false, + straight: false, + out_mode: 'out', + bounce: false, + attract: { + enable: false, + rotateX: 3000, + rotateY: 3000 + } + }, + array: [] + }, + interactivity: { + detect_on: 'canvas', + events: { + onhover: { + enable: true, + mode: 'grab' + }, + onclick: { + enable: true, + mode: 'push' + }, + resize: true + }, + modes: { + grab:{ + distance: 100, + line_linked:{ + opacity: 1 + } + }, + bubble:{ + distance: 200, + size: 80, + duration: 0.4 + }, + repulse:{ + distance: 200, + duration: 0.4 + }, + push:{ + particles_nb: 4 + }, + remove:{ + particles_nb: 2 + } + }, + mouse:{} + }, + retina_detect: false, + fn: { + interact: {}, + modes: {}, + vendors:{} + }, + tmp: {} + }; + + var pJS = this.pJS; + + /* params settings */ + if(params){ + Object.deepExtend(pJS, params); + } + + pJS.tmp.obj = { + size_value: pJS.particles.size.value, + size_anim_speed: pJS.particles.size.anim.speed, + move_speed: pJS.particles.move.speed, + line_linked_distance: pJS.particles.line_linked.distance, + line_linked_width: pJS.particles.line_linked.width, + mode_grab_distance: pJS.interactivity.modes.grab.distance, + mode_bubble_distance: pJS.interactivity.modes.bubble.distance, + mode_bubble_size: pJS.interactivity.modes.bubble.size, + mode_repulse_distance: pJS.interactivity.modes.repulse.distance + }; + + + pJS.fn.retinaInit = function(){ + + if(pJS.retina_detect && window.devicePixelRatio > 1){ + pJS.canvas.pxratio = window.devicePixelRatio; + pJS.tmp.retina = true; + } + else{ + pJS.canvas.pxratio = 1; + pJS.tmp.retina = false; + } + + pJS.canvas.w = pJS.canvas.el.offsetWidth * pJS.canvas.pxratio; + pJS.canvas.h = pJS.canvas.el.offsetHeight * pJS.canvas.pxratio; + + pJS.particles.size.value = pJS.tmp.obj.size_value * pJS.canvas.pxratio; + pJS.particles.size.anim.speed = pJS.tmp.obj.size_anim_speed * pJS.canvas.pxratio; + pJS.particles.move.speed = pJS.tmp.obj.move_speed * pJS.canvas.pxratio; + pJS.particles.line_linked.distance = pJS.tmp.obj.line_linked_distance * pJS.canvas.pxratio; + pJS.interactivity.modes.grab.distance = pJS.tmp.obj.mode_grab_distance * pJS.canvas.pxratio; + pJS.interactivity.modes.bubble.distance = pJS.tmp.obj.mode_bubble_distance * pJS.canvas.pxratio; + pJS.particles.line_linked.width = pJS.tmp.obj.line_linked_width * pJS.canvas.pxratio; + pJS.interactivity.modes.bubble.size = pJS.tmp.obj.mode_bubble_size * pJS.canvas.pxratio; + pJS.interactivity.modes.repulse.distance = pJS.tmp.obj.mode_repulse_distance * pJS.canvas.pxratio; + + }; + + + + /* ---------- pJS functions - canvas ------------ */ + + pJS.fn.canvasInit = function(){ + pJS.canvas.ctx = pJS.canvas.el.getContext('2d'); + }; + + pJS.fn.canvasSize = function(){ + + pJS.canvas.el.width = pJS.canvas.w; + pJS.canvas.el.height = pJS.canvas.h; + + if(pJS && pJS.interactivity.events.resize){ + + window.addEventListener('resize', function(){ + + pJS.canvas.w = pJS.canvas.el.offsetWidth; + pJS.canvas.h = pJS.canvas.el.offsetHeight; + + /* resize canvas */ + if(pJS.tmp.retina){ + pJS.canvas.w *= pJS.canvas.pxratio; + pJS.canvas.h *= pJS.canvas.pxratio; + } + + pJS.canvas.el.width = pJS.canvas.w; + pJS.canvas.el.height = pJS.canvas.h; + + /* repaint canvas on anim disabled */ + if(!pJS.particles.move.enable){ + pJS.fn.particlesEmpty(); + pJS.fn.particlesCreate(); + pJS.fn.particlesDraw(); + pJS.fn.vendors.densityAutoParticles(); + } + + /* density particles enabled */ + pJS.fn.vendors.densityAutoParticles(); + + }); + + } + + }; + + + pJS.fn.canvasPaint = function(){ + pJS.canvas.ctx.fillRect(0, 0, pJS.canvas.w, pJS.canvas.h); + }; + + pJS.fn.canvasClear = function(){ + pJS.canvas.ctx.clearRect(0, 0, pJS.canvas.w, pJS.canvas.h); + }; + + + /* --------- pJS functions - particles ----------- */ + + pJS.fn.particle = function(color, opacity, position){ + + /* size */ + this.radius = (pJS.particles.size.random ? Math.random() : 1) * pJS.particles.size.value; + if(pJS.particles.size.anim.enable){ + this.size_status = false; + this.vs = pJS.particles.size.anim.speed / 100; + if(!pJS.particles.size.anim.sync){ + this.vs = this.vs * Math.random(); + } + } + + /* position */ + this.x = position ? position.x : Math.random() * pJS.canvas.w; + this.y = position ? position.y : Math.random() * pJS.canvas.h; + + /* check position - into the canvas */ + if(this.x > pJS.canvas.w - this.radius*2) this.x = this.x - this.radius; + else if(this.x < this.radius*2) this.x = this.x + this.radius; + if(this.y > pJS.canvas.h - this.radius*2) this.y = this.y - this.radius; + else if(this.y < this.radius*2) this.y = this.y + this.radius; + + /* check position - avoid overlap */ + if(pJS.particles.move.bounce){ + pJS.fn.vendors.checkOverlap(this, position); + } + + /* color */ + this.color = {}; + if(typeof(color.value) == 'object'){ + + if(color.value instanceof Array){ + var color_selected = color.value[Math.floor(Math.random() * pJS.particles.color.value.length)]; + this.color.rgb = hexToRgb(color_selected); + }else{ + if(color.value.r != undefined && color.value.g != undefined && color.value.b != undefined){ + this.color.rgb = { + r: color.value.r, + g: color.value.g, + b: color.value.b + } + } + if(color.value.h != undefined && color.value.s != undefined && color.value.l != undefined){ + this.color.hsl = { + h: color.value.h, + s: color.value.s, + l: color.value.l + } + } + } + + } + else if(color.value == 'random'){ + this.color.rgb = { + r: (Math.floor(Math.random() * (255 - 0 + 1)) + 0), + g: (Math.floor(Math.random() * (255 - 0 + 1)) + 0), + b: (Math.floor(Math.random() * (255 - 0 + 1)) + 0) + } + } + else if(typeof(color.value) == 'string'){ + this.color = color; + this.color.rgb = hexToRgb(this.color.value); + } + + /* opacity */ + this.opacity = (pJS.particles.opacity.random ? Math.random() : 1) * pJS.particles.opacity.value; + if(pJS.particles.opacity.anim.enable){ + this.opacity_status = false; + this.vo = pJS.particles.opacity.anim.speed / 100; + if(!pJS.particles.opacity.anim.sync){ + this.vo = this.vo * Math.random(); + } + } + + /* animation - velocity for speed */ + var velbase = {} + switch(pJS.particles.move.direction){ + case 'top': + velbase = { x:0, y:-1 }; + break; + case 'top-right': + velbase = { x:0.5, y:-0.5 }; + break; + case 'right': + velbase = { x:1, y:-0 }; + break; + case 'bottom-right': + velbase = { x:0.5, y:0.5 }; + break; + case 'bottom': + velbase = { x:0, y:1 }; + break; + case 'bottom-left': + velbase = { x:-0.5, y:1 }; + break; + case 'left': + velbase = { x:-1, y:0 }; + break; + case 'top-left': + velbase = { x:-0.5, y:-0.5 }; + break; + default: + velbase = { x:0, y:0 }; + break; + } + + if(pJS.particles.move.straight){ + this.vx = velbase.x; + this.vy = velbase.y; + if(pJS.particles.move.random){ + this.vx = this.vx * (Math.random()); + this.vy = this.vy * (Math.random()); + } + }else{ + this.vx = velbase.x + Math.random()-0.5; + this.vy = velbase.y + Math.random()-0.5; + } + + // var theta = 2.0 * Math.PI * Math.random(); + // this.vx = Math.cos(theta); + // this.vy = Math.sin(theta); + + this.vx_i = this.vx; + this.vy_i = this.vy; + + + + /* if shape is image */ + + var shape_type = pJS.particles.shape.type; + if(typeof(shape_type) == 'object'){ + if(shape_type instanceof Array){ + var shape_selected = shape_type[Math.floor(Math.random() * shape_type.length)]; + this.shape = shape_selected; + } + }else{ + this.shape = shape_type; + } + + if(this.shape == 'image'){ + var sh = pJS.particles.shape; + this.img = { + src: sh.image.src, + ratio: sh.image.width / sh.image.height + } + if(!this.img.ratio) this.img.ratio = 1; + if(pJS.tmp.img_type == 'svg' && pJS.tmp.source_svg != undefined){ + pJS.fn.vendors.createSvgImg(this); + if(pJS.tmp.pushing){ + this.img.loaded = false; + } + } + } + + + + }; + + + pJS.fn.particle.prototype.draw = function() { + + var p = this; + + if(p.radius_bubble != undefined){ + var radius = p.radius_bubble; + }else{ + var radius = p.radius; + } + + if(p.opacity_bubble != undefined){ + var opacity = p.opacity_bubble; + }else{ + var opacity = p.opacity; + } + + if(p.color.rgb){ + var color_value = 'rgba('+p.color.rgb.r+','+p.color.rgb.g+','+p.color.rgb.b+','+opacity+')'; + }else{ + var color_value = 'hsla('+p.color.hsl.h+','+p.color.hsl.s+'%,'+p.color.hsl.l+'%,'+opacity+')'; + } + + pJS.canvas.ctx.fillStyle = color_value; + pJS.canvas.ctx.beginPath(); + + switch(p.shape){ + + case 'circle': + pJS.canvas.ctx.arc(p.x, p.y, radius, 0, Math.PI * 2, false); + break; + + case 'edge': + pJS.canvas.ctx.rect(p.x-radius, p.y-radius, radius*2, radius*2); + break; + + case 'triangle': + pJS.fn.vendors.drawShape(pJS.canvas.ctx, p.x-radius, p.y+radius / 1.66, radius*2, 3, 2); + break; + + case 'polygon': + pJS.fn.vendors.drawShape( + pJS.canvas.ctx, + p.x - radius / (pJS.particles.shape.polygon.nb_sides/3.5), // startX + p.y - radius / (2.66/3.5), // startY + radius*2.66 / (pJS.particles.shape.polygon.nb_sides/3), // sideLength + pJS.particles.shape.polygon.nb_sides, // sideCountNumerator + 1 // sideCountDenominator + ); + break; + + case 'star': + pJS.fn.vendors.drawShape( + pJS.canvas.ctx, + p.x - radius*2 / (pJS.particles.shape.polygon.nb_sides/4), // startX + p.y - radius / (2*2.66/3.5), // startY + radius*2*2.66 / (pJS.particles.shape.polygon.nb_sides/3), // sideLength + pJS.particles.shape.polygon.nb_sides, // sideCountNumerator + 2 // sideCountDenominator + ); + break; + + case 'image': + + function draw(){ + pJS.canvas.ctx.drawImage( + img_obj, + p.x-radius, + p.y-radius, + radius*2, + radius*2 / p.img.ratio + ); + } + + if(pJS.tmp.img_type == 'svg'){ + var img_obj = p.img.obj; + }else{ + var img_obj = pJS.tmp.img_obj; + } + + if(img_obj){ + draw(); + } + + break; + + } + + pJS.canvas.ctx.closePath(); + + if(pJS.particles.shape.stroke.width > 0){ + pJS.canvas.ctx.strokeStyle = pJS.particles.shape.stroke.color; + pJS.canvas.ctx.lineWidth = pJS.particles.shape.stroke.width; + pJS.canvas.ctx.stroke(); + } + + pJS.canvas.ctx.fill(); + + }; + + + pJS.fn.particlesCreate = function(){ + for(var i = 0; i < pJS.particles.number.value; i++) { + pJS.particles.array.push(new pJS.fn.particle(pJS.particles.color, pJS.particles.opacity.value)); + } + }; + + pJS.fn.particlesUpdate = function(){ + + for(var i = 0; i < pJS.particles.array.length; i++){ + + /* the particle */ + var p = pJS.particles.array[i]; + + // var d = ( dx = pJS.interactivity.mouse.click_pos_x - p.x ) * dx + ( dy = pJS.interactivity.mouse.click_pos_y - p.y ) * dy; + // var f = -BANG_SIZE / d; + // if ( d < BANG_SIZE ) { + // var t = Math.atan2( dy, dx ); + // p.vx = f * Math.cos(t); + // p.vy = f * Math.sin(t); + // } + + /* move the particle */ + if(pJS.particles.move.enable){ + var ms = pJS.particles.move.speed/2; + p.x += p.vx * ms; + p.y += p.vy * ms; + } + + /* change opacity status */ + if(pJS.particles.opacity.anim.enable) { + if(p.opacity_status == true) { + if(p.opacity >= pJS.particles.opacity.value) p.opacity_status = false; + p.opacity += p.vo; + }else { + if(p.opacity <= pJS.particles.opacity.anim.opacity_min) p.opacity_status = true; + p.opacity -= p.vo; + } + if(p.opacity < 0) p.opacity = 0; + } + + /* change size */ + if(pJS.particles.size.anim.enable){ + if(p.size_status == true){ + if(p.radius >= pJS.particles.size.value) p.size_status = false; + p.radius += p.vs; + }else{ + if(p.radius <= pJS.particles.size.anim.size_min) p.size_status = true; + p.radius -= p.vs; + } + if(p.radius < 0) p.radius = 0; + } + + /* change particle position if it is out of canvas */ + if(pJS.particles.move.out_mode == 'bounce'){ + var new_pos = { + x_left: p.radius, + x_right: pJS.canvas.w, + y_top: p.radius, + y_bottom: pJS.canvas.h + } + }else{ + var new_pos = { + x_left: -p.radius, + x_right: pJS.canvas.w + p.radius, + y_top: -p.radius, + y_bottom: pJS.canvas.h + p.radius + } + } + + if(p.x - p.radius > pJS.canvas.w){ + p.x = new_pos.x_left; + p.y = Math.random() * pJS.canvas.h; + } + else if(p.x + p.radius < 0){ + p.x = new_pos.x_right; + p.y = Math.random() * pJS.canvas.h; + } + if(p.y - p.radius > pJS.canvas.h){ + p.y = new_pos.y_top; + p.x = Math.random() * pJS.canvas.w; + } + else if(p.y + p.radius < 0){ + p.y = new_pos.y_bottom; + p.x = Math.random() * pJS.canvas.w; + } + + /* out of canvas modes */ + switch(pJS.particles.move.out_mode){ + case 'bounce': + if (p.x + p.radius > pJS.canvas.w) p.vx = -p.vx; + else if (p.x - p.radius < 0) p.vx = -p.vx; + if (p.y + p.radius > pJS.canvas.h) p.vy = -p.vy; + else if (p.y - p.radius < 0) p.vy = -p.vy; + break; + } + + /* events */ + if(isInArray('grab', pJS.interactivity.events.onhover.mode)){ + pJS.fn.modes.grabParticle(p); + } + + if(isInArray('bubble', pJS.interactivity.events.onhover.mode) || isInArray('bubble', pJS.interactivity.events.onclick.mode)){ + pJS.fn.modes.bubbleParticle(p); + } + + if(isInArray('repulse', pJS.interactivity.events.onhover.mode) || isInArray('repulse', pJS.interactivity.events.onclick.mode)){ + pJS.fn.modes.repulseParticle(p); + } + + /* interaction auto between particles */ + if(pJS.particles.line_linked.enable || pJS.particles.move.attract.enable){ + for(var j = i + 1; j < pJS.particles.array.length; j++){ + var p2 = pJS.particles.array[j]; + + /* link particles */ + if(pJS.particles.line_linked.enable){ + pJS.fn.interact.linkParticles(p,p2); + } + + /* attract particles */ + if(pJS.particles.move.attract.enable){ + pJS.fn.interact.attractParticles(p,p2); + } + + /* bounce particles */ + if(pJS.particles.move.bounce){ + pJS.fn.interact.bounceParticles(p,p2); + } + + } + } + + + } + + }; + + pJS.fn.particlesDraw = function(){ + + /* clear canvas */ + pJS.canvas.ctx.clearRect(0, 0, pJS.canvas.w, pJS.canvas.h); + + /* update each particles param */ + pJS.fn.particlesUpdate(); + + /* draw each particle */ + for(var i = 0; i < pJS.particles.array.length; i++){ + var p = pJS.particles.array[i]; + p.draw(); + } + + }; + + pJS.fn.particlesEmpty = function(){ + pJS.particles.array = []; + }; + + pJS.fn.particlesRefresh = function(){ + + /* init all */ + cancelRequestAnimFrame(pJS.fn.checkAnimFrame); + cancelRequestAnimFrame(pJS.fn.drawAnimFrame); + pJS.tmp.source_svg = undefined; + pJS.tmp.img_obj = undefined; + pJS.tmp.count_svg = 0; + pJS.fn.particlesEmpty(); + pJS.fn.canvasClear(); + + /* restart */ + pJS.fn.vendors.start(); + + }; + + + /* ---------- pJS functions - particles interaction ------------ */ + + pJS.fn.interact.linkParticles = function(p1, p2){ + + var dx = p1.x - p2.x, + dy = p1.y - p2.y, + dist = Math.sqrt(dx*dx + dy*dy); + + /* draw a line between p1 and p2 if the distance between them is under the config distance */ + if(dist <= pJS.particles.line_linked.distance){ + + var opacity_line = pJS.particles.line_linked.opacity - (dist / (1/pJS.particles.line_linked.opacity)) / pJS.particles.line_linked.distance; + + if(opacity_line > 0){ + + /* style */ + var color_line = pJS.particles.line_linked.color_rgb_line; + pJS.canvas.ctx.strokeStyle = 'rgba('+color_line.r+','+color_line.g+','+color_line.b+','+opacity_line+')'; + pJS.canvas.ctx.lineWidth = pJS.particles.line_linked.width; + //pJS.canvas.ctx.lineCap = 'round'; /* performance issue */ + + /* path */ + pJS.canvas.ctx.beginPath(); + pJS.canvas.ctx.moveTo(p1.x, p1.y); + pJS.canvas.ctx.lineTo(p2.x, p2.y); + pJS.canvas.ctx.stroke(); + pJS.canvas.ctx.closePath(); + + } + + } + + }; + + + pJS.fn.interact.attractParticles = function(p1, p2){ + + /* condensed particles */ + var dx = p1.x - p2.x, + dy = p1.y - p2.y, + dist = Math.sqrt(dx*dx + dy*dy); + + if(dist <= pJS.particles.line_linked.distance){ + + var ax = dx/(pJS.particles.move.attract.rotateX*1000), + ay = dy/(pJS.particles.move.attract.rotateY*1000); + + p1.vx -= ax; + p1.vy -= ay; + + p2.vx += ax; + p2.vy += ay; + + } + + + } + + + pJS.fn.interact.bounceParticles = function(p1, p2){ + + var dx = p1.x - p2.x, + dy = p1.y - p2.y, + dist = Math.sqrt(dx*dx + dy*dy), + dist_p = p1.radius+p2.radius; + + if(dist <= dist_p){ + p1.vx = -p1.vx; + p1.vy = -p1.vy; + + p2.vx = -p2.vx; + p2.vy = -p2.vy; + } + + } + + + /* ---------- pJS functions - modes events ------------ */ + + pJS.fn.modes.pushParticles = function(nb, pos){ + + pJS.tmp.pushing = true; + + for(var i = 0; i < nb; i++){ + pJS.particles.array.push( + new pJS.fn.particle( + pJS.particles.color, + pJS.particles.opacity.value, + { + 'x': pos ? pos.pos_x : Math.random() * pJS.canvas.w, + 'y': pos ? pos.pos_y : Math.random() * pJS.canvas.h + } + ) + ) + if(i == nb-1){ + if(!pJS.particles.move.enable){ + pJS.fn.particlesDraw(); + } + pJS.tmp.pushing = false; + } + } + + }; + + + pJS.fn.modes.removeParticles = function(nb){ + + pJS.particles.array.splice(0, nb); + if(!pJS.particles.move.enable){ + pJS.fn.particlesDraw(); + } + + }; + + + pJS.fn.modes.bubbleParticle = function(p){ + + /* on hover event */ + if(pJS.interactivity.events.onhover.enable && isInArray('bubble', pJS.interactivity.events.onhover.mode)){ + + var dx_mouse = p.x - pJS.interactivity.mouse.pos_x, + dy_mouse = p.y - pJS.interactivity.mouse.pos_y, + dist_mouse = Math.sqrt(dx_mouse*dx_mouse + dy_mouse*dy_mouse), + ratio = 1 - dist_mouse / pJS.interactivity.modes.bubble.distance; + + function init(){ + p.opacity_bubble = p.opacity; + p.radius_bubble = p.radius; + } + + /* mousemove - check ratio */ + if(dist_mouse <= pJS.interactivity.modes.bubble.distance){ + + if(ratio >= 0 && pJS.interactivity.status == 'mousemove'){ + + /* size */ + if(pJS.interactivity.modes.bubble.size != pJS.particles.size.value){ + + if(pJS.interactivity.modes.bubble.size > pJS.particles.size.value){ + var size = p.radius + (pJS.interactivity.modes.bubble.size*ratio); + if(size >= 0){ + p.radius_bubble = size; + } + }else{ + var dif = p.radius - pJS.interactivity.modes.bubble.size, + size = p.radius - (dif*ratio); + if(size > 0){ + p.radius_bubble = size; + }else{ + p.radius_bubble = 0; + } + } + + } + + /* opacity */ + if(pJS.interactivity.modes.bubble.opacity != pJS.particles.opacity.value){ + + if(pJS.interactivity.modes.bubble.opacity > pJS.particles.opacity.value){ + var opacity = pJS.interactivity.modes.bubble.opacity*ratio; + if(opacity > p.opacity && opacity <= pJS.interactivity.modes.bubble.opacity){ + p.opacity_bubble = opacity; + } + }else{ + var opacity = p.opacity - (pJS.particles.opacity.value-pJS.interactivity.modes.bubble.opacity)*ratio; + if(opacity < p.opacity && opacity >= pJS.interactivity.modes.bubble.opacity){ + p.opacity_bubble = opacity; + } + } + + } + + } + + }else{ + init(); + } + + + /* mouseleave */ + if(pJS.interactivity.status == 'mouseleave'){ + init(); + } + + } + + /* on click event */ + else if(pJS.interactivity.events.onclick.enable && isInArray('bubble', pJS.interactivity.events.onclick.mode)){ + + + if(pJS.tmp.bubble_clicking){ + var dx_mouse = p.x - pJS.interactivity.mouse.click_pos_x, + dy_mouse = p.y - pJS.interactivity.mouse.click_pos_y, + dist_mouse = Math.sqrt(dx_mouse*dx_mouse + dy_mouse*dy_mouse), + time_spent = (new Date().getTime() - pJS.interactivity.mouse.click_time)/1000; + + if(time_spent > pJS.interactivity.modes.bubble.duration){ + pJS.tmp.bubble_duration_end = true; + } + + if(time_spent > pJS.interactivity.modes.bubble.duration*2){ + pJS.tmp.bubble_clicking = false; + pJS.tmp.bubble_duration_end = false; + } + } + + + function process(bubble_param, particles_param, p_obj_bubble, p_obj, id){ + + if(bubble_param != particles_param){ + + if(!pJS.tmp.bubble_duration_end){ + if(dist_mouse <= pJS.interactivity.modes.bubble.distance){ + if(p_obj_bubble != undefined) var obj = p_obj_bubble; + else var obj = p_obj; + if(obj != bubble_param){ + var value = p_obj - (time_spent * (p_obj - bubble_param) / pJS.interactivity.modes.bubble.duration); + if(id == 'size') p.radius_bubble = value; + if(id == 'opacity') p.opacity_bubble = value; + } + }else{ + if(id == 'size') p.radius_bubble = undefined; + if(id == 'opacity') p.opacity_bubble = undefined; + } + }else{ + if(p_obj_bubble != undefined){ + var value_tmp = p_obj - (time_spent * (p_obj - bubble_param) / pJS.interactivity.modes.bubble.duration), + dif = bubble_param - value_tmp; + value = bubble_param + dif; + if(id == 'size') p.radius_bubble = value; + if(id == 'opacity') p.opacity_bubble = value; + } + } + + } + + } + + if(pJS.tmp.bubble_clicking){ + /* size */ + process(pJS.interactivity.modes.bubble.size, pJS.particles.size.value, p.radius_bubble, p.radius, 'size'); + /* opacity */ + process(pJS.interactivity.modes.bubble.opacity, pJS.particles.opacity.value, p.opacity_bubble, p.opacity, 'opacity'); + } + + } + + }; + + + pJS.fn.modes.repulseParticle = function(p){ + + if(pJS.interactivity.events.onhover.enable && isInArray('repulse', pJS.interactivity.events.onhover.mode) && pJS.interactivity.status == 'mousemove') { + + var dx_mouse = p.x - pJS.interactivity.mouse.pos_x, + dy_mouse = p.y - pJS.interactivity.mouse.pos_y, + dist_mouse = Math.sqrt(dx_mouse*dx_mouse + dy_mouse*dy_mouse); + + var normVec = {x: dx_mouse/dist_mouse, y: dy_mouse/dist_mouse}, + repulseRadius = pJS.interactivity.modes.repulse.distance, + velocity = 100, + repulseFactor = clamp((1/repulseRadius)*(-1*Math.pow(dist_mouse/repulseRadius,2)+1)*repulseRadius*velocity, 0, 50); + + var pos = { + x: p.x + normVec.x * repulseFactor, + y: p.y + normVec.y * repulseFactor + } + + if(pJS.particles.move.out_mode == 'bounce'){ + if(pos.x - p.radius > 0 && pos.x + p.radius < pJS.canvas.w) p.x = pos.x; + if(pos.y - p.radius > 0 && pos.y + p.radius < pJS.canvas.h) p.y = pos.y; + }else{ + p.x = pos.x; + p.y = pos.y; + } + + } + + + else if(pJS.interactivity.events.onclick.enable && isInArray('repulse', pJS.interactivity.events.onclick.mode)) { + + if(!pJS.tmp.repulse_finish){ + pJS.tmp.repulse_count++; + if(pJS.tmp.repulse_count == pJS.particles.array.length){ + pJS.tmp.repulse_finish = true; + } + } + + if(pJS.tmp.repulse_clicking){ + + var repulseRadius = Math.pow(pJS.interactivity.modes.repulse.distance/6, 3); + + var dx = pJS.interactivity.mouse.click_pos_x - p.x, + dy = pJS.interactivity.mouse.click_pos_y - p.y, + d = dx*dx + dy*dy; + + var force = -repulseRadius / d * 1; + + function process(){ + + var f = Math.atan2(dy,dx); + p.vx = force * Math.cos(f); + p.vy = force * Math.sin(f); + + if(pJS.particles.move.out_mode == 'bounce'){ + var pos = { + x: p.x + p.vx, + y: p.y + p.vy + } + if (pos.x + p.radius > pJS.canvas.w) p.vx = -p.vx; + else if (pos.x - p.radius < 0) p.vx = -p.vx; + if (pos.y + p.radius > pJS.canvas.h) p.vy = -p.vy; + else if (pos.y - p.radius < 0) p.vy = -p.vy; + } + + } + + // default + if(d <= repulseRadius){ + process(); + } + + // bang - slow motion mode + // if(!pJS.tmp.repulse_finish){ + // if(d <= repulseRadius){ + // process(); + // } + // }else{ + // process(); + // } + + + }else{ + + if(pJS.tmp.repulse_clicking == false){ + + p.vx = p.vx_i; + p.vy = p.vy_i; + + } + + } + + } + + } + + + pJS.fn.modes.grabParticle = function(p){ + + if(pJS.interactivity.events.onhover.enable && pJS.interactivity.status == 'mousemove'){ + + var dx_mouse = p.x - pJS.interactivity.mouse.pos_x, + dy_mouse = p.y - pJS.interactivity.mouse.pos_y, + dist_mouse = Math.sqrt(dx_mouse*dx_mouse + dy_mouse*dy_mouse); + + /* draw a line between the cursor and the particle if the distance between them is under the config distance */ + if(dist_mouse <= pJS.interactivity.modes.grab.distance){ + + var opacity_line = pJS.interactivity.modes.grab.line_linked.opacity - (dist_mouse / (1/pJS.interactivity.modes.grab.line_linked.opacity)) / pJS.interactivity.modes.grab.distance; + + if(opacity_line > 0){ + + /* style */ + var color_line = pJS.particles.line_linked.color_rgb_line; + pJS.canvas.ctx.strokeStyle = 'rgba('+color_line.r+','+color_line.g+','+color_line.b+','+opacity_line+')'; + pJS.canvas.ctx.lineWidth = pJS.particles.line_linked.width; + //pJS.canvas.ctx.lineCap = 'round'; /* performance issue */ + + /* path */ + pJS.canvas.ctx.beginPath(); + pJS.canvas.ctx.moveTo(p.x, p.y); + pJS.canvas.ctx.lineTo(pJS.interactivity.mouse.pos_x, pJS.interactivity.mouse.pos_y); + pJS.canvas.ctx.stroke(); + pJS.canvas.ctx.closePath(); + + } + + } + + } + + }; + + + + /* ---------- pJS functions - vendors ------------ */ + + pJS.fn.vendors.eventsListeners = function(){ + + /* events target element */ + if(pJS.interactivity.detect_on == 'window'){ + pJS.interactivity.el = window; + }else{ + pJS.interactivity.el = pJS.canvas.el; + } + + + /* detect mouse pos - on hover / click event */ + if(pJS.interactivity.events.onhover.enable || pJS.interactivity.events.onclick.enable){ + + /* el on mousemove */ + pJS.interactivity.el.addEventListener('mousemove', function(e){ + + if(pJS.interactivity.el == window){ + var pos_x = e.clientX, + pos_y = e.clientY; + } + else{ + var pos_x = e.offsetX || e.clientX, + pos_y = e.offsetY || e.clientY; + } + + pJS.interactivity.mouse.pos_x = pos_x; + pJS.interactivity.mouse.pos_y = pos_y; + + if(pJS.tmp.retina){ + pJS.interactivity.mouse.pos_x *= pJS.canvas.pxratio; + pJS.interactivity.mouse.pos_y *= pJS.canvas.pxratio; + } + + pJS.interactivity.status = 'mousemove'; + + }); + + /* el on onmouseleave */ + pJS.interactivity.el.addEventListener('mouseleave', function(e){ + + pJS.interactivity.mouse.pos_x = null; + pJS.interactivity.mouse.pos_y = null; + pJS.interactivity.status = 'mouseleave'; + + }); + + } + + /* on click event */ + if(pJS.interactivity.events.onclick.enable){ + + pJS.interactivity.el.addEventListener('click', function(){ + + pJS.interactivity.mouse.click_pos_x = pJS.interactivity.mouse.pos_x; + pJS.interactivity.mouse.click_pos_y = pJS.interactivity.mouse.pos_y; + pJS.interactivity.mouse.click_time = new Date().getTime(); + + if(pJS.interactivity.events.onclick.enable){ + + switch(pJS.interactivity.events.onclick.mode){ + + case 'push': + if(pJS.particles.move.enable){ + pJS.fn.modes.pushParticles(pJS.interactivity.modes.push.particles_nb, pJS.interactivity.mouse); + }else{ + if(pJS.interactivity.modes.push.particles_nb == 1){ + pJS.fn.modes.pushParticles(pJS.interactivity.modes.push.particles_nb, pJS.interactivity.mouse); + } + else if(pJS.interactivity.modes.push.particles_nb > 1){ + pJS.fn.modes.pushParticles(pJS.interactivity.modes.push.particles_nb); + } + } + break; + + case 'remove': + pJS.fn.modes.removeParticles(pJS.interactivity.modes.remove.particles_nb); + break; + + case 'bubble': + pJS.tmp.bubble_clicking = true; + break; + + case 'repulse': + pJS.tmp.repulse_clicking = true; + pJS.tmp.repulse_count = 0; + pJS.tmp.repulse_finish = false; + setTimeout(function(){ + pJS.tmp.repulse_clicking = false; + }, pJS.interactivity.modes.repulse.duration*1000) + break; + + } + + } + + }); + + } + + + }; + + pJS.fn.vendors.densityAutoParticles = function(){ + + if(pJS.particles.number.density.enable){ + + /* calc area */ + var area = pJS.canvas.el.width * pJS.canvas.el.height / 1000; + if(pJS.tmp.retina){ + area = area/(pJS.canvas.pxratio*2); + } + + /* calc number of particles based on density area */ + var nb_particles = area * pJS.particles.number.value / pJS.particles.number.density.value_area; + + /* add or remove X particles */ + var missing_particles = pJS.particles.array.length - nb_particles; + if(missing_particles < 0) pJS.fn.modes.pushParticles(Math.abs(missing_particles)); + else pJS.fn.modes.removeParticles(missing_particles); + + } + + }; + + + pJS.fn.vendors.checkOverlap = function(p1, position){ + for(var i = 0; i < pJS.particles.array.length; i++){ + var p2 = pJS.particles.array[i]; + + var dx = p1.x - p2.x, + dy = p1.y - p2.y, + dist = Math.sqrt(dx*dx + dy*dy); + + if(dist <= p1.radius + p2.radius){ + p1.x = position ? position.x : Math.random() * pJS.canvas.w; + p1.y = position ? position.y : Math.random() * pJS.canvas.h; + pJS.fn.vendors.checkOverlap(p1); + } + } + }; + + + pJS.fn.vendors.createSvgImg = function(p){ + + /* set color to svg element */ + var svgXml = pJS.tmp.source_svg, + rgbHex = /#([0-9A-F]{3,6})/gi, + coloredSvgXml = svgXml.replace(rgbHex, function (m, r, g, b) { + if(p.color.rgb){ + var color_value = 'rgba('+p.color.rgb.r+','+p.color.rgb.g+','+p.color.rgb.b+','+p.opacity+')'; + }else{ + var color_value = 'hsla('+p.color.hsl.h+','+p.color.hsl.s+'%,'+p.color.hsl.l+'%,'+p.opacity+')'; + } + return color_value; + }); + + /* prepare to create img with colored svg */ + var svg = new Blob([coloredSvgXml], {type: 'image/svg+xml;charset=utf-8'}), + DOMURL = window.URL || window.webkitURL || window, + url = DOMURL.createObjectURL(svg); + + /* create particle img obj */ + var img = new Image(); + img.addEventListener('load', function(){ + p.img.obj = img; + p.img.loaded = true; + DOMURL.revokeObjectURL(url); + pJS.tmp.count_svg++; + }); + img.src = url; + + }; + + + pJS.fn.vendors.destroypJS = function(){ + cancelAnimationFrame(pJS.fn.drawAnimFrame); + canvas_el.remove(); + pJSDom = null; + }; + + + pJS.fn.vendors.drawShape = function(c, startX, startY, sideLength, sideCountNumerator, sideCountDenominator){ + + // By Programming Thomas - https://programmingthomas.wordpress.com/2013/04/03/n-sided-shapes/ + var sideCount = sideCountNumerator * sideCountDenominator; + var decimalSides = sideCountNumerator / sideCountDenominator; + var interiorAngleDegrees = (180 * (decimalSides - 2)) / decimalSides; + var interiorAngle = Math.PI - Math.PI * interiorAngleDegrees / 180; // convert to radians + c.save(); + c.beginPath(); + c.translate(startX, startY); + c.moveTo(0,0); + for (var i = 0; i < sideCount; i++) { + c.lineTo(sideLength,0); + c.translate(sideLength,0); + c.rotate(interiorAngle); + } + //c.stroke(); + c.fill(); + c.restore(); + + }; + + pJS.fn.vendors.exportImg = function(){ + window.open(pJS.canvas.el.toDataURL('image/png'), '_blank'); + }; + + + pJS.fn.vendors.loadImg = function(type){ + + pJS.tmp.img_error = undefined; + + if(pJS.particles.shape.image.src != ''){ + + if(type == 'svg'){ + + var xhr = new XMLHttpRequest(); + xhr.open('GET', pJS.particles.shape.image.src); + xhr.onreadystatechange = function (data) { + if(xhr.readyState == 4){ + if(xhr.status == 200){ + pJS.tmp.source_svg = data.currentTarget.response; + pJS.fn.vendors.checkBeforeDraw(); + }else{ + console.log('Error pJS - Image not found'); + pJS.tmp.img_error = true; + } + } + } + xhr.send(); + + }else{ + + var img = new Image(); + img.addEventListener('load', function(){ + pJS.tmp.img_obj = img; + pJS.fn.vendors.checkBeforeDraw(); + }); + img.src = pJS.particles.shape.image.src; + + } + + }else{ + console.log('Error pJS - No image.src'); + pJS.tmp.img_error = true; + } + + }; + + + pJS.fn.vendors.draw = function(){ + + if(pJS.particles.shape.type == 'image'){ + + if(pJS.tmp.img_type == 'svg'){ + + if(pJS.tmp.count_svg >= pJS.particles.number.value){ + pJS.fn.particlesDraw(); + if(!pJS.particles.move.enable) cancelRequestAnimFrame(pJS.fn.drawAnimFrame); + else pJS.fn.drawAnimFrame = requestAnimFrame(pJS.fn.vendors.draw); + }else{ + //console.log('still loading...'); + if(!pJS.tmp.img_error) pJS.fn.drawAnimFrame = requestAnimFrame(pJS.fn.vendors.draw); + } + + }else{ + + if(pJS.tmp.img_obj != undefined){ + pJS.fn.particlesDraw(); + if(!pJS.particles.move.enable) cancelRequestAnimFrame(pJS.fn.drawAnimFrame); + else pJS.fn.drawAnimFrame = requestAnimFrame(pJS.fn.vendors.draw); + }else{ + if(!pJS.tmp.img_error) pJS.fn.drawAnimFrame = requestAnimFrame(pJS.fn.vendors.draw); + } + + } + + }else{ + pJS.fn.particlesDraw(); + if(!pJS.particles.move.enable) cancelRequestAnimFrame(pJS.fn.drawAnimFrame); + else pJS.fn.drawAnimFrame = requestAnimFrame(pJS.fn.vendors.draw); + } + + }; + + + pJS.fn.vendors.checkBeforeDraw = function(){ + + // if shape is image + if(pJS.particles.shape.type == 'image'){ + + if(pJS.tmp.img_type == 'svg' && pJS.tmp.source_svg == undefined){ + pJS.tmp.checkAnimFrame = requestAnimFrame(check); + }else{ + //console.log('images loaded! cancel check'); + cancelRequestAnimFrame(pJS.tmp.checkAnimFrame); + if(!pJS.tmp.img_error){ + pJS.fn.vendors.init(); + pJS.fn.vendors.draw(); + } + + } + + }else{ + pJS.fn.vendors.init(); + pJS.fn.vendors.draw(); + } + + }; + + + pJS.fn.vendors.init = function(){ + + /* init canvas + particles */ + pJS.fn.retinaInit(); + pJS.fn.canvasInit(); + pJS.fn.canvasSize(); + pJS.fn.canvasPaint(); + pJS.fn.particlesCreate(); + pJS.fn.vendors.densityAutoParticles(); + + /* particles.line_linked - convert hex colors to rgb */ + pJS.particles.line_linked.color_rgb_line = hexToRgb(pJS.particles.line_linked.color); + + }; + + + pJS.fn.vendors.start = function(){ + + if(isInArray('image', pJS.particles.shape.type)){ + pJS.tmp.img_type = pJS.particles.shape.image.src.substr(pJS.particles.shape.image.src.length - 3); + pJS.fn.vendors.loadImg(pJS.tmp.img_type); + }else{ + pJS.fn.vendors.checkBeforeDraw(); + } + + }; + + + + + /* ---------- pJS - start ------------ */ + + + pJS.fn.vendors.eventsListeners(); + + pJS.fn.vendors.start(); + + + +}; + +/* ---------- global functions - vendors ------------ */ + +Object.deepExtend = function(destination, source) { + for (var property in source) { + if (source[property] && source[property].constructor && + source[property].constructor === Object) { + destination[property] = destination[property] || {}; + arguments.callee(destination[property], source[property]); + } else { + destination[property] = source[property]; + } + } + return destination; +}; + +window.requestAnimFrame = (function(){ + return window.requestAnimationFrame || + window.webkitRequestAnimationFrame || + window.mozRequestAnimationFrame || + window.oRequestAnimationFrame || + window.msRequestAnimationFrame || + function(callback){ + window.setTimeout(callback, 1000 / 60); + }; +})(); + +window.cancelRequestAnimFrame = ( function() { + return window.cancelAnimationFrame || + window.webkitCancelRequestAnimationFrame || + window.mozCancelRequestAnimationFrame || + window.oCancelRequestAnimationFrame || + window.msCancelRequestAnimationFrame || + clearTimeout +} )(); + +function hexToRgb(hex){ + // By Tim Down - http://stackoverflow.com/a/5624139/3493650 + // Expand shorthand form (e.g. "03F") to full form (e.g. "0033FF") + var shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i; + hex = hex.replace(shorthandRegex, function(m, r, g, b) { + return r + r + g + g + b + b; + }); + var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex); + return result ? { + r: parseInt(result[1], 16), + g: parseInt(result[2], 16), + b: parseInt(result[3], 16) + } : null; +}; + +function clamp(number, min, max) { + return Math.min(Math.max(number, min), max); +}; + +function isInArray(value, array) { + return array.indexOf(value) > -1; +} + + +/* ---------- particles.js functions - start ------------ */ + +window.pJSDom = []; + +window.particlesJS = function(tag_id, params){ + + //console.log(params); + + /* no string id? so it's object params, and set the id with default id */ + if(typeof(tag_id) != 'string'){ + params = tag_id; + tag_id = 'particles-js'; + } + + /* no id? set the id to default id */ + if(!tag_id){ + tag_id = 'particles-js'; + } + + /* pJS elements */ + var pJS_tag = document.getElementById(tag_id), + pJS_canvas_class = 'particles-js-canvas-el', + exist_canvas = pJS_tag.getElementsByClassName(pJS_canvas_class); + + /* remove canvas if exists into the pJS target tag */ + if(exist_canvas.length){ + while(exist_canvas.length > 0){ + pJS_tag.removeChild(exist_canvas[0]); + } + } + + /* create canvas element */ + var canvas_el = document.createElement('canvas'); + canvas_el.className = pJS_canvas_class; + + /* set size canvas */ + canvas_el.style.width = "100%"; + canvas_el.style.height = "100%"; + + /* append canvas */ + var canvas = document.getElementById(tag_id).appendChild(canvas_el); + + /* launch particle.js */ + if(canvas != null){ + pJSDom.push(new pJS(tag_id, params)); + } + +}; + +window.particlesJS.load = function(tag_id, path_config_json, callback){ + + /* load json config */ + var xhr = new XMLHttpRequest(); + xhr.open('GET', path_config_json); + xhr.onreadystatechange = function (data) { + if(xhr.readyState == 4){ + if(xhr.status == 200){ + var params = JSON.parse(data.currentTarget.response); + window.particlesJS(tag_id, params); + if(callback) callback(); + }else{ + console.log('Error pJS - XMLHttpRequest status: '+xhr.status); + console.log('Error pJS - File config not found'); + } + } + }; + xhr.send(); + +}; + +/* particlesJS.load(@dom-id, @path-json, @callback (optional)); */ +particlesJS.load('particles-js', '/static/particles.json', function() { + console.log('callback - particles.js config loaded'); +}); \ No newline at end of file diff --git a/static/particles.json b/static/particles.json new file mode 100644 index 0000000..a752029 --- /dev/null +++ b/static/particles.json @@ -0,0 +1,110 @@ +{ + "particles": { + "number": { + "value": 80, + "density": { + "enable": true, + "value_area": 800 + } + }, + "color": { + "value": "#f5c2e7" + }, + "shape": { + "type": "circle", + "stroke": { + "width": 0, + "color": "#000000" + }, + "polygon": { + "nb_sides": 5 + }, + "image": { + "src": "img/github.svg", + "width": 100, + "height": 100 + } + }, + "opacity": { + "value": 0.5, + "random": false, + "anim": { + "enable": false, + "speed": 1, + "opacity_min": 0.1, + "sync": false + } + }, + "size": { + "value": 3, + "random": true, + "anim": { + "enable": false, + "speed": 40, + "size_min": 0.1, + "sync": false + } + }, + "line_linked": { + "enable": true, + "distance": 150, + "color": "#f5c2e7", + "opacity": 0.4, + "width": 1 + }, + "move": { + "enable": true, + "speed": 6, + "direction": "none", + "random": false, + "straight": false, + "out_mode": "out", + "bounce": false, + "attract": { + "enable": false, + "rotateX": 600, + "rotateY": 1200 + } + } + }, + "interactivity": { + "detect_on": "window", + "events": { + "onhover": { + "enable": true, + "mode": "repulse" + }, + "onclick": { + "enable": true, + "mode": "remove" + }, + "resize": true + }, + "modes": { + "grab": { + "distance": 400, + "line_linked": { + "opacity": 1 + } + }, + "bubble": { + "distance": 400, + "size": 40, + "duration": 2, + "opacity": 8, + "speed": 3 + }, + "repulse": { + "distance": 200, + "duration": 0.4 + }, + "push": { + "particles_nb": 4 + }, + "remove": { + "particles_nb": 2 + } + } + }, + "retina_detect": true +} \ No newline at end of file diff --git a/static/style.css b/static/style.css new file mode 100644 index 0000000..c8631fa --- /dev/null +++ b/static/style.css @@ -0,0 +1,109 @@ +@import url("https://api.fonts.coollabs.io/css2?family=Atkinson+Hyperlegible&display=swap"); +@import url('https://api.fonts.coollabs.io/css2?family=Roboto+Mono:ital,wght@0,100..700;1,100..700&display=swap'); +html, body{ + padding: 0; + margin: 0; + height: 100%; + font-size: 1.1em; +} +body * { + color: #cdd6f4; + font-family: 'Atkinson Hyperlegible', 'Roboto Mono' Arial, sans-serif; +} +.page { + display: flex; + width: 65%; + margin: 0 auto; + + align-items: start; + padding-top: 3em; +} +.page .content{ + flex-grow: 7; + padding: 0.25em; + max-width: 70%; + min-width: 68%; +} +.page .sidebar { + flex-grow: 3; + min-width: 27%; /* this is highly cursed */ + max-width: 40%; + +} +.container { + border-color: #f5c2e7; + border-width: 2px; + border-style: solid; + margin: 1em; + background-color: #1e1e2e; + padding: 0.6em; +} +/* time to fix these cursed media queries */ +@media only screen and (min-width: 0px) and (max-width: 600px){ + .page { + width: 100%; + margin-top: 0; + flex-direction: column-reverse; + + } + .container { + margin: 0.5em; + } + .sidebar { + min-width: 95% !important; + /*max-width: 100% !important;*/ + width: 100% !important; + + } + .content { + min-width: 95% !important; + width: 100% !important; + } +} +@media only screen and (min-width: 600px) and (max-width: 1000px){ + .page { + margin-top: 0; + width: 85%; + } +} + +.page .sidebar header{ + text-align: right; +} + + canvas { + display: block; + vertical-align: bottom; + } + + + #particles-js { + z-index: -1; + position: absolute; + width: 100%; + height: 100%; + background-color: #1e1e2e; + background-image: url(""); + background-repeat: no-repeat; + background-size: cover; + background-position: 50% 50%; + } + + .content hr:last-of-type { + display:none; + } + .socials { + background-color: #fff; + display: inline-block; + padding:5px; + padding-bottom: 0px; + border: 2px solid #f5c2e7; + margin-bottom: 1em; + } + #animal_img { + width: 100%; + height: auto; + } + #gif_buttons { + image-rendering: pixelated; + } \ No newline at end of file diff --git a/tags/linux/index.html b/tags/linux/index.html new file mode 100644 index 0000000..6a843d8 --- /dev/null +++ b/tags/linux/index.html @@ -0,0 +1,77 @@ + + + + # linux + + + + + + + + + + + + + + + + + +
+
+
+ + + + +

# linux

+ +
+

+ I installed linux on my phone +

+
Mon 19 Feb 2024
+

+ +

+
+
+ + + +
+ + +
+ + + \ No newline at end of file diff --git a/tags/mobile/index.html b/tags/mobile/index.html new file mode 100644 index 0000000..ff8422f --- /dev/null +++ b/tags/mobile/index.html @@ -0,0 +1,77 @@ + + + + # mobile + + + + + + + + + + + + + + + + + +
+
+
+ + + + +

# mobile

+ +
+

+ I installed linux on my phone +

+
Mon 19 Feb 2024
+

+ +

+
+
+ + + +
+ + +
+ + + \ No newline at end of file