Permalink
Browse files

Add Rotation

  • Loading branch information...
ryanlsimms committed Sep 13, 2017
1 parent c81584e commit ae784e5966b13426cdb178562c9138184810f8c6
Showing with 149 additions and 8 deletions.
  1. +1 −0 index.html
  2. +23 −1 js/app.js
  3. +91 −0 js/pie_selection_rotation.js
  4. +9 −3 js/pie_transitions.js
  5. +25 −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_selection_rotation.js"></script>
<script src="js/pie_transitions.js"></script>
<script src="js/basic_legend.js"></script>
@@ -6,6 +6,7 @@ document.addEventListener('DOMContentLoaded', function() {
function build() {
donut = APP.rotatingDonut()
.alignmentAngle(90)
.thickness(0.5)
.value(function(d) {return d.value;})
.color(function(d) {return d.color;})
@@ -39,8 +40,10 @@ document.addEventListener('DOMContentLoaded', function() {
}
function addListeners() {
donut.on('mouseenter', events.donutMouseEnter)
donut.on('click', events.donutClick)
.on('mouseenter', events.donutMouseEnter)
.on('mouseleave', events.donutMouseLeave);
legend.on('click', events.legendClick);
d3.select('button').on('click', events.dataButtonClick);
d3.selectAll('.donut-size').on('change', events.resizeSliderChange);
}
@@ -61,6 +64,19 @@ document.addEventListener('DOMContentLoaded', function() {
.call(donut);
},
donutClick: function(d) {
var container = this;
d3.selectAll('.donut')
.filter(function() {return this !== container;})
.call(donut.selectedSegment, d)
.call(donut);
d3.select('#legend')
.call(legend.selectedItem, d)
.call(legend);
},
donutMouseEnter: function(d) {
d3.select('#legend')
.call(legend.highlight, d)
@@ -71,6 +87,12 @@ document.addEventListener('DOMContentLoaded', function() {
.call(legend.unhighlight, d)
},
legendClick: function(d) {
d3.selectAll('.donut')
.call(donut.selectedSegment, d)
.call(donut);
},
resizeSliderChange: function() {
var target = d3.select(this).attr('data-target'),
value = this.value * 2;
@@ -0,0 +1,91 @@
if(typeof APP === 'undefined') {APP = {};}
APP.pieSelectionRotation = function() {
'use strict';
var local = {
angle: d3.local(),
selectedSegment: d3.local(),
selectedKey: d3.local()
};
var o = {
key: null,
alignmentAngle: 0
};
function rotation(group) {
group.each(function() {
var selectedData = getSelectedData(this);
local.angle.set(this, local.angle.get(this) || 0);
local.selectedSegment.set(this, selectedData);
if (selectedData) {
local.angle.set(this, newAngle(local.angle.get(this), meanAngle(selectedData)));
}
});
}
function newAngle(offsetAngle, currentAngle) {
var radiansToTurn = degreesToRadians(o.alignmentAngle) - currentAngle - offsetAngle;
return shorterRotation(radiansToTurn) + offsetAngle;
}
function meanAngle(data) {
return d3.mean([data.startAngle, data.endAngle]);
}
function degreesToRadians(degrees) {
return degrees * Math.PI * 2 / 360;
}
function shorterRotation(offset) {
var tau = Math.PI * 2;
offset = offset % tau;
return (Math.abs(offset) > tau / 2) ? offset + tau * Math.sign(-offset) : offset;
}
function getSelectedData(node) {
return d3.select(node)
.datum()
.filter(function(d) {return o.key(d.data) === local.selectedKey.get(node)})[0];
}
rotation.selectedSegment = function(selection, d) {
var returnArray;
function nodeMap(node) {
return (local.selectedSegment.get(node) || {}).data;
}
if (typeof d === 'undefined' ) {
returnArray = selection.nodes().map(nodeMap);
return selection._groups[0] instanceof NodeList ? returnArray : returnArray[0];
}
selection.each(function() {
local.selectedKey.set(this, o.key(d));
});
return rotation;
};
rotation.getAngle = function(selection) {
var returnArray = selection.nodes()
.map(function(node) {return local.angle.get(node) || 0;});
return selection._groups[0] instanceof NodeList ? returnArray : returnArray[0];
};
rotation.key = function(_) {
if (!arguments.length) {return o.key;}
o.key = _;
return rotation;
};
rotation.alignmentAngle = function(_) {
if (!arguments.length) {return o.alignmentAngle;}
o.alignmentAngle = _;
return rotation;
};
return rotation;
};
@@ -11,7 +11,8 @@ APP.pieTransition = function() {
var o = {
arc: null,
sort: null
sort: null,
offset: 0
};
var methods = {
@@ -112,8 +113,8 @@ APP.pieTransition = function() {
function interpolate(segment) {
var d = d3.select(segment).datum();
var newData = {
startAngle: d.startAngle,
endAngle: d.endAngle,
startAngle: d.startAngle + o.offset,
endAngle: d.endAngle + o.offset,
innerRadius: o.arc.innerRadius()(),
outerRadius: o.arc.outerRadius()()
};
@@ -142,6 +143,11 @@ APP.pieTransition = function() {
o.sort = _;
return methods;
};
methods.offset = function(_) {
if (!arguments.length) {return o.offset;}
o.offset = _;
return methods;
};
return methods;
};
@@ -3,7 +3,8 @@ APP.rotatingDonut = function() {
'use strict';
var o,
events,
local;
local,
rotation;
o = {
animationDuration: 600,
@@ -14,14 +15,17 @@ APP.rotatingDonut = function() {
sort: null
};
events = d3.dispatch('mouseenter', 'mouseleave');
events = d3.dispatch('mouseenter', 'mouseleave', 'click');
local = {
label: d3.local(),
animate: d3.local(),
dimensions: d3.local()
};
rotation = APP.pieSelectionRotation()
.key(function(d) {return o.key(d);});
function donut(group) {
group.each(function(data) {
render.call(this, data, group);
@@ -62,6 +66,7 @@ APP.rotatingDonut = function() {
context.selectAll('svg')
.data([pie(data.sort(o.sort))])
.call(rotation)
.enter()
.append('svg')
.append('g')
@@ -90,13 +95,14 @@ APP.rotatingDonut = function() {
.append('path')
.attr('class', 'segment')
.attr('fill', dataAccess('color'))
.on('mouseenter mouseleave', onPathEvent(context));
.on('mouseenter mouseleave click', onPathEvent(context));
pieTransition
.arc(arc)
.sort(o.sort)
.enteringSegments(segmentEnter)
.transitioningSegments(segments);
.transitioningSegments(segments)
.offset(rotation.getAngle(context.select('svg')));
segmentEnter
.transition(t)
@@ -114,6 +120,10 @@ APP.rotatingDonut = function() {
function onPathEvent(context) {
return function(d) {
if (d3.event.type === 'click') {
rotation.selectedSegment(context.select('svg'), d.data);
context.call(donut);
}
events.call(d3.event.type, context.node(), d.data);
};
}
@@ -139,6 +149,17 @@ APP.rotatingDonut = function() {
};
}
donut.selectedSegment = function(context, d) {
if (typeof d === 'undefined' ) {return rotation.selectedSegment(context.select('svg'));}
rotation.selectedSegment(context.select('svg'), d);
return donut;
};
donut.alignmentAngle = function(_) {
if (typeof _ === 'undefined' ) {return rotation.alignmentAngle();}
rotation.alignmentAngle(_);
return donut;
};
donut.animationDuration = function(_) {
if (!arguments.length) {return o.animationDuration;}
o.animationDuration = _;

0 comments on commit ae784e5

Please sign in to comment.