Commit 2998829a8d27dee4e1e8a9686cf4eebcb765a4b2

Authored by Rémi Emonet
0 parents
Exists in master

sample network showing a distribution when selecting pairs

Showing 5 changed files with 237 additions and 0 deletions

... ... @@ -0,0 +1,21 @@
  1 +{
  2 + "name": "angular-d3-network-demo",
  3 + "version": "0.0.1",
  4 + "authors": [
  5 + "Rémi Emonet <remi.emonet@reverse--com.heeere>"
  6 + ],
  7 + "description": "Testing AngularJS + D3 for a network",
  8 + "license": "undefined",
  9 + "private": true,
  10 + "ignore": [
  11 + "**/.*",
  12 + "node_modules",
  13 + "bower_components",
  14 + "test",
  15 + "tests"
  16 + ],
  17 + "dependencies": {
  18 + "angular": "~1.3.15",
  19 + "d3": "~3.5.5"
  20 + }
  21 +}
distribution.html View file @ 2998829
... ... @@ -0,0 +1,15 @@
  1 +<div class="distribution" style="display: inline-block; width: {{width}}px; height: {{height}}px; border: 1px solid black; position: relative;">
  2 + <div ng-repeat="v in values track by $index"
  3 + ng-style="{
  4 + padding: '1px',
  5 + 'box-sizing': 'border-box',
  6 + position: 'absolute',
  7 + background: 'rgba(0,0,0,'+(normalize ? v / sumValues : v)+')',
  8 + top: ($index * 100 / values.length)+'%',
  9 + height: (100 / values.length)+'%',
  10 + width: '100%',
  11 + 'border-top': '1px solid black',
  12 + 'border-bottom': '1px solid white'
  13 + }"
  14 + title="{{v}} ({{100*v/sumValues}}%)"></div>
  15 +</div>
... ... @@ -0,0 +1,30 @@
  1 +<!DOCTYPE html>
  2 +<html>
  3 +<head>
  4 + <meta charset="utf-8">
  5 + <script src="bower_components/angular/angular.js"></script>
  6 + <script src="bower_components/d3/d3.js"></script>
  7 + <script src="network-test.js"></script>
  8 +</head>
  9 +
  10 +<body ng-app="network-test" ng-controller="network-test">
  11 + <my-network spring="false"
  12 + nodes="currentNodes" edges="currentEdges"
  13 + on-selection-change="selected"
  14 + width="500"
  15 + height="500"
  16 + ></my-network>
  17 + <my-distribution normalize="true"
  18 + values="currentData"
  19 + width="100"
  20 + height="500"
  21 + ></my-distribution>
  22 + <my-distribution
  23 + values="currentData"
  24 + width="50"
  25 + height="500"
  26 + ></my-distribution>
  27 +
  28 +</body>
  29 +
  30 +</html>
network-test.js View file @ 2998829
... ... @@ -0,0 +1,148 @@
  1 +
  2 +angular.module('d3mod', []).factory('d3', function(){ return d3; });
  3 +
  4 +var mod = angular.module('network-test', [
  5 + 'd3mod'
  6 +]);
  7 +
  8 +mod.controller('network-test', ['$scope', function($scope) {
  9 + $scope.allData = [
  10 + [ [.8, .01, .24, 0], // 0,0
  11 + ],
  12 + [ [.5, .5, .24, 0], // 1,0
  13 + [.2, .5, .4, 0] // 1,1
  14 + ],
  15 + [ [0.2, 0, .2, 0], // 2,0
  16 + [0, .5, .444, 0], // 2,1
  17 + [.1, .1, .88, 0] // 2,2
  18 + ],
  19 + [ [0.2, 0, .2, 1], // 3,0
  20 + [0, .5, .444, 8], // 3,1
  21 + [.1, .1, .88, 7], // 3,2
  22 + [.1, .1, .88, 5] // 3,3
  23 + ]
  24 + ];
  25 + $scope.currentData = [];
  26 + $scope.currentNodes = [
  27 + {name: 'hum', x: 100, y: 100},
  28 + {name: 'yeah', x:80, y: 200},
  29 + {name: 'hum hum', x: 200, y: 150},
  30 + {name: 'right', x: 200, y: 200},
  31 + ];
  32 + var e = function(i,j,d) { return {source:i, target:j, value:100, name:d}; };
  33 + $scope.currentEdges = [
  34 + e(0, 1, 'a'),
  35 + e(0, 2, 'b'),
  36 + e(1, 3, 'c'),
  37 + ];
  38 + $scope.selected = function(v) {
  39 + var i = Math.max(v[0], v[1]);
  40 + var j = Math.min(v[0], v[1]);
  41 + if (j < -1) return;
  42 + $scope.currentData = $scope.allData[i][j];
  43 + };
  44 +}]);
  45 +
  46 +mod.directive('myDistribution', [function() {
  47 + return {
  48 + restrict: 'E',
  49 + templateUrl: 'distribution.html',
  50 + scope: {
  51 + values: '=',
  52 + normalize: '=',
  53 + width: '@',
  54 + height: '@',
  55 + },
  56 + link: function(scope, element, attrs) {
  57 + scope.$watch('values', function() {
  58 + if (!scope.values) return;
  59 + scope.sumValues = scope.values.reduce(function(prev, curr) {return prev + curr;}, 0);
  60 + });
  61 + }
  62 + }
  63 +}]);
  64 +
  65 +mod.directive('myNetwork', ['d3', function(d3) {
  66 + return {
  67 + restrict: 'E',
  68 + templateUrl: 'svg-network.html',
  69 + scope: {
  70 + spring: '=',
  71 + nodes: '=',
  72 + edges: '=',
  73 + width: '@',
  74 + height: '@',
  75 + onSelectionChange: '='
  76 + },
  77 + link: function(scope, element, attrs) {
  78 + scope.sel = [-1, -1];
  79 + scope.$watchGroup(['nodes', 'edges', 'sel'], function() {
  80 + if (!scope.nodes || !scope.edges) return;
  81 + var width = scope.width;
  82 + var height = scope.height;
  83 + var n = 100;
  84 + var force = d3.layout.force()
  85 + .nodes(scope.nodes)
  86 + .links(scope.edges)
  87 + .linkDistance(function(d) { return d.value; })
  88 + .size([width, height]);
  89 +
  90 + var svg = d3.select('svg')
  91 + .attr("width", width)
  92 + .attr("height", height);
  93 +
  94 + var loading = svg.append("text")
  95 + .attr("x", width / 2)
  96 + .attr("y", height / 2)
  97 + .attr("dy", ".35em")
  98 + .attr("text-anchor", "middle");
  99 +
  100 + if (scope.spring) {
  101 + // Run the layout a fixed number of times.
  102 + // The ideal number of times scales with graph complexity.
  103 + // Of course, don't run too long—you'll hang the page!
  104 + force.start();
  105 + for (var i = n * n; i > 0; --i) {
  106 + force.tick()
  107 + }
  108 + force.stop();
  109 + }
  110 +
  111 + var link = svg.selectAll(".zedge").data(scope.edges);
  112 + link.enter().append("line").classed("zedge", true);
  113 + link
  114 + .attr("x1", function(d) { return scope.nodes[d.source].x; })
  115 + .attr("y1", function(d) { return scope.nodes[d.source].y; })
  116 + .attr("x2", function(d) { return scope.nodes[d.target].x; })
  117 + .attr("y2", function(d) { return scope.nodes[d.target].y; });
  118 +
  119 + var node = svg.selectAll(".znode").data(scope.nodes);
  120 + node.enter().append("g").classed("znode", true);
  121 + node.attr('transform', function(d) { return 'translate('+d.x+','+d.y+')'; });
  122 + node.classed('selected', function(d, i) {
  123 + return (i == scope.sel[0] || i == scope.sel[1]);
  124 + });
  125 + node.classed('lastSelected', function(d, i) {
  126 + return i == scope.sel[1];
  127 + });
  128 + node.on('click', function(d, i) {
  129 + var newOne = [scope.sel[1], i];
  130 + scope.$apply(function() {
  131 + scope.sel = newOne;
  132 + if (scope.onSelectionChange) {
  133 + scope.onSelectionChange(newOne, scope.sel);
  134 + }
  135 + });
  136 + });
  137 + node.append('circle')
  138 + .attr("r", 20);
  139 + node.append("text")
  140 + .attr("dy", ".35em")
  141 + .attr("text-anchor", "middle")
  142 + .text(function(d, i){return i;});
  143 +
  144 + });
  145 + }
  146 + };
  147 +}]);
  148 +
svg-network.html View file @ 2998829
... ... @@ -0,0 +1,23 @@
  1 +<svg style="border: 1px solid red;">
  2 + <style>
  3 +.znode circle {
  4 + stroke: black;
  5 + stroke-width: 3px;
  6 + fill: #A40000;
  7 +}
  8 +.znode.selected circle {
  9 + fill: #0000A4;
  10 +}
  11 +.znode.lastSelected circle {
  12 + fill: #0000F4;
  13 +}
  14 +.znode text {
  15 + font-weight: bold;
  16 + fill: white;
  17 +}
  18 +.zedge {
  19 + stroke: black;
  20 + stroke-width: 5px;
  21 +}
  22 + </style>
  23 +</svg>