├── 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 |
30 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | Falling Man Button
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 | Log Out
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 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 | Log Out
76 |
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 |
--------------------------------------------------------------------------------