├── README.md ├── index.html ├── style.css └── script.js /README.md: -------------------------------------------------------------------------------- 1 | # Falling Man Button 2 | This is a simple web page that shows a button which, when clicked, triggers an animation that makes a man fall out of a door. The door is placed on the button. 3 | 4 | ## Technologies Used 5 | The project uses the following technologies: 6 | 7 | - HTML 8 | - CSS 9 | - JS 10 | - SVG 11 | 12 | ## How to Use 13 | To use this project, simply open the `index.html` file in a web browser. 14 | 15 | When the page loads, you will see a button with the text "Logout". Click on this button to trigger the animation. The animation will make a man fall out of a door that is placed on the button. 16 | 17 | ## Code Description 18 | The `index.html` file contains the HTML code for the web page. It includes a `div` element with the class `background`, which is used to create the background for the page. Inside this `div` element, there is a `button` element with the classes `logoutButton` and `logoutButton--dark`. This is the button that triggers the animation. 19 | 20 | The button includes two SVG elements: 21 | 22 | * The first SVG element, with the class `doorway`, is used to create the door that the man falls out of. It contains two `path` elements that define the shape of the door and the "bang" that appears when the man hits the ground. 23 | 24 | * The second SVG element, with the class `figure`, is used to create the man that falls out of the door. It contains a `circle` element that defines the head of the man and several `path` elements that define the body, arms, and legs of the man. 25 | 26 | The `style.css` file contains the CSS code for the web page. It is used to style the button and the SVG elements. 27 | 28 | ## Preview 29 | Screenshot 2023-03-01 205245 30 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Falling Man Button 9 | 10 | 11 |
12 | 43 |
44 | 45 |
46 | 77 |
78 | 79 | 80 | 81 | -------------------------------------------------------------------------------- /style.css: -------------------------------------------------------------------------------- 1 | .logoutButton { 2 | --figure-duration: 100ms; 3 | --transform-figure: none; 4 | --walking-duration: 100ms; 5 | --transform-arm1: none; 6 | --transform-wrist1: none; 7 | --transform-arm2: none; 8 | --transform-wrist2: none; 9 | --transform-leg1: none; 10 | --transform-calf1: none; 11 | --transform-leg2: none; 12 | --transform-calf2: none; 13 | background: none; 14 | border: 0; 15 | color: #f4f7ff; 16 | cursor: pointer; 17 | display: block; 18 | font-family: "Quicksand", sans-serif; 19 | font-size: 14px; 20 | font-weight: 500; 21 | height: 40px; 22 | outline: none; 23 | padding: 0 0 0 20px; 24 | perspective: 100px; 25 | position: relative; 26 | text-align: left; 27 | width: 130px; 28 | -webkit-tap-highlight-color: transparent; 29 | } 30 | .logoutButton::before { 31 | background-color: #1f2335; 32 | border-radius: 5px; 33 | content: ""; 34 | display: block; 35 | height: 100%; 36 | left: 0; 37 | position: absolute; 38 | top: 0; 39 | transform: none; 40 | transition: transform 50ms ease; 41 | width: 100%; 42 | z-index: 2; 43 | } 44 | .logoutButton:hover .door { 45 | transform: rotateY(20deg); 46 | } 47 | .logoutButton:active::before { 48 | transform: scale(0.96); 49 | } 50 | .logoutButton:active .door { 51 | transform: rotateY(28deg); 52 | } 53 | .logoutButton.clicked::before { 54 | transform: none; 55 | } 56 | .logoutButton.clicked .door { 57 | transform: rotateY(35deg); 58 | } 59 | .logoutButton.door-slammed .door { 60 | transform: none; 61 | transition: transform 100ms ease-in 250ms; 62 | } 63 | .logoutButton.falling { 64 | animation: shake 200ms linear; 65 | } 66 | .logoutButton.falling .bang { 67 | animation: flash 300ms linear; 68 | } 69 | .logoutButton.falling .figure { 70 | animation: spin 1000ms infinite linear; 71 | bottom: -1080px; 72 | opacity: 0; 73 | right: 1px; 74 | transition: transform calc(var(--figure-duration) * 1ms) linear, bottom calc(var(--figure-duration) * 1ms) cubic-bezier(0.7, 0.1, 1, 1) 100ms, opacity calc(var(--figure-duration) * 0.25ms) linear calc(var(--figure-duration) * 0.75ms); 75 | z-index: 1; 76 | } 77 | .logoutButton--light::before { 78 | background-color: #f4f7ff; 79 | } 80 | .logoutButton--light .button-text { 81 | color: #1f2335; 82 | } 83 | .logoutButton--light .door, 84 | .logoutButton--light .doorway { 85 | fill: #1f2335; 86 | } 87 | 88 | .button-text { 89 | color: #f4f7ff; 90 | font-weight: 500; 91 | position: relative; 92 | z-index: 10; 93 | } 94 | 95 | svg { 96 | display: block; 97 | position: absolute; 98 | } 99 | 100 | .figure { 101 | bottom: 5px; 102 | fill: #4371f7; 103 | right: 18px; 104 | transform: var(--transform-figure); 105 | transition: transform calc(var(--figure-duration) * 1ms) cubic-bezier(0.2, 0.1, 0.8, 0.9); 106 | width: 30px; 107 | z-index: 4; 108 | } 109 | 110 | .door, 111 | .doorway { 112 | bottom: 4px; 113 | fill: #f4f7ff; 114 | right: 12px; 115 | width: 32px; 116 | } 117 | 118 | .door { 119 | transform: rotateY(20deg); 120 | transform-origin: 100% 50%; 121 | transform-style: preserve-3d; 122 | transition: transform 200ms ease; 123 | z-index: 5; 124 | } 125 | .door path { 126 | fill: #4371f7; 127 | stroke: #4371f7; 128 | stroke-width: 4; 129 | } 130 | 131 | .doorway { 132 | z-index: 3; 133 | } 134 | 135 | .bang { 136 | opacity: 0; 137 | } 138 | 139 | .arm1, .wrist1, .arm2, .wrist2, .leg1, .calf1, .leg2, .calf2 { 140 | transition: transform calc(var(--walking-duration) * 1ms) ease-in-out; 141 | } 142 | 143 | .arm1 { 144 | transform: var(--transform-arm1); 145 | transform-origin: 52% 45%; 146 | } 147 | 148 | .wrist1 { 149 | transform: var(--transform-wrist1); 150 | transform-origin: 59% 55%; 151 | } 152 | 153 | .arm2 { 154 | transform: var(--transform-arm2); 155 | transform-origin: 47% 43%; 156 | } 157 | 158 | .wrist2 { 159 | transform: var(--transform-wrist2); 160 | transform-origin: 35% 47%; 161 | } 162 | 163 | .leg1 { 164 | transform: var(--transform-leg1); 165 | transform-origin: 47% 64.5%; 166 | } 167 | 168 | .calf1 { 169 | transform: var(--transform-calf1); 170 | transform-origin: 55.5% 71.5%; 171 | } 172 | 173 | .leg2 { 174 | transform: var(--transform-leg2); 175 | transform-origin: 43% 63%; 176 | } 177 | 178 | .calf2 { 179 | transform: var(--transform-calf2); 180 | transform-origin: 41.5% 73%; 181 | } 182 | 183 | @keyframes spin { 184 | from { 185 | transform: rotate(0deg) scale(0.94); 186 | } 187 | to { 188 | transform: rotate(359deg) scale(0.94); 189 | } 190 | } 191 | @keyframes shake { 192 | 0% { 193 | transform: rotate(-1deg); 194 | } 195 | 50% { 196 | transform: rotate(2deg); 197 | } 198 | 100% { 199 | transform: rotate(-1deg); 200 | } 201 | } 202 | @keyframes flash { 203 | 0% { 204 | opacity: 0.4; 205 | } 206 | 100% { 207 | opacity: 0; 208 | } 209 | } 210 | /**** Wrapper styles ****************/ 211 | html, 212 | body { 213 | height: 100%; 214 | } 215 | 216 | body { 217 | align-items: center; 218 | background: #f4f7ff; 219 | display: flex; 220 | justify-content: center; 221 | overflow: hidden; 222 | -webkit-font-smoothing: antialiased; 223 | } 224 | body .background { 225 | align-items: center; 226 | display: flex; 227 | height: 100%; 228 | justify-content: center; 229 | width: 50%; 230 | } 231 | body .background--light { 232 | background: #f4f7ff; 233 | } 234 | body .background--dark { 235 | background: #1f2335; 236 | } 237 | body button { 238 | margin: 20px; 239 | } -------------------------------------------------------------------------------- /script.js: -------------------------------------------------------------------------------- 1 | document.querySelectorAll(".logoutButton").forEach((button) => { 2 | button.state = "default"; 3 | 4 | // function to transition a button from one state to the next 5 | let updateButtonState = (button, state) => { 6 | if (logoutButtonStates[state]) { 7 | button.state = state; 8 | for (let key in logoutButtonStates[state]) { 9 | button.style.setProperty(key, logoutButtonStates[state][key]); 10 | } 11 | } 12 | }; 13 | 14 | // mouse hover listeners on button 15 | button.addEventListener("mouseenter", () => { 16 | if (button.state === "default") { 17 | updateButtonState(button, "hover"); 18 | } 19 | }); 20 | button.addEventListener("mouseleave", () => { 21 | if (button.state === "hover") { 22 | updateButtonState(button, "default"); 23 | } 24 | }); 25 | 26 | // click listener on button 27 | button.addEventListener("click", () => { 28 | if (button.state === "default" || button.state === "hover") { 29 | button.classList.add("clicked"); 30 | updateButtonState(button, "walking1"); 31 | setTimeout(() => { 32 | button.classList.add("door-slammed"); 33 | updateButtonState(button, "walking2"); 34 | setTimeout(() => { 35 | button.classList.add("falling"); 36 | updateButtonState(button, "falling1"); 37 | setTimeout(() => { 38 | updateButtonState(button, "falling2"); 39 | setTimeout(() => { 40 | updateButtonState(button, "falling3"); 41 | setTimeout(() => { 42 | button.classList.remove("clicked"); 43 | button.classList.remove("door-slammed"); 44 | button.classList.remove("falling"); 45 | updateButtonState(button, "default"); 46 | }, 1000); 47 | }, logoutButtonStates["falling2"]["--walking-duration"]); 48 | }, logoutButtonStates["falling1"]["--walking-duration"]); 49 | }, logoutButtonStates["walking2"]["--figure-duration"]); 50 | }, logoutButtonStates["walking1"]["--figure-duration"]); 51 | } 52 | }); 53 | }); 54 | 55 | const logoutButtonStates = { 56 | default: { 57 | "--figure-duration": "100", 58 | "--transform-figure": "none", 59 | "--walking-duration": "100", 60 | "--transform-arm1": "none", 61 | "--transform-wrist1": "none", 62 | "--transform-arm2": "none", 63 | "--transform-wrist2": "none", 64 | "--transform-leg1": "none", 65 | "--transform-calf1": "none", 66 | "--transform-leg2": "none", 67 | "--transform-calf2": "none" 68 | }, 69 | hover: { 70 | "--figure-duration": "100", 71 | "--transform-figure": "translateX(1.5px)", 72 | "--walking-duration": "100", 73 | "--transform-arm1": "rotate(-5deg)", 74 | "--transform-wrist1": "rotate(-15deg)", 75 | "--transform-arm2": "rotate(5deg)", 76 | "--transform-wrist2": "rotate(6deg)", 77 | "--transform-leg1": "rotate(-10deg)", 78 | "--transform-calf1": "rotate(5deg)", 79 | "--transform-leg2": "rotate(20deg)", 80 | "--transform-calf2": "rotate(-20deg)" 81 | }, 82 | walking1: { 83 | "--figure-duration": "300", 84 | "--transform-figure": "translateX(11px)", 85 | "--walking-duration": "300", 86 | "--transform-arm1": "translateX(-4px) translateY(-2px) rotate(120deg)", 87 | "--transform-wrist1": "rotate(-5deg)", 88 | "--transform-arm2": "translateX(4px) rotate(-110deg)", 89 | "--transform-wrist2": "rotate(-5deg)", 90 | "--transform-leg1": "translateX(-3px) rotate(80deg)", 91 | "--transform-calf1": "rotate(-30deg)", 92 | "--transform-leg2": "translateX(4px) rotate(-60deg)", 93 | "--transform-calf2": "rotate(20deg)" 94 | }, 95 | walking2: { 96 | "--figure-duration": "400", 97 | "--transform-figure": "translateX(17px)", 98 | "--walking-duration": "300", 99 | "--transform-arm1": "rotate(60deg)", 100 | "--transform-wrist1": "rotate(-15deg)", 101 | "--transform-arm2": "rotate(-45deg)", 102 | "--transform-wrist2": "rotate(6deg)", 103 | "--transform-leg1": "rotate(-5deg)", 104 | "--transform-calf1": "rotate(10deg)", 105 | "--transform-leg2": "rotate(10deg)", 106 | "--transform-calf2": "rotate(-20deg)" 107 | }, 108 | falling1: { 109 | "--figure-duration": "1600", 110 | "--walking-duration": "400", 111 | "--transform-arm1": "rotate(-60deg)", 112 | "--transform-wrist1": "none", 113 | "--transform-arm2": "rotate(30deg)", 114 | "--transform-wrist2": "rotate(120deg)", 115 | "--transform-leg1": "rotate(-30deg)", 116 | "--transform-calf1": "rotate(-20deg)", 117 | "--transform-leg2": "rotate(20deg)" 118 | }, 119 | falling2: { 120 | "--walking-duration": "300", 121 | "--transform-arm1": "rotate(-100deg)", 122 | "--transform-arm2": "rotate(-60deg)", 123 | "--transform-wrist2": "rotate(60deg)", 124 | "--transform-leg1": "rotate(80deg)", 125 | "--transform-calf1": "rotate(20deg)", 126 | "--transform-leg2": "rotate(-60deg)" 127 | }, 128 | falling3: { 129 | "--walking-duration": "500", 130 | "--transform-arm1": "rotate(-30deg)", 131 | "--transform-wrist1": "rotate(40deg)", 132 | "--transform-arm2": "rotate(50deg)", 133 | "--transform-wrist2": "none", 134 | "--transform-leg1": "rotate(-30deg)", 135 | "--transform-leg2": "rotate(20deg)", 136 | "--transform-calf2": "none" 137 | } 138 | }; 139 | --------------------------------------------------------------------------------