// HTML
#veil
#preloader
#grid
<!-- HTML -->
<!-- SCSS -->
$fade-in-ms: 500ms;
$fade-out-ms: 600ms;
$unfold-ms: 300ms;
$rotate-ms: 150ms;
$din-light: "din-light";
$din-medium: "din-medium";
@font-face {
font-family: 'din-light';
src: url('http://labs.juan.me/gallery/css/fonts/din-light-webfont.eot');
src: url('http://labs.juan.me/gallery/css/fonts/din-light-webfont.eot?#iefix') format("embedded-opentype"), url('http://labs.juan.me/gallery/css/fonts/din-light-webfont.woff') format("woff"), url('http://labs.juan.me/gallery/css/fonts/din-light-webfont.ttf') format("truetype"), url('http://labs.juan.me/gallery/css/fonts/din-light-webfont.svg#din-bold-webfont') format("svg");
font-weight: normal;
font-style: normal;
}
@font-face {
font-family: 'din-medium';
src: url('http://labs.juan.me/gallery/css/fonts/din-medium-webfont.eot');
src: url('http://labs.juan.me/gallery/css/fonts/din-medium-webfont.eot?#iefix') format("embedded-opentype"), url('http://labs.juan.me/gallery/css/fonts/din-medium-webfont.woff') format("woff"), url('http://labs.juan.me/gallery/css/fonts/din-medium-webfont.ttf') format("truetype"), url('http://labs.juan.me/gallery/css/fonts/din-medium-webfont.svg#din-bold-webfont') format("svg");
font-weight: normal;
font-style: normal;
}
$din-light: "din-light";
$din-medium: "din-medium";
#preloader {
position: absolute;
width: 24px;
height: 24px;
left: 50%;
top: 50%;
margin: -12px 0 0 -12px;
background: url(http://labs.juan.me/gallery/images/loading-24.gif) no-repeat center center;
@include transition($fade-out-ms, opacity, ease-out);
@include opacity(1);
&.o {
@include opacity(0);
}
}
#veil {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 0;
background: rgba(0, 0, 0, 0.84);
z-index: 7;
@include transition-property(opacity, height);
@include transition-duration($unfold-ms * 3, 0s);
@include transition-timing-function(ease-out);
@include transition-delay(0s, $unfold-ms * 3);
@include opacity(0);
&.o {
@include transition-delay(0s, 0s);
@include opacity(1);
height: 100%;
}
}
#grid {
width: 100%;
height: 100%;
@include transition($fade-in-ms, opacity, ease-out);
@include opacity(0);
font-size: 20px;
&.loaded {
@include opacity(1);
}
.cell {
position: absolute;
width: 256px;
height: 256px;
overflow: hidden;
background: url(http://labs.juan.me/gallery/images/loading-10.gif) no-repeat center center;
&.ov {
overflow: visible;
}
.detail {
position: absolute;
top: 0;
left: 0;
width: 200%;
height: 200%;
@include opacity(0);
&.l {
left: -100%;
}
&.t {
top: -100%;
}
.close {
position: absolute;
top: 3%;
right: 3%;
width: 35px;
height:35px;
z-index: 9;
background: black;
@include opacity(0);
@include transition($fade-in-ms, opacity, ease-out, ($unfold-ms * 3) + $fade-in-ms);
span {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
background: url(http://labs.juan.me/gallery/images/icon-close.png) no-repeat center center;
@include transition($rotate-ms, all, ease-out);
&:hover {
@include rotate(90deg);
}
}
}
.image-detail {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: white;
@include opacity(0);
z-index: 8;
@include transition($fade-out-ms, opacity, ease-out, $unfold-ms * 3);
img {
width: 100%;
}
}
&.o {
@include opacity(1);
}
&.open {
z-index: 7;
@include perspective(500);
@include perspective-origin(25%, 0%);
.close {
@include opacity(.5);
}
.tl {
@include transform(rotateX(0deg));
@include opacity(1);
}
.bl {
@include transform(rotateX(0deg));
@include opacity(1);
}
.tr {
@include transform(rotateY(0deg));
@include opacity(1);
}
.image-detail {
@include opacity(1);
}
}
&.close {
.close {
@include transition($fade-out-ms, opacity, ease-out, 0s);
@include opacity(0);
}
.image-detail {
@include transition($fade-out-ms, opacity, ease-out, 0s);
@include opacity(0);
}
.tr {
@include transition($unfold-ms, all, linear, $fade-out-ms);
@include transform(rotateY(90deg));
@include opacity(0);
}
.bl {
@include transition($unfold-ms, all, linear, $fade-out-ms + $unfold-ms);
@include transform(rotateX(-90deg));
@include opacity(0);
}
.tl {
@include transition($unfold-ms, all, linear, $fade-out-ms + ($unfold-ms * 2));
@include transform(rotateX(-90deg));
@include opacity(0);
}
}
.tl {
position: absolute;
top: 0;
left: 0;
width: 50%;
height: 50%;
background: white;
@include transition($unfold-ms, all, linear);
@include opacity(0);
@include transform-origin(0%, 0%);
@include transform(rotateX(-90deg));
z-index: 6;
}
.bl {
position: absolute;
top: 50%;
left: 0;
width: 50%;
height: 50%;
background: white;
@include transition($unfold-ms, all, linear, $unfold-ms );
@include opacity(0);
@include transform-origin(0%, 0%);
@include transform(rotateX(-90deg));
z-index: 5;
}
.tr {
position: absolute;
top: 0;
left: 50%;
width: 50%;
height: 100%;
background: white;
z-index: 4;
@include transition($unfold-ms, all, linear, ($unfold-ms * 2));
@include opacity(0);
@include transform-origin(0%, 0%);
@include transform(rotateY(90deg));
}
}
&.no-bg {
background: none;
}
&.loaded {
.image {
img {
@include opacity(1);
}
}
.info {
display: table;
}
}
.info {
display: none;
position: absolute;
height: inherit;
width: inherit;
top: 0;
right: 0;
bottom: 0;
left: 0;
z-index: 2;
background: rgba(255, 255, 255, 0.8);
@include opacity(0);
@include transition($fade-out-ms, opacity, ease-out);
&:hover {
@include opacity(1);
}
.w {
display: table-cell;
vertical-align: middle;
h2 {
color: #333;
background: none;
text-align: center;
@include font($din-light, 100%);
padding: 0 5% 0 5%;
}
}
}
.image {
position: absolute;
height: inherit;
width: inherit;
top: 0;
right: 0;
bottom: 0;
left: 0;
z-index: 1;
img {
width: 100%;
@include transition($fade-out-ms, opacity, ease-out);
@include opacity(0);
}
}
}
}
<!-- /SCSS -->
<!-- JS -->
function App() {
var self = this;
// this.feedUrl = "json/media.json";
this.debug = true;
this.cellElement = null;
this.window = $(window);
this.grid = $("#grid");
this.fadeOutMs = 500;
this.unFoldMs = 300;
this.preloader = $("#preloader");
this.veil = $("#veil");
this.currentMedia = null;
// initialize
this._init = function() {
// load media feed
self.loadFeed(function(d) {
// add elements to the DOM
self.addToDOM(d);
self.cellElement = $(".cell");
self.window.on('resize', self.resizeHandler).resize();
// hide loader and show grid
self.preloader.addClass('o');
window.setTimeout(function() {
self.grid.addClass('loaded');
}, self.fadeOutMs);
});
// prepare pop state to load medias
window.onpopstate = function(e) {
if (e.state) self.loadMedia(e.state);
}
// click on veil will close the current media
self.veil.on('click', function(e) {
e.preventDefault();
if (self.currentMedia) self.closeMedia(self.currentMedia);
});
// hotkeys
$(document).on('keydown', function(event) {
switch (event.keyCode) {
// ESC
case 27:
// close the current media
if (self.currentMedia != null) self.closeMedia(self.currentMedia);
return false;
}
});
}
// load media.json
this.loadFeed = function(callback) {
callback(media);
// $.ajax({
// url: self.feedUrl,
// type: 'GET',
// dataType: 'json',
// complete: function(xhr, textStatus) {
// },
// success: function(data, textStatus, xhr) {
// callback(data);
// },
// error: function(xhr, textStatus, errorThrown) {
// }
// });
}
// add media elements to the DOM
this.addToDOM = function(d) {
var htmlImage = '<a href="#" class="cell image" data-id-media="{id-media}"><div class="detail"><div class="close"><span></span></div><div class="image-detail"></div><div class="tl"></div><div class="bl"></div><div class="tr"></div></div><div class="info"><div class="w"><h2>{title}</h2></div></div><div class="image"><img src="{img-src}"></div></a>',
nroMedia = d.media.length;
$.each(d.media, function(i, v) {
self.grid.append(htmlImage.replace('{img-src}', v.url).replace('{title}', v.title).replace('{id-media}', v.id));
// moving the detail view if media element is at the end of the grid
if ((i + 1) % 5 == 0) $("a[data-id-media='" + v.id + "']").find('.detail:first').addClass('l');
if (i >= (nroMedia - 5)) $("a[data-id-media='" + v.id + "']").find('.detail:first').addClass('t');
// event to load media
$("a[data-id-media='" + v.id + "']").on('click', function(e) {
e.preventDefault();
console.log(v);
self.loadMedia(v);
});
// doesn't show the image until it's fully loaded, and then will fade in.
self.grid.find("img:last").on('load', function() {
$(this).closest('a.cell').addClass("loaded");
window.setTimeout(function() {
$(this).closest('a.cell').addClass('no-bg');
}, self.fadeOutMs);
})
});
}
// load media and set push state
this.loadMedia = function(m) {
window.history.pushState(m, m.title + m.id, "/" + m.id + ".html");
if (m.id != self.currentMedia) {
self.openMedia(m);
} else {
if (self.currentMedia != null) self.closeMedia(self.currentMedia);
}
}
// open a media element
this.openMedia = function(m) {
var $cellMedia = $("a[data-id-media='" + m.id + "']"),
$detail = $cellMedia.find('.detail'),
htmlImage = '<img src="{img-src}" />',
waitForIt = 0;
// if a media element is open will close it first
if (self.currentMedia != null) {
self.closeMedia(self.currentMedia);
waitForIt = (self.unFoldMs * 2) + (self.fadeOutMs * 2);
}
window.setTimeout(function() {
// if press back button in browser it will scroll to the position of the media element
$('body, html').animate({scrollTop:$cellMedia.offset().top - 100}, 600);
$detail.find('.image-detail:first').append(htmlImage.replace('{img-src}', m.url));
$cellMedia.addClass('ov');
$detail.addClass('open o');
self.veil.addClass('o');
self.currentMedia = m.id;
}, waitForIt);
}
// close a media element
this.closeMedia = function(m) {
var $cellMedia = $("a[data-id-media='" + m + "']"),
$detail = $cellMedia.find('.detail');
$detail.addClass('close');
window.setTimeout(function() {
$detail.removeClass('open close o');
$detail.find('.image-detail:first').html('');
self.currentMedia = null;
}, (self.unFoldMs * 2) + (self.fadeOutMs * 2));
window.setTimeout(function() {
self.veil.removeClass('o');
}, self.fadeOutMs);
}
// resize handler for fluid grid
this.resizeHandler = function() {
var c = 0,
r = 0,
widthCell = Math.ceil(self.window.width() / 5);
$.each(self.cellElement, function(i, v) {
$(v).css({'top': (r * widthCell), 'left': (c * widthCell), 'width': widthCell, 'height': widthCell});
c++;
if (c % 5 == 0) {
c = 0;
r++;
}
});
}
self._init();
}
var Gallery;
$(window).load(function() {
Gallery = new App();
});
<!-- /JS -->
Be the first to comment
You can use [html][/html], [css][/css], [php][/php] and more to embed the code. Urls are automatically hyperlinked. Line breaks and paragraphs are automatically generated.