| <!DOCTYPE html> | |
| <html> | |
| <head> | |
| <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.10/angular.min.js"></script> | |
| <script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script> | |
| </head> | |
| <style> | |
| .label { | |
| font: 300 10pt 'Futura', sans-serif; | |
| } | |
| div.label { | |
| } | |
| input.slider { | |
| width: 75%; | |
| margin: auto; | |
| display: block; | |
| } | |
| input.number { | |
| text-align: center; | |
| margin-left: 2px; | |
| } | |
| .donut { | |
| margin: auto; | |
| display: flex; | |
| justify-content: center; /* align horizontal */ | |
| align-items: center; /* align vertical */ | |
| } | |
| .chartContainer { | |
| padding: 20px; | |
| display: inline-block; | |
| margin: auto; | |
| width: 230; | |
| } | |
| .header { | |
| font: 300 14pt 'Futura', sans-serif; | |
| text-align: center; | |
| vertical-align: middle; | |
| } | |
| .sub-header { | |
| font: 100 8pt 'Futura', sans-serif; | |
| } | |
| .label-value { | |
| /*display: inline;*/ | |
| font: 300 10pt 'Helvetica Neue', sans-serif; | |
| position: relative; | |
| margin: auto; | |
| display: flex; | |
| justify-content: center; /* align horizontal */ | |
| align-items: center; /* align vertical */ | |
| /*float: none;*/ | |
| } | |
| </style> | |
| <body> | |
| <div ng-app="myApp"> | |
| <div ng-controller="mainCtrl"> | |
| <div class="chartContainer"> | |
| <div class="header">Residency<br><span class="sub-header">CA-RESIDENT | NON-RESIDENT</span></div> | |
| <res-donut data="data_res" accessor="accessor_res" class="donut"></res-donut> | |
| <div ng-repeat="datum in data_res | filter: {label:'Non-Resident'}" > | |
| <div class="label-value">% {{datum.label}} | |
| <input ng-model="datum.value" type="number" min="0" max="100" class="number"></input> | |
| </div> | |
| <div> | |
| <input ng-model="datum.value" type="range" min="0" max="100" class="slider"></input> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="chartContainer"> | |
| <div class="header">Non-Resident Mix<br><span class="sub-header">OUT-OF-STATE | INTERNATIONAL</span></div> | |
| <oos-donut data="data_oos" accessor="accessor_oos" class="donut"></oos-donut> | |
| <div ng-repeat="datum in data_oos | filter: {label:'International'}"> | |
| <div class="label-value">% {{datum.label}} | |
| <input ng-model="datum.value" type="number" min="0" max="100" class="number"></input> | |
| </div> | |
| <div> | |
| <input ng-model="datum.value" type="range" min="0" max="100" class="slider"></input> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="chartContainer"> | |
| <div class="header">% Entry Status<br><span class="sub-header">FRESHMEN | TRANSFER</span></div> | |
| <ent-donut data="data_ent" accessor="accessor_ent" class="donut"></ent-donut> | |
| <div ng-repeat="datum in data_ent | filter: {label:'Freshmen'}"> | |
| <div class="label-value"> {{datum.label}} | |
| <input ng-model="datum.value" type="number" min="0" max="100" class="number"></input> | |
| </div> | |
| <div> | |
| <input ng-model="datum.value" type="range" min="0" max="100" class="slider"></input> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <script> | |
| var myApp = angular.module('myApp', []); | |
| var arc = d3.svg.arc(); | |
| myApp.controller('mainCtrl', function ($scope) { | |
| $scope.data_res = [{ label: 'CA-Residents', value: 76 }, | |
| { label: 'Non-Residents', value: 24 }]; | |
| $scope.data_oos = [{ label: 'Out-of-State', value: 33 }, | |
| { label: 'International', value: 67 }]; | |
| $scope.data_ent = [{ label: 'Freshmen', value: 62 }, | |
| { label: 'Transfers', value: 38 }]; | |
| $scope.accessor_res = function(d){ return +d.value }; | |
| $scope.accessor_oos = function(d){ return +d.value }; | |
| $scope.accessor_ent = function(d){ return +d.value }; | |
| // so that our directive can know how to access the values from our data. | |
| // $scope.accessor = function(d){ return d.value }; | |
| }); | |
| myApp.directive('resDonut', function() { | |
| function link(scope, el, attr){ | |
| var color = d3.scale.ordinal().range(["#bd9e39","#0868ac"]); | |
| var data = scope.data; | |
| var width = 150; | |
| var height = 150; | |
| var min = Math.min(width, height); | |
| var svg = d3.select(el[0]).append('svg'); | |
| var pie = d3.layout.pie().sort(null); | |
| arc.outerRadius(min / 2 * 0.8) | |
| .innerRadius(min / 2 * 0.45); | |
| pie.value(function(d){ return +d.value ; }); | |
| svg.attr({width: width, height: height}); | |
| var g = svg.append('g') | |
| // center the donut chart | |
| .attr('transform', 'translate(' + width / 2 + ',' + height / 2 + ')'); | |
| // add the <path>s for each arc slice | |
| var arcs = g.selectAll('path').data(pie(data)) | |
| .enter().append('path') | |
| .style('stroke', 'white') | |
| .attr('fill-opacity', 0.75) | |
| .attr('fill', function(d, i){ return color(i); }) | |
| // store the initial angles | |
| .each(function(d) { return this._current = d }); | |
| var labels = g.selectAll('.label').data(pie(data)) | |
| .enter().append("text") | |
| .attr("transform", function(d) { return "translate(" + arc.centroid(d) + ")"; }) | |
| .attr("dy", ".35em") | |
| .attr("class", "label") | |
| .style("text-anchor", "middle") | |
| .text(function(d) { return d.data.label === "CA-Residents" ? "CA-Res" : "Non-Res"; }); | |
| scope.$watch('data', function (newVal, oldVal) { | |
| console.log("an element within `data` changed!"); | |
| var ca = newVal.filter(function(d) {return d.label === "CA-Residents";}), | |
| nr = newVal.filter(function(d) {return d.label === "Non-Residents";}), | |
| duration = 750; | |
| nr[0].value = +nr[0].value; | |
| ca[0].value = 100 - nr[0].value; | |
| arcs.data(pie(scope.data)); //.attr('d', arc) | |
| arcs.transition().duration(duration).attrTween('d', arcTween); | |
| labels.data(pie(scope.data)).transition().duration(duration).attr("transform", function(d) { return "translate(" + arc.centroid(d) + ")"; }); | |
| }, true); | |
| } | |
| return { | |
| link: link, | |
| restrict: 'E', | |
| scope: { 'data': '=', | |
| 'accessor': '=' } | |
| }; | |
| }); | |
| myApp.directive('oosDonut', function() { | |
| function link(scope, el, attr){ | |
| var color = d3.scale.ordinal().range(["#2b8cbe","#084081"]); | |
| var data = scope.data; | |
| var width = 150; | |
| var height = 150; | |
| var min = Math.min(width, height); | |
| var svg = d3.select(el[0]).append('svg'); | |
| var pie = d3.layout.pie().sort(null); | |
| arc.outerRadius(min / 2 * 0.8) | |
| .innerRadius(min / 2 * 0.45); | |
| pie.value(function(d){ return +d.value ; }); | |
| svg.attr({width: width, height: height}); | |
| var g = svg.append('g') | |
| // center the donut chart | |
| .attr('transform', 'translate(' + width / 2 + ',' + height / 2 + ')'); | |
| // add the <path>s for each arc slice | |
| var arcs = g.selectAll('path').data(pie(data)) | |
| .enter().append('path') | |
| .style('stroke', 'white') | |
| .attr('fill-opacity', 0.75) | |
| .attr('fill', function(d, i){ return color(i); }) | |
| // store the initial angles | |
| .each(function(d) { return this._current = d }); | |
| var labels = g.selectAll('.label').data(pie(data)) | |
| .enter().append("text") | |
| .attr("transform", function(d) { return "translate(" + arc.centroid(d) + ")"; }) | |
| .attr("dy", ".35em") | |
| .attr("class", "label") | |
| .style("text-anchor", "middle") | |
| .text(function(d) { return d.data.label === "Out-of-State" ? "OoS" : "Int"; }); | |
| scope.$watch('data', function (newVal, oldVal) { | |
| console.log("an element within `data` changed!"); | |
| var intl = newVal.filter(function(d) {return d.label === "International";}), | |
| oos = newVal.filter(function(d) {return d.label === "Out-of-State";}), | |
| duration = 750; | |
| intl[0].value = +intl[0].value; | |
| oos[0].value = 100 - intl[0].value; | |
| arcs.data(pie(scope.data)); //.attr('d', arc) | |
| arcs.transition().duration(duration).attrTween('d', arcTween); | |
| labels.data(pie(scope.data)).transition().duration(duration).attr("transform", function(d) { return "translate(" + arc.centroid(d) + ")"; }); | |
| }, true); | |
| } | |
| return { | |
| link: link, | |
| restrict: 'E', | |
| scope: { 'data': '=', | |
| 'accessor': '=' } | |
| }; | |
| }); | |
| myApp.directive('entDonut', function() { | |
| function link(scope, el, attr){ | |
| var color = d3.scale.ordinal().range(["#7b4173","#ce6dbd"]); | |
| var data = scope.data; | |
| var width = 150; | |
| var height = 150; | |
| var min = Math.min(width, height); | |
| var svg = d3.select(el[0]).append('svg'); | |
| var pie = d3.layout.pie().sort(null); | |
| arc.outerRadius(min / 2 * 0.8) | |
| .innerRadius(min / 2 * 0.45); | |
| pie.value(function(d){ return +d.value ; }); | |
| svg.attr({width: width, height: height}); | |
| var g = svg.append('g') | |
| // center the donut chart | |
| .attr('transform', 'translate(' + width / 2 + ',' + height / 2 + ')'); | |
| // add the <path>s for each arc slice | |
| var arcs = g.selectAll('path').data(pie(data)) | |
| .enter().append('path') | |
| .style('stroke', 'white') | |
| .attr('fill-opacity', 0.75) | |
| .attr('fill', function(d, i){ return color(i); }) | |
| // store the initial angles | |
| .each(function(d) { return this._current = d }); | |
| var labels = g.selectAll('.label').data(pie(data)) | |
| .enter().append("text") | |
| .attr("transform", function(d) { return "translate(" + arc.centroid(d) + ")"; }) | |
| .attr("dy", ".35em") | |
| .attr("class", "label") | |
| .style("text-anchor", "middle") | |
| .text(function(d) { return d.data.label === "Freshmen" ? "Fresh" : "Trans"; }); | |
| scope.$watch('data', function (newVal, oldVal) { | |
| console.log("an element within `data` changed!"); | |
| var intl = newVal.filter(function(d) {return d.label === "Freshmen";}), | |
| oos = newVal.filter(function(d) {return d.label === "Transfers";}), | |
| duration = 750; | |
| intl[0].value = +intl[0].value; | |
| oos[0].value = 100 - intl[0].value; | |
| arcs.data(pie(scope.data)); //.attr('d', arc) | |
| arcs.transition().duration(duration).attrTween('d', arcTween); | |
| labels.data(pie(scope.data)).transition().duration(duration).attr("transform", function(d) { return "translate(" + arc.centroid(d) + ")"; }); | |
| }, true); | |
| } | |
| return { | |
| link: link, | |
| restrict: 'E', | |
| scope: { 'data': '=', | |
| 'accessor': '=' } | |
| }; | |
| }); | |
| function arcTween(a) { | |
| // see: http://bl.ocks.org/mbostock/1346410 | |
| var i = d3.interpolate(this._current, a); | |
| this._current = i(0); | |
| return function(t) { | |
| return arc(i(t)); | |
| }; | |
| } | |
| </script> | |
| </body> | |
| </html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment