├── sound-cropped.mp4 ├── boss-fight-sound-cropped.mp4 ├── README.md ├── LICENSE.txt ├── src ├── index.html ├── style.scss └── script.js ├── index.html ├── dist ├── index.html ├── style.css └── script.js ├── style.scss ├── style.css ├── script.js └── SplitText.min.js /sound-cropped.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kibibit/boss-fight/main/sound-cropped.mp4 -------------------------------------------------------------------------------- /boss-fight-sound-cropped.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kibibit/boss-fight/main/boss-fight-sound-cropped.mp4 -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # achievibit - Boss Battle 2 | 3 | A Pen created on CodePen.io. Original URL: [https://codepen.io/thatkookooguy/pen/JoPKVPO](https://codepen.io/thatkookooguy/pen/JoPKVPO). 4 | 5 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2024 neil kalman (https://codepen.io/thatkookooguy/pen/JoPKVPO) 4 | Fork of an original work GSAP Starter Template (https://codepen.io/GreenSock/pen/aYYOdN) 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. 23 | -------------------------------------------------------------------------------- /src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 | 5 | Made with Pixels to Svg https://codepen.io/shshaw/pen/XbxvNj 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 |
20 |
21 | ARE YOU READY TO BATTLE?? 22 |
23 | 26 |
-------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | achievibit: Boss Battle 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | Made with Pixels to Svg https://codepen.io/shshaw/pen/XbxvNj 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 |
30 | 31 |
32 |
33 | ARE YOU READY TO BATTLE?? 34 |
35 | 38 |
39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /dist/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | achievibit - Boss Battle 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 | 15 | Made with Pixels to Svg https://codepen.io/shshaw/pen/XbxvNj 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 |
28 | 29 |
30 |
31 | ARE YOU READY TO BATTLE?? 32 |
33 | 36 |
37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | -------------------------------------------------------------------------------- /dist/style.css: -------------------------------------------------------------------------------- 1 | @import url("https://fonts.googleapis.com/css2?family=Comfortaa:wght@700&family=Press+Start+2P&family=Righteous&display=swap"); 2 | :root { 3 | --bar-fill: #57e705; 4 | --bar-top: #6aff03; 5 | --pixel-size: 7; 6 | } 7 | 8 | .healthbar { 9 | z-index: 10; 10 | position: fixed; 11 | left: 0; 12 | right: 0; 13 | width: calc(30px * var(--pixel-size)); 14 | margin: 0 auto calc(2px * var(--pixel-size)) auto; 15 | display: block; 16 | } 17 | 18 | .healthbar_fill { 19 | width: 0%; 20 | fill: var(--bar-fill); 21 | transition: width 0.1s ease-in, fill 0.2s linear; 22 | } 23 | 24 | .healthbar_fill-top { 25 | width: 0%; 26 | fill: var(--bar-top); 27 | } 28 | 29 | .fill-bar-animation { 30 | animation: fill-bar 4s ease-out forwards; 31 | } 32 | 33 | html, 34 | body { 35 | margin: 0; 36 | padding: 0; 37 | } 38 | 39 | body { 40 | font-family: Avenir, sans-serif; 41 | background-color: #212121; 42 | color: #fffce1; 43 | display: flex; 44 | align-items: center; 45 | justify-content: center; 46 | height: 100vh; 47 | flex-direction: column; 48 | } 49 | 50 | p { 51 | max-width: 70ch; 52 | font-size: 1.4rem; 53 | text-align: center; 54 | line-height: 1.3; 55 | } 56 | 57 | .game { 58 | position: absolute; 59 | width: 100dvw; 60 | height: 100dvh; 61 | overflow: hidden; 62 | bottom: 0; 63 | } 64 | 65 | .rpg-text-box { 66 | color: #ff3860; 67 | height: 100px; 68 | left: 50%; 69 | position: absolute; 70 | bottom: 0; 71 | transform: translate(-50%, calc(100% + 50px + 50px)); 72 | max-width: 500px; 73 | width: 80vw; 74 | line-height: 1.5em; 75 | margin: 2em 0; 76 | background: white; 77 | border: 1px solid white; 78 | padding: 1em; 79 | font-size: 0.7rem; 80 | font-family: "Press Start 2P", cursive; 81 | font-weight: bolder; 82 | border-radius: 0.2em; 83 | box-shadow: 0 1px 0 1px black, inset 0 1px 0 1px black, 0 0 0 1px black, inset 0 0 0 1px black, 3px 5px 0px 1px rgba(0, 0, 0, 0.25); 84 | opacity: 0; 85 | transition: all 250ms; 86 | z-index: 10; 87 | } 88 | 89 | .rpg-text-box.visible { 90 | opacity: 1; 91 | transform: translate(-50%); 92 | } 93 | 94 | .code-editor { 95 | position: absolute; 96 | top: 0; 97 | /* bottom: 0; */ 98 | left: 0; 99 | right: 0; 100 | background: black; 101 | transition: all 500ms cubic-bezier(0.47, 1.64, 0.41, 0.8); 102 | height: 0; 103 | } 104 | 105 | .code-editor.reveal { 106 | height: 100%; 107 | } 108 | 109 | .monster { 110 | width: 100%; 111 | height: 100%; 112 | position: absolute; 113 | bottom: 25px; 114 | display: flex; 115 | align-items: center; 116 | justify-content: center; 117 | position: relative; 118 | /* Keep relative positioning for better layout control */ 119 | animation: rise-up 4s ease-out forwards, shake-constant 2s infinite; 120 | } 121 | .monster img { 122 | width: 100%; 123 | max-width: 700px; 124 | } 125 | 126 | @keyframes fill-bar { 127 | from { 128 | width: 0%; 129 | } 130 | to { 131 | width: 100%; 132 | } 133 | } 134 | /* Keyframes for rising up */ 135 | @keyframes rise-up { 136 | from { 137 | transform: translateY(100%); 138 | /* Start below the original position */ 139 | } 140 | to { 141 | transform: translateY(0); 142 | /* End at the original position */ 143 | } 144 | } 145 | .monster .shake-constant { 146 | animation-timing-function: cubic-bezier(0.25, 0.1, 0.25, 1); 147 | /* Smooth timing */ 148 | animation-duration: 2s; 149 | /* Slower shake timing */ 150 | } 151 | 152 | #textbox2 { 153 | display: flex; 154 | align-items: center; 155 | justify-content: center; 156 | } 157 | 158 | #canvas { 159 | position: fixed; 160 | z-index: 5; 161 | pointer-events: none; 162 | } -------------------------------------------------------------------------------- /src/style.scss: -------------------------------------------------------------------------------- 1 | @import url("https://fonts.googleapis.com/css2?family=Comfortaa:wght@700&family=Press+Start+2P&family=Righteous&display=swap"); 2 | 3 | :root { 4 | --bar-fill: #57e705; 5 | --bar-top: #6aff03; 6 | --pixel-size: 7; 7 | } 8 | 9 | .healthbar { 10 | z-index: 10; 11 | position: fixed; 12 | left: 0; 13 | right: 0; 14 | width: calc(30px * var(--pixel-size)); 15 | margin: 0 auto calc(2px * var(--pixel-size)) auto; 16 | display: block; 17 | } 18 | 19 | .healthbar_fill { 20 | width: 0%; 21 | fill: var(--bar-fill); 22 | transition: width 0.1s ease-in, fill 0.2s linear; 23 | } 24 | .healthbar_fill-top { 25 | width: 0%; 26 | fill: var(--bar-top); 27 | } 28 | 29 | .fill-bar-animation { 30 | animation: fill-bar 4s ease-out forwards; 31 | } 32 | 33 | html, 34 | body { 35 | margin: 0; 36 | padding: 0; 37 | } 38 | 39 | body { 40 | font-family: Avenir, sans-serif; 41 | background-color: #212121; 42 | color: #fffce1; 43 | display: flex; 44 | align-items: center; 45 | justify-content: center; 46 | height: 100vh; 47 | flex-direction: column; 48 | } 49 | 50 | p { 51 | max-width: 70ch; 52 | font-size: 1.4rem; 53 | text-align: center; 54 | line-height: 1.3; 55 | } 56 | 57 | .game { 58 | position: absolute; 59 | width: 100dvw; 60 | height: 100dvh; 61 | overflow: hidden; 62 | bottom: 0; 63 | } 64 | 65 | .rpg-text-box { 66 | color: hsl(348, 100%, 61%); 67 | height: 100px; 68 | left: 50%; 69 | position: absolute; 70 | bottom: 0; 71 | transform: translate(-50%, calc(100% + 50px + 50px)); 72 | max-width: 500px; 73 | width: 80vw; 74 | line-height: 1.5em; 75 | margin: 2em 0; 76 | background: white; 77 | border: 1px solid white; 78 | padding: 1em; 79 | font-size: 0.7rem; 80 | font-family: "Press Start 2P", cursive; 81 | font-weight: bolder; 82 | border-radius: 0.2em; 83 | box-shadow: 0 1px 0 1px black, inset 0 1px 0 1px black, 0 0 0 1px black, 84 | inset 0 0 0 1px black, 3px 5px 0px 1px rgba(0, 0, 0, 0.25); 85 | opacity: 0; 86 | transition: all 250ms; 87 | z-index: 10; 88 | } 89 | 90 | .rpg-text-box.visible { 91 | opacity: 1; 92 | transform: translate(-50%); 93 | } 94 | 95 | .code-editor { 96 | position: absolute; 97 | top: 0; 98 | /* bottom: 0; */ 99 | left: 0; 100 | right: 0; 101 | background: black; 102 | transition: all 500ms cubic-bezier(0.47, 1.64, 0.41, 0.8); 103 | height: 0; 104 | } 105 | 106 | .code-editor.reveal { 107 | height: 100%; 108 | } 109 | 110 | .monster { 111 | width: 100%; 112 | height: 100%; 113 | position: absolute; 114 | bottom: 25px; 115 | display: flex; 116 | align-items: center; 117 | justify-content: center; 118 | position: relative; /* Keep relative positioning for better layout control */ 119 | animation: rise-up 4s ease-out forwards, shake-constant 2s infinite; 120 | 121 | img { 122 | width: 100%; 123 | max-width: 700px; 124 | } 125 | } 126 | 127 | @keyframes fill-bar { 128 | from { 129 | width: 0%; 130 | } 131 | to { 132 | width: 100%; 133 | } 134 | } 135 | 136 | /* Keyframes for rising up */ 137 | @keyframes rise-up { 138 | from { 139 | transform: translateY(100%); /* Start below the original position */ 140 | } 141 | to { 142 | transform: translateY(0); /* End at the original position */ 143 | } 144 | } 145 | 146 | .monster .shake-constant { 147 | animation-timing-function: cubic-bezier( 148 | 0.25, 149 | 0.1, 150 | 0.25, 151 | 1 152 | ); /* Smooth timing */ 153 | animation-duration: 2s; /* Slower shake timing */ 154 | } 155 | 156 | #textbox2 { 157 | display: flex; 158 | align-items: center; 159 | justify-content: center; 160 | } 161 | 162 | #canvas { 163 | position: fixed; 164 | z-index: 5; 165 | pointer-events: none; 166 | } 167 | -------------------------------------------------------------------------------- /style.scss: -------------------------------------------------------------------------------- 1 | @import url("https://fonts.googleapis.com/css2?family=Comfortaa:wght@700&family=Press+Start+2P&family=Righteous&display=swap"); 2 | 3 | :root { 4 | --bar-fill: #57e705; 5 | --bar-top: #6aff03; 6 | --pixel-size: 7; 7 | } 8 | 9 | .healthbar { 10 | z-index: 10; 11 | position: fixed; 12 | left: 0; 13 | right: 0; 14 | width: calc(30px * var(--pixel-size)); 15 | margin: 0 auto calc(2px * var(--pixel-size)) auto; 16 | display: block; 17 | } 18 | 19 | .healthbar_fill { 20 | width: 0%; 21 | fill: var(--bar-fill); 22 | transition: width 0.1s ease-in, fill 0.2s linear; 23 | } 24 | .healthbar_fill-top { 25 | width: 0%; 26 | fill: var(--bar-top); 27 | } 28 | 29 | .fill-bar-animation { 30 | animation: fill-bar 4s ease-out forwards; 31 | } 32 | 33 | html, 34 | body { 35 | margin: 0; 36 | padding: 0; 37 | } 38 | 39 | body { 40 | font-family: Avenir, sans-serif; 41 | background-color: #212121; 42 | color: #fffce1; 43 | display: flex; 44 | align-items: center; 45 | justify-content: center; 46 | height: 100vh; 47 | flex-direction: column; 48 | } 49 | 50 | p { 51 | max-width: 70ch; 52 | font-size: 1.4rem; 53 | text-align: center; 54 | line-height: 1.3; 55 | } 56 | 57 | .game { 58 | position: absolute; 59 | width: 100dvw; 60 | height: 100dvh; 61 | overflow: hidden; 62 | bottom: 0; 63 | } 64 | 65 | .rpg-text-box { 66 | color: hsl(348, 100%, 61%); 67 | height: 100px; 68 | left: 50%; 69 | position: absolute; 70 | bottom: 0; 71 | transform: translate(-50%, calc(100% + 50px + 50px)); 72 | max-width: 500px; 73 | width: 80vw; 74 | line-height: 1.5em; 75 | margin: 2em 0; 76 | background: white; 77 | border: 1px solid white; 78 | padding: 1em; 79 | font-size: 0.7rem; 80 | font-family: "Press Start 2P", cursive; 81 | font-weight: bolder; 82 | border-radius: 0.2em; 83 | box-shadow: 0 1px 0 1px black, inset 0 1px 0 1px black, 0 0 0 1px black, 84 | inset 0 0 0 1px black, 3px 5px 0px 1px rgba(0, 0, 0, 0.25); 85 | opacity: 0; 86 | transition: all 250ms; 87 | z-index: 10; 88 | } 89 | 90 | .rpg-text-box.visible { 91 | opacity: 1; 92 | transform: translate(-50%); 93 | } 94 | 95 | .code-editor { 96 | position: absolute; 97 | top: 0; 98 | /* bottom: 0; */ 99 | left: 0; 100 | right: 0; 101 | background: black; 102 | transition: all 500ms cubic-bezier(0.47, 1.64, 0.41, 0.8); 103 | height: 0; 104 | } 105 | 106 | .code-editor.reveal { 107 | height: 100%; 108 | } 109 | 110 | .monster { 111 | width: 100%; 112 | height: 100%; 113 | position: absolute; 114 | bottom: 25px; 115 | display: flex; 116 | align-items: center; 117 | justify-content: center; 118 | position: relative; /* Keep relative positioning for better layout control */ 119 | animation: rise-up 4s ease-out forwards, shake-constant 2s infinite; 120 | 121 | img { 122 | width: 100%; 123 | max-width: 700px; 124 | } 125 | } 126 | 127 | @keyframes fill-bar { 128 | from { 129 | width: 0%; 130 | } 131 | to { 132 | width: 100%; 133 | } 134 | } 135 | 136 | /* Keyframes for rising up */ 137 | @keyframes rise-up { 138 | from { 139 | transform: translateY(100%); /* Start below the original position */ 140 | } 141 | to { 142 | transform: translateY(0); /* End at the original position */ 143 | } 144 | } 145 | 146 | .monster .shake-constant { 147 | animation-timing-function: cubic-bezier( 148 | 0.25, 149 | 0.1, 150 | 0.25, 151 | 1 152 | ); /* Smooth timing */ 153 | animation-duration: 2s; /* Slower shake timing */ 154 | } 155 | 156 | #textbox2 { 157 | display: flex; 158 | align-items: center; 159 | justify-content: center; 160 | } 161 | 162 | #canvas { 163 | position: fixed; 164 | z-index: 5; 165 | pointer-events: none; 166 | } 167 | -------------------------------------------------------------------------------- /dist/script.js: -------------------------------------------------------------------------------- 1 | // Testing animation concepts for boss battle 2 | 3 | const textBoxText = document.getElementById("textbox"); 4 | const textBoxText2 = document.getElementById("textbox2"); 5 | 6 | const split = new SplitText(textBoxText, { 7 | charsClass: "kb-char shake-constant", 8 | linesClass: "kb-line" 9 | }); 10 | 11 | const chars = split.chars; 12 | 13 | const nextSplit = new SplitText(textBoxText2, { 14 | charsClass: "kb-char shake-constant", 15 | linesClass: "kb-line" 16 | }); 17 | 18 | const chars2 = nextSplit.chars; 19 | 20 | const codeEditorDiv = document.createElement("div"); 21 | codeEditorDiv.className = "code-editor"; 22 | 23 | const codeEditorDiv2 = document.createElement("div"); 24 | codeEditorDiv2.className = "code-editor reveal"; 25 | 26 | // Insert it at the beginning of textBoxText 27 | textBoxText.prepend(codeEditorDiv); 28 | textBoxText2.prepend(codeEditorDiv2); 29 | 30 | chars.forEach((char, index) => { 31 | char.classList.add("shake-little"); 32 | 33 | // Calculate a pseudo-random delay based on the index 34 | const delay = Math.random() * 0.2 + index * 0.05; // Adjust randomness and staggering here 35 | 36 | // Set the delay as an inline style 37 | char.style.animationDelay = `${delay}s`; 38 | }); 39 | 40 | chars2.forEach((char, index) => { 41 | char.classList.add("shake-little"); 42 | 43 | // Calculate a pseudo-random delay based on the index 44 | const delay = Math.random() * 0.2 + index * 0.05; // Adjust randomness and staggering here 45 | 46 | // Set the delay as an inline style 47 | char.style.animationDelay = `${delay}s`; 48 | }); 49 | 50 | let currentLine; 51 | 52 | var tl = new TimelineMax({ 53 | // onComplete: () => { 54 | // codeEditorDiv.classList.add("reveal"); 55 | // } 56 | }); 57 | 58 | tl.delay(2); 59 | 60 | tl.call( 61 | function () { 62 | textBoxText.classList.add("visible"); 63 | }, 64 | null, 65 | null, 66 | 0 67 | ) 68 | .staggerFrom( 69 | chars, 70 | 0.8, 71 | { 72 | opacity: 0, 73 | ease: SteppedEase.config(1) 74 | }, 75 | 0.08, 76 | "+=0" 77 | ) 78 | .call( 79 | function () { 80 | codeEditorDiv.classList.add("reveal"); 81 | }, 82 | null, 83 | "+=0.5", 84 | 0 85 | ) 86 | .call( 87 | function () { 88 | textBoxText.style.display = "none"; 89 | textBoxText2.style.display = "flex"; 90 | }, 91 | null, 92 | "+=0.5", 93 | 0 94 | ) 95 | .staggerFrom( 96 | chars2, 97 | 0.8, 98 | { 99 | opacity: 0, 100 | ease: SteppedEase.config(1) 101 | }, 102 | 0.08, 103 | "+=0" 104 | ) 105 | .pause(); 106 | 107 | tl.play(); 108 | 109 | /////// 110 | 111 | console.clear(); 112 | 113 | var canvasLightning = function (c, cw, ch) { 114 | this.init = function () { 115 | this.loop(); 116 | }; 117 | 118 | var _this = this; 119 | this.c = c; 120 | this.ctx = c.getContext("2d"); 121 | this.cw = cw; 122 | this.ch = ch; 123 | this.mx = 0; 124 | this.my = 0; 125 | 126 | this.now = Date.now(); 127 | this.delta = 0; 128 | this.then = this.now; 129 | 130 | this.lightning = []; 131 | this.lightTimeCurrent = 0; 132 | this.lightTimeTotal = 50; 133 | 134 | this.rand = function (rMi, rMa) { 135 | return ~~(Math.random() * (rMa - rMi + 1) + rMi); 136 | }; 137 | 138 | this.createL = function (x, y, canSpawn) { 139 | this.lightning.push({ 140 | x: x, 141 | y: y, 142 | xRange: this.rand(5, 30), 143 | yRange: this.rand(5, 25), 144 | path: [ 145 | { 146 | x: x, 147 | y: y 148 | } 149 | ], 150 | pathLimit: this.rand(10, 35), 151 | canSpawn: canSpawn, 152 | hasFired: false, 153 | grower: 0, 154 | growerLimit: 5 //this.rand(5, 15) 155 | }); 156 | }; 157 | 158 | this.updateL = function () { 159 | var i = this.lightning.length; 160 | while (i--) { 161 | var light = this.lightning[i]; 162 | 163 | light.grower += this.delta; 164 | 165 | if (light.grower >= light.growerLimit) { 166 | light.grower = 0; 167 | light.growerLimit *= 1.05; 168 | 169 | light.path.push({ 170 | x: 171 | light.path[light.path.length - 1].x + 172 | (this.rand(0, light.xRange) - light.xRange / 2), 173 | y: light.path[light.path.length - 1].y + this.rand(0, light.yRange) 174 | }); 175 | 176 | if (light.path.length > light.pathLimit) { 177 | this.lightning.splice(i, 1); 178 | } 179 | light.hasFired = true; 180 | } 181 | } 182 | }; 183 | 184 | this.renderL = function () { 185 | var i = this.lightning.length; 186 | while (i--) { 187 | var light = this.lightning[i]; 188 | 189 | const randomColor = Math.random(); 190 | this.ctx.strokeStyle = 191 | "hsla(0, 100%, 100%, " + this.rand(10, 100) / 100 + ")"; 192 | if (randomColor >= 0.33 && randomColor < 0.8) { 193 | this.ctx.strokeStyle = 194 | "hsla(248, 53%, 58%, " + this.rand(10, 100) / 100 + ")"; 195 | } 196 | 197 | if (randomColor >= 0.8) { 198 | this.ctx.strokeStyle = 199 | "hsla(204, 86%, 53%, " + this.rand(10, 100) / 100 + ")"; 200 | } 201 | 202 | this.ctx.lineWidth = 4; 203 | if (this.rand(0, 30) == 0) { 204 | this.ctx.lineWidth = 5; 205 | } 206 | if (this.rand(0, 60) == 0) { 207 | this.ctx.lineWidth = 6; 208 | } 209 | if (this.rand(0, 90) == 0) { 210 | this.ctx.lineWidth = 7; 211 | } 212 | 213 | this.ctx.beginPath(); 214 | 215 | var pathCount = light.path.length; 216 | this.ctx.moveTo(light.x, light.y); 217 | for (var pc = 0; pc < pathCount; pc++) { 218 | this.ctx.lineTo(light.path[pc].x, light.path[pc].y); 219 | 220 | if (light.canSpawn) { 221 | if (this.rand(0, 100) == 0) { 222 | light.canSpawn = false; 223 | this.createL(light.path[pc].x, light.path[pc].y, false); 224 | } 225 | } 226 | } 227 | 228 | if (!light.hasFired) { 229 | this.ctx.fillStyle = 230 | "rgba(255, 255, 255, " + this.rand(4, 12) / 100 + ")"; 231 | this.ctx.fillRect(0, 0, this.cw, this.ch); 232 | } 233 | 234 | if (this.rand(0, 60) == 0) { 235 | this.ctx.fillStyle = 236 | "rgba(255, 255, 255, " + this.rand(1, 3) / 100 + ")"; 237 | this.ctx.fillRect(0, 0, this.cw, this.ch); 238 | } 239 | 240 | this.ctx.stroke(); 241 | } 242 | }; 243 | 244 | this.lightningTimer = function () { 245 | this.lightTimeCurrent += this.delta; 246 | if (this.lightTimeCurrent >= this.lightTimeTotal) { 247 | var newX = this.rand(100, cw - 100); 248 | var newY = this.rand(0, ch / 2); 249 | var createCount = this.rand(1, 3); 250 | while (createCount--) { 251 | this.createL(newX, newY, true); 252 | } 253 | this.lightTimeCurrent = 0; 254 | this.lightTimeTotal = this.rand(200, 1500); 255 | } 256 | }; 257 | 258 | this.clearCanvas = function () { 259 | this.ctx.globalCompositeOperation = "destination-out"; 260 | this.ctx.fillStyle = "rgba(0,0,0," + this.rand(1, 30) / 100 + ")"; 261 | this.ctx.fillRect(0, 0, this.cw, this.ch); 262 | this.ctx.globalCompositeOperation = "source-over"; 263 | }; 264 | 265 | window.addEventListener("resize", () => { 266 | this.cw = this.c.width = window.innerWidth; 267 | this.ch = this.c.height = window.innerHeight; 268 | }); 269 | 270 | this.loop = function () { 271 | requestAnimationFrame(this.loop.bind(this)); 272 | 273 | this.now = Date.now(); 274 | this.delta = this.now - this.then; 275 | this.then = this.now; 276 | 277 | this.clearCanvas(); 278 | this.updateL(); 279 | this.lightningTimer(); 280 | this.renderL(); 281 | }; 282 | }; 283 | 284 | var c = document.getElementById("canvas"); 285 | var cw = (c.width = window.innerWidth); 286 | var ch = (c.height = window.innerHeight); 287 | var cl = new canvasLightning(c, cw, ch); 288 | 289 | cl.init(); -------------------------------------------------------------------------------- /src/script.js: -------------------------------------------------------------------------------- 1 | // Testing animation concepts for boss battle 2 | 3 | const textBoxText = document.getElementById("textbox"); 4 | const textBoxText2 = document.getElementById("textbox2"); 5 | 6 | const split = new SplitText(textBoxText, { 7 | charsClass: "kb-char shake-constant", 8 | linesClass: "kb-line" 9 | }); 10 | 11 | const chars = split.chars; 12 | 13 | const nextSplit = new SplitText(textBoxText2, { 14 | charsClass: "kb-char shake-constant", 15 | linesClass: "kb-line" 16 | }); 17 | 18 | const chars2 = nextSplit.chars; 19 | 20 | const codeEditorDiv = document.createElement("div"); 21 | codeEditorDiv.className = "code-editor"; 22 | 23 | const codeEditorDiv2 = document.createElement("div"); 24 | codeEditorDiv2.className = "code-editor reveal"; 25 | 26 | // Insert it at the beginning of textBoxText 27 | textBoxText.prepend(codeEditorDiv); 28 | textBoxText2.prepend(codeEditorDiv2); 29 | 30 | chars.forEach((char, index) => { 31 | char.classList.add("shake-little"); 32 | 33 | // Calculate a pseudo-random delay based on the index 34 | const delay = Math.random() * 0.2 + index * 0.05; // Adjust randomness and staggering here 35 | 36 | // Set the delay as an inline style 37 | char.style.animationDelay = `${delay}s`; 38 | }); 39 | 40 | chars2.forEach((char, index) => { 41 | char.classList.add("shake-little"); 42 | 43 | // Calculate a pseudo-random delay based on the index 44 | const delay = Math.random() * 0.2 + index * 0.05; // Adjust randomness and staggering here 45 | 46 | // Set the delay as an inline style 47 | char.style.animationDelay = `${delay}s`; 48 | }); 49 | 50 | let currentLine; 51 | 52 | var tl = new TimelineMax({ 53 | // onComplete: () => { 54 | // codeEditorDiv.classList.add("reveal"); 55 | // } 56 | }); 57 | 58 | tl.delay(2); 59 | 60 | tl.call( 61 | function () { 62 | textBoxText.classList.add("visible"); 63 | }, 64 | null, 65 | null, 66 | 0 67 | ) 68 | .staggerFrom( 69 | chars, 70 | 0.8, 71 | { 72 | opacity: 0, 73 | ease: SteppedEase.config(1) 74 | }, 75 | 0.08, 76 | "+=0" 77 | ) 78 | .call( 79 | function () { 80 | codeEditorDiv.classList.add("reveal"); 81 | }, 82 | null, 83 | "+=0.5", 84 | 0 85 | ) 86 | .call( 87 | function () { 88 | textBoxText.style.display = "none"; 89 | textBoxText2.style.display = "flex"; 90 | }, 91 | null, 92 | "+=0.5", 93 | 0 94 | ) 95 | .staggerFrom( 96 | chars2, 97 | 0.8, 98 | { 99 | opacity: 0, 100 | ease: SteppedEase.config(1) 101 | }, 102 | 0.08, 103 | "+=0" 104 | ) 105 | .pause(); 106 | 107 | tl.play(); 108 | 109 | /////// 110 | 111 | console.clear(); 112 | 113 | var canvasLightning = function (c, cw, ch) { 114 | this.init = function () { 115 | this.loop(); 116 | }; 117 | 118 | var _this = this; 119 | this.c = c; 120 | this.ctx = c.getContext("2d"); 121 | this.cw = cw; 122 | this.ch = ch; 123 | this.mx = 0; 124 | this.my = 0; 125 | 126 | this.now = Date.now(); 127 | this.delta = 0; 128 | this.then = this.now; 129 | 130 | this.lightning = []; 131 | this.lightTimeCurrent = 0; 132 | this.lightTimeTotal = 50; 133 | 134 | this.rand = function (rMi, rMa) { 135 | return ~~(Math.random() * (rMa - rMi + 1) + rMi); 136 | }; 137 | 138 | this.createL = function (x, y, canSpawn) { 139 | this.lightning.push({ 140 | x: x, 141 | y: y, 142 | xRange: this.rand(5, 30), 143 | yRange: this.rand(5, 25), 144 | path: [ 145 | { 146 | x: x, 147 | y: y 148 | } 149 | ], 150 | pathLimit: this.rand(10, 35), 151 | canSpawn: canSpawn, 152 | hasFired: false, 153 | grower: 0, 154 | growerLimit: 5 //this.rand(5, 15) 155 | }); 156 | }; 157 | 158 | this.updateL = function () { 159 | var i = this.lightning.length; 160 | while (i--) { 161 | var light = this.lightning[i]; 162 | 163 | light.grower += this.delta; 164 | 165 | if (light.grower >= light.growerLimit) { 166 | light.grower = 0; 167 | light.growerLimit *= 1.05; 168 | 169 | light.path.push({ 170 | x: 171 | light.path[light.path.length - 1].x + 172 | (this.rand(0, light.xRange) - light.xRange / 2), 173 | y: light.path[light.path.length - 1].y + this.rand(0, light.yRange) 174 | }); 175 | 176 | if (light.path.length > light.pathLimit) { 177 | this.lightning.splice(i, 1); 178 | } 179 | light.hasFired = true; 180 | } 181 | } 182 | }; 183 | 184 | this.renderL = function () { 185 | var i = this.lightning.length; 186 | while (i--) { 187 | var light = this.lightning[i]; 188 | 189 | const randomColor = Math.random(); 190 | this.ctx.strokeStyle = 191 | "hsla(0, 100%, 100%, " + this.rand(10, 100) / 100 + ")"; 192 | if (randomColor >= 0.33 && randomColor < 0.8) { 193 | this.ctx.strokeStyle = 194 | "hsla(248, 53%, 58%, " + this.rand(10, 100) / 100 + ")"; 195 | } 196 | 197 | if (randomColor >= 0.8) { 198 | this.ctx.strokeStyle = 199 | "hsla(204, 86%, 53%, " + this.rand(10, 100) / 100 + ")"; 200 | } 201 | 202 | this.ctx.lineWidth = 4; 203 | if (this.rand(0, 30) == 0) { 204 | this.ctx.lineWidth = 5; 205 | } 206 | if (this.rand(0, 60) == 0) { 207 | this.ctx.lineWidth = 6; 208 | } 209 | if (this.rand(0, 90) == 0) { 210 | this.ctx.lineWidth = 7; 211 | } 212 | 213 | this.ctx.beginPath(); 214 | 215 | var pathCount = light.path.length; 216 | this.ctx.moveTo(light.x, light.y); 217 | for (var pc = 0; pc < pathCount; pc++) { 218 | this.ctx.lineTo(light.path[pc].x, light.path[pc].y); 219 | 220 | if (light.canSpawn) { 221 | if (this.rand(0, 100) == 0) { 222 | light.canSpawn = false; 223 | this.createL(light.path[pc].x, light.path[pc].y, false); 224 | } 225 | } 226 | } 227 | 228 | if (!light.hasFired) { 229 | this.ctx.fillStyle = 230 | "rgba(255, 255, 255, " + this.rand(4, 12) / 100 + ")"; 231 | this.ctx.fillRect(0, 0, this.cw, this.ch); 232 | } 233 | 234 | if (this.rand(0, 60) == 0) { 235 | this.ctx.fillStyle = 236 | "rgba(255, 255, 255, " + this.rand(1, 3) / 100 + ")"; 237 | this.ctx.fillRect(0, 0, this.cw, this.ch); 238 | } 239 | 240 | this.ctx.stroke(); 241 | } 242 | }; 243 | 244 | this.lightningTimer = function () { 245 | this.lightTimeCurrent += this.delta; 246 | if (this.lightTimeCurrent >= this.lightTimeTotal) { 247 | var newX = this.rand(100, cw - 100); 248 | var newY = this.rand(0, ch / 2); 249 | var createCount = this.rand(1, 3); 250 | while (createCount--) { 251 | this.createL(newX, newY, true); 252 | } 253 | this.lightTimeCurrent = 0; 254 | this.lightTimeTotal = this.rand(200, 1500); 255 | } 256 | }; 257 | 258 | this.clearCanvas = function () { 259 | this.ctx.globalCompositeOperation = "destination-out"; 260 | this.ctx.fillStyle = "rgba(0,0,0," + this.rand(1, 30) / 100 + ")"; 261 | this.ctx.fillRect(0, 0, this.cw, this.ch); 262 | this.ctx.globalCompositeOperation = "source-over"; 263 | }; 264 | 265 | window.addEventListener("resize", () => { 266 | this.cw = this.c.width = window.innerWidth; 267 | this.ch = this.c.height = window.innerHeight; 268 | }); 269 | 270 | this.loop = function () { 271 | requestAnimationFrame(this.loop.bind(this)); 272 | 273 | this.now = Date.now(); 274 | this.delta = this.now - this.then; 275 | this.then = this.now; 276 | 277 | this.clearCanvas(); 278 | this.updateL(); 279 | this.lightningTimer(); 280 | this.renderL(); 281 | }; 282 | }; 283 | 284 | var c = document.getElementById("canvas"); 285 | var cw = (c.width = window.innerWidth); 286 | var ch = (c.height = window.innerHeight); 287 | var cl = new canvasLightning(c, cw, ch); 288 | 289 | cl.init(); 290 | -------------------------------------------------------------------------------- /style.css: -------------------------------------------------------------------------------- 1 | @import url("https://fonts.googleapis.com/css2?family=Comfortaa:wght@700&family=Press+Start+2P&family=Righteous&display=swap"); 2 | :root { 3 | --bar-fill: #57e705; 4 | --bar-top: #6aff03; 5 | --pixel-size: 7; 6 | } 7 | 8 | .healthbar { 9 | z-index: 10; 10 | position: fixed; 11 | left: 0; 12 | right: 0; 13 | width: calc(30px * var(--pixel-size)); 14 | margin: 0 auto calc(2px * var(--pixel-size)) auto; 15 | display: block; 16 | } 17 | 18 | .healthbar_fill { 19 | width: 0%; 20 | fill: var(--bar-fill); 21 | transition: width 0.1s ease-in, fill 0.2s linear; 22 | } 23 | 24 | .healthbar_fill-top { 25 | width: 0%; 26 | fill: var(--bar-top); 27 | } 28 | 29 | .fill-bar-animation { 30 | animation: fill-bar 6s ease-out forwards; 31 | } 32 | 33 | html, 34 | body { 35 | margin: 0; 36 | padding: 0; 37 | } 38 | 39 | body { 40 | font-family: Avenir, sans-serif; 41 | background-color: #212121; 42 | color: #fffce1; 43 | display: flex; 44 | align-items: center; 45 | justify-content: center; 46 | height: 100vh; 47 | flex-direction: column; 48 | } 49 | 50 | p { 51 | max-width: 70ch; 52 | font-size: 1.4rem; 53 | text-align: center; 54 | line-height: 1.3; 55 | } 56 | 57 | .game { 58 | position: absolute; 59 | width: 100dvw; 60 | height: 100dvh; 61 | overflow: hidden; 62 | bottom: 0; 63 | } 64 | 65 | .rpg-text-box { 66 | overflow: hidden; 67 | color: #ff3860; 68 | height: 100px; 69 | left: 50%; 70 | position: absolute; 71 | bottom: 0; 72 | transform: translate(-50%, calc(100% + 50px + 50px)); 73 | max-width: 500px; 74 | width: 80vw; 75 | line-height: 1.5em; 76 | margin: 2em 0; 77 | background: white; 78 | border: 1px solid white; 79 | padding: 1em; 80 | font-size: 0.7rem; 81 | font-family: "Press Start 2P", cursive; 82 | font-weight: bolder; 83 | border-radius: 0.2em; 84 | box-shadow: 0 1px 0 1px black, inset 0 1px 0 1px black, 0 0 0 1px black, inset 0 0 0 1px black, 3px 5px 0px 1px rgba(0, 0, 0, 0.25); 85 | opacity: 0; 86 | transition: all 250ms; 87 | z-index: 10; 88 | } 89 | .rpg-text-box.cont-dot:after { 90 | opacity: 1; 91 | } 92 | .rpg-text-box:after { 93 | opacity: 0; 94 | content: ""; 95 | display: block; 96 | position: absolute; 97 | width: 10px; 98 | height: 10px; 99 | background-color: currentColor; 100 | bottom: 1em; 101 | right: 1em; 102 | animation: gelatine 1s infinite; 103 | transition: 250ms opacity; 104 | } 105 | 106 | .gelatine { 107 | animation: gelatine 0.5s infinite; 108 | } 109 | 110 | @keyframes gelatine { 111 | from, to { 112 | transform: scale(1, 1); 113 | } 114 | 25% { 115 | transform: scale(0.9, 1.1); 116 | } 117 | 50% { 118 | transform: scale(1.1, 0.9); 119 | } 120 | 75% { 121 | transform: scale(0.95, 1.05); 122 | } 123 | } 124 | .rpg-text-box.visible { 125 | opacity: 1; 126 | transform: translate(-50%); 127 | } 128 | 129 | .code-editor { 130 | position: absolute; 131 | top: 0; 132 | /* bottom: 0; */ 133 | left: 0; 134 | right: 0; 135 | background: black; 136 | height: 0; 137 | } 138 | 139 | .code-editor.reveal { 140 | height: 100%; 141 | transition: all 500ms cubic-bezier(0.47, 1.64, 0.41, 0.8); 142 | } 143 | 144 | .monster { 145 | width: 100%; 146 | height: 100%; 147 | position: absolute; 148 | bottom: 25px; 149 | display: flex; 150 | align-items: center; 151 | justify-content: center; 152 | position: relative; 153 | /* Keep relative positioning for better layout control */ 154 | animation: rise-up 6s ease-out forwards, shake-constant 2s infinite; 155 | } 156 | .monster img { 157 | width: 100%; 158 | max-width: 700px; 159 | } 160 | 161 | @keyframes fill-bar { 162 | from { 163 | width: 0%; 164 | } 165 | to { 166 | width: 100%; 167 | } 168 | } 169 | /* Keyframes for rising up */ 170 | @keyframes rise-up { 171 | from { 172 | transform: translateY(100%); 173 | /* Start below the original position */ 174 | } 175 | to { 176 | transform: translateY(0); 177 | /* End at the original position */ 178 | } 179 | } 180 | .monster .shake-constant { 181 | animation-timing-function: cubic-bezier(0.25, 0.1, 0.25, 1); 182 | /* Smooth timing */ 183 | animation-duration: 2s; 184 | /* Slower shake timing */ 185 | } 186 | 187 | #textbox2 { 188 | display: flex; 189 | align-items: center; 190 | justify-content: center; 191 | } 192 | 193 | #canvas { 194 | position: fixed; 195 | z-index: 5; 196 | pointer-events: none; 197 | } 198 | 199 | .cont { 200 | --angle: 180deg; 201 | --color: #ff5233; 202 | top: 0; 203 | left: 0; 204 | width: 100%; 205 | bottom: -15px; 206 | position: absolute; 207 | overflow: hidden; 208 | border-top: 2px solid var(--color); 209 | border-bottom: 15px solid var(--color); 210 | filter: url("#goo"); 211 | animation: fill-up 1s ease-out forwards; 212 | } 213 | .cont .drip { 214 | height: 30px; 215 | width: 30px; 216 | border-radius: 50%; 217 | background: black; 218 | position: absolute; 219 | top: -100%; 220 | animation: falling 500ms linear infinite; 221 | } 222 | @keyframes fill-up { 223 | from { 224 | border-bottom-width: 15px; 225 | } 226 | to { 227 | border-bottom-width: 150px; 228 | } 229 | } 230 | @keyframes falling { 231 | 0% { 232 | top: -100%; 233 | } 234 | 50% { 235 | top: 0%; 236 | } 237 | 80% { 238 | top: 80%; 239 | } 240 | 100% { 241 | top: 100%; 242 | } 243 | } 244 | .cont .drip:nth-child(1) { 245 | border-color: var(--color); 246 | height: 14px; 247 | width: 14px; 248 | animation-delay: -0.2s; 249 | background: var(--color); 250 | left: 234px; 251 | margin-left: 60px; 252 | } 253 | .cont .drip:nth-child(2) { 254 | border-color: var(--color); 255 | height: 2px; 256 | width: 2px; 257 | animation-delay: -0.4s; 258 | background: var(--color); 259 | left: 75px; 260 | margin-left: 60px; 261 | } 262 | .cont .drip:nth-child(3) { 263 | border-color: var(--color); 264 | height: 39px; 265 | width: 39px; 266 | animation-delay: -0.6s; 267 | background: var(--color); 268 | left: 15px; 269 | margin-left: 60px; 270 | } 271 | .cont .drip:nth-child(4) { 272 | border-color: var(--color); 273 | height: 33px; 274 | width: 33px; 275 | animation-delay: -0.8s; 276 | background: var(--color); 277 | left: 88px; 278 | margin-left: 60px; 279 | } 280 | .cont .drip:nth-child(5) { 281 | border-color: var(--color); 282 | height: 40px; 283 | width: 40px; 284 | animation-delay: -1s; 285 | background: var(--color); 286 | left: 133px; 287 | margin-left: 60px; 288 | } 289 | .cont .drip:nth-child(6) { 290 | border-color: var(--color); 291 | height: 39px; 292 | width: 39px; 293 | animation-delay: -1.2s; 294 | background: var(--color); 295 | left: 185px; 296 | margin-left: 60px; 297 | } 298 | .cont .drip:nth-child(7) { 299 | border-color: var(--color); 300 | height: 20px; 301 | width: 20px; 302 | animation-delay: -1.4s; 303 | background: var(--color); 304 | left: 38px; 305 | margin-left: 60px; 306 | } 307 | .cont .drip:nth-child(8) { 308 | border-color: var(--color); 309 | height: 2px; 310 | width: 2px; 311 | animation-delay: -1.6s; 312 | background: var(--color); 313 | left: 211px; 314 | margin-left: 60px; 315 | } 316 | .cont .drip:nth-child(9) { 317 | border-color: var(--color); 318 | height: 3px; 319 | width: 3px; 320 | animation-delay: -1.8s; 321 | background: var(--color); 322 | left: 174px; 323 | margin-left: 60px; 324 | } 325 | .cont .drip:nth-child(10) { 326 | border-color: var(--color); 327 | height: 17px; 328 | width: 17px; 329 | animation-delay: -2s; 330 | background: var(--color); 331 | left: 60px; 332 | margin-left: 60px; 333 | } 334 | .cont .drip:nth-child(11) { 335 | border-color: var(--color); 336 | height: 39px; 337 | width: 39px; 338 | animation-delay: -2.2s; 339 | background: var(--color); 340 | left: 206px; 341 | margin-left: 60px; 342 | } 343 | .cont .drip:nth-child(12) { 344 | border-color: var(--color); 345 | height: 14px; 346 | width: 14px; 347 | animation-delay: -2.4s; 348 | background: var(--color); 349 | left: 232px; 350 | margin-left: 60px; 351 | } 352 | .cont .drip:nth-child(13) { 353 | border-color: var(--color); 354 | height: 21px; 355 | width: 21px; 356 | animation-delay: -2.6s; 357 | background: var(--color); 358 | left: 175px; 359 | margin-left: 60px; 360 | } 361 | .cont .drip:nth-child(14) { 362 | border-color: var(--color); 363 | height: 15px; 364 | width: 15px; 365 | animation-delay: -2.8s; 366 | background: var(--color); 367 | left: 300px; 368 | margin-left: 60px; 369 | } 370 | .cont .drip:nth-child(15) { 371 | border-color: var(--color); 372 | height: 5px; 373 | width: 5px; 374 | animation-delay: -3s; 375 | background: var(--color); 376 | left: 178px; 377 | margin-left: 60px; 378 | } 379 | .cont .drip:nth-child(16) { 380 | border-color: var(--color); 381 | height: 30px; 382 | width: 30px; 383 | animation-delay: -3.2s; 384 | background: var(--color); 385 | left: 297px; 386 | margin-left: 60px; 387 | } 388 | .cont .drip:nth-child(17) { 389 | border-color: var(--color); 390 | height: 9px; 391 | width: 9px; 392 | animation-delay: -3.4s; 393 | background: var(--color); 394 | left: 223px; 395 | margin-left: 60px; 396 | } 397 | .cont .drip:nth-child(18) { 398 | border-color: var(--color); 399 | height: 28px; 400 | width: 28px; 401 | animation-delay: -3.6s; 402 | background: var(--color); 403 | left: 240px; 404 | margin-left: 60px; 405 | } 406 | .cont .drip:nth-child(19) { 407 | border-color: var(--color); 408 | height: 2px; 409 | width: 2px; 410 | animation-delay: -3.8s; 411 | background: var(--color); 412 | left: 9px; 413 | margin-left: 60px; 414 | } 415 | .cont .drip:nth-child(20) { 416 | border-color: var(--color); 417 | height: 27px; 418 | width: 27px; 419 | animation-delay: -4s; 420 | background: var(--color); 421 | left: 118px; 422 | margin-left: 60px; 423 | } -------------------------------------------------------------------------------- /script.js: -------------------------------------------------------------------------------- 1 | // Testing animation concepts for boss battle 2 | 3 | const textBoxText = document.getElementById("textbox"); 4 | const textBoxText2 = document.getElementById("textbox2"); 5 | 6 | const split = new SplitText(textBoxText, { 7 | charsClass: "kb-char shake-constant", 8 | linesClass: "kb-line" 9 | }); 10 | 11 | const chars = split.chars; 12 | 13 | const nextSplit = new SplitText(textBoxText2, { 14 | charsClass: "kb-char shake-constant", 15 | linesClass: "kb-line" 16 | }); 17 | 18 | const chars2 = nextSplit.chars; 19 | 20 | const codeEditorDiv = document.createElement("div"); 21 | codeEditorDiv.className = "code-editor"; 22 | 23 | const codeEditorDiv2 = document.createElement("div"); 24 | codeEditorDiv2.className = "code-editor reveal"; 25 | 26 | // Insert it at the beginning of textBoxText 27 | textBoxText.prepend(codeEditorDiv); 28 | textBoxText2.prepend(codeEditorDiv2); 29 | 30 | chars.forEach((char, index) => { 31 | char.classList.add("shake-little"); 32 | 33 | // Calculate a pseudo-random delay based on the index 34 | const delay = Math.random() * 0.2 + index * 0.05; // Adjust randomness and staggering here 35 | 36 | // Set the delay as an inline style 37 | char.style.animationDelay = `${delay}s`; 38 | }); 39 | 40 | chars2.forEach((char, index) => { 41 | char.classList.add("shake-little"); 42 | 43 | // Calculate a pseudo-random delay based on the index 44 | const delay = Math.random() * 0.2 + index * 0.05; // Adjust randomness and staggering here 45 | 46 | // Set the delay as an inline style 47 | char.style.animationDelay = `${delay}s`; 48 | }); 49 | 50 | let currentLine; 51 | 52 | var tl = new TimelineMax({ 53 | // onComplete: () => { 54 | // codeEditorDiv.classList.add("reveal"); 55 | // } 56 | }); 57 | 58 | tl.delay(3); 59 | 60 | tl.call( 61 | function () { 62 | textBoxText.classList.add("visible"); 63 | }, 64 | null, 65 | null, 66 | 0 67 | ) 68 | .staggerFrom( 69 | chars, 70 | 0.8, 71 | { 72 | opacity: 0, 73 | ease: SteppedEase.config(1) 74 | }, 75 | 0.08, 76 | "+=0" 77 | ) 78 | .call( 79 | function () { 80 | textBoxText.classList.add("cont-dot"); 81 | }, 82 | null, 83 | "+=0", 84 | 0 85 | ) 86 | .call( 87 | function () { 88 | codeEditorDiv.classList.add("reveal"); 89 | }, 90 | null, 91 | "+=2", 92 | 0 93 | ) 94 | .call( 95 | function () { 96 | textBoxText.style.display = "none"; 97 | textBoxText2.style.display = "flex"; 98 | }, 99 | null, 100 | "+=2", 101 | 0 102 | ) 103 | .staggerFrom( 104 | chars2, 105 | 0.8, 106 | { 107 | opacity: 0, 108 | ease: SteppedEase.config(1) 109 | }, 110 | 0.08, 111 | "+=0" 112 | ) 113 | .call( 114 | function () { 115 | textBoxText2.classList.add("cont-dot"); 116 | }, 117 | null, 118 | "+=0", 119 | 0 120 | ) 121 | // .call( 122 | // function () { 123 | // textBoxText2.innerHTML += LiquidHTML(); 124 | // }, 125 | // null, 126 | // "+=3", 127 | // 0 128 | // ) 129 | // .call( 130 | // function () { 131 | // const textBox2Code = document 132 | // .getElementById("textbox2") 133 | // .querySelector(".code-editor"); 134 | // textBox2Code.classList.remove("reveal"); 135 | // textBox2Code.style.zIndex = "10"; 136 | // }, 137 | // null, 138 | // "+=0", 139 | // 0 140 | // ) 141 | // .call( 142 | // function () { 143 | // const textBox2Code = document 144 | // .getElementById("textbox2") 145 | // .querySelector(".code-editor"); 146 | // textBox2Code.classList.add("reveal"); 147 | // }, 148 | // null, 149 | // "+=3", 150 | // 0 151 | // ) 152 | .pause(); 153 | 154 | tl.play(); 155 | 156 | /////// 157 | 158 | console.clear(); 159 | 160 | var canvasLightning = function (c, cw, ch) { 161 | this.init = function () { 162 | this.loop(); 163 | }; 164 | 165 | var _this = this; 166 | this.c = c; 167 | this.ctx = c.getContext("2d"); 168 | this.cw = cw; 169 | this.ch = ch; 170 | this.mx = 0; 171 | this.my = 0; 172 | 173 | this.now = Date.now(); 174 | this.delta = 0; 175 | this.then = this.now; 176 | 177 | this.lightning = []; 178 | this.lightTimeCurrent = 0; 179 | this.lightTimeTotal = 50; 180 | 181 | this.rand = function (rMi, rMa) { 182 | return ~~(Math.random() * (rMa - rMi + 1) + rMi); 183 | }; 184 | 185 | this.createL = function (x, y, canSpawn) { 186 | this.lightning.push({ 187 | x: x, 188 | y: y, 189 | xRange: this.rand(5, 30), 190 | yRange: this.rand(5, 25), 191 | path: [ 192 | { 193 | x: x, 194 | y: y 195 | } 196 | ], 197 | pathLimit: this.rand(10, 35), 198 | canSpawn: canSpawn, 199 | hasFired: false, 200 | grower: 0, 201 | growerLimit: 5 //this.rand(5, 15) 202 | }); 203 | }; 204 | 205 | this.updateL = function () { 206 | var i = this.lightning.length; 207 | while (i--) { 208 | var light = this.lightning[i]; 209 | 210 | light.grower += this.delta; 211 | 212 | if (light.grower >= light.growerLimit) { 213 | light.grower = 0; 214 | light.growerLimit *= 1.05; 215 | 216 | light.path.push({ 217 | x: 218 | light.path[light.path.length - 1].x + 219 | (this.rand(0, light.xRange) - light.xRange / 2), 220 | y: light.path[light.path.length - 1].y + this.rand(0, light.yRange) 221 | }); 222 | 223 | if (light.path.length > light.pathLimit) { 224 | this.lightning.splice(i, 1); 225 | } 226 | light.hasFired = true; 227 | } 228 | } 229 | }; 230 | 231 | this.renderL = function () { 232 | var i = this.lightning.length; 233 | while (i--) { 234 | var light = this.lightning[i]; 235 | 236 | const randomColor = Math.random(); 237 | this.ctx.strokeStyle = 238 | "hsla(0, 100%, 100%, " + this.rand(10, 100) / 100 + ")"; 239 | if (randomColor >= 0.33 && randomColor < 0.8) { 240 | this.ctx.strokeStyle = 241 | "hsla(248, 53%, 58%, " + this.rand(10, 100) / 100 + ")"; 242 | } 243 | 244 | if (randomColor >= 0.8) { 245 | this.ctx.strokeStyle = 246 | "hsla(204, 86%, 53%, " + this.rand(10, 100) / 100 + ")"; 247 | } 248 | 249 | this.ctx.lineWidth = 4; 250 | if (this.rand(0, 30) == 0) { 251 | this.ctx.lineWidth = 5; 252 | } 253 | if (this.rand(0, 60) == 0) { 254 | this.ctx.lineWidth = 6; 255 | } 256 | if (this.rand(0, 90) == 0) { 257 | this.ctx.lineWidth = 7; 258 | } 259 | 260 | this.ctx.beginPath(); 261 | 262 | var pathCount = light.path.length; 263 | this.ctx.moveTo(light.x, light.y); 264 | for (var pc = 0; pc < pathCount; pc++) { 265 | this.ctx.lineTo(light.path[pc].x, light.path[pc].y); 266 | 267 | if (light.canSpawn) { 268 | if (this.rand(0, 100) == 0) { 269 | light.canSpawn = false; 270 | this.createL(light.path[pc].x, light.path[pc].y, false); 271 | } 272 | } 273 | } 274 | 275 | if (!light.hasFired) { 276 | this.ctx.fillStyle = 277 | "rgba(255, 255, 255, " + this.rand(4, 12) / 100 + ")"; 278 | this.ctx.fillRect(0, 0, this.cw, this.ch); 279 | } 280 | 281 | if (this.rand(0, 60) == 0) { 282 | this.ctx.fillStyle = 283 | "rgba(255, 255, 255, " + this.rand(1, 3) / 100 + ")"; 284 | this.ctx.fillRect(0, 0, this.cw, this.ch); 285 | } 286 | 287 | this.ctx.stroke(); 288 | } 289 | }; 290 | 291 | this.lightningTimer = function () { 292 | this.lightTimeCurrent += this.delta; 293 | if (this.lightTimeCurrent >= this.lightTimeTotal) { 294 | var newX = this.rand(100, cw - 100); 295 | var newY = this.rand(0, ch / 2); 296 | var createCount = this.rand(1, 3); 297 | while (createCount--) { 298 | this.createL(newX, newY, true); 299 | } 300 | this.lightTimeCurrent = 0; 301 | this.lightTimeTotal = this.rand(200, 1500); 302 | } 303 | }; 304 | 305 | this.clearCanvas = function () { 306 | this.ctx.globalCompositeOperation = "destination-out"; 307 | this.ctx.fillStyle = "rgba(0,0,0," + this.rand(1, 30) / 100 + ")"; 308 | this.ctx.fillRect(0, 0, this.cw, this.ch); 309 | this.ctx.globalCompositeOperation = "source-over"; 310 | }; 311 | 312 | window.addEventListener("resize", () => { 313 | this.cw = this.c.width = window.innerWidth; 314 | this.ch = this.c.height = window.innerHeight; 315 | }); 316 | 317 | this.loop = function () { 318 | requestAnimationFrame(this.loop.bind(this)); 319 | 320 | this.now = Date.now(); 321 | this.delta = this.now - this.then; 322 | this.then = this.now; 323 | 324 | this.clearCanvas(); 325 | this.updateL(); 326 | this.lightningTimer(); 327 | this.renderL(); 328 | }; 329 | }; 330 | 331 | var c = document.getElementById("canvas"); 332 | var cw = (c.width = window.innerWidth); 333 | var ch = (c.height = window.innerHeight); 334 | var cl = new canvasLightning(c, cw, ch); 335 | 336 | cl.init(); 337 | 338 | function LiquidHTML() { 339 | return ` 340 |
341 |
342 |
343 |
344 |
345 |
346 |
347 |
348 |
349 |
350 |
351 |
352 |
353 |
354 |
355 |
356 |
357 |
358 |
359 |
360 |
361 | 362 | 363 | 364 | 365 | 366 | 367 | 368 | 369 | 370 | 371 |
372 | `.trim(); 373 | } -------------------------------------------------------------------------------- /SplitText.min.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * SplitText 3.12.5 3 | * https://gsap.com 4 | * 5 | * @license Copyright 2024, GreenSock. All rights reserved. 6 | * This plugin is a membership benefit of Club GSAP and is only authorized for use in sites/apps/products developed by individuals/companies with an active Club GSAP membership. See https://gsap.com/pricing 7 | * @author: Jack Doyle, jack@greensock.com 8 | */ 9 | 10 | !function(D,u){"object"==typeof exports&&"undefined"!=typeof module?u(exports):"function"==typeof define&&define.amd?define(["exports"],u):u((D=D||self).window=D.window||{})}(this,function(D){"use strict";var b=/([\uD800-\uDBFF][\uDC00-\uDFFF](?:[\u200D\uFE0F][\uD800-\uDBFF][\uDC00-\uDFFF]){2,}|\uD83D\uDC69(?:\u200D(?:(?:\uD83D\uDC69\u200D)?\uD83D\uDC67|(?:\uD83D\uDC69\u200D)?\uD83D\uDC66)|\uD83C[\uDFFB-\uDFFF])|\uD83D\uDC69\u200D(?:\uD83D\uDC69\u200D)?\uD83D\uDC66\u200D\uD83D\uDC66|\uD83D\uDC69\u200D(?:\uD83D\uDC69\u200D)?\uD83D\uDC67\u200D(?:\uD83D[\uDC66\uDC67])|\uD83C\uDFF3\uFE0F\u200D\uD83C\uDF08|(?:\uD83C[\uDFC3\uDFC4\uDFCA]|\uD83D[\uDC6E\uDC71\uDC73\uDC77\uDC81\uDC82\uDC86\uDC87\uDE45-\uDE47\uDE4B\uDE4D\uDE4E\uDEA3\uDEB4-\uDEB6]|\uD83E[\uDD26\uDD37-\uDD39\uDD3D\uDD3E\uDDD6-\uDDDD])(?:\uD83C[\uDFFB-\uDFFF])\u200D[\u2640\u2642]\uFE0F|\uD83D\uDC69(?:\uD83C[\uDFFB-\uDFFF])\u200D(?:\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92])|(?:\uD83C[\uDFC3\uDFC4\uDFCA]|\uD83D[\uDC6E\uDC6F\uDC71\uDC73\uDC77\uDC81\uDC82\uDC86\uDC87\uDE45-\uDE47\uDE4B\uDE4D\uDE4E\uDEA3\uDEB4-\uDEB6]|\uD83E[\uDD26\uDD37-\uDD39\uDD3C-\uDD3E\uDDD6-\uDDDF])\u200D[\u2640\u2642]\uFE0F|\uD83C\uDDFD\uD83C\uDDF0|\uD83C\uDDF6\uD83C\uDDE6|\uD83C\uDDF4\uD83C\uDDF2|\uD83C\uDDE9(?:\uD83C[\uDDEA\uDDEC\uDDEF\uDDF0\uDDF2\uDDF4\uDDFF])|\uD83C\uDDF7(?:\uD83C[\uDDEA\uDDF4\uDDF8\uDDFA\uDDFC])|\uD83C\uDDE8(?:\uD83C[\uDDE6\uDDE8\uDDE9\uDDEB-\uDDEE\uDDF0-\uDDF5\uDDF7\uDDFA-\uDDFF])|(?:\u26F9|\uD83C[\uDFCB\uDFCC]|\uD83D\uDD75)(?:\uFE0F\u200D[\u2640\u2642]|(?:\uD83C[\uDFFB-\uDFFF])\u200D[\u2640\u2642])\uFE0F|(?:\uD83D\uDC41\uFE0F\u200D\uD83D\uDDE8|\uD83D\uDC69(?:\uD83C[\uDFFB-\uDFFF])\u200D[\u2695\u2696\u2708]|\uD83D\uDC69\u200D[\u2695\u2696\u2708]|\uD83D\uDC68(?:(?:\uD83C[\uDFFB-\uDFFF])\u200D[\u2695\u2696\u2708]|\u200D[\u2695\u2696\u2708]))\uFE0F|\uD83C\uDDF2(?:\uD83C[\uDDE6\uDDE8-\uDDED\uDDF0-\uDDFF])|\uD83D\uDC69\u200D(?:\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D(?:\uD83D[\uDC68\uDC69])|\uD83D[\uDC68\uDC69]))|\uD83C\uDDF1(?:\uD83C[\uDDE6-\uDDE8\uDDEE\uDDF0\uDDF7-\uDDFB\uDDFE])|\uD83C\uDDEF(?:\uD83C[\uDDEA\uDDF2\uDDF4\uDDF5])|\uD83C\uDDED(?:\uD83C[\uDDF0\uDDF2\uDDF3\uDDF7\uDDF9\uDDFA])|\uD83C\uDDEB(?:\uD83C[\uDDEE-\uDDF0\uDDF2\uDDF4\uDDF7])|[#\*0-9]\uFE0F\u20E3|\uD83C\uDDE7(?:\uD83C[\uDDE6\uDDE7\uDDE9-\uDDEF\uDDF1-\uDDF4\uDDF6-\uDDF9\uDDFB\uDDFC\uDDFE\uDDFF])|\uD83C\uDDE6(?:\uD83C[\uDDE8-\uDDEC\uDDEE\uDDF1\uDDF2\uDDF4\uDDF6-\uDDFA\uDDFC\uDDFD\uDDFF])|\uD83C\uDDFF(?:\uD83C[\uDDE6\uDDF2\uDDFC])|\uD83C\uDDF5(?:\uD83C[\uDDE6\uDDEA-\uDDED\uDDF0-\uDDF3\uDDF7-\uDDF9\uDDFC\uDDFE])|\uD83C\uDDFB(?:\uD83C[\uDDE6\uDDE8\uDDEA\uDDEC\uDDEE\uDDF3\uDDFA])|\uD83C\uDDF3(?:\uD83C[\uDDE6\uDDE8\uDDEA-\uDDEC\uDDEE\uDDF1\uDDF4\uDDF5\uDDF7\uDDFA\uDDFF])|\uD83C\uDFF4\uDB40\uDC67\uDB40\uDC62(?:\uDB40\uDC77\uDB40\uDC6C\uDB40\uDC73|\uDB40\uDC73\uDB40\uDC63\uDB40\uDC74|\uDB40\uDC65\uDB40\uDC6E\uDB40\uDC67)\uDB40\uDC7F|\uD83D\uDC68(?:\u200D(?:\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D)?\uD83D\uDC68|(?:(?:\uD83D[\uDC68\uDC69])\u200D)?\uD83D\uDC66\u200D\uD83D\uDC66|(?:(?:\uD83D[\uDC68\uDC69])\u200D)?\uD83D\uDC67\u200D(?:\uD83D[\uDC66\uDC67])|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92])|(?:\uD83C[\uDFFB-\uDFFF])\u200D(?:\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]))|\uD83C\uDDF8(?:\uD83C[\uDDE6-\uDDEA\uDDEC-\uDDF4\uDDF7-\uDDF9\uDDFB\uDDFD-\uDDFF])|\uD83C\uDDF0(?:\uD83C[\uDDEA\uDDEC-\uDDEE\uDDF2\uDDF3\uDDF5\uDDF7\uDDFC\uDDFE\uDDFF])|\uD83C\uDDFE(?:\uD83C[\uDDEA\uDDF9])|\uD83C\uDDEE(?:\uD83C[\uDDE8-\uDDEA\uDDF1-\uDDF4\uDDF6-\uDDF9])|\uD83C\uDDF9(?:\uD83C[\uDDE6\uDDE8\uDDE9\uDDEB-\uDDED\uDDEF-\uDDF4\uDDF7\uDDF9\uDDFB\uDDFC\uDDFF])|\uD83C\uDDEC(?:\uD83C[\uDDE6\uDDE7\uDDE9-\uDDEE\uDDF1-\uDDF3\uDDF5-\uDDFA\uDDFC\uDDFE])|\uD83C\uDDFA(?:\uD83C[\uDDE6\uDDEC\uDDF2\uDDF3\uDDF8\uDDFE\uDDFF])|\uD83C\uDDEA(?:\uD83C[\uDDE6\uDDE8\uDDEA\uDDEC\uDDED\uDDF7-\uDDFA])|\uD83C\uDDFC(?:\uD83C[\uDDEB\uDDF8])|(?:\u26F9|\uD83C[\uDFCB\uDFCC]|\uD83D\uDD75)(?:\uD83C[\uDFFB-\uDFFF])|(?:\uD83C[\uDFC3\uDFC4\uDFCA]|\uD83D[\uDC6E\uDC71\uDC73\uDC77\uDC81\uDC82\uDC86\uDC87\uDE45-\uDE47\uDE4B\uDE4D\uDE4E\uDEA3\uDEB4-\uDEB6]|\uD83E[\uDD26\uDD37-\uDD39\uDD3D\uDD3E\uDDD6-\uDDDD])(?:\uD83C[\uDFFB-\uDFFF])|(?:[\u261D\u270A-\u270D]|\uD83C[\uDF85\uDFC2\uDFC7]|\uD83D[\uDC42\uDC43\uDC46-\uDC50\uDC66\uDC67\uDC70\uDC72\uDC74-\uDC76\uDC78\uDC7C\uDC83\uDC85\uDCAA\uDD74\uDD7A\uDD90\uDD95\uDD96\uDE4C\uDE4F\uDEC0\uDECC]|\uD83E[\uDD18-\uDD1C\uDD1E\uDD1F\uDD30-\uDD36\uDDD1-\uDDD5])(?:\uD83C[\uDFFB-\uDFFF])|\uD83D\uDC68(?:\u200D(?:(?:(?:\uD83D[\uDC68\uDC69])\u200D)?\uD83D\uDC67|(?:(?:\uD83D[\uDC68\uDC69])\u200D)?\uD83D\uDC66)|\uD83C[\uDFFB-\uDFFF])|(?:[\u261D\u26F9\u270A-\u270D]|\uD83C[\uDF85\uDFC2-\uDFC4\uDFC7\uDFCA-\uDFCC]|\uD83D[\uDC42\uDC43\uDC46-\uDC50\uDC66-\uDC69\uDC6E\uDC70-\uDC78\uDC7C\uDC81-\uDC83\uDC85-\uDC87\uDCAA\uDD74\uDD75\uDD7A\uDD90\uDD95\uDD96\uDE45-\uDE47\uDE4B-\uDE4F\uDEA3\uDEB4-\uDEB6\uDEC0\uDECC]|\uD83E[\uDD18-\uDD1C\uDD1E\uDD1F\uDD26\uDD30-\uDD39\uDD3D\uDD3E\uDDD1-\uDDDD])(?:\uD83C[\uDFFB-\uDFFF])?|(?:[\u231A\u231B\u23E9-\u23EC\u23F0\u23F3\u25FD\u25FE\u2614\u2615\u2648-\u2653\u267F\u2693\u26A1\u26AA\u26AB\u26BD\u26BE\u26C4\u26C5\u26CE\u26D4\u26EA\u26F2\u26F3\u26F5\u26FA\u26FD\u2705\u270A\u270B\u2728\u274C\u274E\u2753-\u2755\u2757\u2795-\u2797\u27B0\u27BF\u2B1B\u2B1C\u2B50\u2B55]|\uD83C[\uDC04\uDCCF\uDD8E\uDD91-\uDD9A\uDDE6-\uDDFF\uDE01\uDE1A\uDE2F\uDE32-\uDE36\uDE38-\uDE3A\uDE50\uDE51\uDF00-\uDF20\uDF2D-\uDF35\uDF37-\uDF7C\uDF7E-\uDF93\uDFA0-\uDFCA\uDFCF-\uDFD3\uDFE0-\uDFF0\uDFF4\uDFF8-\uDFFF]|\uD83D[\uDC00-\uDC3E\uDC40\uDC42-\uDCFC\uDCFF-\uDD3D\uDD4B-\uDD4E\uDD50-\uDD67\uDD7A\uDD95\uDD96\uDDA4\uDDFB-\uDE4F\uDE80-\uDEC5\uDECC\uDED0-\uDED2\uDEEB\uDEEC\uDEF4-\uDEF8]|\uD83E[\uDD10-\uDD3A\uDD3C-\uDD3E\uDD40-\uDD45\uDD47-\uDD4C\uDD50-\uDD6B\uDD80-\uDD97\uDDC0\uDDD0-\uDDE6])|(?:[#\*0-9\xA9\xAE\u203C\u2049\u2122\u2139\u2194-\u2199\u21A9\u21AA\u231A\u231B\u2328\u23CF\u23E9-\u23F3\u23F8-\u23FA\u24C2\u25AA\u25AB\u25B6\u25C0\u25FB-\u25FE\u2600-\u2604\u260E\u2611\u2614\u2615\u2618\u261D\u2620\u2622\u2623\u2626\u262A\u262E\u262F\u2638-\u263A\u2640\u2642\u2648-\u2653\u2660\u2663\u2665\u2666\u2668\u267B\u267F\u2692-\u2697\u2699\u269B\u269C\u26A0\u26A1\u26AA\u26AB\u26B0\u26B1\u26BD\u26BE\u26C4\u26C5\u26C8\u26CE\u26CF\u26D1\u26D3\u26D4\u26E9\u26EA\u26F0-\u26F5\u26F7-\u26FA\u26FD\u2702\u2705\u2708-\u270D\u270F\u2712\u2714\u2716\u271D\u2721\u2728\u2733\u2734\u2744\u2747\u274C\u274E\u2753-\u2755\u2757\u2763\u2764\u2795-\u2797\u27A1\u27B0\u27BF\u2934\u2935\u2B05-\u2B07\u2B1B\u2B1C\u2B50\u2B55\u3030\u303D\u3297\u3299]|\uD83C[\uDC04\uDCCF\uDD70\uDD71\uDD7E\uDD7F\uDD8E\uDD91-\uDD9A\uDDE6-\uDDFF\uDE01\uDE02\uDE1A\uDE2F\uDE32-\uDE3A\uDE50\uDE51\uDF00-\uDF21\uDF24-\uDF93\uDF96\uDF97\uDF99-\uDF9B\uDF9E-\uDFF0\uDFF3-\uDFF5\uDFF7-\uDFFF]|\uD83D[\uDC00-\uDCFD\uDCFF-\uDD3D\uDD49-\uDD4E\uDD50-\uDD67\uDD6F\uDD70\uDD73-\uDD7A\uDD87\uDD8A-\uDD8D\uDD90\uDD95\uDD96\uDDA4\uDDA5\uDDA8\uDDB1\uDDB2\uDDBC\uDDC2-\uDDC4\uDDD1-\uDDD3\uDDDC-\uDDDE\uDDE1\uDDE3\uDDE8\uDDEF\uDDF3\uDDFA-\uDE4F\uDE80-\uDEC5\uDECB-\uDED2\uDEE0-\uDEE5\uDEE9\uDEEB\uDEEC\uDEF0\uDEF3-\uDEF8]|\uD83E[\uDD10-\uDD3A\uDD3C-\uDD3E\uDD40-\uDD45\uDD47-\uDD4C\uDD50-\uDD6B\uDD80-\uDD97\uDDC0\uDDD0-\uDDE6])\uFE0F)/;function n(D){X=document,e=window,(C=C||D||e.gsap||console.warn("Please gsap.registerPlugin(SplitText)"))&&(E=C.utils.toArray,i=C.core.context||function(){},F=1)}function o(D){return e.getComputedStyle(D)}function p(D){return"absolute"===D.position||!0===D.absolute}function q(D,u){for(var e,t=u.length;-1<--t;)if(e=u[t],D.substr(0,e.length)===e)return e.length}function s(D,u){void 0===D&&(D="");var e=~D.indexOf("++"),t=1;return e&&(D=D.split("++").join("")),function(){return"<"+u+" style='position:relative;display:inline-block;'"+(D?" class='"+D+(e?t++:"")+"'>":">")}}function t(D,u,e){var F=D.nodeType;if(1===F||9===F||11===F)for(D=D.firstChild;D;D=D.nextSibling)t(D,u,e);else 3!==F&&4!==F||(D.nodeValue=D.nodeValue.split(u).join(e))}function u(D,u){for(var e=u.length;-1<--e;)D.push(u[e])}function v(D,u,e){for(var t;D&&D!==u;){if(t=D._next||D.nextSibling)return t.textContent.charAt(0)===e;D=D.parentNode||D._parent}}function w(D){var u,e,t=E(D.childNodes),F=t.length;for(u=0;uW&&("BR"!==d.nodeName||0===E)&&(B=[],P.push(B),S=y),G&&(d._x=d.offsetLeft,d._y=y,d._w=d.offsetWidth,d._h=d.offsetHeight),P&&((d._isSplit&&h||!q&&h||z&&h||!z&&d.parentNode.parentNode===D&&!d.parentNode._isSplit)&&(B.push(d),d._x-=_,v(d,D,R)&&(d._wordEnd=!0)),"BR"===d.nodeName&&(d.nextSibling&&"BR"===d.nextSibling.nodeName||0===E)&&P.push([])));for(E=0;ED.clientHeight&&(D.style.height=s-N+"px",D.clientHeightD.clientWidth&&(D.style.width=n-L+"px",D.clientWidth",c=1,x=u.specialChars?"function"==typeof u.specialChars?u.specialChars:q:null,g=X.createElement("div"),y=D.parentNode;for(y.insertBefore(g,D),g.textContent=D.nodeValue,y.removeChild(D),l=-1!==(C=function getText(D){var u=D.nodeType,e="";if(1===u||9===u||11===u){if("string"==typeof D.textContent)return D.textContent;for(D=D.firstChild;D;D=D.nextSibling)e+=getText(D)}else if(3===u||4===u)return D.nodeValue;return e}(D=g)).indexOf("<"),!1!==u.reduceWhiteSpace&&(C=C.replace(S," ").replace(_,"")),l&&(C=C.split("<").join("{{LT}}")),E=C.length,i=(" "===C.charAt(0)?f:"")+e(),n=0;n":r,n+=o-1;else if(eb(r)&&!eb(C.charAt(n-1))&&n){for(i+=c?A:"",c=0;eb(C.charAt(n+1));)i+=f,n++;n===E-1?i+=f:")"!==C.charAt(n+1)&&(i+=f+e(),c=1)}else"{"===r&&"{{LT}}"===C.substr(n,6)?(i+=a?F()+"{{LT}}":"{{LT}}",n+=5):55296<=r.charCodeAt(0)&&r.charCodeAt(0)<=56319||65024<=C.charCodeAt(n+1)&&C.charCodeAt(n+1)<=65039?(s=((C.substr(n,12).split(b)||[])[1]||"").length||2,i+=a&&" "!==r?F()+C.substr(n,s)+"":C.substr(n,s),n+=s-1):i+=a&&" "!==r?F()+r+"":r;D.outerHTML=i+(c?A:""),l&&t(y,"{{LT}}","<")}function A(D,u,e,t){var F,C,i=E(D.childNodes),n=i.length,s=p(u);if(3!==D.nodeType||1