Skip to content

Instantly share code, notes, and snippets.

@ashconnell
Last active August 29, 2015 14:20
Show Gist options
  • Save ashconnell/0c2bff1138977b9af6da to your computer and use it in GitHub Desktop.
Save ashconnell/0c2bff1138977b9af6da to your computer and use it in GitHub Desktop.
Image Viewer/Modal
.image-modal {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 150;
opacity: 1;
transition: opacity .15s ease;
overflow: hidden;
.close {
position: absolute;
top: 20px;
right: 20px;
padding: 12px 25px;
font-size: 13px;
font-weight: 500;
color: #fff;
text-transform: uppercase;
background: rgba($white, .26);
&:hover {
cursor: pointer;
background: rgba($white, .36);
}
}
.overlay {
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
background: rgba($black, .86);
opacity: 0;
transition: all .15s ease-in-out;
}
.image {
position: absolute;
top: 0;
left: 0;
background-size: cover;
background-position: center;
background-repeat: no-repeat;
box-shadow: 0 2px 10px rgba($black, .4);
transform: translate3d(0, 0, 0);
&.animate {
transition: all .15s ease-in-out;
}
}
}
// Sass styles
//
// .image {
// width: 100px;
// background-color: rgba(0, 0, 0, .1);
// background-size: cover;
// background-position: center;
// background-repeat: no-repeat;
// border-radius: 2px;
// position: relative;
// overflow: hidden;
// &:after {
// content: '';
// display: block;
// padding-bottom: 56.25% // 16:9 ratio
// }
// }
.image(ng-style='imageStyle(item.imageUrl)' image-viewer='item.imageUrl')
/* global ionic */
(function () {
'use strict';
angular
.module('app.core.imageModal')
.directive('imageModal', imageModal);
// --------------------
/* @ngInject */
function imageModal ($window, $document, $animate, $timeout) {
return {
restrict: 'E',
templateUrl: 'imageModal.html',
link: link
};
// -----
function link (scope, elem) {
var rootElem;
var imageElem;
var overlayElem;
var img;
scope.close = hide;
scope.$on('imageModal:close', hide);
// force digest then init
$timeout(init, 100);
// -----
function init () {
// element refs
rootElem = angular.element(elem[0].getElementsByClassName('image-modal'));
imageElem = angular.element(elem[0].getElementsByClassName('image'));
overlayElem = angular.element(elem[0].getElementsByClassName('overlay'));
// prevent scrolling
rootElem.on('mousewheel touchmove', preventScroll);
// watch for resizes
angular.element($window).on('resize', onWindowResize);
// show the dialog
overlayElem.css('opacity', 1);
// begin loading
loadImage();
}
function loadImage () {
img = new Image();
img.addEventListener('load', onImageLoaded, false);
img.src = scope.imageUrl;
imageElem.css('background-image', 'url("' + scope.imageUrl + '")');
}
function onImageLoaded () {
// with start transition
if (scope.startElem) {
setPosition(getStartPos());
raf(function () {
$timeout(function () { // required for android, why doesnt raf work?
toggleAnimate(true);
raf(function () {
setPosition(getEndPos());
});
});
});
// no start transition
} else {
setPosition(getEndPos());
}
}
function setPosition (pos) {
imageElem.css('top', pos.top + 'px');
imageElem.css('left', pos.left + 'px');
imageElem.css('width', pos.width + 'px');
imageElem.css('height', pos.height + 'px');
}
function getStartPos () {
var rect = scope.startElem[0].getBoundingClientRect();
return {
top: rect.top,
left: rect.left,
width: scope.startElem[0].clientWidth,
height: scope.startElem[0].clientHeight
};
}
function toggleAnimate (shouldAnimate) {
var method = shouldAnimate ? 'addClass' : 'removeClass';
imageElem[method]('animate');
}
function onWindowResize () {
toggleAnimate(false);
raf(function () {
setPosition(getEndPos());
});
}
function getEndPos () {
// Dimensions
var padding = 0;
var maxWidth = rootElem[0].clientWidth - (padding * 2);
var maxHeight = rootElem[0].clientHeight - (padding * 2);
var imgWidth = img.width;
var imgHeight = img.height;
var width;
var height;
var widthScaler = imgWidth / imgHeight;
var heightScaler = imgHeight / imgWidth;
// portrait
if (imgHeight > imgWidth) {
height = imgHeight > maxHeight ? maxHeight : imgHeight;
width = height * widthScaler;
// landscape / square
} else {
width = imgWidth > maxWidth ? maxWidth : imgWidth;
height = width * heightScaler;
}
// check over-height
if (height > maxHeight) {
height = maxHeight;
width = height * widthScaler;
}
// check over-width
if (width > maxWidth) {
width = maxWidth;
height = width * heightScaler;
}
// Position
var winWidth = rootElem[0].clientWidth;
var winHeight = rootElem[0].clientHeight;
var top = (winHeight - height) / 2;
var left = (winWidth - width) / 2;
return {
top: top,
left: left,
width: width,
height: height
};
}
function hide () {
angular.element($window).off('resize', onWindowResize);
elem.remove();
}
function preventScroll (e) {
e.preventDefault();
e.stopPropagation();
e.stopImmediatePropagation();
}
}
}
})();
.image-modal(ng-click='close()')
.overlay
.image
//- .close(ng-click='close()') Close
(function () {
'use strict';
var dependencies = [];
angular
.module('app.core.imageModal', dependencies);
// --------------------
})();
(function () {
'use strict';
angular
.module('app.core.imageModal')
.factory('imageModal', imageModal);
// --------------------
/* @ngInject */
function imageModal ($rootScope, $timeout, $compile, $templateCache) {
return {
show: show
};
// -----
function show (imageUrl, startElem) {
if (!imageUrl) {
return;
}
// scope
var scope = $rootScope.$new();
scope.imageUrl = imageUrl;
scope.startElem = startElem;
// close other dialogs
$rootScope.$broadcast('imageModal:close');
// create directive element
var element = $compile('<image-modal></image-modal>')(scope);
// attach to DOM
angular.element(document.body).append(element);
}
}
})();
/* global ionic */
(function () {
'use strict';
angular
.module('app.core.imageViewer')
.directive('imageViewer', imageViewer);
// --------------------
/* @ngInject */
function imageViewer (imageModal) {
return {
restrict: 'A',
templateUrl: 'imageViewer.html',
replace: true,
transclude: true,
scope: {
imageViewer: '='
},
link: link
};
// -----
function link (scope, elem, attrs) {
scope.view = view;
// -----
function view () {
imageModal.show(scope.imageViewer, elem);
console.log(scope.imageViewer);
}
}
}
})();
div(ng-click='view()' ng-transclude)
(function () {
'use strict';
var dependencies = [];
angular
.module('app.core.imageViewer', dependencies);
// --------------------
})();
(function () {
'use strict';
angular
.module('app.core.imageViewer')
.factory('imageViewer', imageViewer);
// --------------------
/* @ngInject */
function imageViewer ($rootScope, $timeout, $compile, $templateCache) {
return {
show: show
};
// -----
function show (imageUrl) {
if (!imageUrl) {
return;
}
// scope
var scope = $rootScope.$new();
scope.imageUrl = imageUrl;
// close other dialogs
$rootScope.$broadcast('imageViewer:close');
// create directive element
var element = $compile('<image-viewer></image-viewer>')(scope);
// attach to DOM
angular.element(document.body).append(element);
}
}
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment