UNPKG

angular-pixlive

Version:

Plugin to use PixLive Augmented Reality toolkit the Angular way

314 lines (258 loc) 13.5 kB
/* * angular-pixlive v1 * (c) 2015-2016 Vidinoti https://vidinoti.com * License: MIT */ 'use strict'; pixliveModule /** * @ngdoc directive * @name pxlView * @memberof pixlive * @param {service} $timeout Angular $timeout service * @param {service} $ionicPosition Ionic $ionicPosition service * @param {service} $ionicPlatform Ionic $ionicPlatform service * @param {service} $ionicBackdrop Ionic $ionicBackdrop service * @restrict E * * @description * Add an augmented reality view to your Ionic app. * * **Notice**: You should minimize the number of AR view included into your app to the minimum as this is CPU resource intensive. * You should also avoid having two AR views visible at the same time as this will create unexpected behaviors. * * **Warning**: This view has to be inside an `ion-view` element whose background has been set to transparent. Failing to do so will make the AR view invisible. * * @example * <ion-view view-title="AR" style="background-color: transparent !important;"> * <pxl-view> * <!-- Any overlay you want --> * </pxl-view> * </ion-view> */ .directive('pxlView', [ '$timeout', '$ionicPosition', '$ionicPlatform', '$ionicBackdrop', function($timeout, $ionicPosition, $ionicPlatform, $ionicBackdrop) { return { restrict: 'E', require: '^?ionNavView', priority: 800, compile: function(element, attr) { element.addClass('scroll-content ionic-scroll scroll-content-false'); function prelink($scope, $element, $attr, navViewCtrl) { var parentScope = $scope.$parent; $scope.$watch(function() { return (parentScope.$hasHeader ? ' has-header' : '') + (parentScope.$hasSubheader ? ' has-subheader' : '') + (parentScope.$hasFooter ? ' has-footer' : '') + (parentScope.$hasSubfooter ? ' has-subfooter' : '') + (parentScope.$hasTabs ? ' has-tabs' : '') + (parentScope.$hasTabsTop ? ' has-tabs-top' : ''); }, function(className, oldClassName) { $element.removeClass(oldClassName); $element.addClass(className); }); } function postlink($scope, $element, $attr, navViewCtrl) { $scope.$on("$ionicView.beforeEnter", function(scopes, states) { if ($scope.arView) { $scope.arView.beforeEnter(); } }); $scope.$on("$ionicView.afterEnter", function(scopes, states) { if (!$scope.arView) { $ionicPlatform.ready(function() { if (window.cordova && window.cordova.plugins && window.cordova.plugins.PixLive) { //FIXME: The timeout is a Dirty hack as on iOS, the status bar CSS style is applied after // this directive is loaded, hence we fail to get the proper Y value for the view. $scope.pixliveTimeout = $timeout(function() { var offset = $ionicPosition.offset($element); var y = offset.top; var x = offset.left; var width = offset.width; var height = offset.height; $scope.pixliveTimeout = null; $scope.arView = window.cordova.plugins.PixLive.createARView(x, y, width, height, true); if ($ionicBackdrop.isDisplayed() != false) { $scope.arView.disableTouch(); } else { $scope.arView.enableTouch(); } $scope.onResize = function() { var offset = $ionicPosition.offset($element); var y = offset.top; var x = offset.left; var width = offset.width; var height = offset.height; $scope.arView.resize(x, y, width, height); }; $scope.onModalShown = function() { $scope.arView.disableTouch(); }; $scope.onModalHidden = function() { $scope.arView.enableTouch(); }; $scope.transferShown = function(){ ionic.trigger('transfer.shown', { target: window }); }; $scope.transferHidden = function(){ ionic.trigger('transfer.hidden', { target: window }); }; ionic.on('resize', $scope.onResize, window); ionic.on('backdrop.shown', $scope.onModalShown, window); ionic.on('backdrop.hidden', $scope.onModalHidden, window); $scope.$on('popover.shown', $scope.transferShown); $scope.$on('popover.hidden', $scope.transferHidden); }, 300); } }); } else { $scope.onResize(); $scope.arView.afterEnter(); } }); $scope.$on("$ionicView.beforeLeave", function(scopes, states) { if ($scope.pixliveTimeout) { $timeout.cancel($scope.pixliveTimeout); $scope.pixliveTimeout = null; } if ($scope.arView) { $scope.arView.beforeLeave(); } }); $scope.$on("$ionicView.afterLeave", function(scopes, states) { if ($scope.arView) { $scope.arView.afterLeave(); } }); $scope.$on('$destroy', function() { if ($scope.pixliveTimeout) { $timeout.cancel($scope.pixliveTimeout); $scope.pixliveTimeout = null; } if ($scope.arView) { ionic.off('resize', $scope.onResize, window); $scope.arView.destroy(); } if ($scope.onModalShown) { ionic.off('backdrop.shown', $scope.onModalShown, window); $scope.onModalShown = null; } if ($scope.onModalHidden) { ionic.off('backdrop.hidden', $scope.onModalHidden, window); $scope.onModalHidden = null; } }); } return { pre: prelink, post: postlink }; } }; } ]) .config(["$provide", function($provide) { // Use the `decorator` solution to substitute or attach behaviors to // original service instance; @see angular-mocks for more examples.... $provide.decorator('$ionicBackdrop', ["$delegate", function($delegate) { // Save the original $log.retain() var retainFn = $delegate.retain; var releaseFn = $delegate.release; $delegate.backdropHolds = 0; $delegate.addBackdropHolds = function(){ $delegate.backdropHolds++; //Call the disable if ($delegate.backdropHolds == 1) { ionic.trigger('backdrop.shown', { target: window }); } }; $delegate.removeBackdropHolds = function(){ $delegate.backdropHolds--; //Call the disable if ($delegate.backdropHolds == 0) { ionic.trigger('backdrop.hidden', { target: window }); } }; ionic.on('transfer.shown', $delegate.addBackdropHolds, window); ionic.on('transfer.hidden', $delegate.removeBackdropHolds, window); $delegate.retain = function() { var args = [].slice.call(arguments); // Call the original method retainFn.apply(null, args) $delegate.addBackdropHolds(); }; $delegate.release = function() { var args = [].slice.call(arguments); // Call the original method releaseFn.apply(null, args) $delegate.removeBackdropHolds(); }; $delegate.isDisplayed = function() { return $delegate.backdropHolds>0; }; return $delegate; } ]); } ]).config(["$provide", function($provide) { $provide.decorator('$ionicModal', ["$delegate","$q", function($delegate,$q) { // Save the original $log.show() var fromTemplate = $delegate.fromTemplate; var fromTemplateUrl = $delegate.fromTemplateUrl; var overrideShowHide = function (ret) { // Save old methods ret.showOld = ret.show; ret.hideOld = ret.hide; ret.show=function() { ionic.trigger('transfer.shown', { target: window }); var args2 = [].slice.call(arguments); return this.showOld.apply(this, args2); }; ret.hide=function() { ionic.trigger('transfer.hidden', { target: window }); var args2 = [].slice.call(arguments); return this.hideOld.apply(this, args2); }; }; $delegate.fromTemplate = function() { var args = [].slice.call(arguments); var ret = fromTemplate.apply(null, args); overrideShowHide(ret); return ret; }; $delegate.fromTemplateUrl = function() { var args = [].slice.call(arguments); var deferred = $q.defer(); fromTemplateUrl.apply(null, args).then(function(modal) { overrideShowHide(modal); deferred.resolve(modal); }, function(err) { deferred.reject(err); }); return deferred.promise; }; return $delegate; } ]); } ]);