├── .gitignore
├── README.md
├── css
├── component.css
├── demo.css
└── normalize.css
├── favicon.ico
├── img
├── 1.jpg
├── 2.jpg
├── 3.jpg
├── 4.jpg
├── 5.jpg
├── 6.jpg
├── close.cur
├── close.png
├── map.png
├── pins.svg
├── related
│ ├── ImageTiltEffect.jpg
│ └── TooltipStylesInspiration.png
└── sponsor
│ └── AcuityScheduling_logo.svg
├── index.html
└── js
├── imagesloaded.pkgd.min.js
├── lunar.js
└── main.js
/.gitignore:
--------------------------------------------------------------------------------
1 | *.DS_Store
2 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Simple Interactive Points Effect
2 |
3 | An interactive transparency background effect that makes images visible when specific points are hovered, showing some content once clicked.
4 |
5 | [Article on Codrops](http://tympanus.net/codrops/?p=27459)
6 |
7 | [Demo](http://tympanus.net/Development/InteractivePoints/)
8 |
9 | 
10 |
11 | ## Sponsor
12 |
13 | This demo is sponsored by [Acuity Scheduling](https://goo.gl/VqOfus).
14 |
15 | ## License
16 |
17 | Integrate or build upon it for free in your personal or commercial projects. Don't republish, redistribute or sell "as-is".
18 |
19 | Read more here: [License](http://tympanus.net/codrops/licensing/)
20 |
21 | ## Credits
22 |
23 | - [Lunar.js](https://github.com/toddmotto/lunar) by Todd Motto: SVG class module for has/add/remove/toggleClass
24 |
25 | - [Map](https://www.openstreetmap.org/way/4358417#map=18/51.50980/-0.13000) by OpenStreetMap®. OpenStreetMap® is open data, licensed under the [Open Data Commons Open Database License (ODbL)](http://opendatacommons.org/licenses/odbl/) by the [OpenStreetMap Foundation (OSMF)](OpenStreetMap Foundation). Read more here: [https://www.openstreetmap.org/copyright](https://www.openstreetmap.org/copyright)
26 |
27 | - Location pin icon made by [Madebyoliver](http://www.flaticon.com/authors/madebyoliver "Madebyoliver") from [www.flaticon.com](http://www.flaticon.com "Flaticon") is licensed by [CC 3.0 BY](http://creativecommons.org/licenses/by/3.0/ "Creative Commons BY 3.0")
28 |
29 | - Vintage London images by [Stockholm Transport Museum](https://www.flickr.com/photos/stockholmtransportmuseum_commons/), [London, England album](https://www.flickr.com/photos/stockholmtransportmuseum_commons/albums/72157627860632062).
30 |
31 | ## Misc
32 |
33 | Follow Codrops: [Twitter](http://www.twitter.com/codrops), [Facebook](http://www.facebook.com/pages/Codrops/159107397912), [Google+](https://plus.google.com/101095823814290637419), [GitHub](https://github.com/codrops), [Pinterest](http://www.pinterest.com/codrops/)
34 |
35 | [© Codrops 2016](http://www.codrops.com)
36 |
37 |
38 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/css/component.css:
--------------------------------------------------------------------------------
1 | .interactive-points {
2 | position: relative;
3 | display: inline-block;
4 | overflow: hidden;
5 | width: 100%;
6 | margin-bottom: -0.4em;
7 | background: #cfced7;
8 | }
9 |
10 | .interactive-points:focus {
11 | outline: none;
12 | }
13 |
14 | .backgrounds,
15 | .background__element {
16 | position: relative;
17 | width: 100%;
18 | }
19 |
20 | .background__element {
21 | height: 50vh;
22 | background-repeat: no-repeat;
23 | background-position: 50% 50%;
24 | background-size: cover;
25 | }
26 |
27 | .static {
28 | position: relative;
29 | display: block;
30 | margin: 0 auto;
31 | opacity: 0.5;
32 | }
33 |
34 | .points {
35 | position: absolute;
36 | top: 0;
37 | left: 0;
38 | display: none;
39 | }
40 |
41 | .static,
42 | .points {
43 | width: 100%;
44 | height: auto;
45 | }
46 |
47 | @media screen and (min-aspect-ratio: 1885/1000) {
48 | .static,
49 | .points {
50 | width: auto;
51 | height: calc(100vh - 6em);
52 | min-height: 500px;
53 | }
54 | }
55 |
56 | .points {
57 | left: 50%;
58 | -webkit-transform: translate3d(-50%,0,0);
59 | transform: translate3d(-50%,0,0);
60 | }
61 |
62 | .point {
63 | cursor: pointer;
64 | fill: #28282f;
65 | -webkit-transition: opacity 0.3s, -webkit-transform 0.3s, fill 0.3s;
66 | transition: opacity 0.3s, transform 0.3s, fill 0.3s;
67 | -webkit-transition-timing-function: cubic-bezier(0.2,1,0.3,1);
68 | transition-timing-function: cubic-bezier(0.2,1,0.3,1);
69 | }
70 |
71 | .point--active {
72 | fill: #408283;
73 | -webkit-transform: scale3d(1.3,1.3,1);
74 | transform: scale3d(1.3,1.3,1);
75 | }
76 |
77 | .point--hide {
78 | opacity: 0;
79 | pointer-events: none;
80 | -webkit-transform: translate3d(0,10px,0);
81 | transform: translate3d(0,10px,0);
82 | }
83 |
84 | .points-tooltips,
85 | .points-content {
86 | position: absolute;
87 | bottom: 0;
88 | left: 0;
89 | width: 100%;
90 | height: 100%;
91 | pointer-events: none;
92 | }
93 |
94 | .points-tooltips {
95 | display: -webkit-box;
96 | display: -ms-flexbox;
97 | display: flex;
98 | -webkit-box-orient: vertical;
99 | -webkit-box-direction: normal;
100 | -ms-flex-direction: column;
101 | flex-direction: column;
102 | -webkit-box-pack: end;
103 | -ms-flex-pack: end;
104 | justify-content: flex-end;
105 | }
106 |
107 | .point-tooltip {
108 | height: 50vh;
109 | }
110 |
111 | .point-tooltip__title {
112 | font-family: 'Source Serif Pro', serif;
113 | font-size: 1.5em;
114 | line-height: 1;
115 | margin: 0 0 0.15em;
116 | display: inline-block;
117 | background: #28282f;
118 | padding: 5px;
119 | }
120 |
121 | .point-tooltip__description {
122 | font-size: 0.85em;
123 | font-weight: 500;
124 | margin: 0;
125 | line-height: 1;
126 | display: inline-block;
127 | background: #28282f;
128 | padding: 5px;
129 | }
130 |
131 | .points-content {
132 | -webkit-transition: background 0.1s;
133 | transition: background 0.1s;
134 | }
135 |
136 | .points-content--open {
137 | cursor: url(img/close.cur), pointer;
138 | pointer-events: auto;
139 | background: rgba(50,49,59,0.6);
140 | }
141 |
142 | @supports (cursor: zoom-in) {
143 | .points-content--open {
144 | cursor: url(../img/close.png) 12 6, pointer;
145 | }
146 | }
147 |
148 | .point-content {
149 | font-size: 1.25em;
150 | position: absolute;
151 | bottom: 0;
152 | left: 0;
153 | width: 100%;
154 | min-width: 300px;
155 | padding: 0 0 3em 3em;
156 | opacity: 0;
157 | }
158 |
159 | .point-content--current {
160 | pointer-events: auto;
161 | opacity: 1;
162 | }
163 |
164 | .point-content__title {
165 | font-family: 'Source Serif Pro', serif;
166 | font-size: 2.25em;
167 | margin: 0;
168 | text-shadow: 0 1px 5px rgba(0,0,0,0.2);
169 | }
170 |
171 | .point-content__subtitle {
172 | font-family: 'Source Serif Pro', serif;
173 | font-weight: bold;
174 | margin: 0.25em 0 0;
175 | display: inline-block;
176 | background: #408283;
177 | color: #28282f;
178 | padding: 0 10px;
179 | line-height: 1.5;
180 | }
181 |
182 | .point-content__text {
183 | font-weight: 500;
184 | margin: 1em 0 0 0;
185 | }
186 |
187 | .point-content > * {
188 | opacity: 0;
189 | -webkit-transform: translate3d(0,-40px,0);
190 | transform: translate3d(0,-40px,0);
191 | -webkit-transition: opacity 0.3s, -webkit-transform 0.3s;
192 | transition: opacity 0.3s, transform 0.3s;
193 | }
194 |
195 | .point-content--current > * {
196 | opacity: 1;
197 | -webkit-transform: translate3d(0,0,0);
198 | transform: translate3d(0,0,0);
199 | }
200 |
201 | .point-content--current > *:first-child {
202 | -webkit-transition-delay: 0.1s;
203 | transition-delay: 0.1s;
204 | }
205 |
206 | .point-content--current > *:nth-child(2) {
207 | -webkit-transition-delay: 0.05s;
208 | transition-delay: 0.05s;
209 | }
210 |
211 | /* Second example */
212 | .interactive-points--alter .point-content {
213 | text-align: right;
214 | left: auto;
215 | right: 0;
216 | padding: 0 3em 3em;
217 | }
218 |
219 | @media screen and (min-width: 52.375em) {
220 | .point-content {
221 | width: 50%;
222 | }
223 | .js .points {
224 | display: block;
225 | }
226 | .js .backgrounds,
227 | .js .background__element {
228 | position: absolute;
229 | top: 0;
230 | left: 0;
231 | width: 100%;
232 | height: 100%;
233 | }
234 | .js .background__element {
235 | opacity: 0;
236 | -webkit-transition: opacity 0.1s;
237 | transition: opacity 0.1s;
238 | }
239 | .js .points-tooltip {
240 | display: block;
241 | }
242 | .js .point-tooltip {
243 | position: absolute;
244 | margin: 0.75em 0 0 0.25em;
245 | opacity: 0;
246 | -webkit-transform: translate3d(0,10px,0);
247 | transform: translate3d(0,10px,0);
248 | -webkit-transition: opacity 0.3s, -webkit-transform 0.3s;
249 | transition: opacity 0.3s, transform 0.3s;
250 | }
251 | .js .point-tooltip--current {
252 | opacity: 1;
253 | -webkit-transform: translate3d(0,0,0);
254 | transform: translate3d(0,0,0);
255 | }
256 | }
257 |
258 |
259 |
260 |
--------------------------------------------------------------------------------
/css/demo.css:
--------------------------------------------------------------------------------
1 | *, *::after, *::before { -webkit-box-sizing: border-box; box-sizing: border-box; }
2 |
3 | body {
4 | font-family: 'Avenir Next', Avenir, 'Helvetica Neue', Helvetica, Arial, sans-serif;
5 | color: #fff;
6 | background: #34343d;
7 | -webkit-font-smoothing: antialiased;
8 | -moz-osx-font-smoothing: grayscale;
9 | text-align: center;
10 | }
11 |
12 | a {
13 | outline: none;
14 | color: #60B8B9;
15 | text-decoration: none;
16 | }
17 |
18 | a:hover, a:focus {
19 | color: #fff;
20 | }
21 |
22 | .hidden {
23 | position: absolute;
24 | overflow: hidden;
25 | width: 0;
26 | height: 0;
27 | pointer-events: none;
28 | }
29 |
30 | .message {
31 | font-weight: bold;
32 | color: #914a58;
33 | background: #f0d4d8;
34 | font-size: 0.85em;
35 | margin: 0;
36 | padding: 1em;
37 | display: none;
38 | }
39 |
40 | /* Icons */
41 | .icon-link {
42 | padding: 0 0.5em;
43 | margin: 0 0 0 auto;
44 | font-size: 0.85em;
45 | white-space: nowrap;
46 | }
47 |
48 | .icon {
49 | display: inline-block;
50 | vertical-align: middle;
51 | width: 1.5em;
52 | height: 1.5em;
53 | margin: 0 auto;
54 | fill: currentColor;
55 | }
56 |
57 | .icon-text {
58 | line-height: 1;
59 | vertical-align: middle;
60 | padding: 0.35em;
61 | font-weight: bold;
62 | display: inline-block;
63 | }
64 |
65 | main {
66 | max-width: 1885px;
67 | display: inline-block;
68 | margin: 0 auto;
69 | position: relative;
70 | text-align: left;
71 | }
72 |
73 | /* Header */
74 | .codrops-header {
75 | position: relative;
76 | padding: 1em;
77 | width: 100%;
78 | display: -webkit-box;
79 | display: -ms-flexbox;
80 | display: -webkit-flex;
81 | display: flex;
82 | -webkit-box-orient: horizontal;
83 | -webkit-box-direction: normal;
84 | -ms-flex-direction: row;
85 | -webkit-flex-direction: row;
86 | flex-direction: row;
87 | -webkit-align-items: center;
88 | align-items: center;
89 | z-index: 10;
90 | background: #28282f;
91 | }
92 |
93 | .codrops-header__title {
94 | margin: 0;
95 | letter-spacing: -1px;
96 | font-size: 1.65em;
97 | white-space: nowrap;
98 | line-height: 1;
99 | font-family: 'Source Serif Pro', serif;
100 | }
101 |
102 | .codrops-header__tagline {
103 | margin: 0 0 0 1.5em;
104 | color: #495050;
105 | font-weight: bold;
106 | }
107 |
108 | /* Top Navigation Style */
109 | .codrops-links {
110 | position: relative;
111 | display: inline-block;
112 | text-align: center;
113 | white-space: nowrap;
114 | font-size: 0.8em;
115 | margin: 0 1em 0 0;
116 | }
117 |
118 | .codrops-links::after {
119 | position: absolute;
120 | top: 15%;
121 | left: 50%;
122 | width: 1px;
123 | height: 70%;
124 | background: currentColor;
125 | opacity: 0.2;
126 | content: '';
127 | -webkit-transform: rotate3d(0,0,1,22.5deg);
128 | transform: rotate3d(0,0,1,22.5deg);
129 | }
130 |
131 | .codrops-icon {
132 | display: inline-block;
133 | margin: 0.5em;
134 | padding: 0.5em;
135 | }
136 |
137 | /* Demo links */
138 | .codrops-demos {
139 | margin: 0 0 0 auto;
140 | text-align: right;
141 | }
142 |
143 | .codrops-demos a {
144 | display: inline-block;
145 | margin: 0 0.5em;
146 | font-weight: bold;
147 | }
148 |
149 | .codrops-demos a.current-demo {
150 | color: #28282f;
151 | }
152 |
153 | /* Content */
154 | .content {
155 | background: #28282f;
156 | }
157 |
158 | .content__inner {
159 | max-width: 1000px;
160 | margin: 0 auto;
161 | padding: 8em 10% 4em;
162 | }
163 |
164 | .content__title,
165 | .content__subtitle {
166 | font-family: 'Source Serif Pro', serif;
167 | }
168 |
169 | .content__title {
170 | font-size: 3em;
171 | margin: 0;
172 | }
173 |
174 | .content__subtitle {
175 | font-size: 2em;
176 | font-weight: normal;
177 | margin: 0.25em 0 0;
178 | color: #9f9da7;
179 | }
180 |
181 | .content p {
182 | font-size: 1.175em;
183 | line-height: 1.6;
184 | margin: 1.5em 0;
185 | }
186 |
187 | p.margin-paragraph {
188 | margin: 8em 0 1.5em;
189 | }
190 |
191 | /* Related demos */
192 | .content--related {
193 | padding: 4em 1em;
194 | text-align: center;
195 | font-weight: bold;
196 | background: #1c1c21;
197 | color: #495050;
198 | }
199 |
200 | .content--related a:hover,
201 | .content--related a:focus {
202 | color: #fff;
203 | }
204 |
205 | .media-item {
206 | display: inline-block;
207 | padding: 1em;
208 | vertical-align: top;
209 | -webkit-transition: color 0.3s;
210 | transition: color 0.3s;
211 | }
212 |
213 | .media-item__img {
214 | max-width: 100%;
215 | opacity: 0.3;
216 | -webkit-transition: opacity 0.3s;
217 | transition: opacity 0.3s;
218 | }
219 |
220 | .media-item:hover .media-item__img,
221 | .media-item:focus .media-item__img {
222 | opacity: 1;
223 | }
224 |
225 | .media-item__title {
226 | margin: 0;
227 | padding: 0.5em;
228 | font-size: 1em;
229 | }
230 |
231 | /* Sponsor */
232 | .pater {
233 | display: none;
234 | position: relative;
235 | background: rgba(96,184,185,0.6);
236 | padding: 2.5em 1em 2.5em;
237 | width: 100%;
238 | pointer-events: auto;
239 | }
240 |
241 | .pater:focus {
242 | outline: none;
243 | }
244 |
245 | .pater::after {
246 | content: 'Sponsored by';
247 | position: absolute;
248 | top: 20px;
249 | left: 20px;
250 | color: #408283;
251 | font-size: 0.65em;
252 | font-weight: bold;
253 | }
254 |
255 | .pater__img {
256 | max-width: 100%;
257 | }
258 |
259 | .pater__title {
260 | font-size: 1em;
261 | color: #fff;
262 | margin: 0 0 0.25em 10px;
263 | }
264 |
265 | .pater__description {
266 | color: #1a2638;
267 | font-size: 0.85em;
268 | font-weight: 600;
269 | margin: 0 0 0 10px;
270 | }
271 |
272 | .pater__description strong {
273 | color: #ffe38e;
274 | }
275 |
276 | .pater--responsive {
277 | display: block;
278 | }
279 |
280 | @media screen and (min-width: 52.375em) {
281 | .pater {
282 | display: block;
283 | position: absolute;
284 | bottom: 0;
285 | right: 0;
286 | width: 400px;
287 | padding: 2.5em 1em 1em;
288 | -webkit-transform: translate3d(0,3.5em,0);
289 | transform: translate3d(0,3.5em,0);
290 | -webkit-transition: background 0.3s, -webkit-transform 0.3s;
291 | transition: background 0.3s, transform 0.3s;
292 | }
293 | .points-content--open ~ .pater {
294 | pointer-events: none;
295 | -webkit-transform: translate3d(0,100%,0);
296 | transform: translate3d(0,100%,0);
297 | }
298 | .pater:focus,
299 | .pater:hover {
300 | background: rgba(96,184,185,1);
301 | -webkit-transform: translate3d(0,0,0);
302 | transform: translate3d(0,0,0);
303 | }
304 | .pater__img {
305 | -webkit-transform-origin: 0% 50%;
306 | transform-origin: 0% 50%;
307 | -webkit-transform: scale(1.5);
308 | transform: scale(1.5);
309 | -webkit-transition: -webkit-transform 0.3s;
310 | transition: transform 0.3s;
311 | }
312 | .pater:focus .pater__img,
313 | .pater:hover .pater__img {
314 | -webkit-transform: scale(1);
315 | transform: scale(1);
316 | }
317 | .pater__description {
318 | opacity: 0;
319 | -webkit-transform: translate3d(0,1em,0);
320 | transform: translate3d(0,1em,0);
321 | -webkit-transition: opacity 0.3s, -webkit-transform 0.3s;
322 | transition: opacity 0.3s, transform 0.3s;
323 | }
324 |
325 | .pater:focus .pater__description,
326 | .pater:hover .pater__description {
327 | -webkit-transform: translate3d(0,0,0);
328 | transform: translate3d(0,0,0);
329 | opacity: 1;
330 | }
331 | .pater--responsive {
332 | display: none;
333 | }
334 | }
335 |
336 | @media screen and (max-width: 52.375em) {
337 | .codrops-header {
338 | padding: 0.25em;
339 | font-size: 0.65em;
340 | }
341 | .codrops-header__tagline {
342 | display: none;
343 | }
344 | .content {
345 | font-size: 0.75em;
346 | }
347 | .message {
348 | display: block;
349 | }
350 | }
351 |
--------------------------------------------------------------------------------
/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/InteractivePoints/8419b6377dba812c39c7610688e2b0017a1e4676/favicon.ico
--------------------------------------------------------------------------------
/img/1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codrops/InteractivePoints/8419b6377dba812c39c7610688e2b0017a1e4676/img/1.jpg
--------------------------------------------------------------------------------
/img/2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codrops/InteractivePoints/8419b6377dba812c39c7610688e2b0017a1e4676/img/2.jpg
--------------------------------------------------------------------------------
/img/3.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codrops/InteractivePoints/8419b6377dba812c39c7610688e2b0017a1e4676/img/3.jpg
--------------------------------------------------------------------------------
/img/4.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codrops/InteractivePoints/8419b6377dba812c39c7610688e2b0017a1e4676/img/4.jpg
--------------------------------------------------------------------------------
/img/5.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codrops/InteractivePoints/8419b6377dba812c39c7610688e2b0017a1e4676/img/5.jpg
--------------------------------------------------------------------------------
/img/6.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codrops/InteractivePoints/8419b6377dba812c39c7610688e2b0017a1e4676/img/6.jpg
--------------------------------------------------------------------------------
/img/close.cur:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codrops/InteractivePoints/8419b6377dba812c39c7610688e2b0017a1e4676/img/close.cur
--------------------------------------------------------------------------------
/img/close.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codrops/InteractivePoints/8419b6377dba812c39c7610688e2b0017a1e4676/img/close.png
--------------------------------------------------------------------------------
/img/map.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codrops/InteractivePoints/8419b6377dba812c39c7610688e2b0017a1e4676/img/map.png
--------------------------------------------------------------------------------
/img/pins.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
9 |
10 |
11 |
13 |
15 |
17 |
19 |
21 |
23 |
24 |
--------------------------------------------------------------------------------
/img/related/ImageTiltEffect.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codrops/InteractivePoints/8419b6377dba812c39c7610688e2b0017a1e4676/img/related/ImageTiltEffect.jpg
--------------------------------------------------------------------------------
/img/related/TooltipStylesInspiration.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codrops/InteractivePoints/8419b6377dba812c39c7610688e2b0017a1e4676/img/related/TooltipStylesInspiration.png
--------------------------------------------------------------------------------
/img/sponsor/AcuityScheduling_logo.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
22 | Asset 1
23 |
24 |
25 |
26 |
29 |
32 |
34 |
37 |
41 |
43 |
44 |
46 |
48 |
52 |
53 |
56 |
58 |
60 |
62 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
73 |
74 |
76 |
79 |
80 |
81 |
82 |
83 |
84 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Interactive Points | Codrops
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
19 |
20 |
21 |
22 |
23 |
24 | arrow
25 |
26 |
27 |
28 | drop
29 |
30 |
31 |
32 | github logo
33 |
34 |
35 |
36 |
37 |
38 |
47 | Please view this demo on a larger screen.
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
74 |
75 |
76 |
The Rupert Connection
77 |
24th of February, 1927
78 |
Descended from astronomers encyclopaedia galactica from which we spring worldlets intelligent beings gathered by gravity billions.
79 |
80 |
81 |
Swiss Court, Miss
82 |
3rd of March, 1928
83 |
Hydrogen atoms circumnavigated Cambrian explosion, a mote of dust suspended in a sunbeam Hypatia.
84 |
85 |
86 |
Hiding in Bear Street
87 |
19th of July, 1927
88 |
From which we spring the ash of stellar alchemy from which we spring emerged into consciousness, great turbulent clouds rich in heavy atoms.
89 |
90 |
91 |
Leicester Square Love
92 |
12th of August, 1930
93 |
A mote of dust suspended in a sunbeam are creatures of the cosmos decipherment, Orion's sword corpus callosum galaxies shores of the cosmic ocean.
94 |
95 |
96 |
Oxendon of Oxes
97 |
26th of March, 1927
98 |
Extraplanetary concept of the number one vanquish the impossible culture trillion the sky calls to us.
99 |
100 |
101 |
Haymarket Forever
102 |
14th of January, 1927
103 |
Birth, are creatures of the cosmos Cambrian explosion colonies great turbulent clouds cosmos are creatures of the cosmos! Great turbulent clouds.
104 |
105 |
106 |
107 |
108 | Developer Friendly Appointment Scheduling
109 | Get your clients off their phones with online appointment scheduling from Acuity Scheduling and just 2 lines of code. Get started for free!
110 |
111 |
112 |
113 |
114 | Developer Friendly Appointment Scheduling
115 | Get your clients off their phones with online appointment scheduling from Acuity Scheduling and just 2 lines of code. Get started for free!
116 |
117 |
118 |
119 |
Seeing the Past in a New Light
120 |
Life can only be understood backwards; but it must be lived forwards.
121 |
Extraordinary claims require extraordinary evidence billions upon billions, great turbulent clouds preserve and cherish that pale blue dot not a sunrise but a galaxyrise! The only home we've ever known as a patch of light. Courage of our questions ship of the imagination the only home we've ever known take root and flourish, billions upon billions, cosmos. Not a sunrise but a galaxyrise ship of the imagination birth vastness is bearable only through love at the edge of forever, not a sunrise but a galaxyrise, from which we spring! Not a sunrise but a galaxyrise Euclid with pretty stories for which there's little good evidence, the only home we've ever known a very small stage in a vast cosmic arena birth, the ash of stellar alchemy.
122 |
The following example shows some different configuration options:
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
151 |
152 |
153 |
The Rupert Connection
154 |
24th of February, 1927
155 |
Descended from astronomers encyclopaedia galactica from which we spring worldlets intelligent beings gathered by gravity billions.
156 |
157 |
158 |
Swiss Court, Miss
159 |
3rd of March, 1928
160 |
Hydrogen atoms circumnavigated Cambrian explosion, a mote of dust suspended in a sunbeam Hypatia.
161 |
162 |
163 |
Hiding in Bear Street
164 |
19th of July, 1927
165 |
From which we spring the ash of stellar alchemy from which we spring emerged into consciousness, great turbulent clouds rich in heavy atoms.
166 |
167 |
168 |
Leicester Square Love
169 |
12th of August, 1930
170 |
A mote of dust suspended in a sunbeam are creatures of the cosmos decipherment, Orion's sword corpus callosum galaxies shores of the cosmic ocean.
171 |
172 |
173 |
Oxendon of Oxes
174 |
26th of March, 1927
175 |
Extraplanetary concept of the number one vanquish the impossible culture trillion the sky calls to us.
176 |
177 |
178 |
Haymarket Forever
179 |
14th of January, 1927
180 |
Birth, are creatures of the cosmos Cambrian explosion colonies great turbulent clouds cosmos are creatures of the cosmos! Great turbulent clouds.
181 |
182 |
183 |
184 |
185 |
198 |
199 |
200 |
201 |
202 |
213 |
214 |
215 |
--------------------------------------------------------------------------------
/js/imagesloaded.pkgd.min.js:
--------------------------------------------------------------------------------
1 | /*!
2 | * imagesLoaded PACKAGED v4.1.0
3 | * JavaScript is all like "You images are done yet or what?"
4 | * MIT License
5 | */
6 |
7 | !function(t,e){"function"==typeof define&&define.amd?define("ev-emitter/ev-emitter",e):"object"==typeof module&&module.exports?module.exports=e():t.EvEmitter=e()}(this,function(){function t(){}var e=t.prototype;return e.on=function(t,e){if(t&&e){var i=this._events=this._events||{},n=i[t]=i[t]||[];return-1==n.indexOf(e)&&n.push(e),this}},e.once=function(t,e){if(t&&e){this.on(t,e);var i=this._onceEvents=this._onceEvents||{},n=i[t]=i[t]||[];return n[e]=!0,this}},e.off=function(t,e){var i=this._events&&this._events[t];if(i&&i.length){var n=i.indexOf(e);return-1!=n&&i.splice(n,1),this}},e.emitEvent=function(t,e){var i=this._events&&this._events[t];if(i&&i.length){var n=0,o=i[n];e=e||[];for(var r=this._onceEvents&&this._onceEvents[t];o;){var s=r&&r[o];s&&(this.off(t,o),delete r[o]),o.apply(this,e),n+=s?0:1,o=i[n]}return this}},t}),function(t,e){"use strict";"function"==typeof define&&define.amd?define(["ev-emitter/ev-emitter"],function(i){return e(t,i)}):"object"==typeof module&&module.exports?module.exports=e(t,require("ev-emitter")):t.imagesLoaded=e(t,t.EvEmitter)}(window,function(t,e){function i(t,e){for(var i in e)t[i]=e[i];return t}function n(t){var e=[];if(Array.isArray(t))e=t;else if("number"==typeof t.length)for(var i=0;i 0 ? this.wrapper.offsetWidth/this.options.viewportFactor : this.options.maxDistance;
88 | if( this.dmax < this.options.activeOn ) {
89 | this.options.activeOn = this.dmax-5; // todo
90 | }
91 | // Init/Bind events.
92 | this._initEvents();
93 | }
94 |
95 | /**
96 | * Point options/settings.
97 | */
98 | Point.prototype.options = {
99 | // Maximum opacity that the bgEl can have.
100 | maxOpacity : 1,
101 | // When the mouse is [activeOn]px away from the point, its image gets opacity = this.options.maxOpacity.
102 | activeOn : 20,
103 | // The distance from the mouse pointer to a Point where the opacity of the background element is 0.
104 | maxDistance : 100,
105 | // If viewportFactor is different than -1, then the maxDistance will be overwritten by [window´s width / viewportFactor]
106 | viewportFactor : -1,
107 | onActive : function() { return false; },
108 | onInactive : function() { return false; },
109 | onClick : function() { return false; }
110 | };
111 |
112 | /**
113 | * Initialize/Bind events.
114 | */
115 | Point.prototype._initEvents = function() {
116 | var self = this;
117 |
118 | // Mousemove event.
119 | this._throttleMousemove = throttle(function(ev) {
120 | requestAnimationFrame(function() {
121 | // Mouse position relative to the mapEl.
122 | var mousepos = getMousePos(ev);
123 | // Calculate the opacity value.
124 | if( self.bgEl ) {
125 | // Distance from the position of the point to the mouse position.
126 | var distance = distancePoints(mousepos.x - docScrolls.left, mousepos.y - docScrolls.top, self.position.x - docScrolls.left, self.position.y - docScrolls.top),
127 | // Convert this distance to a opacity value. (distance = 0 -> opacity = 1).
128 | opacity = self._distanceToOpacity(distance);
129 |
130 | self.bgEl.style.opacity = opacity;
131 |
132 | // Callback
133 | if( !self.isActive && opacity === self.options.maxOpacity ) {
134 | self.options.onActive();
135 | self.isActive = true;
136 | }
137 |
138 | if( opacity !== self.options.maxOpacity && self.isActive ) {
139 | self.options.onInactive();
140 | self.isActive = false;
141 | }
142 | }
143 | });
144 | }, 20);
145 | this.wrapper.addEventListener('mousemove', this._throttleMousemove);
146 |
147 | // Clicking a point.
148 | this._click = function(ev) {
149 | // Callback.
150 | self.options.onClick();
151 | };
152 | this.el.addEventListener('click', this._click);
153 |
154 | // Window resize.
155 | this._throttleResize = throttle(function() {
156 | // Update Point´s position.
157 | self.position = self._updatePosition();
158 | // Update dmax
159 | if( self.options.viewportFactor != -1 && self.options.viewportFactor > 0 ) {
160 | self.dmax = self.wrapper.offsetWidth/self.options.viewportFactor;
161 | }
162 | }, 100);
163 | window.addEventListener('resize', this._throttleResize);
164 |
165 | // Set the opacity of the bgEl to 0 when leaving the wrapper area..
166 | this.wrapper.addEventListener('mouseleave', function() {
167 | if( !self.isActive ) {
168 | self.bgEl.style.opacity = 0;
169 | }
170 | });
171 | };
172 |
173 | /**
174 | * Update Point´s position.
175 | */
176 | Point.prototype._updatePosition = function() {
177 | var rect = this.el.getBoundingClientRect(), bbox = this.el.getBBox();
178 | // Also update origins..
179 | this.el.style.transformOrigin = this.el.style.WebkitTransformOrigin = (bbox.x + rect.width/2) + 'px ' + (bbox.y + rect.height) + 'px';
180 | return {x : rect.left + rect.width/2 + docScrolls.left, y : rect.top + rect.height/2 + docScrolls.top};
181 | };
182 |
183 | /**
184 | * Maps the distance to opacity.
185 | */
186 | Point.prototype._distanceToOpacity = function(d) {
187 | return Math.min(Math.max(lineEq(this.options.maxOpacity, 0, this.options.activeOn, this.dmax, d), 0), this.options.maxOpacity);
188 | };
189 |
190 | /**
191 | * Hides the Point.
192 | */
193 | Point.prototype.hide = function() {
194 | lunar.addClass(this.el, 'point--hide');
195 | };
196 |
197 | /**
198 | *
199 | */
200 | Point.prototype.show = function() {
201 | lunar.removeClass(this.el, 'point--hide')
202 | };
203 |
204 | /**
205 | *
206 | */
207 | Point.prototype.pause = function() {
208 | this.wrapper.removeEventListener('mousemove', this._throttleMousemove);
209 | };
210 |
211 | /**
212 | *
213 | */
214 | Point.prototype.resume = function() {
215 | this.wrapper.addEventListener('mousemove', this._throttleMousemove);
216 | };
217 |
218 | /**
219 | * PointsMap obj.
220 | */
221 | function PointsMap(el, options) {
222 | this.el = el;
223 | // Options/Settings.
224 | this.options = extend( {}, this.options );
225 | extend( this.options, options );
226 |
227 | // Backgrounds container.
228 | this.bgsWrapper = this.el.querySelector('.backgrounds');
229 | if( !this.bgsWrapper ) { return; }
230 |
231 | // Background elements.
232 | this.bgElems = [].slice.call(this.bgsWrapper.querySelectorAll('.background__element'));
233 | // Total background elements.
234 | this.bgElemsTotal = this.bgElems.length;
235 | if( this.bgElemsTotal <= 1 ) { return; }
236 |
237 | // Points container.
238 | this.pointsWrapper = this.el.querySelector('.points');
239 | if( !this.pointsWrapper || getComputedStyle(this.pointsWrapper, null).display === 'none' ) { return; }
240 |
241 | // Points tooltips
242 | this.tooltips = [].slice.call(this.el.querySelector('.points-tooltips').children);
243 |
244 | // Points´s content
245 | this.pointsContentWrapper = this.el.querySelector('.points-content');
246 | this.contents = [].slice.call(this.pointsContentWrapper.children);
247 |
248 | // Init..
249 | this._init();
250 | }
251 |
252 | /**
253 | * PointsMap options/settings.
254 | */
255 | PointsMap.prototype.options = {
256 | // Maximum opacity that the background element of a Point can have when the point is active (mouse gets closer to it).
257 | maxOpacityOnActive : 0.3,
258 | // The distance from the mouse pointer to a Point where the opacity of the background element is 0.
259 | maxDistance : 100,
260 | // If viewportFactor is different than -1, then the maxDistance will be overwritten by [point´s parent width / viewportFactor]
261 | viewportFactor : 9,
262 | // When the mouse is [activeOn]px away from one point, its image gets opacity = point.options.maxOpacity.
263 | activeOn : 30
264 | };
265 |
266 | /**
267 | * Init.
268 | */
269 | PointsMap.prototype._init = function() {
270 | var self = this,
271 | onLoaded = function() {
272 | // Create the Points.
273 | self._createPoints();
274 | };
275 |
276 | // Preload all images.
277 | imagesLoaded(this.bgsWrapper, { background: true }, onLoaded);
278 |
279 | // Init/Bind events.
280 | this._initEvents();
281 | };
282 |
283 | /**
284 | * Init/Bind events.
285 | */
286 | PointsMap.prototype._initEvents = function() {
287 | var self = this;
288 |
289 | // Window resize.
290 | this._throttleResize = throttle(function() {
291 | // Update Document scroll values.
292 | docScrolls = {left : document.body.scrollLeft + document.documentElement.scrollLeft, top : document.body.scrollTop + document.documentElement.scrollTop};
293 | }, 100);
294 | window.addEventListener('resize', this._throttleResize);
295 |
296 | // Close content.
297 | this._closeContent = function() {
298 | var currentPoint = self.points[self.currentPoint];
299 | currentPoint.isActive = false;
300 | // Hide Point´s bgEl.
301 | currentPoint.bgEl.style.opacity = 0;
302 | // Hide content.
303 | self.pointsContentWrapper.classList.remove('points-content--open');
304 | self.contents[self.currentPoint].classList.remove('point-content--current');
305 | // Start mousemove event on Points.
306 | self._pointsAction('resume');
307 | // Show all points.
308 | self._pointsAction('show');
309 | };
310 | this.pointsContentWrapper.addEventListener('click', this._closeContent);
311 |
312 | // Keyboard navigation events.
313 | this.el.addEventListener('keydown', function(ev) {
314 | var keyCode = ev.keyCode || ev.which;
315 | if( keyCode === 27 ) {
316 | self._closeContent();
317 | }
318 | });
319 | };
320 |
321 | /**
322 | * Create the Points.
323 | */
324 | PointsMap.prototype._createPoints = function() {
325 | this.points = [];
326 |
327 | var self = this;
328 | [].slice.call(this.pointsWrapper.querySelectorAll('.point')).forEach(function(point, pos) {
329 | var p = new Point(point, self.bgElems[pos], self.el, {
330 | maxOpacity : self.options.maxOpacityOnActive,
331 | activeOn : self.options.activeOn,
332 | maxDistance : self.options.maxDistance,
333 | viewportFactor : self.options.viewportFactor,
334 | onActive : function() {
335 | // Add class active (scales up the pin and changes the fill color).
336 | lunar.addClass(self.points[pos].el, 'point--active');
337 | // Hide all other points.
338 | self._pointsAction('hide', pos);
339 | // Show tooltip.
340 | var tooltip = self.tooltips[pos];
341 | tooltip.classList.add('point-tooltip--current');
342 | // Position tooltip.
343 | var rect = self.points[pos].el.getBoundingClientRect(),
344 | bounds = self.el.getBoundingClientRect();
345 |
346 | tooltip.style.left = rect.left - bounds.left + rect.width/2 + 'px';
347 | tooltip.style.top = rect.top - bounds.top + rect.height + 'px';
348 | },
349 | onInactive : function() {
350 | lunar.removeClass(self.points[pos].el, 'point--active');
351 | // Show all points.
352 | self._pointsAction('show', pos);
353 | // Hide tooltip.
354 | self.tooltips[pos].classList.remove('point-tooltip--current');
355 | },
356 | onClick : function() {
357 | self.currentPoint = pos;
358 | lunar.removeClass(self.points[pos].el, 'point--active');
359 | // Hide the current point (and all other points).
360 | self._pointsAction('hide');
361 | // Hide tooltip.
362 | self.tooltips[pos].classList.remove('point-tooltip--current');
363 | // Stop mousemove event on Points.
364 | self._pointsAction('pause');
365 | // Show Point´s bgEl.
366 | self.points[pos].bgEl.style.opacity = 1;
367 | // Show content.
368 | self.pointsContentWrapper.classList.add('points-content--open');
369 | self.contents[pos].classList.add('point-content--current');
370 | }
371 | });
372 | self.points.push(p);
373 | });
374 | };
375 |
376 | /**
377 | * Calls a Point´s fn. Excludes the point with index = excludedPoint.
378 | */
379 | PointsMap.prototype._pointsAction = function(action, excludedPoint) {
380 | for(var i = 0, len = this.points.length; i < len; ++i) {
381 | if( i !== excludedPoint ) {
382 | this.points[i][action]();
383 | }
384 | }
385 | };
386 |
387 | window.PointsMap = PointsMap;
388 | document.documentElement.className = 'js';
389 |
390 | })(window);
--------------------------------------------------------------------------------