I've reached the final stages of developing a mobile application using AngularJS wrapped in a cordova webview. However, I'm encountering some issues with the panel transition animations.
After experiencing strange behavior with ngAnimate, I decided to utilize two divs that remain in the DOM permanently to encapsulate the current and next panel content I compile. To animate them, I turned to the GSAP Framework, known for its performance. Yet, the animations are still sluggish.
To troubleshoot, I conducted a frame-by-frame profiling using Chrome Dev Tools Timeline and discovered that my scripting time was excessively long during controller initialization.
As a solution, I have come up with two ideas: either find a way to detect when the controller initialization is complete (though unsure how in Angular) or devise a method to spread out the execution across multiple frames.
Could anyone provide guidance in this matter?
Below is the structure in index.html:
<!doctype html>
<html ng-app="SparterApp" lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<title>MyApp</title>
<link rel="stylesheet" href="styles/styles.css">
</head>
<body>
<div id="panelCtrl" ng-controller="panelCtrl">
<nav id="menu" ng-include="'views/menu.html'"></nav>
<section id="currentPanel"></section>
<section id="nextPanel"></section>
</div>
<script src="bower_components/angular/angular.min.js"></script>
<script src="scripts/TweenMax.min.js"></script>
<!-- Various vendor scripts and custom Angular scripts -->
</body>
</html>
Here is my panel controller code:
'use strict';
angular.module('SparterApp')
.controller('panelCtrl', function ($scope, $compile, $http, $timeout, animService) {
nextPanelHandler = $('#nextPanel');
currentPanelHandler = $('#currentPanel');
var protect = false;
$scope.callbackNextPanel = function () {
currentPanelHandler.hide();
nextPanelHandler.attr('id', 'currentPanel');
currentPanelHandler.attr('id', 'nextPanel');
var buffer = nextPanelHandler;
nextPanelHandler = currentPanelHandler;
currentPanelHandler = buffer;
protect = false;
};
/*
** Load the next panel in the 'section.nextPanel' element, compile it with angular, and execute the setted animation
**
** templateUrl : the desired template url relative to the views folder or 'close' for closing popup
** options : an object with two attributes
** enterClass : the initialisation class for the next panel
** time : the time of the animation
** params : an object with all the arguments you want to transfer between panels
*/
$scope.nextPanel = function (templateUrl, options, params) {
// Prevent multi trigger
if (!protect) {
protect = true;
var tl = new TimelineLite({
paused: true,
onComplete: $scope.callbackNextPanel
});
// Get a initialisation in a list
var enterAnimFrom = animService.getAnimFrom(options.enterClass);
enterAnimFrom.onComplete = nextPanelHandler.show;
//Prepare the animation
tl.fromTo(
nextPanelHandler,
options.time,
enterAnimFrom,
{
x: 0,
y: 0,
scale: 1,
rotation: 0,
opacity: 1,
ease: options.ease
},
'start'
);
// Get the template to compile
var newPanel = $http({method: 'GET', url: 'views/' + templateUrl})
.success(function(data, status, headers, config) {
nextPanelHandler.html(data);
$scope.params = params;
$compile(nextPanelHandler.contents())($scope);
// Play the animation
tl.play();
})
.error(function(data, status, headers, config) {
alert('An error occured with the next panel loading');
});
}
};
});
Lastly, here is the structure of a panel:
<div ng-controller="loginCtrl" class="panel">
<!-- Panel content goes here -->
</div>
If sharing the timeline would aid in resolving the issue, please let me know.