Last active
August 29, 2015 14:20
-
-
Save ashconnell/0c2bff1138977b9af6da to your computer and use it in GitHub Desktop.
Image Viewer/Modal
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
.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; | |
} | |
} | |
} | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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') |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* 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(); | |
} | |
} | |
} | |
})(); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
.image-modal(ng-click='close()') | |
.overlay | |
.image | |
//- .close(ng-click='close()') Close |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(function () { | |
'use strict'; | |
var dependencies = []; | |
angular | |
.module('app.core.imageModal', dependencies); | |
// -------------------- | |
})(); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(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); | |
} | |
} | |
})(); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* 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); | |
} | |
} | |
} | |
})(); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
div(ng-click='view()' ng-transclude) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(function () { | |
'use strict'; | |
var dependencies = []; | |
angular | |
.module('app.core.imageViewer', dependencies); | |
// -------------------- | |
})(); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(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