Permalink
Browse files

Add Transitions

  • Loading branch information...
ryanlsimms committed Sep 12, 2017
1 parent d57830f commit cea1a748b5432d26adf705d70e31f09a0ca1c2e0
Showing with 196 additions and 4 deletions.
  1. +1 −0 index.html
  2. +11 −0 js/app.js
  3. +147 −0 js/pie_transitions.js
  4. +37 −4 js/rotating_donut.js
@@ -7,6 +7,7 @@
<script src="node_modules/d3/build/d3.js"></script>
<script src="js/data.js"></script>
<script src="js/rotating_donut.js"></script>
<script src="js/pie_transitions.js"></script>
<link rel="stylesheet" href="css/button.css">
<link rel="stylesheet" href="css/style.css">
@@ -16,11 +16,15 @@ document.addEventListener('DOMContentLoaded', function() {
d3.select('#donut1')
.datum(APP.generateData())
.call(donut.label, 'Smith')
.transition()
.duration(0)
.call(donut);
d3.select('#donut2')
.datum(APP.generateData())
.call(donut.label, 'Jones')
.transition()
.duration(0)
.call(donut);
}
@@ -33,10 +37,15 @@ document.addEventListener('DOMContentLoaded', function() {
dataButtonClick: function() {
d3.select('#donut1')
.datum(APP.generateData(true))
.transition()
.duration(600)
.call(donut);
d3.select('#donut2')
.datum(APP.generateData(true))
.transition()
.delay(400)
.duration(200)
.call(donut);
},
@@ -47,6 +56,8 @@ document.addEventListener('DOMContentLoaded', function() {
d3.selectAll(target)
.call(donut.dimensions, {width: value, height: value})
.call(donut)
.transition()
.duration(donut.animationDuration())
.style('width', value + 'px')
.style('height', value + 'px');
}
@@ -0,0 +1,147 @@
if(typeof APP === 'undefined') {APP = {};}
APP.pieTransition = function() {
'use strict';
var allNodes,
firstPreviousNode,
firstCurrentNode,
enteringSegments,
transitioningSegments;
var previousSegmentData = d3.local();
var o = {
arc: null,
sort: null
};
var methods = {
enter: function(transition) {
transition
.each(setEnterAngle)
.call(render);
},
transition: render,
exit: function(transition) {
transition
.each(setExitAngle)
.call(render);
}
};
function previousAdjacentAngle(node) {
var index = allNodes.indexOf(node);
if (index) {
return previousSegmentData.get(allNodes[index - 1]).endAngle;
} else if (firstPreviousNode) {
return previousSegmentData.get(firstPreviousNode).startAngle;
} else {
return nodeData(node).startAngle;
}
}
function currentAdjacentAngle(node) {
var index = allNodes.indexOf(node);
if (index) {
return nodeData(allNodes[index - 1]).endAngle;
} else {
return nodeData(firstCurrentNode).startAngle;
}
}
function updateNodes() {
if (!transitioningSegments || !enteringSegments) {return;}
allNodes = transitioningSegments.nodes()
.concat(transitioningSegments.exit().nodes())
.concat(enteringSegments.nodes())
.sort(sortNodes);
firstPreviousNode = transitioningSegments.nodes()
.concat(transitioningSegments.exit().nodes())
.sort(sortNodes)[0];
firstCurrentNode = transitioningSegments.nodes()
.concat(enteringSegments.nodes())
.sort(sortNodes)[0];
function sortNodes(a, b) {
return o.sort(nodeData(a).data, nodeData(b).data);
}
}
function nodeData(node) {
return d3.select(node).datum();
}
function setEnterAngle() {
var enterAngle = previousAdjacentAngle(this);
previousSegmentData.set(this, {
startAngle: enterAngle,
endAngle: enterAngle,
innerRadius: o.arc.innerRadius()(),
outerRadius: o.arc.outerRadius()()
});
}
function setExitAngle(d) {
var exitAngle = currentAdjacentAngle(this);
d.startAngle = exitAngle;
d.endAngle = exitAngle;
}
function render(transition) {
transition.attrTween('d', arcTween);
}
function arcTween() {
var i = interpolate(this);
previousSegmentData.set(this, i(0));
return function(t) {
var interation = i(t);
o.arc
.innerRadius(interation.innerRadius)
.outerRadius(interation.outerRadius);
return o.arc(interation);
};
}
function interpolate(segment) {
var d = d3.select(segment).datum();
var newData = {
startAngle: d.startAngle,
endAngle: d.endAngle,
innerRadius: o.arc.innerRadius()(),
outerRadius: o.arc.outerRadius()()
};
return d3.interpolate(previousSegmentData.get(segment), newData);
}
methods.enteringSegments = function (_) {
enteringSegments = _;
updateNodes();
return methods;
};
methods.transitioningSegments = function (_) {
transitioningSegments = _;
updateNodes();
return methods;
};
methods.arc = function(_) {
if (!arguments.length) {return o.arc;}
o.arc = _;
return methods;
};
methods.sort = function(_) {
if (!arguments.length) {return o.sort;}
o.sort = _;
return methods;
};
return methods;
};
@@ -5,6 +5,7 @@ APP.rotatingDonut = function() {
local;
o = {
animationDuration: 600,
thickness: 0.4,
value: null,
color: null,
@@ -14,24 +15,36 @@ APP.rotatingDonut = function() {
local = {
label: d3.local(),
animate: d3.local(),
dimensions: d3.local()
};
function donut(group) {
group.each(render);
group.each(function(data) {
render.call(this, data, group);
});
}
function render(data) {
function render(data, group) {
var context,
t,
dim,
pie,
arc,
pieTransition,
segments,
segmentEnter;
if (!data) {return;}
context = d3.select(this);
if (group instanceof d3.transition) {
t = d3.transition(group);
} else {
t = d3.transition().duration(o.animationDuration);
}
dim = getDimensions(context);
pie = d3.pie()
@@ -42,6 +55,8 @@ APP.rotatingDonut = function() {
.outerRadius(dim.outerRadius)
.innerRadius(dim.innerRadius);
pieTransition = local.animate.get(this) || local.animate.set(this, APP.pieTransition());
context.selectAll('svg')
.data([pie(data.sort(o.sort))])
.enter()
@@ -54,6 +69,7 @@ APP.rotatingDonut = function() {
.attr('dominant-baseline', 'middle');
context.selectAll('svg')
.transition(t)
.attr('width', dim.width)
.attr('height', dim.height)
.selectAll('g.group')
@@ -72,11 +88,23 @@ APP.rotatingDonut = function() {
.attr('class', 'segment')
.attr('fill', dataAccess('color'));
pieTransition
.arc(arc)
.sort(o.sort)
.enteringSegments(segmentEnter)
.transitioningSegments(segments);
segmentEnter
.merge(segments)
.attr('d', arc);
.transition(t)
.call(pieTransition.enter);
segments
.transition(t)
.call(pieTransition.transition);
segments.exit()
.transition(t)
.call(pieTransition.exit)
.remove();
}
@@ -101,6 +129,11 @@ APP.rotatingDonut = function() {
};
}
donut.animationDuration = function(_) {
if (!arguments.length) {return o.animationDuration;}
o.animationDuration = _;
return donut;
};
donut.thickness = function(_) {
if (!arguments.length) {return o.thickness;}
o.thickness = _;

0 comments on commit cea1a74

Please sign in to comment.