├── .gitignore
├── README.md
├── css
├── base.css
├── demo1.css
├── demo2.css
├── demo3.css
├── demo4.css
├── demo5.css
├── demo6.css
├── demo7.css
└── demo8.css
├── favicon.ico
├── img
├── 1.jpg
├── 10.jpg
├── 11.jpg
├── 12.jpg
├── 13.jpg
├── 14.jpg
├── 15.jpg
├── 16.jpg
├── 17.jpg
├── 18.jpg
├── 2.jpg
├── 3.jpg
├── 4.jpg
├── 5.jpg
├── 6.jpg
├── 7.jpg
├── 8.jpg
└── 9.jpg
├── index.html
├── index2.html
├── index3.html
├── index4.html
├── index5.html
├── index6.html
├── index7.html
├── index8.html
├── js
├── MathUtils.js
├── demo1
│ ├── draggableImage.js
│ └── index.js
├── demo2
│ ├── draggableImage.js
│ └── index.js
├── demo3
│ ├── draggableImage.js
│ └── index.js
├── demo4
│ ├── draggableImage.js
│ └── index.js
├── demo5
│ ├── draggableImage.js
│ └── index.js
├── demo6
│ ├── draggableImage.js
│ └── index.js
├── demo7
│ ├── draggableImage.js
│ └── index.js
└── demo8
│ ├── draggableImage.js
│ └── index.js
└── package.json
/.gitignore:
--------------------------------------------------------------------------------
1 | .cache/
2 | dist/
3 | node_modules/
4 |
5 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Image Dragging Effects
2 |
3 | A set of playful effects for dragging images.
4 |
5 | 
6 |
7 | [Article on Codrops](https://tympanus.net/codrops/?p=47024)
8 |
9 | [Demo](http://tympanus.net/Development/ImageDraggingEffects/)
10 |
11 |
12 | ## Installation
13 |
14 | Install dependencies:
15 |
16 | ```
17 | npm install
18 | ```
19 |
20 | Compile the code for development and start a local server:
21 |
22 | ```
23 | npm start
24 | ```
25 |
26 | Create the build:
27 |
28 | ```
29 | npm run build
30 | ```
31 |
32 | ## Credits
33 |
34 | - [Draggabilly](https://draggabilly.desandro.com/) by Dave DeSandro
35 | - [imagesLoaded](https://imagesloaded.desandro.com/) by Dave DeSandro
36 | - [GSAP](https://greensock.com/) by Greensock
37 | - Images from [Unsplash.com](https://unsplash.com/)
38 |
39 |
40 | ## License
41 |
42 | 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.
43 |
44 | ## Misc
45 |
46 | 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/)
47 |
48 | [© Codrops 2020](http://www.codrops.com)
49 |
50 |
51 |
52 |
53 |
54 |
--------------------------------------------------------------------------------
/css/base.css:
--------------------------------------------------------------------------------
1 | *,
2 | *::after,
3 | *::before {
4 | box-sizing: border-box;
5 | }
6 |
7 | :root {
8 | font-size: 14px;
9 | }
10 |
11 | body {
12 | margin: 0;
13 | --color-text: #000;
14 | --color-bg: #85827a;
15 | --color-link: #594343;
16 | --color-link-hover: #000;
17 | color: var(--color-text);
18 | background-color: var(--color-bg);
19 | --font-main: Geneva, Tahoma, Verdana, sans-serif;
20 | --font-alt: bigmoore, serif;
21 | --font-weight-alt: 400;
22 | --color-title: inherit;
23 | font-family: var(--font-main);
24 | -webkit-font-smoothing: antialiased;
25 | -moz-osx-font-smoothing: grayscale;
26 | line-height: 1;
27 | }
28 |
29 | .demo-1 {
30 | --color-title: #fff;
31 | }
32 |
33 | .demo-2 {
34 | --color-link: #fff;
35 | --color-bg: #a1e0e7;
36 | --font-alt: meno-banner, serif;
37 | }
38 |
39 | .demo-3 {
40 | --color-text: #000;
41 | --color-link: #fff;
42 | --color-bg: #d0c6ad;
43 | --font-alt: freight-big-pro, serif;
44 | }
45 |
46 | .demo-4 {
47 | --color-link: #eaeaef;
48 | --color-bg: #0859ca;
49 | --font-alt: bely-display, sans-serif;
50 | --color-title: #eaeaef;
51 | }
52 |
53 | .demo-5 {
54 | --color-link: #dc4823;
55 | --color-bg: #eceae9;
56 | --font-alt: louvette-display, serif;
57 | font-family: 'Barlow', sans-serif;
58 | text-transform: uppercase;
59 | }
60 |
61 | .demo-6 {
62 | --color-text: #fff;
63 | --color-link: #a17d66;
64 | --color-bg: #dacca9;
65 | --font-alt: bigmoore, serif;
66 | }
67 |
68 | .demo-7 {
69 | --color-link: #343129;
70 | --color-bg: #77705e;
71 | --font-alt: meno-banner, serif;
72 | --color-text: #e6ae4d;
73 | }
74 |
75 | .demo-8 {
76 | --color-text: #000;
77 | --color-link: #7e0c0c;
78 | --color-bg: #bc3d3d;
79 | --font-alt: freight-big-pro, serif;
80 | --color-title: #fff;
81 | }
82 |
83 | /* Page Loader */
84 | .js .loading::before {
85 | content: '';
86 | position: fixed;
87 | z-index: 100000;
88 | top: 0;
89 | left: 0;
90 | width: 100%;
91 | height: 100%;
92 | background: var(--color-bg);
93 | }
94 |
95 | .js .loading::after {
96 | content: '';
97 | position: fixed;
98 | z-index: 100000;
99 | top: 50%;
100 | left: 50%;
101 | width: 60px;
102 | height: 60px;
103 | margin: -30px 0 0 -30px;
104 | pointer-events: none;
105 | border-radius: 50%;
106 | opacity: 0.4;
107 | background: var(--color-link);
108 | animation: loaderAnim 0.7s linear infinite alternate forwards;
109 | }
110 |
111 | @keyframes loaderAnim {
112 | to {
113 | opacity: 1;
114 | transform: scale3d(0.5,0.5,1);
115 | }
116 | }
117 |
118 | a {
119 | text-decoration: none;
120 | color: var(--color-link);
121 | outline: none;
122 | }
123 |
124 | a:hover,
125 | a:focus {
126 | color: var(--color-link-hover);
127 | outline: none;
128 | }
129 |
130 | .frame {
131 | padding: 3rem 5vw;
132 | text-align: center;
133 | position: relative;
134 | z-index: 1000;
135 | }
136 |
137 | .frame__title {
138 | font-size: 1rem;
139 | margin: 0 0 1rem;
140 | font-weight: inherit;
141 | }
142 |
143 | .frame__links {
144 | display: block;
145 | }
146 |
147 | .frame__links a:not(:last-child),
148 | .frame__demos a:not(:last-child) {
149 | margin: 0 1rem 0.35rem 0;
150 | }
151 |
152 | .frame__demos {
153 | margin: 1rem 0;
154 | }
155 |
156 | .frame__demo--current,
157 | .frame__demo--current:hover {
158 | color: var(--color-text);
159 | }
160 |
161 | .frame__initials {
162 | font-family: var(--font-alt);
163 | font-weight: var(--font-weight-alt);
164 | font-size: 2rem;
165 | pointer-events: none;
166 | line-height: 14px;
167 | }
168 |
169 | .content {
170 | display: flex;
171 | position: relative;
172 | flex-direction: column;
173 | width: 100vw;
174 | height: calc(100vh - 13rem);
175 | position: relative;
176 | justify-content: flex-start;
177 | align-items: center;
178 | }
179 |
180 | .content__title {
181 | font-size: 10vw;
182 | font-family: var(--font-alt);
183 | font-weight: var(--font-weight-alt);
184 | margin: 0;
185 | position: relative;
186 | pointer-events: none;
187 | z-index: 1000;
188 | color: var(--color-title);
189 | text-align: center;
190 | }
191 |
192 | .content__title--multiline {
193 | font-size: 8.5vw;
194 | line-height: 1.3;
195 | text-transform: none;
196 | }
197 |
198 | .content__title-row {
199 | display: block;
200 | }
201 |
202 | .content__title-row:first-child {
203 | margin-right: 22vw;
204 | }
205 |
206 | .content__title--up {
207 | text-transform: uppercase;
208 | }
209 |
210 | .month {
211 | font-weight: 700;
212 | font-size: 4vw;
213 | }
214 |
215 | .year {
216 | font-size: 10vw;
217 | }
218 |
219 | .content__drag-area {
220 | position: absolute;
221 | width: 100%;
222 | height: 100%;
223 | display: flex;
224 | align-items: center;
225 | justify-content: center;
226 | }
227 |
228 | .img-drag,
229 | .img-wrap {
230 | flex: none;
231 | }
232 |
233 | @media screen and (max-width: 42em) {
234 | .content .img-drag,
235 | .content .img-wrap {
236 | margin: 1rem;
237 | }
238 | }
239 |
240 | @media screen and (min-width: 53em) {
241 | .frame {
242 | position: fixed;
243 | text-align: left;
244 | z-index: 10000;
245 | top: 0;
246 | left: 0;
247 | display: grid;
248 | align-content: space-between;
249 | width: 100%;
250 | max-width: none;
251 | height: 100vh;
252 | padding: 2.5rem 4rem;
253 | pointer-events: none;
254 | grid-template-columns: 40% 20% 40%;
255 | grid-template-rows: auto auto auto;
256 | grid-template-areas: 'title initials demos'
257 | '... ... ...'
258 | '... ... info';
259 | }
260 | .frame__title-wrap {
261 | grid-area: title;
262 | }
263 | .frame__title {
264 | margin: 0 0 3rem 0;
265 | }
266 | .frame__initials {
267 | grid-area: initials;
268 | margin: 0;
269 | justify-self: center;
270 | align-self: start;
271 | }
272 | .frame__demos {
273 | margin: 0;
274 | grid-area: demos;
275 | justify-self: end;
276 | align-self: start;
277 | }
278 | .frame__links {
279 | grid-area: links;
280 | padding: 0;
281 | justify-self: end;
282 | display: flex;
283 | flex-direction: column;
284 | align-items: flex-start;
285 | }
286 | .frame__info {
287 | grid-area: info;
288 | margin: 0;
289 | justify-self: end;
290 | }
291 | .frame a {
292 | pointer-events: auto;
293 | }
294 | .content {
295 | height: 100vh;
296 | justify-content: center;
297 | }
298 | }
299 |
--------------------------------------------------------------------------------
/css/demo1.css:
--------------------------------------------------------------------------------
1 | .img-drag {
2 | position: relative;
3 | overflow: hidden;
4 | width: 260px;
5 | height: 330px;
6 | max-width: 100%;
7 | cursor: grab;
8 | margin: 4rem;
9 | display: flex;
10 | align-items: center;
11 | justify-content: center;
12 | }
13 |
14 | .img-drag:nth-child(1) {
15 | margin-top: 20vh;
16 | }
17 |
18 | .img-drag:nth-child(2) {
19 | margin-top: 0;
20 | width: 210px;
21 | height: 290px;
22 | }
23 |
24 | .img-drag__inner {
25 | flex: none;
26 | --overflow: 70px;
27 | position: relative;
28 | background-size: cover;
29 | background-position: 50% 50%;
30 | width: calc(100% + var(--overflow));
31 | height: calc(100% + var(--overflow));
32 | }
--------------------------------------------------------------------------------
/css/demo2.css:
--------------------------------------------------------------------------------
1 | .img-drag {
2 | position: relative;
3 | overflow: hidden;
4 | width: 290px;
5 | height: 400px;
6 | max-width: 100%;
7 | cursor: grab;
8 | display: flex;
9 | align-items: center;
10 | justify-content: center;
11 | }
12 |
13 | .img-drag__inner {
14 | flex: none;
15 | --overflow: 100px;
16 | position: relative;
17 | background-size: cover;
18 | background-position: 50% 50%;
19 | width: calc(100% + var(--overflow));
20 | height: calc(100% + var(--overflow));
21 | will-change: transform;
22 | }
--------------------------------------------------------------------------------
/css/demo3.css:
--------------------------------------------------------------------------------
1 | .img-drag {
2 | position: relative;
3 | background-size: cover;
4 | width: 220px;
5 | height: 300px;
6 | max-width: 100%;
7 | cursor: grab;
8 | margin: 4rem;
9 | will-change: transform;
10 | }
11 |
12 | .img-drag:nth-child(1) {
13 | margin-top: 30vh;
14 | }
15 |
16 | .img-drag:nth-child(2) {
17 | margin-top: 0;
18 | }
--------------------------------------------------------------------------------
/css/demo4.css:
--------------------------------------------------------------------------------
1 | .img-wrap {
2 | position: relative;
3 | pointer-events: none;
4 | width: 350px;
5 | height: 450px;
6 | max-width: 100%;
7 | }
8 |
9 | .img-drag,
10 | .img-trail {
11 | cursor: grab;
12 | background-size: cover;
13 | background-position: 50% 50%;
14 | position: relative;
15 | width: 100%;
16 | height: 100%;
17 | pointer-events: auto;
18 | }
19 |
20 | .img-trail {
21 | position: absolute;
22 | top: 0;
23 | left: 0;
24 | opacity: 0.8;
25 | }
26 |
27 | .content__title {
28 | font-size: 8vw;
29 | mix-blend-mode: exclusion;
30 | }
31 |
--------------------------------------------------------------------------------
/css/demo5.css:
--------------------------------------------------------------------------------
1 | .img-wrap {
2 | --img-width: 210px;
3 | --img-height: 300px;
4 | width: var(--img-width);
5 | height: var(--img-height);
6 | position: relative;
7 | pointer-events: none;
8 |
9 | }
10 |
11 | .img-drag {
12 | position: relative;
13 | width: 100%;
14 | height: 100%;
15 | overflow: hidden;
16 | pointer-events: auto;
17 | cursor: grab;
18 | will-change: transform;
19 | }
20 |
21 | .img-drag__inner {
22 | background-size: cover;
23 | background-position: 50% 50%;
24 | width: 100%;
25 | height: 100%;
26 | }
27 |
28 | .img-trail {
29 | width: 100%;
30 | height: 100%;
31 | position: absolute;
32 | top: 0;
33 | left: 0;
34 | opacity: 0;
35 | will-change: transform;
36 | }
--------------------------------------------------------------------------------
/css/demo6.css:
--------------------------------------------------------------------------------
1 | .img-wrap {
2 | --img-width: 200px;
3 | --img-height: 270px;
4 | width: var(--img-width);
5 | height: var(--img-height);
6 | position: relative;
7 | pointer-events: none;
8 | margin: 4rem;
9 | }
10 |
11 | .img-wrap:nth-child(1) {
12 | margin-top: 30vh;
13 | }
14 |
15 | .img-wrap:nth-child(2) {
16 | margin-top: 0;
17 | }
18 |
19 | .img-drag {
20 | position: relative;
21 | width: 100%;
22 | height: 100%;
23 | overflow: hidden;
24 | opacity: 1;
25 | pointer-events: auto;
26 | cursor: grab;
27 | }
28 |
29 | .img-drag__inner {
30 | background-size: cover;
31 | background-position: 50% 50%;
32 | width: 100%;
33 | height: 100%;
34 | }
35 |
36 | .img-trail {
37 | width: var(--img-width);
38 | height: var(--img-height);
39 | position: absolute;
40 | top: 0;
41 | left: 0;
42 | opacity: 0;
43 | mix-blend-mode: color-dodge;
44 | }
45 |
46 | .content__title {
47 | mix-blend-mode: difference;
48 | }
49 |
--------------------------------------------------------------------------------
/css/demo7.css:
--------------------------------------------------------------------------------
1 | .img-drag {
2 | position: relative;
3 | max-width: 100%;
4 | display: flex;
5 | flex-wrap: wrap;
6 | cursor: grab;
7 | margin: 3rem;
8 | }
9 |
10 | .img-drag:nth-child(1) {
11 | margin-top: 20vh;
12 | }
13 |
14 | .img-drag:nth-child(2) {
15 | margin-top: 0;
16 | }
17 |
18 | .img-drag svg {
19 | display: block;
20 | }
21 |
--------------------------------------------------------------------------------
/css/demo8.css:
--------------------------------------------------------------------------------
1 | .img-wrap {
2 | width: 180px;
3 | height: 250px;
4 | max-width: 100%;
5 | position: relative;
6 | pointer-events: none;
7 | }
8 |
9 | .img-drag {
10 | cursor: grab;
11 | }
12 |
13 | .img-drag {
14 | background-size: cover;
15 | background-position: 50% 50%;
16 | position: relative;
17 | width: 100%;
18 | height: 100%;
19 | pointer-events: auto;
20 | will-change: transform;
21 | }
22 |
23 | .img-trail {
24 | position: absolute;
25 | top: 0;
26 | left: 0;
27 | opacity: 0.8;
28 | will-change: transform;
29 | }
30 |
--------------------------------------------------------------------------------
/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codrops/ImageDraggingEffects/a1faf9fcb5975bf356501236ae987bf89486b412/favicon.ico
--------------------------------------------------------------------------------
/img/1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codrops/ImageDraggingEffects/a1faf9fcb5975bf356501236ae987bf89486b412/img/1.jpg
--------------------------------------------------------------------------------
/img/10.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codrops/ImageDraggingEffects/a1faf9fcb5975bf356501236ae987bf89486b412/img/10.jpg
--------------------------------------------------------------------------------
/img/11.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codrops/ImageDraggingEffects/a1faf9fcb5975bf356501236ae987bf89486b412/img/11.jpg
--------------------------------------------------------------------------------
/img/12.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codrops/ImageDraggingEffects/a1faf9fcb5975bf356501236ae987bf89486b412/img/12.jpg
--------------------------------------------------------------------------------
/img/13.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codrops/ImageDraggingEffects/a1faf9fcb5975bf356501236ae987bf89486b412/img/13.jpg
--------------------------------------------------------------------------------
/img/14.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codrops/ImageDraggingEffects/a1faf9fcb5975bf356501236ae987bf89486b412/img/14.jpg
--------------------------------------------------------------------------------
/img/15.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codrops/ImageDraggingEffects/a1faf9fcb5975bf356501236ae987bf89486b412/img/15.jpg
--------------------------------------------------------------------------------
/img/16.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codrops/ImageDraggingEffects/a1faf9fcb5975bf356501236ae987bf89486b412/img/16.jpg
--------------------------------------------------------------------------------
/img/17.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codrops/ImageDraggingEffects/a1faf9fcb5975bf356501236ae987bf89486b412/img/17.jpg
--------------------------------------------------------------------------------
/img/18.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codrops/ImageDraggingEffects/a1faf9fcb5975bf356501236ae987bf89486b412/img/18.jpg
--------------------------------------------------------------------------------
/img/2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codrops/ImageDraggingEffects/a1faf9fcb5975bf356501236ae987bf89486b412/img/2.jpg
--------------------------------------------------------------------------------
/img/3.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codrops/ImageDraggingEffects/a1faf9fcb5975bf356501236ae987bf89486b412/img/3.jpg
--------------------------------------------------------------------------------
/img/4.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codrops/ImageDraggingEffects/a1faf9fcb5975bf356501236ae987bf89486b412/img/4.jpg
--------------------------------------------------------------------------------
/img/5.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codrops/ImageDraggingEffects/a1faf9fcb5975bf356501236ae987bf89486b412/img/5.jpg
--------------------------------------------------------------------------------
/img/6.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codrops/ImageDraggingEffects/a1faf9fcb5975bf356501236ae987bf89486b412/img/6.jpg
--------------------------------------------------------------------------------
/img/7.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codrops/ImageDraggingEffects/a1faf9fcb5975bf356501236ae987bf89486b412/img/7.jpg
--------------------------------------------------------------------------------
/img/8.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codrops/ImageDraggingEffects/a1faf9fcb5975bf356501236ae987bf89486b412/img/8.jpg
--------------------------------------------------------------------------------
/img/9.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codrops/ImageDraggingEffects/a1faf9fcb5975bf356501236ae987bf89486b412/img/9.jpg
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Image Dragging Effects | Demo 1 | Codrops
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
Image Dragging Effects
21 |
26 |
27 |
KH
28 |
Drag the images
29 |
30 |
1
31 |
2
32 |
3
33 |
4
34 |
5
35 |
6
36 |
7
37 |
8
38 |
39 |
40 |
41 |
49 |
Kai & Harper
50 |
51 |
52 |
53 |
54 |
55 |
--------------------------------------------------------------------------------
/index2.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Image Dragging Effects | Demo 2 | Codrops
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
Image Dragging Effects
21 |
26 |
27 |
KA
28 |
Drag the images
29 |
30 |
1
31 |
2
32 |
3
33 |
4
34 |
5
35 |
6
36 |
7
37 |
8
38 |
39 |
40 |
48 |
49 |
50 |
51 |
52 |
--------------------------------------------------------------------------------
/index3.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Image Dragging Effects | Demo 3 | Codrops
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
Image Dragging Effects
22 |
27 |
28 |
MP
29 |
Drag the images (fast)
30 |
31 |
1
32 |
2
33 |
3
34 |
4
35 |
5
36 |
6
37 |
7
38 |
8
39 |
40 |
41 |
42 |
46 |
Markopoulos
47 |
48 |
49 |
50 |
51 |
52 |
--------------------------------------------------------------------------------
/index4.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Image Dragging Effects | Demo 4 | Codrops
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
Image Dragging Effects
21 |
26 |
27 |
TD
28 |
Drag the images (fast)
29 |
30 |
1
31 |
2
32 |
3
33 |
4
34 |
5
35 |
6
36 |
7
37 |
8
38 |
39 |
40 |
41 |
46 |
Tyler Dice
47 |
48 |
49 |
50 |
51 |
52 |
--------------------------------------------------------------------------------
/index5.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Image Dragging Effects | Demo 5 | Codrops
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
Image Dragging Effects
22 |
27 |
28 |
2020
29 |
Drag the images (fast)
30 |
31 |
1
32 |
2
33 |
3
34 |
4
35 |
5
36 |
6
37 |
7
38 |
8
39 |
40 |
41 |
42 |
49 |
50 | Italy
51 | Art Fair @ Savona
52 | Apr — 2020
53 |
54 |
55 |
56 |
57 |
58 |
59 |
--------------------------------------------------------------------------------
/index6.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Image Dragging Effects | Demo 6 | Codrops
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
Image Dragging Effects
21 |
26 |
27 |
ML
28 |
Drag the images (fast)
29 |
30 |
1
31 |
2
32 |
3
33 |
4
34 |
5
35 |
6
36 |
7
37 |
8
38 |
39 |
40 |
41 |
53 |
Mayra & Louise
54 |
55 |
56 |
57 |
58 |
59 |
--------------------------------------------------------------------------------
/index7.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Image Dragging Effects | Demo 7 | Codrops
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
Image Dragging Effects
21 |
26 |
27 |
KH
28 |
Drag the images (fast)
29 |
30 |
1
31 |
2
32 |
3
33 |
4
34 |
5
35 |
6
36 |
7
37 |
8
38 |
39 |
40 |
41 |
42 |
43 |
54 |
55 |
56 |
67 |
68 |
69 |
Genevieve
70 |
71 |
72 |
73 |
74 |
75 |
--------------------------------------------------------------------------------
/index8.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Image Dragging Effects | Demo 8 | Codrops
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
Image Dragging Effects
21 |
26 |
27 |
AG
28 |
Drag the images
29 |
30 |
1
31 |
2
32 |
3
33 |
4
34 |
5
35 |
6
36 |
7
37 |
8
38 |
39 |
40 |
41 |
42 |
43 |

44 |

45 |

46 |

47 |

48 |

49 |
50 |
51 |
52 |
Antonella Gallo
53 |
54 |
55 |
56 |
57 |
58 |
--------------------------------------------------------------------------------
/js/MathUtils.js:
--------------------------------------------------------------------------------
1 | /**
2 | * MathUtils.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 2020, Codrops
9 | * http://www.codrops.com
10 | */
11 |
12 | // Map number x from range [a, b] to [c, d]
13 | const map = (x, a, b, c, d) => (x - a) * (d - c) / (b - a) + c;
14 |
15 | // Linear interpolation
16 | const lerp = (a, b, n) => (1 - n) * a + n * b;
17 |
18 | // Clamp val within min and max
19 | const clamp = (val, min, max) => Math.max(Math.min(val, max), min);
20 |
21 | // Random float
22 | const getRandomFloat = (min, max) => (Math.random() * (max - min) + min).toFixed(2);
23 |
24 | // distance between two points
25 | const distance = (x1,y1,x2,y2) => Math.hypot(x2-x1, y2-y1);
26 |
27 | export { map, lerp, clamp, getRandomFloat, distance };
28 |
--------------------------------------------------------------------------------
/js/demo1/draggableImage.js:
--------------------------------------------------------------------------------
1 | /**
2 | * draggableImage.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 2020, Codrops
9 | * http://www.codrops.com
10 | */
11 | import { map, lerp, clamp } from './../MathUtils';
12 | const Draggabilly = require('draggabilly');
13 |
14 | // Draggabilly: Preserve transforms by using left and top rather than transform values (see https://codepen.io/desandro/pen/dEyIg)
15 | Draggabilly.prototype.positionDrag = Draggabilly.prototype.setLeftTop;
16 |
17 | // Image that gets dragged gets this zIndex value which then gets incremented
18 | let zIndex = 1;
19 |
20 | class DraggableImage {
21 | constructor(el) {
22 | // image container (the draggable element)
23 | this.DOM = {el: el};
24 | // image element
25 | this.DOM.innerEl = this.DOM.el.querySelector('.img-drag__inner');
26 | // css --overflow value
27 | // this will define how much the innerEl can move inside the parent without getting cut off
28 | this.overflowVal = parseInt(getComputedStyle(this.DOM.innerEl).getPropertyValue('--overflow'),10);
29 | // Dragging position
30 | this.draggingPos = {
31 | previous: {x: 0, y: 0},
32 | current: {x: 0, y: 0},
33 | amt: 0.1
34 | };
35 | // Inner Element scale
36 | this.innerScale = {
37 | previous: 1,
38 | current: 1,
39 | amt: 0.15
40 | };
41 | // outer Element scale
42 | this.outerScale = {
43 | previous: 1,
44 | current: 1,
45 | amt: 0.15
46 | };
47 | // Initialize Draggabilly
48 | this.draggie = new Draggabilly(this.DOM.el);
49 | // Init/Bind events
50 | this.initEvents();
51 | // Loop
52 | requestAnimationFrame(() => this.render());
53 | }
54 | initEvents() {
55 | this.onDragStart = () => {
56 | // Reset
57 | this.draggingPos.previous = {x: 0, y: 0};
58 | };
59 |
60 | this.onDragMove = (event, pointer, moveVector) => {
61 | this.draggingPos.current = moveVector;
62 | };
63 |
64 | this.onPointerDown = () => {
65 | this.DOM.el.style.zIndex = zIndex++;
66 | this.innerScale.current = 1.3;
67 | this.outerScale.current = 0.8;
68 | document.body.style.cursor = 'grabbing';
69 | this.DOM.el.style.cursor = 'grabbing';
70 | };
71 |
72 | this.onPointerUp = () => {
73 | // Reset
74 | this.innerScale.current = 1;
75 | this.outerScale.current = 1;
76 | document.body.style.cursor = 'default';
77 | this.DOM.el.style.cursor = 'grab';
78 | };
79 |
80 | this.draggie.on('pointerDown', this.onPointerDown);
81 | this.draggie.on('dragStart', this.onDragStart);
82 | this.draggie.on('dragMove', this.onDragMove);
83 | this.draggie.on('pointerUp', this.onPointerUp);
84 | }
85 | render() {
86 | this.draggingPos.previous.x = lerp(this.draggingPos.previous.x, this.draggingPos.current.x, this.draggingPos.amt);
87 | this.draggingPos.previous.y = lerp(this.draggingPos.previous.y, this.draggingPos.current.y, this.draggingPos.amt);
88 | this.innerScale.previous = lerp(this.innerScale.previous, this.innerScale.current, this.innerScale.amt);
89 | this.outerScale.previous = lerp(this.outerScale.previous, this.outerScale.current, this.outerScale.amt);
90 |
91 | this.layout();
92 | // loop
93 | requestAnimationFrame(() => this.render());
94 | }
95 | layout() {
96 | // The inner element transform
97 | this.DOM.innerEl.style.transform = `translate3d(${this.getInnerTranslation('x')}px,${this.getInnerTranslation('y')}px,0) scale3d(${this.innerScale.previous}, ${this.innerScale.previous}, 1) rotate3d(1,1,1,0.1deg)`;
98 | // The draggable element transform
99 | this.DOM.el.style.transform = `translate3d(${(this.draggingPos.previous.x - this.draggingPos.current.x).toFixed(2)}px,${(this.draggingPos.previous.y - this.draggingPos.current.y).toFixed(2)}px,0) scale3d(${this.outerScale.previous}, ${this.outerScale.previous}, 1) rotate3d(1,1,1,0.1deg)`;
100 | }
101 | // Calculate how much to translate the inner element
102 | getInnerTranslation(axis) {
103 | const distance = this.draggingPos.previous[axis] - this.draggingPos.current[axis];
104 | const boundaries = {
105 | distance: {min: 0, max: 400},
106 | translation: {min: 0, max: this.overflowVal/2*this.innerScale.previous/this.outerScale.previous}
107 | };
108 |
109 | let translationVal = map(Math.abs(distance), boundaries.distance.min, boundaries.distance.max, boundaries.translation.min, boundaries.translation.max);
110 | translationVal = clamp(translationVal, boundaries.translation.min, boundaries.translation.max);
111 |
112 | return distance > 0 ? translationVal.toFixed(2) : -1*translationVal.toFixed(2);
113 | }
114 | }
115 |
116 | export default DraggableImage;
--------------------------------------------------------------------------------
/js/demo1/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * index.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 2020, Codrops
9 | * http://www.codrops.com
10 | */
11 | import DraggableImage from "./draggableImage";
12 | const imagesLoaded = require('imagesloaded');
13 |
14 | // Preload images
15 | const preloadImages = () => {
16 | return new Promise((resolve, reject) => {
17 | imagesLoaded(document.querySelectorAll('.img-drag__inner'), {background: true}, resolve);
18 | });
19 | };
20 |
21 | // Preload fonts
22 | const preloadFonts = () => {
23 | return new Promise((resolve, reject) => {
24 | WebFont.load({
25 | typekit: {
26 | id: 'hsm8jwd'
27 | },
28 | active: resolve
29 | });
30 | });
31 | };
32 |
33 | Promise.all([
34 | preloadImages(),
35 | preloadFonts()
36 | ]).then(() => {
37 | [...document.querySelectorAll('.img-drag')].forEach((draggableEl) => new DraggableImage(draggableEl));
38 | document.body.classList.remove('loading');
39 | });
40 |
--------------------------------------------------------------------------------
/js/demo2/draggableImage.js:
--------------------------------------------------------------------------------
1 | /**
2 | * draggableImage.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 2020, Codrops
9 | * http://www.codrops.com
10 | */
11 | import { map, lerp, clamp } from './../MathUtils';
12 | const Draggabilly = require('draggabilly');
13 | import { gsap, Power2 } from 'gsap';
14 |
15 | // Draggabilly: Preserve transforms by using left and top rather than transform values (see https://codepen.io/desandro/pen/dEyIg)
16 | Draggabilly.prototype.positionDrag = Draggabilly.prototype.setLeftTop;
17 |
18 | // Image that gets dragged gets this zIndex value which then gets incremented
19 | let zIndex = 1;
20 |
21 | class DraggableImage {
22 | constructor(el) {
23 | // image container (the draggable element)
24 | this.DOM = {el: el};
25 | // image element
26 | this.DOM.innerEl = this.DOM.el.querySelector('.img-drag__inner');
27 | // css --overflow value
28 | // this will define how much the innerEl can move inside the parent without getting cut off
29 | this.overflowVal = parseInt(getComputedStyle(this.DOM.innerEl).getPropertyValue('--overflow'),10);
30 | // Dragging position
31 | this.draggingPos = {
32 | previous: {x: 0, y: 0},
33 | current: {x: 0, y: 0},
34 | amt: 0.1
35 | };
36 | // Inner Element scale
37 | this.innerScale = {
38 | previous: 1,
39 | current: 1,
40 | amt: 0.15
41 | };
42 | // outer Element scale
43 | this.outerScale = {
44 | previous: 1,
45 | current: 1,
46 | amt: 0.15
47 | };
48 | // Initialize Draggabilly
49 | this.draggie = new Draggabilly(this.DOM.el);
50 | // Init/Bind events
51 | this.initEvents();
52 | // Loop
53 | requestAnimationFrame(() => this.render());
54 | }
55 | initEvents() {
56 | this.onDragStart = () => {
57 | // Reset
58 | this.draggingPos.previous = {x: 0, y: 0};
59 | };
60 |
61 | this.onDragMove = (event, pointer, moveVector) => {
62 | this.draggingPos.current = moveVector;
63 | };
64 |
65 | this.onPointerDown = () => {
66 | this.DOM.el.style.zIndex = zIndex++;
67 |
68 | this.innerScale.current = 1;
69 | this.outerScale.current = 1.2;
70 |
71 | gsap.to(document.body, {duration: 0.5, ease: Power2.easeOut, backgroundColor: '#588186'});
72 |
73 | document.body.style.cursor = 'grabbing';
74 | this.DOM.el.style.cursor = 'grabbing';
75 | };
76 |
77 | this.onPointerUp = () => {
78 | // Reset
79 | this.innerScale.current = 1;
80 | this.outerScale.current = 1;
81 |
82 | gsap.to(document.body, {duration: 0.5, ease: Power2.easeOut, backgroundColor: '#a1e0e7'});
83 |
84 | document.body.style.cursor = 'default';
85 | this.DOM.el.style.cursor = 'grab';
86 | };
87 |
88 | this.onMouseEnter = () => {
89 | if ( this.DOM.el.classList.contains('is-dragging') ) return;
90 | this.innerScale.current = 1.2;
91 | this.outerScale.current = 1.1;
92 | };
93 |
94 | this.onMouseLeave = () => {
95 | if ( this.DOM.el.classList.contains('is-dragging') ) return;
96 | // Reset
97 | this.innerScale.current = 1;
98 | this.outerScale.current = 1;
99 | };
100 |
101 | this.draggie.on('pointerDown', this.onPointerDown);
102 | this.draggie.on('dragStart', this.onDragStart);
103 | this.draggie.on('dragMove', this.onDragMove);
104 | this.draggie.on('pointerUp', this.onPointerUp);
105 | this.DOM.el.addEventListener('mouseenter', this.onMouseEnter);
106 | this.DOM.el.addEventListener('mouseleave', this.onMouseLeave);
107 | }
108 | render() {
109 | this.draggingPos.previous.x = lerp(this.draggingPos.previous.x, this.draggingPos.current.x, this.draggingPos.amt);
110 | this.draggingPos.previous.y = lerp(this.draggingPos.previous.y, this.draggingPos.current.y, this.draggingPos.amt);
111 | this.innerScale.previous = lerp(this.innerScale.previous, this.innerScale.current, this.innerScale.amt);
112 | this.outerScale.previous = lerp(this.outerScale.previous, this.outerScale.current, this.outerScale.amt);
113 |
114 | this.layout();
115 | // loop
116 | requestAnimationFrame(() => this.render());
117 | }
118 | layout() {
119 | // The inner element transform
120 | this.DOM.innerEl.style.transform = `translate3d(${this.getInnerTranslation('x')}px,${this.getInnerTranslation('y')}px,0) scale3d(${this.innerScale.previous}, ${this.innerScale.previous}, 1) rotate3d(1,1,1,0.1deg)`;
121 | // The draggable element transform
122 | this.DOM.el.style.transform = `translate3d(${(this.draggingPos.previous.x - this.draggingPos.current.x).toFixed(2)}px,${(this.draggingPos.previous.y - this.draggingPos.current.y).toFixed(2)}px,0) scale3d(${this.outerScale.previous}, ${this.outerScale.previous}, 1) rotate3d(1,1,1,0.1deg)`;
123 | }
124 | // Calculate how much to translate the inner element
125 | getInnerTranslation(axis) {
126 | const distance = this.draggingPos.previous[axis] - this.draggingPos.current[axis];
127 | const boundaries = {
128 | distance: {min: 0, max: 400},
129 | translation: {min: 0, max: this.overflowVal/2*this.innerScale.previous/this.outerScale.previous}
130 | };
131 |
132 | let translationVal = map(Math.abs(distance), boundaries.distance.min, boundaries.distance.max, boundaries.translation.min, boundaries.translation.max);
133 | translationVal = clamp(translationVal, boundaries.translation.min, boundaries.translation.max);
134 |
135 | return distance > 0 ? translationVal : -1*translationVal;
136 | }
137 | }
138 |
139 | export default DraggableImage;
--------------------------------------------------------------------------------
/js/demo2/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * index.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 2020, Codrops
9 | * http://www.codrops.com
10 | */
11 | import DraggableImage from "./draggableImage";
12 | const imagesLoaded = require('imagesloaded');
13 |
14 | // Preload images
15 | const preloadImages = () => {
16 | return new Promise((resolve, reject) => {
17 | imagesLoaded(document.querySelectorAll('.img-drag__inner'), {background: true}, resolve);
18 | });
19 | };
20 |
21 | // Preload fonts
22 | const preloadFonts = () => {
23 | return new Promise((resolve, reject) => {
24 | WebFont.load({
25 | typekit: {
26 | id: 'mto6dlj'
27 | },
28 | active: resolve
29 | });
30 | });
31 | };
32 |
33 | Promise.all([
34 | preloadImages(),
35 | preloadFonts()
36 | ]).then(() => {
37 | [...document.querySelectorAll('.img-drag')].forEach((draggableEl) => new DraggableImage(draggableEl));
38 | document.body.classList.remove('loading');
39 | });
40 |
--------------------------------------------------------------------------------
/js/demo3/draggableImage.js:
--------------------------------------------------------------------------------
1 | /**
2 | * draggableImage.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 2020, Codrops
9 | * http://www.codrops.com
10 | */
11 | import { map, lerp, clamp, getRandomFloat, distance } from './../MathUtils';
12 | const Draggabilly = require('draggabilly');
13 |
14 | // Draggabilly: Preserve transforms by using left and top rather than transform values (see https://codepen.io/desandro/pen/dEyIg)
15 | Draggabilly.prototype.positionDrag = Draggabilly.prototype.setLeftTop;
16 |
17 | // Image that gets dragged gets this zIndex value which then gets incremented
18 | let zIndex = 1;
19 |
20 | class DraggableImage {
21 | constructor(el) {
22 | // image container (the draggable element)
23 | this.DOM = {el: el};
24 | this.boundingRect = this.DOM.el.getBoundingClientRect();
25 | // Dragging position
26 | this.draggingPos = {
27 | previous: {x: 0, y: 0},
28 | current: {x: 0, y: 0},
29 | amt: 0.13
30 | };
31 | this.pointerOffset = {x: 0,y: 0};
32 | // Initialize Draggabilly
33 | this.draggie = new Draggabilly(this.DOM.el);
34 | // Init/Bind events
35 | this.initEvents();
36 | // Loop
37 | requestAnimationFrame(() => this.render());
38 | }
39 | initEvents() {
40 | this.onDragStart = () => {
41 | this.DOM.el.style.zIndex = zIndex++;
42 | // Reset
43 | this.draggingPos.previous = {x: 0, y: 0};
44 | };
45 |
46 | this.onDragMove = (event, pointer, moveVector) => {
47 | this.draggingPos.current = moveVector;
48 | };
49 |
50 | this.onPointerDown = (event, pointer) => {
51 | this.pointerOffset = {
52 | x: pointer.offsetX,
53 | y: pointer.offsetY
54 | };
55 | document.body.style.cursor = 'grabbing';
56 | this.DOM.el.style.cursor = 'grabbing';
57 | };
58 |
59 | this.onPointerUp = () => {
60 | document.body.style.cursor = 'default';
61 | this.DOM.el.style.cursor = 'grab';
62 | };
63 |
64 | this.onResize = () => {
65 | this.boundingRect = this.DOM.el.getBoundingClientRect();
66 | };
67 |
68 | this.draggie.on('dragStart', this.onDragStart);
69 | this.draggie.on('dragMove', this.onDragMove);
70 | this.draggie.on('pointerDown', this.onPointerDown);
71 | this.draggie.on('pointerUp', this.onPointerUp);
72 | window.addEventListener('resize', this.onResize);
73 | }
74 | render() {
75 | this.draggingPos.previous.x = lerp(this.draggingPos.previous.x, this.draggingPos.current.x, this.draggingPos.amt);
76 | this.draggingPos.previous.y = lerp(this.draggingPos.previous.y, this.draggingPos.current.y, this.draggingPos.amt);
77 |
78 | this.layout();
79 | // loop
80 | requestAnimationFrame(() => this.render());
81 | }
82 | layout() {
83 | const draggingDistance = {
84 | x: (this.draggingPos.previous.x - this.draggingPos.current.x).toFixed(2),
85 | y: (this.draggingPos.previous.y - this.draggingPos.current.y).toFixed(2),
86 | total: distance(this.draggingPos.previous.x, this.draggingPos.previous.y, this.draggingPos.current.x, this.draggingPos.current.y)
87 | };
88 | const blurVal = clamp(map(draggingDistance.total, 0, 400, 0, 10), 0, 10);
89 | const brightnessVal = clamp(map(draggingDistance.total, 0, 400, 1, 1.5), 1, 1.5);
90 |
91 | // The draggable element transform
92 | const skewDirection = {
93 | vertical: this.pointerOffset.y > this.boundingRect.height/2 ? -1 : 1,
94 | horizontal: this.pointerOffset.x > this.boundingRect.width/2 ? -1 : 1
95 | };
96 | this.DOM.el.style.transform = `translate3d(${draggingDistance.x}px,${draggingDistance.y}px,0)
97 | scale(${clamp(map(draggingDistance.total, 0, 800, 1, 0.6), 0.6, 1)})
98 | skewX(${skewDirection.vertical*map(draggingDistance.x, 0, 500, 0, 10)}deg) skewY(${skewDirection.horizontal*map(draggingDistance.y, 0, 500, 0, 10)}deg)`;
99 |
100 | // Filters
101 | this.DOM.el.style.filter = `blur(${blurVal.toFixed(2)}px) brightness(${brightnessVal.toFixed(2)})`;
102 | }
103 | }
104 |
105 | export default DraggableImage;
--------------------------------------------------------------------------------
/js/demo3/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * index.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 2020, Codrops
9 | * http://www.codrops.com
10 | */
11 | import DraggableImage from "./draggableImage";
12 | const imagesLoaded = require('imagesloaded');
13 |
14 | // Preload images
15 | const preloadImages = () => {
16 | return new Promise((resolve, reject) => {
17 | imagesLoaded(document.querySelectorAll('.img-drag'), {background: true}, resolve);
18 | });
19 | };
20 |
21 | // Preload fonts
22 | const preloadFonts = () => {
23 | return new Promise((resolve, reject) => {
24 | WebFont.load({
25 | typekit: {
26 | id: 'wwn4ioo'
27 | },
28 | active: resolve
29 | });
30 | });
31 | };
32 |
33 | Promise.all([
34 | preloadImages(),
35 | preloadFonts()
36 | ]).then(() => {
37 | [...document.querySelectorAll('.img-drag')].forEach((draggableEl) => new DraggableImage(draggableEl));
38 | document.body.classList.remove('loading');
39 | });
40 |
--------------------------------------------------------------------------------
/js/demo4/draggableImage.js:
--------------------------------------------------------------------------------
1 | /**
2 | * draggableImage.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 2020, Codrops
9 | * http://www.codrops.com
10 | */
11 | import { map, lerp, clamp, distance } from './../MathUtils';
12 | const Draggabilly = require('draggabilly');
13 |
14 | // Image that gets dragged gets this zIndex value which then gets incremented
15 | let zIndex = 1;
16 |
17 | class DraggableImage {
18 | constructor(el) {
19 | // Image container
20 | this.DOM = {el: el};
21 | // The draggable element
22 | this.DOM.draggable = this.DOM.el.querySelector('.img-drag');
23 | // Image trails
24 | this.trailsTotal = 5;
25 | for (let i = 0; i <= this.trailsTotal - 1; ++i) {
26 | const el = document.createElement('div');
27 | el.className = 'img-trail';
28 | el.style.backgroundImage = this.DOM.draggable.style.backgroundImage;
29 | this.DOM.el.insertBefore(el, this.DOM.el.firstChild);
30 | }
31 | this.DOM.trails = [...this.DOM.el.querySelectorAll('.img-trail')];
32 |
33 | // Dragging position
34 | this.draggingPos = {
35 | previous: {x: 0, y: 0},
36 | current: {x: 0, y: 0},
37 | amt: 0.1
38 | };
39 | // Trails translations
40 | this.trailsTranslation = [...new Array(this.trailsTotal)].map(() => ({
41 | previous: {x: 0, y: 0},
42 | current: {x: 0, y: 0},
43 | amt: position => 0.15 + 0.05*position
44 | }));
45 | // Initialize Draggabilly
46 | this.draggie = new Draggabilly(this.DOM.draggable);
47 | // Init/Bind events
48 | this.initEvents();
49 | // Loop
50 | requestAnimationFrame(() => this.render());
51 | }
52 | initEvents() {
53 | this.onDragStart = () => {
54 | // Reset
55 | this.draggingPos.previous = {x: 0, y: 0};
56 | };
57 |
58 | this.onDragMove = (event, pointer, moveVector) => {
59 | this.draggingPos.current = moveVector;
60 | for (let i = 0; i <= this.trailsTotal - 1; ++i) {
61 | this.trailsTranslation[i].current = this.draggie.position;
62 | }
63 | };
64 |
65 | this.onPointerDown = () => {
66 | this.DOM.el.style.zIndex = zIndex++;
67 | this.DOM.draggable.style.opacity = 0.8;
68 | document.body.style.cursor = 'grabbing';
69 | this.DOM.draggable.style.cursor = 'grabbing';
70 | };
71 |
72 | this.onPointerUp = () => {
73 | this.DOM.draggable.style.opacity = 1;
74 | document.body.style.cursor = 'default';
75 | this.DOM.draggable.style.cursor = 'grab';
76 | };
77 |
78 | this.draggie.on('pointerDown', this.onPointerDown);
79 | this.draggie.on('dragStart', this.onDragStart);
80 | this.draggie.on('dragMove', this.onDragMove);
81 | this.draggie.on('pointerUp', this.onPointerUp);
82 | }
83 | render() {
84 | this.draggingPos.previous.x = lerp(this.draggingPos.previous.x, this.draggingPos.current.x, this.draggingPos.amt);
85 | this.draggingPos.previous.y = lerp(this.draggingPos.previous.y, this.draggingPos.current.y, this.draggingPos.amt);
86 | for (let i = 0; i <= this.trailsTotal - 1; ++i) {
87 | this.trailsTranslation[i].previous.x = lerp(this.trailsTranslation[i].previous.x, this.trailsTranslation[i].current.x, this.trailsTranslation[i].amt(i));
88 | this.trailsTranslation[i].previous.y = lerp(this.trailsTranslation[i].previous.y, this.trailsTranslation[i].current.y, this.trailsTranslation[i].amt(i));
89 | }
90 | this.layout();
91 | // loop
92 | requestAnimationFrame(() => this.render());
93 | }
94 | layout() {
95 | const draggingDistance = distance(this.draggingPos.previous.x, this.draggingPos.previous.y, this.draggingPos.current.x, this.draggingPos.current.y);
96 |
97 | for (let i = 0; i <= this.trailsTotal - 1; ++i) {
98 | const brightnessVal = clamp(map(draggingDistance, 0, 400, 100, 100+(this.trailsTotal - 1 - i)*40), 100, 100+(this.trailsTotal - 1 - i)*40);
99 | this.DOM.trails[i].style.filter = `brightness(${brightnessVal}%)`;
100 | this.DOM.trails[i].style.transform = `translate3d(${this.trailsTranslation[i].previous.x}px,${this.trailsTranslation[i].previous.y}px,0)`;
101 | }
102 | }
103 | }
104 |
105 | export default DraggableImage;
--------------------------------------------------------------------------------
/js/demo4/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * index.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 2020, Codrops
9 | * http://www.codrops.com
10 | */
11 | import DraggableImage from "./draggableImage";
12 | const imagesLoaded = require('imagesloaded');
13 |
14 | // Preload images
15 | const preloadImages = () => {
16 | return new Promise((resolve, reject) => {
17 | imagesLoaded(document.querySelectorAll('.img-drag, img'), {background: true}, resolve);
18 | });
19 | };
20 |
21 | // Preload fonts
22 | const preloadFonts = () => {
23 | return new Promise((resolve, reject) => {
24 | WebFont.load({
25 | typekit: {
26 | id: 'ngs8vzi'
27 | },
28 | active: resolve
29 | });
30 | });
31 | };
32 |
33 | Promise.all([
34 | preloadImages(),
35 | preloadFonts()
36 | ]).then(() => {
37 | [...document.querySelectorAll('.img-wrap')].forEach((element) => new DraggableImage(element));
38 | document.body.classList.remove('loading');
39 | });
40 |
41 |
42 |
--------------------------------------------------------------------------------
/js/demo5/draggableImage.js:
--------------------------------------------------------------------------------
1 | /**
2 | * draggableImage.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 2020, Codrops
9 | * http://www.codrops.com
10 | */
11 | import { lerp, clamp, distance } from './../MathUtils';
12 | const Draggabilly = require('draggabilly');
13 | import { gsap, Power1 } from 'gsap';
14 |
15 | // Draggabilly: Preserve transforms by using left and top rather than transform values (see https://codepen.io/desandro/pen/dEyIg)
16 | Draggabilly.prototype.positionDrag = Draggabilly.prototype.setLeftTop;
17 |
18 | // Image that gets dragged gets this zIndex value which then gets incremented
19 | let zIndex = 1;
20 |
21 | class DraggableImage {
22 | constructor(el) {
23 | // Image container
24 | this.DOM = {el: el};
25 | // The draggable element
26 | this.DOM.draggable = this.DOM.el.querySelector('.img-drag');
27 | // image element
28 | this.DOM.innerEl = this.DOM.el.querySelector('.img-drag__inner');
29 | // Image trails
30 | this.trailsTotal = 10;
31 | for (let i = 0; i <= this.trailsTotal - 1; ++i) {
32 | const el = document.createElement('img');
33 | el.className = 'img-trail';
34 | el.alt = 'A decorative image';
35 | el.src = this.DOM.innerEl.style.backgroundImage.match(/url\(["']?([^"']*)["']?\)/)[1];
36 | this.DOM.el.insertBefore(el, this.DOM.el.firstChild);
37 | }
38 | this.DOM.trails = [...this.DOM.el.querySelectorAll('.img-trail')];
39 |
40 | // Dragging position
41 | this.draggingPos = {
42 | previous: {x: 0, y: 0},
43 | current: {x: 0, y: 0}
44 | };
45 | // Inner Element scale
46 | this.innerScale = {
47 | previous: 1,
48 | current: 1,
49 | amt: 0.2
50 | };
51 | // outer Element scale
52 | this.outerScale = {
53 | previous: 1,
54 | current: 1,
55 | amt: 0.2
56 | };
57 |
58 | // mouse distance required to show the first trail image
59 | this.threshold = 30;
60 | this.trailPosition = 0;
61 |
62 | // Initialize Draggabilly
63 | this.draggie = new Draggabilly(this.DOM.draggable);
64 | // Init/Bind events
65 | this.initEvents();
66 | // Loop
67 | requestAnimationFrame(() => this.render());
68 | }
69 | initEvents() {
70 | this.onDragStart = () => {
71 | // Reset
72 | this.draggingPos.previous = {x: 0, y: 0};
73 | };
74 |
75 | this.onDragMove = (event, pointer, moveVector) => {
76 | this.draggingPos.current = moveVector;
77 | };
78 |
79 | this.onPointerDown = () => {
80 | this.DOM.el.style.zIndex = zIndex++;
81 | this.innerScale.current = 1.5;
82 | this.outerScale.current = 0.8;
83 | document.body.style.cursor = 'grabbing';
84 | this.DOM.draggable.style.cursor = 'grabbing';
85 | };
86 |
87 | this.onPointerUp = () => {
88 | // Reset
89 | this.innerScale.current = 1;
90 | this.outerScale.current = 1;
91 | document.body.style.cursor = 'default';
92 | this.DOM.draggable.style.cursor = 'grab';
93 | };
94 |
95 | this.draggie.on('pointerDown', this.onPointerDown);
96 | this.draggie.on('dragStart', this.onDragStart);
97 | this.draggie.on('dragMove', this.onDragMove);
98 | this.draggie.on('pointerUp', this.onPointerUp);
99 | }
100 | render() {
101 | this.innerScale.previous = lerp(this.innerScale.previous, this.innerScale.current, this.innerScale.amt);
102 | this.outerScale.previous = lerp(this.outerScale.previous, this.outerScale.current, this.outerScale.amt);
103 |
104 | this.layout();
105 | // loop
106 | requestAnimationFrame(() => this.render());
107 | }
108 | layout() {
109 | const draggingDistance = distance(this.draggingPos.previous.x, this.draggingPos.previous.y, this.draggingPos.current.x, this.draggingPos.current.y);
110 |
111 | // The inner element transform
112 | this.DOM.innerEl.style.transform = `scale3d(${this.innerScale.previous}, ${this.innerScale.previous}, 1)`;
113 | // The draggable element transform
114 | this.DOM.draggable.style.transform = `scale3d(${this.outerScale.previous}, ${this.outerScale.previous}, 1)`;
115 |
116 | // If the mouse moved more than [this.threshold] then show the next image
117 | if ( draggingDistance > this.threshold ) {
118 | this.showNextTrailImage();
119 | this.trailPosition = this.trailPosition < this.trailsTotal-1 ? this.trailPosition+1 : 0;
120 | this.draggingPos.previous = this.draggingPos.current;
121 | }
122 | }
123 | showNextTrailImage() {
124 | const trailEl = this.DOM.trails[this.trailPosition];
125 | // Kill any tween on the trail
126 | gsap.killTweensOf(trailEl);
127 | gsap.timeline({onComplete: () => this.resetTrail(trailEl)})
128 | // show the image
129 | .set(trailEl, {
130 | startAt: {opacity: 0},
131 | opacity: 1,
132 | scale: this.outerScale.previous,
133 | x: this.draggie.position.x,
134 | y: this.draggie.position.y
135 | }, 0)
136 | // then make it disappear
137 | .to(trailEl, 0.3, {
138 | ease: Power1.easeOut,
139 | opacity: 0,
140 | scale: () => this.outerScale.previous
141 | }, 0.1);
142 | }
143 | resetTrail(trailEl) {
144 | gsap.set(trailEl, {
145 | opacity: 0,
146 | scale: 1,
147 | x: this.draggie.position.x,
148 | y: this.draggie.position.y
149 | });
150 | }
151 | }
152 |
153 | export default DraggableImage;
--------------------------------------------------------------------------------
/js/demo5/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * index.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 2020, Codrops
9 | * http://www.codrops.com
10 | */
11 | import DraggableImage from "./draggableImage";
12 | const imagesLoaded = require('imagesloaded');
13 |
14 | // Preload images
15 | const preloadImages = () => {
16 | return new Promise((resolve, reject) => {
17 | imagesLoaded(document.querySelectorAll('.img-drag__inner, img'), {background: true}, resolve);
18 | });
19 | };
20 |
21 | // Preload fonts
22 | const preloadFonts = () => {
23 | return new Promise((resolve, reject) => {
24 | WebFont.load({
25 | typekit: {
26 | id: 'sth6zmv'
27 | },
28 | active: resolve
29 | });
30 | });
31 | };
32 |
33 | Promise.all([
34 | preloadImages(),
35 | preloadFonts()
36 | ]).then(() => {
37 | [...document.querySelectorAll('.img-wrap')].forEach((element) => new DraggableImage(element));
38 | document.body.classList.remove('loading');
39 | });
40 |
41 |
42 |
--------------------------------------------------------------------------------
/js/demo6/draggableImage.js:
--------------------------------------------------------------------------------
1 | /**
2 | * draggableImage.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 2020, Codrops
9 | * http://www.codrops.com
10 | */
11 | import { lerp, clamp, distance, getRandomFloat } from './../MathUtils';
12 | const Draggabilly = require('draggabilly');
13 | import { gsap, Power1 } from 'gsap';
14 |
15 | // Draggabilly: Preserve transforms by using left and top rather than transform values (see https://codepen.io/desandro/pen/dEyIg)
16 | Draggabilly.prototype.positionDrag = Draggabilly.prototype.setLeftTop;
17 |
18 | // Image that gets dragged gets this zIndex value which then gets incremented
19 | let zIndex = 1;
20 |
21 | class DraggableImage {
22 | constructor(el) {
23 | // Image container
24 | this.DOM = {el: el};
25 | // The draggable element
26 | this.DOM.draggable = this.DOM.el.querySelector('.img-drag');
27 | // image element
28 | this.DOM.innerEl = this.DOM.el.querySelector('.img-drag__inner');
29 | // Image trails
30 | this.trailsTotal = 20;
31 | for (let i = 0; i <= this.trailsTotal - 1; ++i) {
32 | const el = document.createElement('img');
33 | el.className = 'img-trail';
34 | el.alt = 'A decorative image';
35 | el.src = this.DOM.innerEl.style.backgroundImage.match(/url\(["']?([^"']*)["']?\)/)[1];
36 | this.DOM.el.insertBefore(el, this.DOM.el.firstChild);
37 | }
38 | this.DOM.trails = [...this.DOM.el.querySelectorAll('.img-trail')];
39 |
40 | // Dragging position
41 | this.draggingPos = {
42 | previous: {x: 0, y: 0},
43 | current: {x: 0, y: 0}
44 | };
45 | // Inner Element scale
46 | this.innerScale = {
47 | previous: 1,
48 | current: 1,
49 | amt: 0.2
50 | };
51 | // outer Element scale
52 | this.outerScale = {
53 | previous: 1,
54 | current: 1,
55 | amt: 0.2
56 | };
57 |
58 | // mouse distance required to show the first trail image
59 | this.threshold = 10;
60 | this.trailPosition = 0;
61 |
62 | // Initialize Draggabilly
63 | this.draggie = new Draggabilly(this.DOM.draggable);
64 | // Init/Bind events
65 | this.initEvents();
66 | // Loop
67 | requestAnimationFrame(() => this.render());
68 | }
69 | initEvents() {
70 | this.onDragStart = () => {
71 | // Reset
72 | this.draggingPos.previous = {x: 0, y: 0};
73 | };
74 |
75 | this.onDragMove = (event, pointer, moveVector) => {
76 | this.draggingPos.current = moveVector;
77 | };
78 |
79 | this.onPointerDown = () => {
80 | this.DOM.el.style.zIndex = zIndex++;
81 | this.innerScale.current = 1.2;
82 | this.outerScale.current = 0.8;
83 | document.body.style.cursor = 'grabbing';
84 | this.DOM.draggable.style.cursor = 'grabbing';
85 | };
86 |
87 | this.onPointerUp = () => {
88 | // Reset
89 | this.innerScale.current = 1;
90 | this.outerScale.current = 1;
91 | document.body.style.cursor = 'default';
92 | this.DOM.draggable.style.cursor = 'grab';
93 | };
94 |
95 | this.draggie.on('pointerDown', this.onPointerDown);
96 | this.draggie.on('dragStart', this.onDragStart);
97 | this.draggie.on('dragMove', this.onDragMove);
98 | this.draggie.on('pointerUp', this.onPointerUp);
99 | }
100 | render() {
101 | this.innerScale.previous = lerp(this.innerScale.previous, this.innerScale.current, this.innerScale.amt);
102 | this.outerScale.previous = lerp(this.outerScale.previous, this.outerScale.current, this.outerScale.amt);
103 |
104 | this.layout();
105 | // loop
106 | requestAnimationFrame(() => this.render());
107 | }
108 | layout() {
109 | const draggingDistance = distance(this.draggingPos.previous.x, this.draggingPos.previous.y, this.draggingPos.current.x, this.draggingPos.current.y);
110 |
111 | // If the mouse moved more than [this.threshold] then show the next image
112 | if ( draggingDistance > this.threshold ) {
113 | this.showNextTrailImage();
114 | this.trailPosition = this.trailPosition < this.trailsTotal-1 ? this.trailPosition+1 : 0;
115 | this.draggingPos.previous = this.draggingPos.current;
116 | }
117 |
118 | // The inner element transform
119 | this.DOM.innerEl.style.transform = `scale3d(${this.innerScale.previous}, ${this.innerScale.previous}, 1) rotate3d(1,1,1,0.1deg)`;
120 | // The draggable element transform
121 | this.DOM.draggable.style.transform = `scale3d(${this.outerScale.previous}, ${this.outerScale.previous}, 1) rotate3d(1,1,1,0.1deg)`;
122 | }
123 | showNextTrailImage() {
124 | const trailEl = this.DOM.trails[this.trailPosition];
125 | // Kill any tween on the trail
126 | gsap.killTweensOf(trailEl);
127 | gsap.timeline({onComplete: () => this.resetTrail(trailEl)})
128 | // show the image
129 | .set(trailEl, {
130 | startAt: {opacity: 0},
131 | opacity: 1,
132 | scale: this.outerScale.previous,
133 | x: this.draggie.position.x,
134 | y: this.draggie.position.y,
135 | rotation: () => getRandomFloat(-10,10)
136 | }, 0)
137 | // then make it disappear
138 | .to(trailEl, 0.3, {
139 | ease: Power1.easeOut,
140 | opacity: 0,
141 | scale: () => this.outerScale.previous
142 | }, 0.1);
143 | }
144 | resetTrail(trailEl) {
145 | gsap.set(trailEl, {
146 | opacity: 0,
147 | scale: 1,
148 | x: this.draggie.position.x,
149 | y: this.draggie.position.y,
150 | rotation: 0
151 | });
152 | }
153 | }
154 |
155 | export default DraggableImage;
--------------------------------------------------------------------------------
/js/demo6/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * index.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 2020, Codrops
9 | * http://www.codrops.com
10 | */
11 | import DraggableImage from "./draggableImage";
12 | const imagesLoaded = require('imagesloaded');
13 |
14 | // Preload images
15 | const preloadImages = () => {
16 | return new Promise((resolve, reject) => {
17 | imagesLoaded(document.querySelectorAll('.img-drag__inner, img'), {background: true}, resolve);
18 | });
19 | };
20 |
21 | // Preload fonts
22 | const preloadFonts = () => {
23 | return new Promise((resolve, reject) => {
24 | WebFont.load({
25 | typekit: {
26 | id: 'hsm8jwd'
27 | },
28 | active: resolve
29 | });
30 | });
31 | };
32 |
33 | Promise.all([
34 | preloadImages(),
35 | preloadFonts()
36 | ]).then(() => {
37 | [...document.querySelectorAll('.img-wrap')].forEach((element) => new DraggableImage(element));
38 | document.body.classList.remove('loading');
39 | });
40 |
41 |
--------------------------------------------------------------------------------
/js/demo7/draggableImage.js:
--------------------------------------------------------------------------------
1 | /**
2 | * draggableImage.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 2020, Codrops
9 | * http://www.codrops.com
10 | */
11 | import { map, lerp, clamp, distance } from './../MathUtils';
12 | const Draggabilly = require('draggabilly');
13 |
14 | // Image that gets dragged gets this zIndex value which then gets incremented
15 | let zIndex = 1;
16 |
17 | class DraggableImage {
18 | constructor(el) {
19 | // image container (the draggable element)
20 | this.DOM = {el: el};
21 | this.DOM.svg = this.DOM.el.querySelector('svg');
22 | this.DOM.img = this.DOM.svg.querySelector('g > image');
23 | // The feDisplacementMap element
24 | this.DOM.feDisplacementMapEl = this.DOM.svg.querySelector('feDisplacementMap');
25 |
26 | // Dragging position
27 | this.draggingPos = {
28 | translation: {
29 | previous: {x: 0, y: 0},
30 | current: {x: 0, y: 0},
31 | amt: 0.15
32 | },
33 | displacement: {
34 | previous: {x: 0, y: 0},
35 | current: {x: 0, y: 0},
36 | amt: 0.08
37 | }
38 | };
39 | // outer Element scale
40 | this.outerScale = {
41 | previous: 1,
42 | current: 1,
43 | amt: 0.1
44 | };
45 |
46 | // Initialize Draggabilly
47 | this.draggie = new Draggabilly(this.DOM.el);
48 | // Init/Bind events
49 | this.initEvents();
50 | // Loop
51 | requestAnimationFrame(() => this.render());
52 | }
53 | initEvents() {
54 | this.onDragStart = () => {
55 | // Reset
56 | this.draggingPos.translation.previous = {x: 0, y: 0};
57 | this.draggingPos.displacement.previous = {x: 0, y: 0};
58 | };
59 |
60 | this.onDragMove = (event, pointer, moveVector) => {
61 | this.draggingPos.translation.current = moveVector;
62 | this.draggingPos.displacement.current = moveVector;
63 | };
64 |
65 | this.onPointerDown = () => {
66 | this.DOM.el.style.zIndex = zIndex++;
67 | this.outerScale.current = 0.75;
68 | document.body.style.cursor = 'grabbing';
69 | this.DOM.el.style.cursor = 'grabbing';
70 | };
71 |
72 | this.onPointerUp = () => {
73 | // Reset
74 | this.outerScale.current = 1;
75 | document.body.style.cursor = 'default';
76 | this.DOM.el.style.cursor = 'grab';
77 | };
78 |
79 | this.draggie.on('pointerDown', this.onPointerDown);
80 | this.draggie.on('dragStart', this.onDragStart);
81 | this.draggie.on('dragMove', this.onDragMove);
82 | this.draggie.on('pointerUp', this.onPointerUp);
83 | }
84 | render() {
85 | this.draggingPos.translation.previous.x = lerp(this.draggingPos.translation.previous.x, this.draggingPos.translation.current.x, this.draggingPos.translation.amt);
86 | this.draggingPos.translation.previous.y = lerp(this.draggingPos.translation.previous.y, this.draggingPos.translation.current.y, this.draggingPos.translation.amt);
87 | this.draggingPos.displacement.previous.x = lerp(this.draggingPos.displacement.previous.x, this.draggingPos.displacement.current.x, this.draggingPos.displacement.amt);
88 | this.draggingPos.displacement.previous.y = lerp(this.draggingPos.displacement.previous.y, this.draggingPos.displacement.current.y, this.draggingPos.displacement.amt);
89 | this.outerScale.previous = lerp(this.outerScale.previous, this.outerScale.current, this.outerScale.amt);
90 |
91 | this.layout();
92 | // loop
93 | requestAnimationFrame(() => this.render());
94 | }
95 | layout() {
96 | // The svg element transform
97 | this.DOM.svg.style.transform = `scale3d(${this.outerScale.previous}, ${this.outerScale.previous}, 1) translate3d(${(this.draggingPos.translation.previous.x - this.draggingPos.translation.current.x).toFixed(2)}px,${(this.draggingPos.translation.previous.y - this.draggingPos.translation.current.y).toFixed(2)}px,0)`;
98 |
99 | const draggingDistance = distance(this.draggingPos.displacement.previous.x, this.draggingPos.displacement.previous.y, this.draggingPos.displacement.current.x, this.draggingPos.displacement.current.y);
100 | // The displacement value
101 | this.DOM.feDisplacementMapEl.scale.baseVal = clamp(map(draggingDistance, 0, 400, 0, 150), 0, 150);
102 | }
103 | }
104 |
105 | export default DraggableImage;
--------------------------------------------------------------------------------
/js/demo7/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * index.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 2020, Codrops
9 | * http://www.codrops.com
10 | */
11 | import DraggableImage from "./draggableImage";
12 |
13 | // Preload fonts
14 | const preloadFonts = () => {
15 | return new Promise((resolve, reject) => {
16 | WebFont.load({
17 | typekit: {
18 | id: 'mto6dlj'
19 | },
20 | active: resolve
21 | });
22 | });
23 | };
24 |
25 | Promise.all([
26 | preloadFonts()
27 | ]).then(() => {
28 | [...document.querySelectorAll('.img-drag')].forEach((draggableEl) => new DraggableImage(draggableEl));
29 | document.body.classList.remove('loading');
30 | });
31 |
--------------------------------------------------------------------------------
/js/demo8/draggableImage.js:
--------------------------------------------------------------------------------
1 | /**
2 | * draggableImage.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 2020, Codrops
9 | * http://www.codrops.com
10 | */
11 | import { map, lerp, clamp, distance, getRandomFloat } from './../MathUtils';
12 | const Draggabilly = require('draggabilly');
13 |
14 | // Draggabilly: Preserve transforms by using left and top rather than transform values (see https://codepen.io/desandro/pen/dEyIg)
15 | Draggabilly.prototype.positionDrag = Draggabilly.prototype.setLeftTop;
16 |
17 | // Image that gets dragged gets this zIndex value which then gets incremented
18 | let zIndex = 1;
19 |
20 | class DraggableImage {
21 | constructor(el) {
22 | // Image container
23 | this.DOM = {el: el};
24 | // The draggable element
25 | this.DOM.draggable = this.DOM.el.querySelector('.img-drag');
26 | this.boundingRect = this.DOM.draggable.getBoundingClientRect();
27 | // Image trails
28 | this.DOM.trails = [...this.DOM.el.querySelectorAll('.img-trail')];
29 | this.trailsTotal = this.DOM.trails.length;
30 |
31 | // Dragging position
32 | this.draggingPos = {
33 | previous: {x: 0, y: 0},
34 | current: {x: 0, y: 0},
35 | amt: 0.13
36 | };
37 | // outer Element scale
38 | this.outerScale = {
39 | previous: 1,
40 | current: 1,
41 | amt: 0.1
42 | };
43 | // Trails translations
44 | this.trailsTranslation = [...new Array(this.trailsTotal)].map(() => ({
45 | previous: {x: 0, y: 0},
46 | current: {x: 0, y: 0},
47 | random: {x: 0, y: 0},
48 | amt: getRandomFloat(0.07,0.11)
49 | }));
50 | // Trails scales
51 | this.trailsScale = [...new Array(this.trailsTotal)].map(() => ({
52 | previous: 0,
53 | current: 0,
54 | amt: 0.1
55 | }));
56 | // Trails rotations
57 | this.trailsRotation = [...new Array(this.trailsTotal)].map(() => ({
58 | previous: 0,
59 | current: 0,
60 | amt: 0.1
61 | }));
62 | // Initialize Draggabilly
63 | this.draggie = new Draggabilly(this.DOM.draggable);
64 | // Init/Bind events
65 | this.initEvents();
66 | // Loop
67 | requestAnimationFrame(() => this.render());
68 | }
69 | initEvents() {
70 | this.onDragStart = () => {
71 | // Reset
72 | this.draggingPos.previous = {x: 0, y: 0};
73 | };
74 |
75 | this.onDragMove = (event, pointer, moveVector) => {
76 | this.draggingPos.current = moveVector;
77 | for (let i = 0; i <= this.trailsTotal - 1; ++i) {
78 | this.trailsTranslation[i].current.x = this.draggie.position.x - parseFloat(this.trailsTranslation[i].random.x);
79 | this.trailsTranslation[i].current.y = this.draggie.position.y - parseFloat(this.trailsTranslation[i].random.y);
80 | }
81 | };
82 |
83 | this.onPointerDown = () => {
84 | this.DOM.el.style.zIndex = zIndex++;
85 | this.outerScale.current = 0.8;
86 | const radius = (this.boundingRect.width + this.boundingRect.height)/2.5;
87 | for (let i = 0; i <= this.trailsTotal - 1; ++i) {
88 | this.trailsTranslation[i].random = {
89 | //x: getRandomFloat(-this.boundingRect.width*.85,this.boundingRect.width*.85),
90 | x: Math.round(radius * Math.cos(2*(i+1)*Math.PI/this.trailsTotal)),
91 | //y: getRandomFloat(-this.boundingRect.height*.85,this.boundingRect.height*.85)
92 | y: Math.round(radius * Math.sin(2*(i+1)*Math.PI/this.trailsTotal))
93 | };
94 | this.trailsTranslation[i].current.x = this.draggie.position.x - parseFloat(this.trailsTranslation[i].random.x);
95 | this.trailsTranslation[i].current.y = this.draggie.position.y - parseFloat(this.trailsTranslation[i].random.y);
96 | this.trailsScale[i].current = 0.5;
97 | this.trailsRotation[i].current = getRandomFloat(-10,10);
98 | }
99 | document.body.style.cursor = 'grabbing';
100 | this.DOM.draggable.style.cursor = 'grabbing';
101 | };
102 |
103 | this.onPointerUp = () => {
104 | this.outerScale.current = 1;
105 | for (let i = 0; i <= this.trailsTotal - 1; ++i) {
106 | this.trailsTranslation[i].current = {x: this.draggie.position.x, y: this.draggie.position.y};
107 | this.trailsScale[i].current = 0;
108 | this.trailsRotation[i].current = 0;
109 | }
110 | document.body.style.cursor = 'default';
111 | this.DOM.draggable.style.cursor = 'grab';
112 | };
113 |
114 | this.onResize = () => {
115 | this.boundingRect = this.DOM.el.getBoundingClientRect();
116 | };
117 |
118 | this.draggie.on('pointerDown', this.onPointerDown);
119 | this.draggie.on('dragStart', this.onDragStart);
120 | this.draggie.on('dragMove', this.onDragMove);
121 | this.draggie.on('pointerUp', this.onPointerUp);
122 | window.addEventListener('resize', this.onResize);
123 | }
124 | render() {
125 | this.draggingPos.previous.x = lerp(this.draggingPos.previous.x, this.draggingPos.current.x, this.draggingPos.amt);
126 | this.draggingPos.previous.y = lerp(this.draggingPos.previous.y, this.draggingPos.current.y, this.draggingPos.amt);
127 | this.outerScale.previous = lerp(this.outerScale.previous, this.outerScale.current, this.outerScale.amt);
128 |
129 | for (let i = 0; i <= this.trailsTotal - 1; ++i) {
130 | this.trailsTranslation[i].previous.x = lerp(this.trailsTranslation[i].previous.x, this.trailsTranslation[i].current.x, this.trailsTranslation[i].amt);
131 | this.trailsTranslation[i].previous.y = lerp(this.trailsTranslation[i].previous.y, this.trailsTranslation[i].current.y, this.trailsTranslation[i].amt);
132 | this.trailsScale[i].previous = lerp(this.trailsScale[i].previous, this.trailsScale[i].current, this.trailsScale[i].amt);
133 | this.trailsRotation[i].previous = lerp(this.trailsRotation[i].previous, this.trailsRotation[i].current, this.trailsRotation[i].amt);
134 | }
135 | this.layout();
136 | // loop
137 | requestAnimationFrame(() => this.render());
138 | }
139 | layout() {
140 | const draggingDistance = distance(this.draggingPos.previous.x, this.draggingPos.previous.y, this.draggingPos.current.x, this.draggingPos.current.y);
141 |
142 | for (let i = 0; i <= this.trailsTotal - 1; ++i) {
143 | const blurVal = clamp(map(draggingDistance, 0, 400, 0, 20), 0, 20);
144 | this.DOM.trails[i].style.filter = `blur(${blurVal}px`;
145 | this.DOM.trails[i].style.transform = `translate3d(${this.trailsTranslation[i].previous.x}px,${this.trailsTranslation[i].previous.y}px,0) scale3d(${this.trailsScale[i].previous},${this.trailsScale[i].previous},1) rotate3d(0,0,1,${this.trailsRotation[i].previous}deg)`;
146 | }
147 |
148 | this.DOM.draggable.style.transform = `translate3d(${(this.draggingPos.previous.x - this.draggingPos.current.x).toFixed(2)}px,${(this.draggingPos.previous.y - this.draggingPos.current.y).toFixed(2)}px,0) scale3d(${this.outerScale.previous}, ${this.outerScale.previous}, 1)`;
149 | }
150 | }
151 |
152 | export default DraggableImage;
--------------------------------------------------------------------------------
/js/demo8/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * index.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 2020, Codrops
9 | * http://www.codrops.com
10 | */
11 | import DraggableImage from "./draggableImage";
12 | const imagesLoaded = require('imagesloaded');
13 |
14 | // Preload images
15 | const preloadImages = () => {
16 | return new Promise((resolve, reject) => {
17 | imagesLoaded(document.querySelectorAll('.img-drag, .img-trail'), {background: true}, resolve);
18 | });
19 | };
20 |
21 | // Preload fonts
22 | const preloadFonts = () => {
23 | return new Promise((resolve, reject) => {
24 | WebFont.load({
25 | typekit: {
26 | id: 'wwn4ioo'
27 | },
28 | active: resolve
29 | });
30 | });
31 | };
32 |
33 | Promise.all([
34 | preloadImages(),
35 | preloadFonts()
36 | ]).then(() => {
37 | [...document.querySelectorAll('.img-wrap')].forEach((element) => new DraggableImage(element));
38 | document.body.classList.remove('loading');
39 | });
40 |
41 |
42 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "ImageDraggingEffects",
3 | "version": "1.0.0",
4 | "description": "A set of playful dragging effects for images using various techniques.",
5 | "main": "index.js",
6 | "scripts": {
7 | "copyimages": "copyfiles --f img/10.jpg img/11.jpg dist",
8 | "start": "npm run copyimages && parcel *.html --open",
9 | "clean": "rm -rf dist/*",
10 | "build:parcel": "parcel build index.html --no-minify --no-source-maps --public-url ./ && npm run copyimages",
11 | "build": "npm run clean && npm run build:parcel"
12 | },
13 | "keywords": [],
14 | "author": "Codrops",
15 | "license": "ISC",
16 | "devDependencies": {
17 | "@babel/core": "^7.8.3",
18 | "babel-preset-env": "^1.7.0"
19 | },
20 | "dependencies": {
21 | "copyfiles": "^2.2.0",
22 | "draggabilly": "^2.2.0",
23 | "gsap": "^3.0.5",
24 | "imagesloaded": "^4.1.4",
25 | "parcel-bundler": "^1.12.4"
26 | }
27 | }
28 |
--------------------------------------------------------------------------------