├── .gitignore
├── README.md
├── css
├── demo.css
├── demo1.css
├── demo2.css
├── demo3.css
├── demo4.css
├── demo5.css
└── normalize.css
├── favicon.ico
├── index.html
├── index2.html
├── index3.html
├── index4.html
├── index5.html
├── js
├── anime.min.js
├── demo.js
├── demo1.js
├── demo2.js
├── demo3.js
├── demo4.js
└── demo5.js
└── pater
├── jetpack.png
├── jetpack_man.png
└── pater.css
/.gitignore:
--------------------------------------------------------------------------------
1 | *.DS_Store
2 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Organic Shape Morph Ideas
2 |
3 | A small set of ideas for organic shape effects. The demos show some ways to use animated SVG morphs interactively on a website, including a menu hover and a content reveal effect.
4 |
5 | 
6 |
7 | [Article on Codrops](https://tympanus.net/codrops/?p=32314)
8 |
9 | [Demo](http://tympanus.net/Development/ShapeMorphIdeas/)
10 |
11 | This demo is kindly sponsored by: [Jetpack Professional](http://go.hackingui.com/JetpackCodrops19092017), the only WordPress plugin you really need.
12 |
13 | ## Credits
14 |
15 | - [anime.js](http://anime-js.com/) by Julian Garnier
16 | - [Keyboard icon](https://thenounproject.com/term/keyboard/783/) by Paul te Kortschot from the Noun Project
17 | - Patterns from [Hero Patterns](http://www.heropatterns.com/)
18 |
19 | ## License
20 | This resource can be used freely if integrated or build upon in personal or commercial projects such as websites, web apps and web templates intended for sale. It is not allowed to take the resource "as-is" and sell it, redistribute, re-publish it, or sell "pluginized" versions of it. Free plugins built using this resource should have a visible mention and link to the original work. Always consider the licenses of all included libraries, scripts and images used.
21 |
22 | ## Misc
23 |
24 | Follow Codrops: [Twitter](http://www.twitter.com/codrops), [Facebook](http://www.facebook.com/codrops), [Google+](https://plus.google.com/101095823814290637419), [GitHub](https://github.com/codrops), [Pinterest](http://www.pinterest.com/codrops/), [Instagram](https://www.instagram.com/codropsss/)
25 |
26 |
27 | [© Codrops 2017](http://www.codrops.com)
28 |
29 |
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/css/demo.css:
--------------------------------------------------------------------------------
1 | *,
2 | *::after,
3 | *::before {
4 | box-sizing: border-box;
5 | }
6 |
7 | html {
8 | background: #fff;
9 | }
10 |
11 | body {
12 | font-family: 'Roboto', sans-serif;
13 | min-height: 100vh;
14 | color: #57585c;
15 | color: var(--color-text);
16 | background-color: #fff;
17 | background-color: var(--color-background);
18 | -webkit-font-smoothing: antialiased;
19 | -moz-osx-font-smoothing: grayscale;
20 | }
21 |
22 | /* Color schemes */
23 | .demo-1 {
24 | --color-text: #d8d1d1;
25 | --color-background: #fff;
26 | --color-link: #72af3a;
27 | --color-link-hover: #d8d1d1;
28 | --color-info: #72af3a;
29 | }
30 |
31 | .demo-2 {
32 | --color-text: #333;
33 | --color-background: #bee897;
34 | --color-link: #72af3a;
35 | --color-link-hover: #485a36;
36 | --color-info: #fff;
37 | }
38 |
39 | .demo-3 {
40 | --color-text: #fff;
41 | --color-background: #193ccf;
42 | --color-link: #fff;
43 | --color-link-hover: #000;
44 | --color-info: #fff473;
45 | }
46 |
47 | .demo-4 {
48 | --color-text: #81838c;
49 | --color-background: #272927;
50 | --color-link: #96e23e;
51 | --color-link-hover: #fff;
52 | --color-info: #ea7836;
53 | }
54 |
55 | .demo-5 {
56 | --color-text: #fff;
57 | --color-background: #2b54ee;
58 | --color-link: #fff;
59 | --color-link-hover: #f7fb40;
60 | --color-info: #f7fb40;
61 | }
62 |
63 | /* Fade effect */
64 | .js body {
65 | opacity: 0;
66 | transition: opacity 0.3s;
67 |
68 | }
69 |
70 | .js body.render {
71 | opacity: 1;
72 | }
73 |
74 | a {
75 | text-decoration: none;
76 | color: #5d93d8;
77 | color: var(--color-link);
78 | outline: none;
79 | }
80 |
81 | a:hover,
82 | a:focus {
83 | color: #423c2b;
84 | color: var(--color-link-hover);
85 | outline: none;
86 | }
87 |
88 | .hidden {
89 | position: absolute;
90 | overflow: hidden;
91 | width: 0;
92 | height: 0;
93 | pointer-events: none;
94 | }
95 |
96 | .message {
97 | background: var(--color-text);
98 | color: var(--color-background);
99 | text-align: center;
100 | padding: 1em;
101 | display: none;
102 | position: relative;
103 | z-index: 100;
104 | }
105 |
106 | /* Icons */
107 | .icon {
108 | display: block;
109 | width: 1.5em;
110 | height: 1.5em;
111 | margin: 0 auto;
112 | fill: currentColor;
113 | }
114 |
115 | .icon--keyboard {
116 | display: none;
117 | }
118 |
119 | main {
120 | position: relative;
121 | width: 100%;
122 | }
123 |
124 | .content {
125 | position: relative;
126 | display: flex;
127 | justify-content: center;
128 | align-items: center;
129 | min-height: 100vh;
130 | margin: 0 auto;
131 | }
132 |
133 | .content--fixed {
134 | position: fixed;
135 | z-index: 10000;
136 | top: 0;
137 | left: 0;
138 | display: grid;
139 | align-content: space-between;
140 | width: 100%;
141 | max-width: none;
142 | height: 100vh;
143 | padding: 1.5em;
144 | pointer-events: none;
145 | grid-template-columns: 50% 50%;
146 | grid-template-rows: auto auto 4em;
147 | grid-template-areas: 'header ...'
148 | '... ...'
149 | 'github demos';
150 | }
151 |
152 | .content--fixed a {
153 | pointer-events: auto;
154 | }
155 |
156 | /* Header */
157 | .codrops-header {
158 | position: relative;
159 | z-index: 100;
160 | display: flex;
161 | flex-direction: row;
162 | align-items: flex-start;
163 | align-items: center;
164 | align-self: start;
165 | grid-area: header;
166 | justify-self: start;
167 | }
168 |
169 | .codrops-header__title {
170 | font-size: 1em;
171 | font-weight: bold;
172 | margin: 0;
173 | padding: 0.75em 0;
174 | }
175 |
176 | .info {
177 | margin: 0 0 0 1.25em;
178 | font-style: italic;
179 | color: var(--color-info);
180 | font-weight: bold;
181 | }
182 |
183 | .github {
184 | display: block;
185 | align-self: end;
186 | grid-area: github;
187 | justify-self: start;
188 | }
189 |
190 | .demos {
191 | position: relative;
192 | display: block;
193 | align-self: end;
194 | text-align: center;
195 | grid-area: demos;
196 | }
197 |
198 | .demo {
199 | margin: 0 0.15em;
200 | }
201 |
202 | .demo:hover,
203 | .demo:focus {
204 | opacity: 0.5;
205 | }
206 |
207 | .demo span {
208 | white-space: nowrap;
209 | text-transform: lowercase;
210 | pointer-events: none;
211 | }
212 |
213 | .demo span::before {
214 | content: '#';
215 | }
216 |
217 | a.demo--current {
218 | pointer-events: none;
219 | }
220 |
221 | /* Top Navigation Style */
222 | .codrops-links {
223 | position: relative;
224 | display: flex;
225 | justify-content: center;
226 | margin: 0 1em 0 0;
227 | text-align: center;
228 | white-space: nowrap;
229 | }
230 |
231 | .codrops-icon {
232 | display: inline-block;
233 | margin: 0.15em;
234 | padding: 0.25em;
235 | }
236 |
237 | .scene {
238 | position: fixed;
239 | top: 0;
240 | left: 0;
241 | width: 100%;
242 | height: 100vh;
243 | pointer-events: none;
244 | z-index: 1;
245 | }
246 |
247 | @media screen and (min-width: 55em) {
248 | .icon--keyboard {
249 | position: absolute;
250 | right: 0.55em;
251 | bottom: -30%;
252 | display: block;
253 | width: 54px;
254 | height: 46px;
255 | fill: var(--color-link);
256 | }
257 | .demos {
258 | display: flex;
259 | padding-right: 80px;
260 | justify-self: end;
261 | }
262 | .demo {
263 | display: block;
264 | width: 17px;
265 | height: 17px;
266 | margin: 0 4px;
267 | border-radius: 50%;
268 | background: var(--color-link);
269 | }
270 | a.demo--current {
271 | background: var(--color-link-hover);
272 | }
273 | .demo span {
274 | position: absolute;
275 | line-height: 1;
276 | right: 100%;
277 | display: none;
278 | margin: 0 1em 0 0;
279 | }
280 | .demo--current span {
281 | display: block;
282 | }
283 | }
284 |
285 | @media screen and (max-width: 55em) {
286 | html,
287 | body {
288 | overflow-x: hidden;
289 | width: 100vw;
290 | height: 100%;
291 | }
292 | .message {
293 | display: block;
294 | }
295 | .content {
296 | height: auto;
297 | min-height: 0;
298 | padding-bottom: 10em;
299 | flex-direction: column;
300 | }
301 | .content--fixed {
302 | position: relative;
303 | z-index: 1000;
304 | display: block;
305 | padding: 0.85em;
306 | }
307 | .codrops-header {
308 | flex-direction: column;
309 | align-items: center;
310 | }
311 | .codrops-header__title {
312 | font-weight: bold;
313 | padding-bottom: 0.25em;
314 | text-align: center;
315 | }
316 | .github {
317 | display: block;
318 | margin: 1em auto;
319 | }
320 | .codrops-links {
321 | margin: 0;
322 | }
323 | }
324 |
--------------------------------------------------------------------------------
/css/demo1.css:
--------------------------------------------------------------------------------
1 | body.scene-hover {
2 | background-color: #000;
3 | }
4 |
5 | .scene {
6 | display: block;
7 | width: 50vh;
8 | height: 50vh;
9 | position: relative;
10 | pointer-events: auto;
11 | transition: transform 0.3s;
12 | }
13 |
14 | .scene-hover .scene {
15 | transform: scale3d(1.1,1.1,1);
16 | }
17 |
18 | .scene__bg {
19 | fill: #e7d2cd;
20 | }
21 |
22 | .scene__bgdots {
23 | fill: #c9bfbd;
24 | stroke: #8b8682;
25 | stroke-width: 1px;
26 | }
27 |
28 | .scene__overlay {
29 | fill: var(--color-link);
30 | }
31 |
32 | .scene-hover .scene__overlay {
33 | opacity: 0;
34 | }
35 |
36 | .scene__bacteria:first-of-type,
37 | .scene__bacteria:nth-of-type(2),
38 | .scene__bacteria:nth-of-type(3) {
39 | fill: #ac9893;
40 | }
41 |
42 | .scene__bacteria:nth-of-type(4),
43 | .scene__bacteria:nth-of-type(5) {
44 | fill: #625857;
45 | }
46 |
47 | .scene__bacteria:nth-of-type(6),
48 | .scene__bacteria:nth-of-type(7),
49 | .scene__bacteria:nth-of-type(8) {
50 | fill: #fff;
51 | stroke: #616161;
52 | }
53 |
54 | .scene__microscope {
55 | fill: #fff;
56 | pointer-events: none;
57 | }
58 |
59 | .scene-hover .scene__microscope {
60 | opacity: 0;
61 | }
62 |
63 | .intro {
64 | margin: 0 0 0 3em;
65 | }
66 |
67 | .intro__title {
68 | margin: 0;
69 | color: #181616;
70 | font-size: 1.85em;
71 | }
72 |
73 | .scene-hover .intro__title {
74 | color: #fff;
75 | }
76 |
77 | .intro__title-sub {
78 | display: block;
79 | font-weight: 400;
80 | font-size: 0.75em;
81 | }
82 |
83 | .intro__nav {
84 | margin: 1em 0 0 0;
85 | }
86 |
87 | .intro__nav-item:not(:last-child) {
88 | margin: 0 0.5em 0 0;
89 | }
90 |
91 | .intro__nav-item:not(:last-child)::after {
92 | content: '\25CF';
93 | margin: 0 0 0 0.5em;
94 | }
95 |
96 | .intro__nav-item:not(:last-child):hover::after {
97 | color: var(--color-link);
98 | }
99 |
100 | @media screen and (max-width: 50em) {
101 | body {
102 | background-color: #000;
103 | }
104 | .scene {
105 | width: 200px;
106 | height: 200px;
107 | margin: 2em 0 0;
108 | }
109 | .scene__overlay,
110 | .scene__microscope {
111 | opacity: 0;
112 | }
113 | .intro {
114 | text-align: center;
115 | margin: 1em 0 0;
116 | }
117 | .intro__title {
118 | color: #fff;
119 | font-size: 1.25em;
120 | }
121 | .info {
122 | display: none;
123 | }
124 | .intro__nav-item {
125 | display: block;
126 | margin: 0.5em 0 0 !important;
127 | }
128 | .intro__nav-item:not(:last-child)::after {
129 | display: none;
130 | }
131 | }
--------------------------------------------------------------------------------
/css/demo2.css:
--------------------------------------------------------------------------------
1 | .scene path {
2 | fill: #b9e194;
3 | }
4 |
5 | .menu {
6 | width: 100%;
7 | height: 100vh;
8 | display: flex;
9 | flex-direction: column;
10 | align-items: center;
11 | justify-content: center;
12 | position: relative;
13 | z-index: 900;
14 | padding-bottom: 10vh;
15 | color: #72ae3a;
16 | }
17 |
18 | .menu__title {
19 | font-weight: normal;
20 | text-transform: uppercase;
21 | letter-spacing: 0.325em;
22 | font-size: 1em;
23 | margin: 0 0 0.35em;
24 | padding: 0 0.25em 0.25em;
25 | border-bottom: 1px solid;
26 | }
27 |
28 | .menu__subtitle {
29 | text-transform: uppercase;
30 | font-size: 0.75em;
31 | letter-spacing: 0.225em;
32 | margin: 0 0 10vh;
33 | font-weight: normal;
34 | }
35 |
36 | .menu__item {
37 | font-family: 'Arapey', serif;
38 | color: #333;
39 | font-size: 2.5em;
40 | padding: 0.25em 0;
41 | }
42 |
43 | .menu__item:hover,
44 | .menu__item:focus {
45 | color: var(--color-link);
46 | }
--------------------------------------------------------------------------------
/css/demo3.css:
--------------------------------------------------------------------------------
1 | .scene {
2 | background: #282886;
3 | }
4 |
5 | .scene path:first-child {
6 | fill: #4f4fea;
7 | }
8 |
9 | .scene path:nth-child(2) {
10 | fill: #0c27cf;
11 | }
12 |
13 | .scene path:nth-child(3) {
14 | fill: #13269c;
15 | }
16 |
17 | .scene path:nth-child(4) {
18 | fill: #242468;
19 | }
20 |
21 | .scene path:nth-child(5) {
22 | fill: #2648e6;
23 | }
24 |
25 | .scene path:nth-child(6) {
26 | fill: #2c31b0;
27 | }
28 |
29 | .scene path:nth-child(7) {
30 | fill: #262689;
31 | }
32 |
33 | .title {
34 | color: #fff;
35 | font-size: 6vw;
36 | font-weight: 400;
37 | z-index: 1000;
38 | font-family: "Arapey", serif;
39 | pointer-events: none;
40 | }
--------------------------------------------------------------------------------
/css/demo4.css:
--------------------------------------------------------------------------------
1 | .title {
2 | color: #fff;
3 | font-size: 6vw;
4 | font-weight: 400;
5 | z-index: 1000;
6 | font-family: "Arapey", serif;
7 | pointer-events: none;
8 | }
9 |
10 | .scene path {
11 | fill: #171817;
12 | }
--------------------------------------------------------------------------------
/css/demo5.css:
--------------------------------------------------------------------------------
1 | .scene {
2 | display: block;
3 | pointer-events: auto;
4 | }
5 |
6 | .scene a {
7 | cursor: pointer;
8 | }
9 |
10 | .content--reveal {
11 | position: absolute;
12 | z-index: 1001;
13 | top: 0;
14 | left: 0;
15 | width: 100%;
16 | height: 100vh;
17 | pointer-events: none;
18 | }
19 |
20 | .content__close {
21 | position: absolute;
22 | top: 0;
23 | right: 0;
24 | border: 0;
25 | padding: 0;
26 | margin: 2em;
27 | background: none;
28 | color: var(--color-link);
29 | opacity: 0;
30 | transition: opacity 0.3s;
31 | }
32 |
33 | .content__close:hover,
34 | .content__close:focus {
35 | outline: none;
36 | color: var(--color-link-hover);
37 | }
38 |
39 | .content__inner {
40 | position: absolute;
41 | left: 0;
42 | top: 0;
43 | width: 100%;
44 | height: 100%;
45 | display: grid;
46 | grid-template-columns: 15% 15% 15% 15%;
47 | grid-template-rows: 25% 25%;
48 | justify-content: center;
49 | align-items: center;
50 | align-content: center;
51 | justify-items: center;
52 | -webkit-touch-callout: none;
53 | -webkit-user-select: none;
54 | -khtml-user-select: none;
55 | -moz-user-select: none;
56 | -ms-user-select: none;
57 | user-select: none;
58 | }
59 |
60 | .js .content__inner {
61 | opacity: 0;
62 | transition: opacity 0.3s;
63 | }
64 |
65 | .js .content__inner--visible {
66 | opacity: 1;
67 | pointer-events: auto;
68 | }
69 |
70 | .content__inner--visible ~ .content__close {
71 | opacity: 1;
72 | pointer-events: auto;
73 | }
74 |
75 | .content__title {
76 | font-size: 12vw;
77 | margin: 0;
78 | position: relative;
79 | z-index: 10;
80 | grid-area: 1 / 1 / 2 / 5;
81 | opacity: 0;
82 | transform: translate3d(-30px,0,0);
83 | transition: transform 1s, opacity 0.6s;
84 | transition-timing-function: cubic-bezier(0.2,1,0.3,1);
85 | }
86 |
87 | .content__inner--visible .content__title {
88 | opacity: 1;
89 | transform: translate3d(0,0,0);
90 | }
91 |
92 | .content__img--1 {
93 | grid-area: 1 / 3 / 2 / 5;
94 | opacity: 0;
95 | transform: translate3d(30px,-30px,0);
96 | transition: transform 1.5s, opacity 0.6s;
97 | transition-timing-function: cubic-bezier(0.2,1,0.3,1);
98 | }
99 |
100 | .content__img--2 {
101 | grid-area: 2 / 1 / 3 / 3;
102 | opacity: 0;
103 | transform: translate3d(-30px,30px,0);
104 | transition: transform 1.5s, opacity 0.6s;
105 | transition-timing-function: cubic-bezier(0.2,1,0.3,1);
106 | }
107 |
108 | .content__inner--visible .content__img--1,
109 | .content__inner--visible .content__img--2 {
110 | opacity: 1;
111 | transform: translate3d(0,0,0);
112 | }
113 |
114 | .content__subtitle {
115 | grid-area: 2 / 2 / 3 / 4;
116 | font-size: 2em;
117 | transform: translate3d(10px,0,0);
118 | transition: transform 0.6s, opacity 0.6s;
119 | }
120 |
121 | .content__inner--visible .content__subtitle {
122 | opacity: 1;
123 | transform: translate3d(0,0,0);
124 | }
125 |
126 | .pattern-color-1 {
127 | fill: #191139;
128 | }
129 |
130 | .pattern-color-2 {
131 | fill: #212499;
132 | }
133 |
134 | .pattern-color-3 {
135 | fill: #6056f2;
136 | }
137 |
138 | .pattern-color-4 {
139 | fill: #90a1f4;
140 | }
141 |
142 | .pattern-color-5 {
143 | fill: #39486c;
144 | }
145 |
146 | .pattern-color-6 {
147 | fill: #4b3b86;
148 | }
149 |
150 | .rect-color-hero {
151 | fill: #33256d;
152 | }
153 |
154 | .rect-color-2 {
155 | fill: #3f43d9;
156 | }
157 |
158 | .rect-color-3 {
159 | fill: #8178ff;
160 | }
161 |
162 | .rect-color-4 {
163 | fill: #adbcf4;
164 | }
165 |
166 | .rect-color-5 {
167 | fill: #191e2d;
168 | }
169 |
170 | .rect-color-6 {
171 | fill: #7461c7;
172 | }
173 |
174 | .content__img--1 rect {
175 | fill: #6554b3;
176 | }
177 |
178 | .content__img--1 circle {
179 | fill: none;
180 | stroke: #1c133f;
181 | }
182 |
183 | .content__img--2 rect {
184 | fill: #6554b3;
185 | }
186 |
187 | .content__img--2 polygon {
188 | fill: none;
189 | stroke: #1c133f;
190 | }
191 |
192 | .label {
193 | font-size: 3em;
194 | fill: #f7fb40;
195 | font-weight: 700;
196 | transition: fill 0.2s;
197 | }
198 |
199 | .label:hover {
200 | fill: #fff;
201 | }
202 |
203 | .label tspan:first-child {
204 | font-size: 0.75em;
205 | border-bottom: 2px solid #ddd;
206 | }
207 |
208 | @media screen and (max-width: 55em) {
209 | main {
210 | height: 100vh;
211 | }
212 | .scene, .content__inner, .content--reveal {
213 | height: calc(100vw * 0.55);
214 | top: auto;
215 | bottom: 0;
216 | }
217 | .content__inner {
218 | grid-template-columns: 25% 25% 25% 25%;
219 | }
220 | .content__title {
221 | font-size: 2em;
222 | }
223 | .content__subtitle {
224 | font-size: 1em;
225 | }
226 | .content__img {
227 | width: 100px;
228 | height: 100px;
229 | }
230 | }
--------------------------------------------------------------------------------
/css/normalize.css:
--------------------------------------------------------------------------------
1 | article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{display:block;}audio,canvas,video{display:inline-block;}audio:not([controls]){display:none;height:0;}[hidden]{display:none;}html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%;}body{margin:0;}a:focus{outline:thin dotted;}a:active,a:hover{outline:0;}h1{font-size:2em;margin:0.67em 0;}abbr[title]{border-bottom:1px dotted;}b,strong{font-weight:bold;}dfn{font-style:italic;}hr{-moz-box-sizing:content-box;box-sizing:content-box;height:0;}mark{background:#ff0;color:#000;}code,kbd,pre,samp{font-family:monospace,serif;font-size:1em;}pre{white-space:pre-wrap;}q{quotes:"\201C" "\201D" "\2018" "\2019";}small{font-size:80%;}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline;}sup{top:-0.5em;}sub{bottom:-0.25em;}img{border:0;}svg:not(:root){overflow:hidden;}figure{margin:0;}fieldset{border:1px solid #c0c0c0;margin:0 2px;padding:0.35em 0.625em 0.75em;}legend{border:0;padding:0;}button,input,select,textarea{font-family:inherit;font-size:100%;margin:0;}button,input{line-height:normal;}button,select{text-transform:none;}button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer;}button[disabled],html input[disabled]{cursor:default;}input[type="checkbox"],input[type="radio"]{box-sizing:border-box;padding:0;}input[type="search"]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box;}input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none;}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0;}textarea{overflow:auto;vertical-align:top;}table{border-collapse:collapse;border-spacing:0;}
--------------------------------------------------------------------------------
/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codrops/ShapeMorphIdeas/eeb7a4f4d7cf580bf8f0b8fb921f1af10f5ffce7/favicon.ico
--------------------------------------------------------------------------------
/index2.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Organic Shape Morph Ideas | Demo 2 | Codrops
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
41 |
42 | Please view this demo on a desktop.
43 |
68 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
--------------------------------------------------------------------------------
/index3.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Organic Shape Morph Ideas | Demo 3 | Codrops
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
41 |
42 | Please view this demo on a desktop.
43 |
68 |
69 |
78 |
Fluid Life
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
--------------------------------------------------------------------------------
/index4.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Organic Shape Morph Ideas | Demo 4 | Codrops
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
41 |
42 | Please view this demo on a desktop.
43 |
68 |
69 |
72 |
Botanic Wisdom
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
--------------------------------------------------------------------------------
/index5.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Organic Shape Morph Ideas | Demo 5 | Codrops
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
44 |
45 | Please view this demo on a desktop.
46 |
47 |
55 |
56 |
64 |
65 |
66 |
150 |
151 |
152 |
153 |
Hero.
154 |
158 |
162 |
An unkissed loaf's hydrogen comes with it.
163 |
164 |
165 |
Qualm.
166 |
170 |
174 |
The pinks could be said to resemble freeborn squirrels.
175 |
176 |
177 |
Waxy.
178 |
182 |
186 |
A surgeon is the glue of a purchase.
187 |
188 |
189 |
Love.
190 |
194 |
198 |
Authors often misinterpret the korean as a heavies gemini.
199 |
200 |
201 |
Woods.
202 |
206 |
210 |
Some servo tips are thought of simply as russias.
211 |
212 |
213 |
Beach.
214 |
218 |
222 |
To be more specific, the angora is a quilt.
223 |
224 |
225 |
226 |
227 |
228 |
229 |
230 |
231 |
232 |
--------------------------------------------------------------------------------
/js/anime.min.js:
--------------------------------------------------------------------------------
1 | /*
2 | 2017 Julian Garnier
3 | Released under the MIT license
4 | */
5 | var $jscomp$this=this;
6 | (function(u,r){"function"===typeof define&&define.amd?define([],r):"object"===typeof module&&module.exports?module.exports=r():u.anime=r()})(this,function(){function u(a){if(!g.col(a))try{return document.querySelectorAll(a)}catch(b){}}function r(a){return a.reduce(function(a,c){return a.concat(g.arr(c)?r(c):c)},[])}function v(a){if(g.arr(a))return a;g.str(a)&&(a=u(a)||a);return a instanceof NodeList||a instanceof HTMLCollection?[].slice.call(a):[a]}function E(a,b){return a.some(function(a){return a===b})}
7 | function z(a){var b={},c;for(c in a)b[c]=a[c];return b}function F(a,b){var c=z(a),d;for(d in a)c[d]=b.hasOwnProperty(d)?b[d]:a[d];return c}function A(a,b){var c=z(a),d;for(d in b)c[d]=g.und(a[d])?b[d]:a[d];return c}function R(a){a=a.replace(/^#?([a-f\d])([a-f\d])([a-f\d])$/i,function(a,b,c,h){return b+b+c+c+h+h});var b=/^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(a);a=parseInt(b[1],16);var c=parseInt(b[2],16),b=parseInt(b[3],16);return"rgb("+a+","+c+","+b+")"}function S(a){function b(a,b,c){0>
8 | c&&(c+=1);1c?b:c<2/3?a+(b-a)*(2/3-c)*6:a}var c=/hsl\((\d+),\s*([\d.]+)%,\s*([\d.]+)%\)/g.exec(a);a=parseInt(c[1])/360;var d=parseInt(c[2])/100,c=parseInt(c[3])/100;if(0==d)d=c=a=c;else{var e=.5>c?c*(1+d):c+d-c*d,k=2*c-e,d=b(k,e,a+1/3),c=b(k,e,a);a=b(k,e,a-1/3)}return"rgb("+255*d+","+255*c+","+255*a+")"}function w(a){if(a=/([\+\-]?[0-9#\.]+)(%|px|pt|em|rem|in|cm|mm|ex|pc|vw|vh|deg|rad|turn)?/.exec(a))return a[2]}function T(a){if(-1k&&q=m&&(f.began=!0,e("begin")),e("run")):(q<=k&&0!==O&&(d(0),p&&g()),q>=h&&O!==h&&(d(h),p||g()));a>=h&&(f.remaining?(t=n,"alternate"===f.direction&&(f.reversed=!f.reversed)):(f.pause(),P(),Q=b(),f.completed||(f.completed=!0,e("complete"))),l=0);if(f.children)for(a=f.children,h=0;h=b&&
22 | 0<=d&&1>=d){var g=new Float32Array(11);if(b!==c||d!==e)for(var h=0;11>h;++h)g[h]=a(.1*h,b,d);return function(h){if(b===c&&d===e)return h;if(0===h)return 0;if(1===h)return 1;for(var k=0,l=1;10!==l&&g[l]<=h;++l)k+=.1;--l;var l=k+(h-g[l])/(g[l+1]-g[l])*.1,n=3*(1-3*d+3*b)*l*l+2*(3*d-6*b)*l+3*b;if(.001<=n){for(k=0;4>k;++k){n=3*(1-3*d+3*b)*l*l+2*(3*d-6*b)*l+3*b;if(0===n)break;var m=a(l,b,d)-h,l=l-m/n}h=l}else if(0===n)h=l;else{var l=k,k=k+.1,f=0;do m=l+(k-l)/2,n=a(m,b,d)-h,0++f);h=m}return a(h,c,e)}}}}(),M=function(){function a(a,b){return 0===a||1===a?a:-Math.pow(2,10*(a-1))*Math.sin(2*(a-1-b/(2*Math.PI)*Math.asin(1))*Math.PI/b)}var b="Quad Cubic Quart Quint Sine Expo Circ Back Elastic".split(" "),c={In:[[.55,.085,.68,.53],[.55,.055,.675,.19],[.895,.03,.685,.22],[.755,.05,.855,.06],[.47,0,.745,.715],[.95,.05,.795,.035],[.6,.04,.98,.335],[.6,-.28,.735,.045],a],Out:[[.25,.46,.45,.94],[.215,.61,.355,1],[.165,.84,.44,1],[.23,1,.32,1],[.39,.575,.565,1],[.19,1,.22,1],
24 | [.075,.82,.165,1],[.175,.885,.32,1.275],function(b,c){return 1-a(1-b,c)}],InOut:[[.455,.03,.515,.955],[.645,.045,.355,1],[.77,0,.175,1],[.86,0,.07,1],[.445,.05,.55,.95],[1,0,0,1],[.785,.135,.15,.86],[.68,-.55,.265,1.55],function(b,c){return.5>b?a(2*b,c)/2:1-a(-2*b+2,c)/2}]},d={linear:x(.25,.25,.75,.75)},e={},k;for(k in c)e.type=k,c[e.type].forEach(function(a){return function(c,e){d["ease"+a.type+b[e]]=g.fnc(c)?c:x.apply($jscomp$this,c)}}(e)),e={type:e.type};return d}(),ha={css:function(a,b,c){return a.style[b]=
25 | c},attribute:function(a,b,c){return a.setAttribute(b,c)},object:function(a,b,c){return a[b]=c},transform:function(a,b,c,d,e){d[e]||(d[e]=[]);d[e].push(b+"("+c+")")}},p=[],y=0,ia=function(){function a(){y=requestAnimationFrame(b)}function b(b){var c=p.length;if(c){for(var e=0;ed&&(b.duration=a.duration);b.children.push(a)});return b};return b};m.random=function(a,b){return Math.floor(Math.random()*(b-a+1))+a};return m});
--------------------------------------------------------------------------------
/js/demo.js:
--------------------------------------------------------------------------------
1 | /**
2 | * demo.js
3 | * http://www.codrops.com
4 | *
5 | * Licensed under the MIT license.
6 | * http://www.opensource.org/licenses/mit-license.php
7 | *
8 | * Copyright 2017, Codrops
9 | * http://www.codrops.com
10 | */
11 | {
12 | setTimeout(() => document.body.classList.add('render'), 60);
13 | const navdemos = Array.from(document.querySelectorAll('nav.demos > .demo'));
14 | const total = navdemos.length;
15 | const current = navdemos.findIndex(el => el.classList.contains('demo--current'));
16 | const navigate = (linkEl) => {
17 | document.body.classList.remove('render');
18 | document.body.addEventListener('transitionend', () => window.location = linkEl.href);
19 | };
20 | navdemos.forEach(link => link.addEventListener('click', (ev) => {
21 | ev.preventDefault();
22 | navigate(ev.target);
23 | }));
24 | document.addEventListener('keydown', (ev) => {
25 | const keyCode = ev.keyCode || ev.which;
26 | let linkEl;
27 | if ( keyCode === 37 ) {
28 | linkEl = current > 0 ? navdemos[current-1] : navdemos[total-1];
29 | }
30 | else if ( keyCode === 39 ) {
31 | linkEl = current < total-1 ? navdemos[current+1] : navdemos[0];
32 | }
33 | else {
34 | return false;
35 | }
36 | navigate(linkEl);
37 | });
38 | }
39 |
--------------------------------------------------------------------------------
/js/demo1.js:
--------------------------------------------------------------------------------
1 | /**
2 | * demo1.js
3 | * http://www.codrops.com
4 | *
5 | * Licensed under the MIT license.
6 | * http://www.opensource.org/licenses/mit-license.php
7 | *
8 | * Copyright 2017, Codrops
9 | * http://www.codrops.com
10 | */
11 | {
12 | const getRandomFloat = (min,max) => {
13 | return Math.random() * (max - min) + min;
14 | };
15 |
16 | // From https://davidwalsh.name/javascript-debounce-function.
17 | const debounce = (func, wait, immediate) => {
18 | let timeout;
19 | return function() {
20 | let context = this;
21 | var args = arguments;
22 | let later = () => {
23 | timeout = null;
24 | if (!immediate) func.apply(context, args);
25 | };
26 | let callNow = immediate && !timeout;
27 | clearTimeout(timeout);
28 | timeout = setTimeout(later, wait);
29 | if (callNow) func.apply(context, args);
30 | };
31 | };
32 |
33 | const DOM = {};
34 | DOM.scene = document.querySelector('svg.scene');
35 | DOM.gElems = Array.from(DOM.scene.querySelectorAll('g > g'));
36 |
37 | class Bacteria {
38 | constructor(el) {
39 | this.DOM = {};
40 | this.DOM.el = el;
41 | this.DOM.path = this.DOM.el.querySelector('path');
42 | this.CONFIG = {
43 | // Random value from 5 to 30px.
44 | motionIncrement: [5,20]
45 | };
46 | this.init();
47 | this.initEvents();
48 | }
49 | init() {
50 | // Measures.
51 | this.getSizes();
52 |
53 | // Different shape/paths.
54 | this.paths = this.DOM.path.getAttribute('pathdata:id').split(';');
55 |
56 | // Current values for the transform.
57 | this.transform = {tx: 0, ty: 0, rz: 0, sx:0, sy:0};
58 | // Current step.
59 | this.step = 0;
60 |
61 | // The element will alternate its shape (initial path plus all the other ones defined in pathdata:id).
62 | this.paths.splice(this.paths.length, 0, this.DOM.path.getAttribute('d'));
63 | // The total number of possible shapes/paths.
64 | this.totalPaths = this.paths.length;
65 |
66 | // Set Origin.
67 | this.DOM.el.style.transformOrigin = '50% 50%';
68 |
69 | // Start the shape animatation (path morphing).
70 | this.changeShape();
71 | // Start the transforms animation.
72 | this.move();
73 | }
74 | initEvents() {
75 | window.addEventListener('resize', debounce(() => this.getSizes(), 10));
76 | }
77 | getSizes() {
78 | this.domrect = {
79 | scene: DOM.scene.getBoundingClientRect(),
80 | el: this.DOM.el.getBoundingClientRect()
81 | };
82 | }
83 | changeShape() {
84 | anime.remove(this.DOM.path);
85 | anime({
86 | targets: this.DOM.path,
87 | duration: anime.random(2000,8000),
88 | easing: 'linear',
89 | d: this.paths,
90 | loop: true
91 | });
92 | }
93 | getTransform(prop) {
94 | let val;
95 | if ( prop === 'rz' ) {
96 | val = anime.random(-30,30);
97 | }
98 | else if (prop === 'sx' || prop === 'sy') {
99 | val = getRandomFloat(0.8,1.2);
100 | }
101 | else {
102 | const inc = anime.random(this.CONFIG.motionIncrement[0],this.CONFIG.motionIncrement[1]) * (anime.random(0,1) ? -1 : 1);
103 |
104 | const vSize = prop === 'tx' ? 'width' : 'height';
105 | const position = prop === 'tx' ? 'left' : 'top';
106 |
107 | val = this.transform[prop] + inc;
108 | // Out of viewport.
109 | if ( val > 0 && val > this.domrect.scene[vSize] - this.domrect.el[position] || val < 0 && Math.abs(val) > this.domrect.el[position] + this.domrect.el[vSize] ) {
110 | val -= 2*inc;
111 | }
112 | }
113 |
114 | return val;
115 | }
116 | move() {
117 | this.step++;
118 | this.transform.tx = this.getTransform('tx');
119 | this.transform.ty = this.getTransform('ty');
120 | this.transform.rz = this.getTransform('rz');
121 | this.transform.sx = this.getTransform('sx');
122 | this.transform.sy = this.getTransform('sy');
123 |
124 | let pos;
125 | if ( this.step % this.totalPaths === 0 ) {
126 | this.step = pos = 0;
127 | }
128 | else {
129 | pos = this.totalPaths - (this.totalPaths - this.step);
130 | }
131 |
132 | const delay = anime.random(0,1) ? 0 : anime.random(0, 1000);
133 | const duration = anime.random(4000,8000);
134 | const easing = 'easeInOutQuad';
135 | anime.remove(this.DOM.el);
136 | anime({
137 | targets: this.DOM.el,
138 | duration: duration,
139 | easing: easing,
140 | delay: delay,
141 | translateX: this.transform.tx,
142 | translateY: this.transform.ty,
143 | scaleX: this.transform.sx,
144 | scaleY: this.transform.sy,
145 | rotate: this.transform.rz,
146 | complete: () => this.move()
147 | });
148 | }
149 | };
150 |
151 | DOM.gElems.forEach(gElem => new Bacteria(gElem));
152 |
153 | DOM.scene.querySelector('g').addEventListener('mouseenter', () => document.body.classList.add('scene-hover'));
154 | DOM.scene.querySelector('g').addEventListener('mouseleave', () => document.body.classList.remove('scene-hover'));
155 | };
--------------------------------------------------------------------------------
/js/demo2.js:
--------------------------------------------------------------------------------
1 | /**
2 | * demo2.js
3 | * http://www.codrops.com
4 | *
5 | * Licensed under the MIT license.
6 | * http://www.opensource.org/licenses/mit-license.php
7 | *
8 | * Copyright 2017, Codrops
9 | * http://www.codrops.com
10 | */
11 | {
12 | class Menu {
13 | constructor(el) {
14 | this.DOM = {};
15 | this.DOM.el = el;
16 | this.DOM.items = Array.from(this.DOM.el.querySelectorAll('.menu__item'));
17 | this.DOM.bgshape = document.querySelector('svg.scene > path');
18 | this.initialShape = this.DOM.bgshape.getAttribute('d');
19 | this.initEvents();
20 | }
21 | changeShape(el) {
22 | anime.remove(this.DOM.bgshape);
23 | anime({
24 | targets: this.DOM.bgshape,
25 | duration: 3000,
26 | easing: 'easeOutQuad',
27 | d: el.dataset.shape
28 | });
29 | }
30 | resetShape() {
31 | anime.remove(this.DOM.bgshape);
32 | anime({
33 | targets: this.DOM.bgshape,
34 | duration: 4000,
35 | easing: 'easeOutQuint',
36 | d: this.initialShape
37 | });
38 | }
39 | initEvents() {
40 | this.mouseenterFn = (ev) => this.mouseTimeout = setTimeout(() => {
41 | this.isActive = true;
42 | this.changeShape(ev.target);
43 | clearTimeout(this.resetTimeout);
44 | }, 50);
45 |
46 | this.mouseleaveFn = () => {
47 | clearTimeout(this.mouseTimeout);
48 | if( !this.isActive ) return;
49 | this.isActive = false;
50 |
51 | this.resetTimeout = setTimeout(() => {
52 | this.resetShape();
53 | }, 300);
54 | };
55 |
56 | this.DOM.items.forEach((item) => {
57 | item.addEventListener('mouseenter', this.mouseenterFn);
58 | item.addEventListener('mouseleave', this.mouseleaveFn);
59 | item.addEventListener('touchstart', this.mouseenterFn);
60 | item.addEventListener('touchend', this.mouseleaveFn);
61 | });
62 | }
63 | };
64 |
65 | new Menu(document.querySelector('nav.menu'));
66 | };
--------------------------------------------------------------------------------
/js/demo3.js:
--------------------------------------------------------------------------------
1 | /**
2 | * demo3.js
3 | * http://www.codrops.com
4 | *
5 | * Licensed under the MIT license.
6 | * http://www.opensource.org/licenses/mit-license.php
7 | *
8 | * Copyright 2017, Codrops
9 | * http://www.codrops.com
10 | */
11 | {
12 | class MorphingBG {
13 | constructor(el) {
14 | this.DOM = {};
15 | this.DOM.el = el;
16 | this.DOM.paths = Array.from(this.DOM.el.querySelectorAll('path'));
17 | this.animate();
18 | }
19 | animate() {
20 | this.DOM.paths.forEach((path) => {
21 | setTimeout(() => {
22 | anime({
23 | targets: path,
24 | duration: anime.random(3000,5000),
25 | easing: [0.5,0,0.5,1],
26 | d: path.getAttribute('pathdata:id'),
27 | loop: true,
28 | direction: 'alternate'
29 | });
30 | }, anime.random(0,1000));
31 | });
32 | }
33 | };
34 |
35 | new MorphingBG(document.querySelector('svg.scene'));
36 | };
--------------------------------------------------------------------------------
/js/demo4.js:
--------------------------------------------------------------------------------
1 | /**
2 | * demo4.js
3 | * http://www.codrops.com
4 | *
5 | * Licensed under the MIT license.
6 | * http://www.opensource.org/licenses/mit-license.php
7 | *
8 | * Copyright 2017, Codrops
9 | * http://www.codrops.com
10 | */
11 | {
12 | // equation of a line
13 | const lineEq = (y2, y1, x2, x1, currentVal) => {
14 | // y = mx + b
15 | const m = (y2 - y1) / (x2 - x1);
16 | const b = y1 - m * x1;
17 |
18 | return m * currentVal + b;
19 | }
20 |
21 | // from http://www.quirksmode.org/js/events_properties.html#position
22 | const getMousePos = (e) => {
23 | let posx = 0;
24 | let posy = 0;
25 | if (!e) {let e = window.event};
26 | if (e.pageX || e.pageY) {
27 | posx = e.pageX;
28 | posy = e.pageY;
29 | }
30 | else if (e.clientX || e.clientY) {
31 | posx = e.clientX + document.body.scrollLeft
32 | + document.documentElement.scrollLeft;
33 | posy = e.clientY + document.body.scrollTop
34 | + document.documentElement.scrollTop;
35 | }
36 | return {
37 | x : posx,
38 | y : posy
39 | };
40 | };
41 |
42 | // From https://davidwalsh.name/javascript-debounce-function.
43 | function debounce(func, wait, immediate) {
44 | var timeout;
45 | return function() {
46 | var context = this, args = arguments;
47 | var later = function() {
48 | timeout = null;
49 | if (!immediate) func.apply(context, args);
50 | };
51 | var callNow = immediate && !timeout;
52 | clearTimeout(timeout);
53 | timeout = setTimeout(later, wait);
54 | if (callNow) func.apply(context, args);
55 | };
56 | };
57 |
58 | class MorphingBG {
59 | constructor(el) {
60 | this.DOM = {};
61 | this.DOM.el = el;
62 | this.DOM.el.style.opacity = 0;
63 | this.DOM.el.style.transition = 'transform 2s ease-out';
64 | this.DOM.pathEl = this.DOM.el.querySelector('path');
65 | this.paths = this.DOM.pathEl.getAttribute('pathdata:id').split(';')
66 | this.paths.splice(this.paths.length, 0, this.DOM.pathEl.getAttribute('d'));
67 | this.win = {width: window.innerWidth, height: window.innerHeight};
68 | this.animate();
69 | this.initEvents();
70 | }
71 | animate() {
72 | anime.remove(this.DOM.pathEl);
73 | anime({
74 | targets: this.DOM.pathEl,
75 | duration: 10000,
76 | easing: [0.5,0,0.5,1],
77 | d: this.paths,
78 | loop: true
79 | });
80 | }
81 | initEvents() {
82 | // Mousemove event / Tilt functionality.
83 | const tilt = {
84 | tx: this.win.width/8,
85 | ty: this.win.height/4,
86 | rz: 45,
87 | sx: [0.8,2],
88 | sy: [0.8,2]
89 | }
90 | const onMouseMoveFn = (ev) => {
91 | requestAnimationFrame(() => {
92 | if ( !this.started ) {
93 | this.started = true;
94 | anime({
95 | targets: this.DOM.el,
96 | duration: 300,
97 | easing: 'linear',
98 | opacity: [0,1]
99 | });
100 | }
101 | else {
102 | const mousepos = getMousePos(ev);
103 | const rotZ = 2*tilt.rz/this.win.height*mousepos.y - tilt.rz;
104 | const scaleX = mousepos.x < this.win.width/2 ? lineEq(tilt.sx[0],tilt.sx[1],this.win.width/2,0,mousepos.x) : lineEq(tilt.sx[1],tilt.sx[0],this.win.width,this.win.width/2,mousepos.x);
105 | const scaleY = mousepos.y < this.win.height/2 ? lineEq(tilt.sy[0],tilt.sy[1],this.win.height/2,0,mousepos.y) : lineEq(tilt.sy[1],tilt.sy[0],this.win.height,this.win.height/2,mousepos.y);
106 | const transX = 2*tilt.tx/this.win.width*mousepos.x - tilt.tx;
107 | const transY = 2*tilt.ty/this.win.height*mousepos.y - tilt.ty;
108 |
109 | this.DOM.el.style.transform = `translate3d(${transX}px, ${transY}px,0) rotate3d(0,0,1,${rotZ}deg) scale3d(${scaleX},${scaleY},1)`;
110 | }
111 | });
112 | };
113 |
114 | // Window resize.
115 | const onResizeFn = debounce(() => this.win = {width: window.innerWidth, height: window.innerHeight}, 20);
116 |
117 | document.addEventListener('mousemove', onMouseMoveFn);
118 | document.addEventListener('touchstart', onMouseMoveFn);
119 | window.addEventListener('resize', ev => onResizeFn());
120 | }
121 | };
122 |
123 | new MorphingBG(document.querySelector('svg.scene'));
124 | };
--------------------------------------------------------------------------------
/js/demo5.js:
--------------------------------------------------------------------------------
1 | /**
2 | * demo5.js
3 | * http://www.codrops.com
4 | *
5 | * Licensed under the MIT license.
6 | * http://www.opensource.org/licenses/mit-license.php
7 | *
8 | * Copyright 2017, Codrops
9 | * http://www.codrops.com
10 | */
11 | {
12 | // equation of a line
13 | const lineEq = (y2, y1, x2, x1, currentVal) => {
14 | // y = mx + b
15 | const m = (y2 - y1) / (x2 - x1);
16 | const b = y1 - m * x1;
17 |
18 | return m * currentVal + b;
19 | }
20 |
21 | // from http://www.quirksmode.org/js/events_properties.html#position
22 | const getMousePos = (e) => {
23 | let posx = 0;
24 | let posy = 0;
25 | if (!e) {let e = window.event};
26 | if (e.pageX || e.pageY) {
27 | posx = e.pageX;
28 | posy = e.pageY;
29 | }
30 | else if (e.clientX || e.clientY) {
31 | posx = e.clientX + document.body.scrollLeft
32 | + document.documentElement.scrollLeft;
33 | posy = e.clientY + document.body.scrollTop
34 | + document.documentElement.scrollTop;
35 | }
36 | return {
37 | x : posx,
38 | y : posy
39 | };
40 | };
41 |
42 | // From https://davidwalsh.name/javascript-debounce-function.
43 | function debounce(func, wait, immediate) {
44 | var timeout;
45 | return function() {
46 | var context = this, args = arguments;
47 | var later = function() {
48 | timeout = null;
49 | if (!immediate) func.apply(context, args);
50 | };
51 | var callNow = immediate && !timeout;
52 | clearTimeout(timeout);
53 | timeout = setTimeout(later, wait);
54 | if (callNow) func.apply(context, args);
55 | };
56 | };
57 |
58 | const ua = navigator.userAgent.toLowerCase();
59 | const isSafari = ua.indexOf('safari') != -1 && ua.indexOf('chrome') <= -1;
60 |
61 | let win = {width: window.innerWidth, height: window.innerHeight};
62 |
63 | class Blob {
64 | constructor(path, link, shape, content) {
65 | this.DOM = {};
66 | this.DOM.path = path;
67 | this.DOM.link = link;
68 | this.DOM.shape = shape;
69 | this.DOM.content = content;
70 | this.DOM.path.style.transformOrigin = this.DOM.link.style.transformOrigin = '50% 50%';
71 | this.DOM.path.style.transition = isSafari ? 'none' : 'transform 0.2s ease-out';
72 | this.transform = {tx: 0, ty: 0, rz: 0};
73 | this.paths = {
74 | reveal: this.DOM.path.getAttribute('pathdata:id'),
75 | unreveal: this.DOM.path.getAttribute('d')
76 | };
77 | this.tilt = true;
78 | this.initEvents();
79 | }
80 | initEvents() {
81 | // Mousemove event / Tilt functionality.
82 | const tilt = {
83 | tx: anime.random(5,40),
84 | ty: anime.random(20,60),
85 | rz: anime.random(-10,10)
86 | }
87 | const onMouseMoveFn = (ev) => {
88 | requestAnimationFrame(() => {
89 | if ( !this.tilt ) return false;
90 | const mousepos = getMousePos(ev);
91 |
92 | const rotZ = 2*tilt.rz/win.width*mousepos.x - tilt.rz;
93 | const transX = 2*tilt.tx/win.width*mousepos.x - tilt.tx;
94 | const transY = 2*tilt.ty/win.height*mousepos.y - tilt.ty;
95 |
96 | this.DOM.path.style.transform = `translateX(${transX}px) translateY(${transY}px) rotate(${rotZ}deg)`;
97 |
98 | this.transform = {tx: transX, ty: transY, rz: rotZ};
99 | });
100 | };
101 | document.addEventListener('mousemove', onMouseMoveFn);
102 | }
103 | reveal() {
104 | this.tilt = false;
105 | if ( this.isRevealed || this.isAnimating ) return false;
106 | this.toggleLink();
107 | this.isRevealed = true;
108 | anime.remove(this.DOM.path);
109 | anime({
110 | targets: this.DOM.path,
111 | duration: 1000,
112 | easing: 'easeInOutQuint',
113 | d: this.paths.reveal,
114 | translateX: 0,
115 | translateY: 0,
116 | rotate: 0,
117 | begin: () => this.isAnimating = true,
118 | complete: () => {
119 | this.isAnimating = false;
120 | }
121 | });
122 | setTimeout(() => this.DOM.content.classList.add('content__inner--visible'), 600);
123 | this.transform = {tx: 0, ty: 0, rz: 0};
124 | }
125 | unreveal() {
126 | setTimeout(() => this.DOM.content.classList.remove('content__inner--visible'), 200);
127 | anime.remove(this.DOM.path);
128 | anime({
129 | targets: this.DOM.path,
130 | duration: 1000,
131 | easing: 'easeInOutQuint',
132 | d: this.paths.unreveal,
133 | begin: () => this.isAnimating = true,
134 | complete: () => {
135 | this.tilt = true;
136 | this.isRevealed = false;
137 | this.isAnimating = false;
138 | }
139 | });
140 | this.toggleLink(true, 550);
141 | }
142 | hide() {
143 | const duration = anime.random(300,600);
144 | const easing = 'easeInOutSine';
145 |
146 | anime.remove(this.DOM.path);
147 | anime({
148 | targets: this.DOM.path,
149 | duration: duration,
150 | easing: easing,
151 | translateX: this.transform.tx,
152 | translateY: this.transform.ty,
153 | scale: [1,0],
154 | rotate: this.transform.rz
155 | });
156 |
157 | anime.remove(this.DOM.shape);
158 | anime({
159 | targets: this.DOM.shape,
160 | duration: duration,
161 | easing: easing,
162 | opacity: [1,0]
163 | });
164 |
165 | this.toggleLink();
166 | }
167 | show() {
168 | this.tilt = false;
169 | const duration = anime.random(300,600);
170 | const easing = 'easeOutQuint';
171 | const delay = 500;
172 |
173 | anime.remove(this.DOM.shape);
174 | anime({
175 | targets: this.DOM.path,
176 | duration: duration,
177 | delay: delay,
178 | easing: easing,
179 | translateX: this.transform.tx,
180 | translateY: this.transform.ty,
181 | scale: [0,1],
182 | rotate: this.transform.rz,
183 | complete: () => {
184 | this.tilt = true;
185 | }
186 | });
187 |
188 | anime.remove(this.DOM.shape);
189 | anime({
190 | targets: this.DOM.shape,
191 | duration: duration,
192 | delay: delay,
193 | easing: easing,
194 | opacity: 1
195 | });
196 |
197 | this.toggleLink(true, 550);
198 | }
199 | toggleLink(isVisible = false, delay = 0) {
200 | setTimeout(() => {
201 | anime.remove(this.DOM.link);
202 | anime({
203 | targets: this.DOM.link,
204 | duration: isVisible ? 700 : 1200,
205 | easing: 'easeOutQuint',
206 | opacity: isVisible ? [0,1] : [1,0],
207 | translateX: isVisible ? (t,i) => {
208 | return [anime.random(-50,50),0];
209 | } : (t,i) => {
210 | return [0,anime.random(-20,20)];
211 | }
212 | });
213 | }, delay);
214 | }
215 | };
216 |
217 | class MorphingBG {
218 | constructor() {
219 | this.DOM = {};
220 | this.DOM.scene = document.querySelector('svg.scene');
221 | this.DOM.links = Array.from(this.DOM.scene.querySelectorAll('a.label'));
222 | this.DOM.shapes = Array.from(this.DOM.scene.querySelectorAll('g.shape'));
223 | this.DOM.contents = Array.from(document.querySelectorAll('.content > .content__inner'));
224 | this.DOM.closeCtrl = document.querySelector('.content__close');
225 |
226 | this.blobs = [];
227 | Array.from(this.DOM.scene.querySelectorAll('clipPath > path')).forEach((path, pos) => this.blobs.push(new Blob(path, this.DOM.links[pos], this.DOM.shapes[pos], this.DOM.contents[pos])));
228 |
229 | this.initEvents();
230 | }
231 | initEvents() {
232 | const onResizeFn = debounce(() => win = {width: window.innerWidth, height: window.innerHeight}, 20);
233 | window.addEventListener('resize', ev => onResizeFn());
234 |
235 | const onRevealFn = (ev, pos) => {
236 | ev.preventDefault();
237 |
238 | this.current = pos;
239 | const currentBlob = this.blobs[this.current];
240 | if ( currentBlob.isAnimating ) return;
241 | currentBlob.reveal();
242 |
243 | this.blobs.filter(el => el != currentBlob).forEach(blob => blob.hide());
244 | };
245 | this.DOM.links.forEach((link,pos) => {
246 | link.addEventListener('click', (ev) => onRevealFn(ev,pos));
247 | link.addEventListener('touchstart', (ev) => onRevealFn(ev,pos));
248 | });
249 |
250 | const onUnrevealFn = (ev) => {
251 | ev.preventDefault();
252 |
253 | const currentBlob = this.blobs[this.current];
254 | if ( currentBlob.isAnimating ) return;
255 | currentBlob.unreveal();
256 |
257 | this.blobs.filter(el => el != currentBlob).forEach(blob => blob.show());
258 | };
259 | this.DOM.closeCtrl.addEventListener('click', onUnrevealFn);
260 | this.DOM.closeCtrl.addEventListener('touchstart', onUnrevealFn);
261 | }
262 | };
263 |
264 | new MorphingBG();
265 | };
--------------------------------------------------------------------------------
/pater/jetpack.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codrops/ShapeMorphIdeas/eeb7a4f4d7cf580bf8f0b8fb921f1af10f5ffce7/pater/jetpack.png
--------------------------------------------------------------------------------
/pater/jetpack_man.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codrops/ShapeMorphIdeas/eeb7a4f4d7cf580bf8f0b8fb921f1af10f5ffce7/pater/jetpack_man.png
--------------------------------------------------------------------------------
/pater/pater.css:
--------------------------------------------------------------------------------
1 | .pater {
2 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif !important;
3 | position: fixed;
4 | z-index: 1000;
5 | right: 0;
6 | bottom: 0;
7 | display: grid;
8 | width: 100%;
9 | padding: 1em 0;
10 | text-align: left;
11 | color: #333;
12 | background: #ddd;
13 | grid-template-columns: auto;
14 | grid-template-rows: auto auto auto;
15 | }
16 |
17 | .pater:hover,
18 | .pater:focus {
19 | color: #000;
20 | }
21 |
22 | .pater--theme-alt {
23 | background: #333333;
24 | color: #e2e2e2;
25 | }
26 |
27 | .pater--theme-alt:hover,
28 | .pater--theme-alt:focus {
29 | color: #fff;
30 | }
31 |
32 | .pater::before {
33 | content: 'Our Sponsor';
34 | font-size: 0.75em;
35 | display: inline-block;
36 | padding: 0 0 5px 10px;
37 | vertical-align: middle;
38 | grid-area: 1 / 1 / 2 / 2;
39 | }
40 |
41 | .pater__img {
42 | display: none;
43 | overflow: hidden;
44 | background-image: url(jetpack.png);
45 | background-size: cover;
46 | grid-area: 2 / 1 / 3 / 2;
47 | }
48 |
49 | .pater__img-inner {
50 | background: url(jetpack_man.png) no-repeat 0 100% ;
51 | background-size: 150px;
52 | width: 100%;
53 | height: 100%;
54 | }
55 |
56 | .pater:hover .pater__img-inner {
57 | animation: animMan 0.4s cubic-bezier(0.1,1,0.3,1) forwards;
58 | }
59 |
60 | @keyframes animMan {
61 | 25% {
62 | opacity: 0;
63 | transform: translate3d(0,0,0);
64 | }
65 | 26% {
66 | opacity: 0;
67 | transform: translate3d(-100%,100%,0) scale3d(0.1,0.1,1);
68 | }
69 | 100% {
70 | opacity: 1;
71 | transform: translate3d(0,0,0);
72 | }
73 | }
74 |
75 | .pater__title {
76 | font-size: 0.85em;
77 | font-weight: normal;
78 | font-weight: bold;
79 | align-self: end;
80 | margin: 0;
81 | }
82 |
83 | .pater__title,
84 | .pater__description {
85 | align-self: start;
86 | padding: 10px 0 0 10px;
87 | grid-area: 2 / 1 / 3 / 3;
88 | }
89 |
90 | .pater__description {
91 | font-size: 0.85em;
92 | display: none;
93 | margin: 0;
94 | opacity: 0;
95 | }
96 |
97 | .pater__description strong {
98 | display: block;
99 | padding-top: 5px;
100 | color: #ee4e97;
101 | }
102 |
103 | @media screen and (min-width: 60em) {
104 | .pater {
105 | top: 0;
106 | right: 0;
107 | bottom: auto;
108 | width: calc(180px + 2em);
109 | margin: 0 1.5em 0 0;
110 | padding: 0;
111 | padding: 1em;
112 | text-align: right;
113 | border-radius: 0 0 5px 5px;
114 | background: #f9f9f9;
115 | }
116 | .pater--theme-alt {
117 | background: #333333;
118 | }
119 | .pater__img {
120 | display: flex;
121 | width: 100%;
122 | height: 180px;
123 | }
124 | .pater::before {
125 | display: block;
126 | padding: 0 0 10px 0;
127 | }
128 | .pater:hover .pater__title {
129 | opacity: 0;
130 | }
131 | .pater:hover .pater__description {
132 | opacity: 1;
133 | }
134 | .pater__description {
135 | display: block;
136 | }
137 | .pater__title {
138 | padding: 10px;
139 | }
140 | .pater__title,
141 | .pater__description {
142 | padding-left: 0;
143 | transition: opacity 0.5s;
144 | grid-area: 3 / 1 / 4 / 2;
145 | }
146 | }
147 |
--------------------------------------------------------------------------------