mirror of
https://github.com/pcottle/learnGitBranching.git
synced 2025-06-27 00:18:56 +02:00
BOOM commit birthing animation done and animation factory fleshed out
This commit is contained in:
parent
bc4b9246eb
commit
23ee6944e2
6 changed files with 106 additions and 20 deletions
|
@ -1,13 +1,41 @@
|
|||
/******************
|
||||
* This class is responsible for a lot of the heavy lifting around creating an animation at a certain state in time.
|
||||
* The tricky thing is that when a new commit has to be "born," say in the middle of a rebase or something, it must animate
|
||||
* out from the parent position to it's birth position.
|
||||
* The tricky thing is that when a new commit has to be "born," say in the middle of a rebase
|
||||
* or something, it must animate out from the parent position to it's birth position.
|
||||
|
||||
* These two positions though may not be where the commit finally ends up. So we actually need to take a snapshot of the tree,
|
||||
* store all those positions, take a snapshot of the tree after a layout refresh afterwards, and then animate between those two spots.
|
||||
* and then essentially animate the entire tree too.
|
||||
|
||||
* not sure if this is necessary yet, so ill hold off for now. lets do some refs
|
||||
|
||||
*/
|
||||
|
||||
// essentially a static class
|
||||
function AnimationFactory() {
|
||||
|
||||
}
|
||||
|
||||
AnimationFactory.prototype.genCommitBirthAnimation = function(animationQueue, commit) {
|
||||
if (!animationQueue) {
|
||||
throw new Error("Need animation queue to add closure to!");
|
||||
}
|
||||
|
||||
var time = GRAPHICS.defaultAnimationTime * 1.0;
|
||||
|
||||
// essentially refresh the entire tree, but do a special thing for the commit
|
||||
var visNode = commit.get('visNode');
|
||||
|
||||
var animation = function() {
|
||||
// this takes care of refs and all that jazz, and updates all the positions
|
||||
gitVisuals.refreshTree(time);
|
||||
|
||||
visNode.setBirthPosition();
|
||||
visNode.setOutgoingEdgesBirthPosition();
|
||||
visNode.parentInFront();
|
||||
|
||||
visNode.animateUpdatedPosition(time);
|
||||
visNode.animateOutgoingEdges(time);
|
||||
};
|
||||
|
||||
animationQueue.add(new Animation({
|
||||
closure: animation
|
||||
}));
|
||||
};
|
||||
|
|
20
src/git.js
20
src/git.js
|
@ -230,7 +230,9 @@ GitEngine.prototype.commitStarter = function() {
|
|||
if (this.commandOptions['-am']) {
|
||||
this.command.addWarning("Don't worry about adding files or commit messages in this demo");
|
||||
}
|
||||
this.commit();
|
||||
|
||||
var newCommit = this.commit();
|
||||
animationFactory.genCommitBirthAnimation(this.animationQueue, newCommit);
|
||||
};
|
||||
|
||||
GitEngine.prototype.commit = function() {
|
||||
|
@ -248,6 +250,7 @@ GitEngine.prototype.commit = function() {
|
|||
var targetBranch = this.HEAD.get('target');
|
||||
targetBranch.set('target', newCommit);
|
||||
}
|
||||
return newCommit;
|
||||
};
|
||||
|
||||
GitEngine.prototype.resolveId = function(idOrTarget) {
|
||||
|
@ -750,22 +753,23 @@ GitEngine.prototype.dispatch = function(command, callback) {
|
|||
} catch (err) {
|
||||
if (err instanceof GitError ||
|
||||
err instanceof CommandResult) {
|
||||
|
||||
// short circuit animation by just setting error and returning
|
||||
command.set('error', err);
|
||||
callback();
|
||||
return;
|
||||
|
||||
} else {
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
this.animationQueue.add(new Animation({
|
||||
closure: function() {
|
||||
gitVisuals.refreshTree();
|
||||
}
|
||||
}));
|
||||
// only add the refresh if we didn't do manual animations
|
||||
if (!this.animationQueue.get('animations').length) {
|
||||
this.animationQueue.add(new Animation({
|
||||
closure: function() {
|
||||
gitVisuals.refreshTree();
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
// animation queue will call the callback when its done
|
||||
this.animationQueue.start();
|
||||
|
|
|
@ -8,10 +8,13 @@ var gitVisuals = null;
|
|||
|
||||
var commandCollection = null;
|
||||
var commandBuffer = null;
|
||||
var animationFactory = null;
|
||||
|
||||
var paper = null;
|
||||
|
||||
$(document).ready(function(){
|
||||
animationFactory = new AnimationFactory();
|
||||
|
||||
// the two major collections that affect everything
|
||||
var commitCollection = new CommitCollection();
|
||||
commandCollection = new CommandCollection();
|
||||
|
|
59
src/tree.js
59
src/tree.js
|
@ -320,6 +320,7 @@ var VisNode = Backbone.Model.extend({
|
|||
defaults: {
|
||||
depth: undefined,
|
||||
maxWidth: null,
|
||||
outgoingEdges: null,
|
||||
id: null,
|
||||
pos: null,
|
||||
radius: null,
|
||||
|
@ -346,6 +347,8 @@ var VisNode = Backbone.Model.extend({
|
|||
|
||||
initialize: function() {
|
||||
this.validateAtInit();
|
||||
|
||||
this.set('outgoingEdges', []);
|
||||
},
|
||||
|
||||
setDepthBasedOn: function(depthIncrement) {
|
||||
|
@ -394,7 +397,8 @@ var VisNode = Backbone.Model.extend({
|
|||
this.get('circle').stop().animate({
|
||||
cx: pos.x,
|
||||
cy: pos.y,
|
||||
opacity: opacity
|
||||
opacity: opacity,
|
||||
r: this.getRadius()
|
||||
},
|
||||
speed !== undefined ? speed : this.get('animationSpeed'),
|
||||
easing || this.get('animationEasing')
|
||||
|
@ -410,6 +414,45 @@ var VisNode = Backbone.Model.extend({
|
|||
return this.get('radius') || GRAPHICS.nodeRadius;
|
||||
},
|
||||
|
||||
getParentScreenCoords: function() {
|
||||
return this.get('commit').get('parents')[0].get('visNode').getScreenCoords();
|
||||
},
|
||||
|
||||
setBirthPosition: function() {
|
||||
// utility method for animating it out from underneath a parent
|
||||
var parentCoords = this.getParentScreenCoords();
|
||||
|
||||
this.get('circle').attr({
|
||||
cx: parentCoords.x,
|
||||
cy: parentCoords.y,
|
||||
opacity: 0,
|
||||
r: 0,
|
||||
});
|
||||
},
|
||||
|
||||
animateOutgoingEdges: function(speed, easing) {
|
||||
_.each(this.get('outgoingEdges'), function(edge) {
|
||||
edge.animateUpdatedPath(speed, easing);
|
||||
}, this);
|
||||
},
|
||||
|
||||
setOutgoingEdgesBirthPosition: function() {
|
||||
var parentCoords = this.getParentScreenCoords();
|
||||
_.each(this.get('outgoingEdges'), function(edge) {
|
||||
var headPos = edge.get('head').getScreenCoords();
|
||||
var path = edge.genSmoothBezierPathStringFromCoords(parentCoords, headPos);
|
||||
edge.get('path').stop().attr({
|
||||
path: path,
|
||||
opacity: 0
|
||||
});
|
||||
}, this);
|
||||
},
|
||||
|
||||
parentInFront: function() {
|
||||
// woof!
|
||||
this.get('commit').get('parents')[0].get('visNode').get('circle').toFront();
|
||||
},
|
||||
|
||||
genGraphics: function(paper) {
|
||||
var pos = this.getScreenCoords();
|
||||
var circle = cuteSmallCircle(paper, pos.x, pos.y, {
|
||||
|
@ -438,11 +481,17 @@ var VisEdge = Backbone.Model.extend({
|
|||
|
||||
initialize: function() {
|
||||
this.validateAtInit();
|
||||
|
||||
this.get('tail').get('outgoingEdges').push(this);
|
||||
},
|
||||
|
||||
genSmoothBezierPathString: function(tail, head) {
|
||||
var tailPos = tail.getScreenCoords();
|
||||
var headPos = head.getScreenCoords();
|
||||
return this.genSmoothBezierPathStringFromCoords(tailPos, headPos);
|
||||
},
|
||||
|
||||
genSmoothBezierPathStringFromCoords: function(tailPos, headPos) {
|
||||
// we need to generate the path and control points for the bezier. format
|
||||
// is M(move abs) C (curve to) (control point 1) (control point 2) (final point)
|
||||
// the control points have to be __below__ to get the curve starting off straight.
|
||||
|
@ -465,8 +514,8 @@ var VisEdge = Backbone.Model.extend({
|
|||
};
|
||||
|
||||
// first offset tail and head by radii
|
||||
tailPos = offset(tailPos, -1, tail.getRadius());
|
||||
headPos = offset(headPos, 1, head.getRadius());
|
||||
tailPos = offset(tailPos, -1, this.get('tail').getRadius());
|
||||
headPos = offset(headPos, 1, this.get('head').getRadius());
|
||||
|
||||
var str = '';
|
||||
// first move to bottom of tail
|
||||
|
@ -514,6 +563,10 @@ var VisEdge = Backbone.Model.extend({
|
|||
|
||||
animateUpdatedPath: function(speed, easing) {
|
||||
var newPath = this.getBezierCurve();
|
||||
this.animateUpdatedPathFromPath(newPath, speed, easing);
|
||||
},
|
||||
|
||||
animateUpdatedPathFromPath: function(newPath, speed, easing) {
|
||||
var opacity = this.getOpacity();
|
||||
|
||||
this.get('path').toBack();
|
||||
|
|
|
@ -81,12 +81,12 @@ GitVisuals.prototype.toScreenCoords = function(pos) {
|
|||
|
||||
**************************************/
|
||||
|
||||
GitVisuals.prototype.refreshTree = function() {
|
||||
GitVisuals.prototype.refreshTree = function(speed) {
|
||||
// this method can only be called after graphics are rendered
|
||||
this.calcTreeCoords();
|
||||
this.calcGraphicsCoords();
|
||||
|
||||
this.animateAll();
|
||||
this.animateAll(speed);
|
||||
};
|
||||
|
||||
GitVisuals.prototype.refreshTreeHarsh = function() {
|
||||
|
|
2
todo.txt
2
todo.txt
|
@ -6,13 +6,11 @@ integrate animation into all git commands
|
|||
|
||||
animation factory? stuff like:
|
||||
|
||||
-commitBirthAnimation(snapshotBefore, snapshotAfter, commit)
|
||||
-highlightCommit(50, 'targetColor') // during search
|
||||
-clearHighlightsAllNodes
|
||||
|
||||
|
||||
ALSO other big things:
|
||||
|
||||
- Text on commit nodes
|
||||
- Division in their rings based on how many / what branches they are part of
|
||||
- Color on branch edges??
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue