Skip to content

Instantly share code, notes, and snippets.

@nicoburns
Last active December 24, 2015 08:39
Show Gist options
  • Select an option

  • Save nicoburns/6772469 to your computer and use it in GitHub Desktop.

Select an option

Save nicoburns/6772469 to your computer and use it in GitHub Desktop.
Example of a "RegionGroup" Backbone view, which can be used to easily animate between two views.
<div class='regiongroup'>
<div class='region'>Initial RegionGroup content</div>
<div class='region region-hidden'></div>
</div>
define(function(require, exports, module) {
var View = require("./view");
var _ = require("lodash");
var ViewCache = require("core/viewcache");
var renderloop = require("core/renderloop");
var RegionGroup = View.extend({
initialize: function (options) {
this.regions = [];
this.createRegions();
},
update: function (params) {
var regiongroup = this;
// startTransition is passed the return value from createTransition
return this.prepareNextRegion(params.view)
.then(function () {
return regiongroup.createTransition(params.view, params.transition);
})
.then(function (transition) {
return regiongroup.startTransition(transition);
});
},
// Create Region views from the immediate children of 'el'
createRegions: function () {
_.each(this.el.children, function (regionElement) {
// Create region from element
var region = new View({"el": regionElement});
// Push region to regions array
this.regions.push(region);
if (!/region\-hidden/.test(regionElement.className)) {
this.activeRegion = region;
}
}, this);
},
prepareNextRegion: function (view) {
return this.prepareRegion(1, view);
},
prepareRegion: function (index, view) {
var region = this.regions[index];
// Update the region's content view
return $.when( region.updateRegion(view) )
.then(function () {
// If view is already rendered, append it's 'el'
if (view.isCacheRender) {
region.el.appendChild(view.el);
}
// Else render the view
else {
return view.render().promise();
}
});
},
createTransition: function (view, transitionParams) {
var transitionOptions = _.extend({}, transitionParams, {
type: null,
view: view,
id: _.uniqueId(),
regions: this.regions
});
var Transition = transitionParams.type;
return new Transition(transitionOptions);
},
startTransition: function (transition) {
// Create progress promise
transition.progress = $.Deferred();
// Call 'animationStart' callback
transition.animationStart();
// Show the incoming region
transition.newRegion.el.style.display = "block";
// Run the '_runTransition' function
renderloop.addPersistentTask("transition" + transition.id, this._runTransition, this, [transition]);
return transition.progress;
},
_runTransition: function (transition, timestamp) {
// Hack because timestamp passed in requestAnimationFrame is inconsistent between browsers
if (!transition.startTime) {
transition.startTime = timestamp;
return;
}
// Calcuate percentDone
transition.percentDone = Math.min(1, ((timestamp - transition.startTime) / transition.options.duration));
// Call 'animationFrame' callback
transition.animationFrame.call(transition);
// If transition is 100% done, stop running this function and call '_endTransition'
if (transition.percentDone === 1) {
renderloop.removePersistentTask("transition" + transition.id);
this._endTransition(transition);
}
},
_endTransition: function (transition) {
// Call the 'animationEnd' callback
transition.animationEnd();
// Hide the old region
transition.activeRegion.el.style.display = "none";
// Remove the contents of old region
var oldViews = transition.activeRegion.getViews();
oldViews.each(function (view) {
if (view.cacheName) {
ViewCache.cacheView(view);
}
else {
view.remove();
}
});
// Swap active region reference
this.regions.push( this.regions.shift() );
// Call view callback
if (transition.view) {
transition.view.trigger("afterAnimation");
if (transition.view.afterAnimation) transition.view.afterAnimation();
}
transition.progress.resolve();
}
});
module.exports = RegionGroup;
});
.regiongroup {
position: relative;
}
.region {
position: absolute;
left: 0;
top: 0;
width: 100%;
-webkit-transform: translate3d(0, 0, 0);
-webkit-backface-visibility: hidden;
//-webkit-perspective: 1000;
> * {
-webkit-transform: translate3d(0, 0, 0);
}
}
.region-hidden {
display: none;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment