block by vicapow 9496218

Using D3 to load data from within Angular.

Full Screen

This is a code excerpt from the book, D3 on Angular. http://leanpub.com/d3angularjs

index.html

<!DOCTYPE html>
<html>
  <head>
    <title></title>
    <style type="text/css">
    body, html{
      margin:0;
      width: 100%;
      height: 100%;
    }
    tweet-map{
      width: 100%;
      height: 100%;
      display: block;
      overflow: hidden;
    }
    tweet-map .boundary{
      fill: none;
      stroke: white;
    }
    </style>
    <script src="//d3js.org/d3.v3.js" charset="utf-8"></script>
    <script src="//d3js.org/topojson.v1.js" charset="utf-8"></script>
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.10/angular.min.js"></script>
  </head>
  <body ng-app="app" ng-controller="MainCtrl">
    <tweet-map land="land" boundary="boundary"></tweet-map>
    
    <script>
var app = angular.module('app', []);

app.controller('MainCtrl', function($scope){
  d3.json('//bl.ocks.org/mbostock/raw/4090846/world-50m.json', function(err, world){
    if(err) throw err;
    $scope.$apply(function(){
      console.log('got world');
      $scope.land = topojson.feature(world, world.objects.countries);
      $scope.boundary = topojson
        .mesh(world, world.objects.countries, function(a, b) { return a !== b; });
    });
  })
});

app.directive('tweetMap', function(){
  // note: this code largely ported from Mike Bostock's Constrained Zoom
  // example at: //bl.ocks.org/mbostock/4987520
  function link(scope, el, attr){
    el = el[0];
    var width;
    var height;
    var projection = d3.geo.mercator().translate([0, 0]);
    var path = d3.geo.path().projection(projection);
    var svg = d3.select(el).append('svg');
    var g = svg.append('g');
    var land = g.append('path');
    var boundary = g.append('path');

    scope.$watch(function(){
      width = el.clientWidth;
      height = el.clientHeight;
      return width * height;
    }, resize);

    scope.$watch('land', function(geo){
      if(!geo) return;
      land.datum(geo).attr('class', 'land').attr('d', path);
    });

    scope.$watch('boundary', function(geo){
      if(!geo) return;
      boundary.datum(geo).attr("class", "boundary").attr("d", path);
    });
    
    function resize(){
      svg.attr({ width: width, height: height });
      projection.translate([width / 2, height / 2]).scale(width / 2 / Math.PI);
    };
  };
  return {
    link: link,
    restrict: 'E',
    scope: { land: '=', boundary: '=' }
  };
});

    </script>
  </body>
</html>