jekyll-theme-ricky 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/assets/img/a.jpg ADDED
Binary file
Binary file
data/assets/img/b.jpg ADDED
Binary file
data/assets/img/c.jpg ADDED
Binary file
data/assets/img/d.jpg ADDED
Binary file
data/assets/img/e.jpg ADDED
Binary file
data/assets/img/f.jpg ADDED
Binary file
Binary file
@@ -0,0 +1,277 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ * Card.
5
+ */
6
+ var Card = (function (window) {
7
+
8
+ /**
9
+ * Enum of CSS selectors.
10
+ */
11
+ var SELECTORS = {
12
+ container: '.card__container',
13
+ content: '.card__content',
14
+ clip: '.clip'
15
+ };
16
+
17
+ /**
18
+ * Enum of CSS classes.
19
+ */
20
+ var CLASSES = {
21
+ containerClosed: 'card__container--closed',
22
+ bodyHidden: 'body--hidden'
23
+ };
24
+
25
+ /**
26
+ * Card.
27
+ */
28
+ var Card = function (id, el) {
29
+
30
+ this.id = id;
31
+
32
+ this._el = el;
33
+
34
+ // Get elements.
35
+ this._container = $(this._el).find(SELECTORS.container)[0];
36
+ this._clip = $(this._el).find(SELECTORS.clip)[0];
37
+ this._content = $(this._el).find(SELECTORS.content)[0];
38
+
39
+ this.isOpen = false;
40
+
41
+ this._TL = null;
42
+ };
43
+
44
+ /**
45
+ * Open card.
46
+ * @param {Function} callback The callback `onCardMove`.
47
+ */
48
+ Card.prototype.openCard = function (callback) {
49
+
50
+ this._TL = new TimelineLite;
51
+
52
+ var slideContentDown = this._slideContentDown();
53
+ var clipImageIn = this._clipImageIn();
54
+ var floatContainer = this._floatContainer(callback);
55
+ var clipImageOut = this._clipImageOut();
56
+ var slideContentUp = this._slideContentUp();
57
+
58
+ // Compose sequence and use duration to overlap tweens.
59
+ this._TL.add(slideContentDown);
60
+ this._TL.add(clipImageIn, 0);
61
+ this._TL.add(floatContainer, '-=' + clipImageIn.duration() * 0.6);
62
+ // this._TL.add(clipImageOut, '-=' + floatContainer.duration() * 0.3);
63
+ this._TL.add(slideContentUp/*, '-=' + clipImageOut.duration() * 0.6*/);
64
+
65
+ this.isOpen = true;
66
+
67
+ return this._TL;
68
+ };
69
+
70
+ /**
71
+ * Slide content down.
72
+ * @private
73
+ */
74
+ Card.prototype._slideContentDown = function () {
75
+
76
+ var tween = TweenLite.to(this._content, 0.8, {
77
+ y: window.innerHeight,
78
+ ease: Expo.easeInOut
79
+ });
80
+
81
+ return tween;
82
+ };
83
+
84
+ /**
85
+ * Clip image in.
86
+ * @private
87
+ */
88
+ Card.prototype._clipImageIn = function () {
89
+
90
+ // Polygon.
91
+ var TL = new TimelineLite;
92
+
93
+ var start = [
94
+ [0, 1200],
95
+ [0, 0],
96
+ [1920, 0],
97
+ [1920, 1200]
98
+ ];
99
+
100
+ var end = [
101
+ [916, 430],
102
+ [1125, 643],
103
+ [960, 607],
104
+ [793, 570]
105
+ ];
106
+
107
+ var points = [];
108
+
109
+ // Create a tween for each point.
110
+ start.forEach(function (point, i) {
111
+
112
+ var tween = TweenLite.to(point, 1.5, end[i]);
113
+
114
+ end[i].onUpdate = function () {
115
+
116
+ points.push(point.join());
117
+
118
+ // Every 4 point update clip-path.
119
+ if (points.length === end.length) {
120
+ $(this._clip).attr('points', points.join(' '));
121
+ // Reset.
122
+ points = [];
123
+ }
124
+
125
+ }.bind(this);
126
+
127
+ tween.vars.ease = Expo.easeInOut;
128
+
129
+ // Add at position 0.
130
+ TL.add(tween, 0);
131
+
132
+ }, this);
133
+
134
+ return TL;
135
+ };
136
+
137
+ /**
138
+ * Float card to final position.
139
+ * @param {Function} callback The callback `onCardMove`.
140
+ * @private
141
+ */
142
+ Card.prototype._floatContainer = function (callback) {
143
+
144
+ $(document.body).addClass(CLASSES.bodyHidden);
145
+
146
+ var TL = new TimelineLite;
147
+
148
+ var rect = this._container.getBoundingClientRect();
149
+ var windowW = window.innerWidth;
150
+
151
+ var track = {
152
+ width: 0,
153
+ x: rect.left + (rect.width / 2),
154
+ y: rect.top + (rect.height / 2)
155
+ };
156
+
157
+ TL.set(this._container, {
158
+ width: rect.width,
159
+ height: rect.height,
160
+ x: rect.left,
161
+ y: rect.top,
162
+ position: 'fixed',
163
+ overflow: 'hidden'
164
+ });
165
+
166
+ TL.to([this._container, track], 2, {
167
+ width: windowW,
168
+ height: '100%',
169
+ x: windowW / 2,
170
+ y: 0,
171
+ xPercent: -50,
172
+ ease: Expo.easeInOut,
173
+ clearProps: 'all',
174
+ className: '-=' + CLASSES.containerClosed,
175
+ onUpdate: callback.bind(this, track),
176
+ // Fix IE: if the image is set to fixed when CLASSES.containerClosed
177
+ // is removed IE doesn't follow the tween, fix by setting
178
+ // the image position to fixed when tween is completed.
179
+ onComplete: function () {
180
+ $(this._container).addClass('card__container--fix-image');
181
+ }.bind(this)
182
+ });
183
+
184
+ return TL;
185
+ };
186
+
187
+ /**
188
+ * Clip image out.
189
+ * @private
190
+ */
191
+ Card.prototype._clipImageOut = function () {
192
+
193
+ var tween = this._clipImageIn();
194
+
195
+ tween.reverse();
196
+
197
+ return tween;
198
+ };
199
+
200
+ /**
201
+ * Slide content up.
202
+ * @private
203
+ */
204
+ Card.prototype._slideContentUp = function () {
205
+
206
+ var tween = TweenLite.to(this._content, 1, {
207
+ y: 0,
208
+ clearProps: 'all',
209
+ ease: Expo.easeInOut
210
+ });
211
+
212
+ return tween;
213
+ };
214
+
215
+ /**
216
+ * Close card.
217
+ */
218
+ Card.prototype.closeCard = function () {
219
+
220
+ TweenLite.to(this._container, 0.4, {
221
+ scrollTo: {
222
+ y: 0
223
+ },
224
+ onComplete: function () {
225
+ $(this._container).css('overflow', 'hidden');
226
+ }.bind(this),
227
+ ease: Power2.easeOut
228
+ });
229
+
230
+ this._TL.eventCallback('onReverseComplete', function () {
231
+
232
+ TweenLite.set([this._container, this._content], {
233
+ clearProps: 'all'
234
+ });
235
+
236
+ $(document.body).removeClass(CLASSES.bodyHidden);
237
+
238
+ this.isOpen = false;
239
+
240
+ }.bind(this));
241
+
242
+ return this._TL.reverse();
243
+ };
244
+
245
+ /**
246
+ * Hide card, called for all cards except the selected one.
247
+ */
248
+ Card.prototype.hideCard = function () {
249
+
250
+ var tween = TweenLite.to(this._el, 0.4, {
251
+ scale: 0.8,
252
+ autoAlpha: 0,
253
+ transformOrigin: 'center bottom',
254
+ ease: Expo.easeInOut
255
+ });
256
+
257
+ return tween;
258
+ };
259
+
260
+ /**
261
+ * Show card, called for all cards except the selected one.
262
+ */
263
+ Card.prototype.showCard = function () {
264
+
265
+ var tween = TweenLite.to(this._el, 0.5, {
266
+ scale: 1,
267
+ autoAlpha: 1,
268
+ clearProps: 'all',
269
+ ease: Expo.easeInOut
270
+ });
271
+
272
+ return tween;
273
+ };
274
+
275
+ return Card;
276
+
277
+ })(window);
@@ -0,0 +1,309 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ * Demo.
5
+ */
6
+ var demo = (function (window) {
7
+
8
+ /**
9
+ * Enum of CSS selectors.
10
+ */
11
+ var SELECTORS = {
12
+ pattern: '.pattern',
13
+ card: '.card',
14
+ cardImage: '.card__image',
15
+ cardClose: '.card__btn-close'
16
+ };
17
+
18
+ /**
19
+ * Enum of CSS classes.
20
+ */
21
+ var CLASSES = {
22
+ patternHidden: 'pattern--hidden',
23
+ polygon: 'polygon',
24
+ polygonHidden: 'polygon--hidden'
25
+ };
26
+
27
+ var ATTRIBUTES = {
28
+ index: 'data-index',
29
+ id: 'data-id'
30
+ };
31
+
32
+ /**
33
+ * Map of svg paths and points.
34
+ */
35
+ var polygonMap = {
36
+ paths: null,
37
+ points: null
38
+ };
39
+
40
+ /**
41
+ * Container of Card instances.
42
+ */
43
+ var layout = {};
44
+
45
+ /**
46
+ * Initialise demo.
47
+ */
48
+ var init = function () {
49
+
50
+ // For options see: https://github.com/qrohlf/Trianglify
51
+ var pattern = Trianglify({
52
+ width: window.innerWidth,
53
+ height: window.innerHeight,
54
+ cell_size: 90,
55
+ variance: 1,
56
+ stroke_width: 1,
57
+ x_colors: 'random',
58
+ y_colors: 'random'
59
+ }).svg(); // Render as SVG.
60
+
61
+ _mapPolygons(pattern);
62
+
63
+ _bindCards();
64
+
65
+ _bindHashChange();
66
+
67
+ _triggerOpenCard('', _getHashFromURL(location.href));
68
+ };
69
+
70
+ /**
71
+ * Store path elements, map coordinates and sizes.
72
+ * @param {Element} pattern The SVG Element generated with Trianglify.
73
+ * @private
74
+ */
75
+ var _mapPolygons = function (pattern) {
76
+
77
+ // Append SVG to pattern container.
78
+ $(SELECTORS.pattern).append(pattern);
79
+
80
+ // Convert nodelist to array,
81
+ // Used `.childNodes` because IE doesn't support `.children` on SVG.
82
+ polygonMap.paths = [].slice.call(pattern.childNodes);
83
+
84
+ polygonMap.points = [];
85
+
86
+ polygonMap.paths.forEach(function (polygon) {
87
+
88
+ // Hide polygons by adding CSS classes to each svg path (used attrs because of IE).
89
+ $(polygon).attr('class', CLASSES.polygon);
90
+
91
+ var rect = polygon.getBoundingClientRect();
92
+
93
+ var point = {
94
+ x: rect.left + rect.width / 2,
95
+ y: rect.top + rect.height / 2
96
+ };
97
+
98
+ polygonMap.points.push(point);
99
+ });
100
+
101
+ // All polygons are hidden now, display the pattern container.
102
+ $(SELECTORS.pattern).removeClass(CLASSES.patternHidden);
103
+ };
104
+
105
+ /**
106
+ * Bind Card elements.
107
+ * @private
108
+ */
109
+ var _bindCards = function () {
110
+
111
+ var elements = $(SELECTORS.card);
112
+
113
+ $.each(elements, function (card, i) {
114
+
115
+ var instance = new Card(i, card);
116
+
117
+ layout[i] = {
118
+ card: instance
119
+ };
120
+
121
+ var $card = $(card);
122
+ $card.attr(ATTRIBUTES.index, i + '');
123
+
124
+ var cardImage = $card.find(SELECTORS.cardImage);
125
+ var cardClose = $card.find(SELECTORS.cardClose);
126
+
127
+ $(cardImage).on('click', function () {
128
+ location.hash = $card.attr(ATTRIBUTES.id);
129
+ });
130
+ $(cardClose).on('click', function () {
131
+ location.hash = '';
132
+ });
133
+ });
134
+ };
135
+
136
+ /**
137
+ * Create a sequence for the open or close animation and play.
138
+ * @param {boolean} isOpenClick Flag to detect when it's a click to open.
139
+ * @param {number} id The id of the clicked card.
140
+ * @private
141
+ *
142
+ */
143
+ var _playSequence = function (isOpenClick, id) {
144
+
145
+ var card = layout[id].card;
146
+
147
+ // Prevent when card already open and user click on image.
148
+ if (card.isOpen && isOpenClick) {
149
+ return;
150
+ }
151
+
152
+ // Create timeline for the whole sequence.
153
+ var sequence = new TimelineLite({paused: true});
154
+
155
+ var tweenOtherCards = _showHideOtherCards(id);
156
+
157
+ if (!card.isOpen) {
158
+ // Open sequence.
159
+
160
+ _setPatternBgImg($(this).find(SELECTORS.cardImage).find('image'));
161
+
162
+ sequence.add(tweenOtherCards);
163
+ sequence.add(card.openCard(_onCardMove), 0);
164
+
165
+ } else {
166
+ // Close sequence.
167
+
168
+ var closeCard = card.closeCard();
169
+ var position = closeCard.duration() * 0.8; // 80% of close card tween.
170
+
171
+ sequence.add(closeCard);
172
+ sequence.add(tweenOtherCards, position);
173
+ }
174
+
175
+ sequence.play();
176
+ };
177
+
178
+ /**
179
+ * Show/Hide all other cards.
180
+ * @param {number} id The id of the clcked card to be avoided.
181
+ * @private
182
+ */
183
+ var _showHideOtherCards = function (id) {
184
+
185
+ var TL = new TimelineLite;
186
+
187
+ var selectedCard = layout[id].card;
188
+
189
+ for (var i in layout) {
190
+
191
+ if (layout.hasOwnProperty(i)) {
192
+ var card = layout[i].card;
193
+
194
+ // When called with `openCard`.
195
+ if (card.id !== id && !selectedCard.isOpen) {
196
+ TL.add(card.hideCard(), 0);
197
+ }
198
+
199
+ // When called with `closeCard`.
200
+ if (card.id !== id && selectedCard.isOpen) {
201
+ TL.add(card.showCard(), 0);
202
+ }
203
+ }
204
+ }
205
+
206
+ return TL;
207
+ };
208
+
209
+ /**
210
+ * Add card image to pattern background.
211
+ * @param {Element} image The clicked SVG Image Element.
212
+ * @private
213
+ */
214
+ var _setPatternBgImg = function (image) {
215
+
216
+ var imagePath = $(image).attr('xlink:href');
217
+
218
+ $(SELECTORS.pattern).css('background-image', 'url(' + imagePath + ')');
219
+ };
220
+
221
+ /**
222
+ * Callback to be executed on Tween update, whatever a polygon
223
+ * falls into a circular area defined by the card width the path's
224
+ * CSS class will change accordingly.
225
+ * @param {Object} track The card sizes and position during the floating.
226
+ * @private
227
+ */
228
+ var _onCardMove = function (track) {
229
+
230
+ var radius = track.width / 2;
231
+
232
+ var center = {
233
+ x: track.x,
234
+ y: track.y
235
+ };
236
+
237
+ polygonMap.points.forEach(function (point, i) {
238
+
239
+ if (_detectPointInCircle(point, radius, center)) {
240
+ $(polygonMap.paths[i]).attr('class', CLASSES.polygon + ' ' + CLASSES.polygonHidden);
241
+ } else {
242
+ $(polygonMap.paths[i]).attr('class', CLASSES.polygon);
243
+ }
244
+ });
245
+ };
246
+
247
+ /**
248
+ * Detect if a point is inside a circle area.
249
+ * @private
250
+ */
251
+ var _detectPointInCircle = function (point, radius, center) {
252
+
253
+ var xp = point.x;
254
+ var yp = point.y;
255
+
256
+ var xc = center.x;
257
+ var yc = center.y;
258
+
259
+ var d = radius * radius;
260
+
261
+ return Math.pow(xp - xc, 2) + Math.pow(yp - yc, 2) <= d;
262
+ };
263
+
264
+ /**
265
+ * initialize page view according to hash
266
+ * @private
267
+ */
268
+ var _triggerOpenCard = function (fromId, toId) {
269
+ var getIndex = function (card) {
270
+ var index = $(card).attr(ATTRIBUTES.index);
271
+ return parseInt(index, 10);
272
+ };
273
+ if (fromId) {
274
+ var fromBlogCard = $('[' + ATTRIBUTES.id + '="' + fromId + '"]')[0];
275
+ if (fromBlogCard) {
276
+ _playSequence.call(fromBlogCard, false, getIndex(fromBlogCard));
277
+ }
278
+ }
279
+ if (toId) {
280
+ var toBlogCard = $('[' + ATTRIBUTES.id + '="' + toId + '"]')[0];
281
+ if (toBlogCard) {
282
+ _playSequence.call(toBlogCard, true, getIndex(toBlogCard));
283
+ }
284
+ }
285
+ };
286
+
287
+ var _getHashFromURL = function (url) {
288
+ var a = document.createElement('a');
289
+ a.href = url;
290
+ return a.hash.slice(1);
291
+ };
292
+
293
+ var _bindHashChange = function () {
294
+ window.addEventListener('hashchange', function (e) {
295
+ var newHash = _getHashFromURL(e.newURL);
296
+ var oldHash = _getHashFromURL(e.oldURL);
297
+ _triggerOpenCard(oldHash, newHash);
298
+ });
299
+ };
300
+
301
+ // Expose methods.
302
+ return {
303
+ init: init
304
+ };
305
+
306
+ })(window);
307
+
308
+ // Kickstart Demo.
309
+ window.onload = demo.init;