Making a Chloropleth Map Directive Using D3.js and Angular.js

by sathish panduga p

HTML

<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.6/d3.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/topojson/1.6.19/topojson.min.js"></script>
<script src="https://www.workshape.io/js/geo/d3.geo.zoom.js"></script>
<div ng-app="myapp">
    <div ng-controller="ctrl1">
        <globe data="data"></globe>
    </div>
</div>

CSS

svg {
    width: 100%
}

path {
    fill: none;
    stroke: black
}

.background {
  fill: rgba(200,212,220,.5);
  stroke-width: .8px;
  stroke: black;
}

.graticule {
    stroke: rgba(0,0,0, .2);
    stroke-width: .5px;
}

.country {
    cursor: pointer;
}

.country .land, .state .land {
    fill: white;
    stroke: rgba(0,0,0, .2);
    stroke-width .3px;
}

.state .overlay {
    fill: blue;
    fill-opacity: 0;
}

.country .overlay {
    fill: orange;
    fill-opacity: 0;
}

JavaScript

var app = angular.module("myapp", []);

    app.directive("globe", function() {
        return {
            restrict   : 'E',
            scope      : {
                data: '=?'
            },
            template: 
            '<div class="globe-wrapper">' +
                '<div class="globe"></div>' +
                '<div class="info"></div>' +
            '</div>',
            link: link
        };
        
        function link(scope, element, attrs) {
            var width = 500, height = width, 
                projection, path,
                svg, features, graticule,
                mapJson = 'https://gist.githubusercontent.com/GordyD/49654901b07cb764c34f/raw/27eff6687f677c984a11f25977adaa4b9332a2a9/countries-and-states.json',
                states, stateSet, countries, countrySet, zoom;
            
            projection = d3.geo.orthographic()
                .translate([width / 2, height / 2])
                .scale(250)
                .clipAngle(90)
                .precision(0.1)
                .rotate([0, -30]);
            
            path = d3.geo.path()
                .projection(projection);
            
            svg = d3.select(element[0]).select('.globe')
                .append('svg')
                .attr('width', width)
                .attr('height', height)
                .attr('viewBox', '0, 0, ' + width + ', ' + height);
           
            features = svg.append('g');
            
            features.append('path')
                .datum({type: 'Sphere'})
                .attr('class', 'background')
                .attr('d', path);
            
            graticule = d3.geo.graticule();

            features.append('path')
              .datum(graticule)
              .attr('class', 'graticule')
              .attr('d', path);
            
            zoom = d3.geo.zoom()
              .projection(projection)
              .scaleExtent([projection.scale() * 0.7, projection.scale() * 8])
             ...