block by almccon 3ab3802dc6837949775a58c7eef65bb5

hexbin Pop vs Soda

Full Screen

Built with blockbuilder.org

References: https://observablehq.com/@larsvers/making-a-tesselated-hexbin-map https://bl.ocks.org/veltman/38149d05ea247cbcebb1/a7e57c31b82bfaf7c46587635e8c119da5e45008 https://bl.ocks.org/mbostock/9885854/8967c821e056e2f8ed3a1432e7b43fa8293078b0 https://bl.ocks.org/veltman/c582a31d347e04dd75d5331b0074558e/123ef658b4db1eee28c662e7a5ee4d4d3258ba95

index.html

<!DOCTYPE html>
<head>
  <meta charset="utf-8">
  <script src="d3.v5.min.js"></script>
  <script src="topojson.v2.min.js"></script>
  <script src="d3-hexbin.v0.2.min.js"></script>
  <style>
    body { margin:0;position:fixed;top:0;right:0;bottom:0;left:0; }
    svg { width: 100%; height: 90%;}
    .landshadow {
      fill: none;
      stroke: #ccc;
      stroke-width: 2px;
      stroke-linejoin: round;
    }
    .states {
      fill: none;
      stroke: #fff;
      stroke-linejoin: round;
    }
    .counties {
      fill: #ffffff;
    }
    svg.circle {
      opacity: 0.2;
    }

  </style>
</head>

<body>
  <script>
    var svg = d3.select("body").append("svg");
    var projection = d3.geoAlbersUsa().translate([400,250]).scale(800);
    var path = d3.geoPath().projection(projection);

    var url = "//enjalot.github.io/wwsd/data/world/world-110m.geojson";
    var data_url = "//enjalot.github.io/wwsd/data/world/ne_50m_populated_places_simple.geojson";

    var us_counties_shapes_url = "us.json";
    var pvs_counties_data_url = "pvscounty_fips.tsv";
    var pvs_points_url = "pvscoords.csv";

    var hexbin = d3.hexbin()
      .extent([[0, 0], [svg.width, svg.height]])
      .radius(10);

    hexbin.x(d => {
      return projection([+d.lon,+d.lat]) ? projection([+d.lon,+d.lat])[0] : null;
    });
    hexbin.y(d => {
      return projection([+d.lon,+d.lat]) ? projection([+d.lon,+d.lat])[1] : null;
    });

    function cmyk(d) {
      if (d.PCTPOP == 0 && d.PCTSODA == 0 && d.PCTCOKE == 0 && d.PCTOTHER == 0) {
        return "white";
      } else {
        return "rgb("
          + Math.round((d.PCTPOP + d.PCTCOKE) * 100) + "%,"
          + Math.round((d.PCTSODA + d.PCTPOP) * 100) + "%,"
          + Math.round((d.PCTCOKE + d.PCTSODA) * 100) + "%)";
      }
    }

    Promise.all([d3.json(us_counties_shapes_url),d3.tsv(pvs_counties_data_url),d3.csv(pvs_points_url)]).then(function(data) {
      var us = data[0];
      var pvscounty_fips = data[1];
      var points = data[2];

      var pvscounty_lookup = {};
      pvscounty_fips.forEach(function(d) {
        pvscounty_lookup[d.id] = {
          PCTPOP: +d.PCTPOP,
          PCTSODA: +d.PCTSODA,
          PCTCOKE: +d.PCTCOKE,
          PCTOTHER: +d.PCTOTHER,
          SUMPOP: +d.SUMPOP,
          SUMSODA: +d.SUMSODA,
          SUMCOKE: +d.SUMCOKE,
          SUMOTHER: +d.SUMOTHER,
        }
      });

      svg.append("path").datum(topojson.feature(us, us.objects.land))
        .attr("class", "landshadow")
        .attr("d", path);

      var counties = svg.append("g")
        .attr("class", "counties")
        .selectAll("path")
          .data(topojson.feature(us, us.objects.counties).features)
        .enter().append("path")
          .attr("d", path);

      /*
      counties
        .style("fill", function(d) {
          //var threshold = 0.6;
          var result = pvscounty_lookup[d.id];
          if (result) {
            //if (result.PCTPOP > threshold || result.PCTSODA > threshold || result.PCTCOKE > threshold)
              return cmyk(result);
          } else {
            console.log("county id not found:", d.id);
            //return 'red';
          }
        });
      */

      points.forEach(d => {
        d.SUMPOP = +d.pop;
        d.SUMSODA = +d.soda;
        d.SUMCOKE = +d.coke;
        d.SUMOTHER = +d.other;
        d.PCTPOP = d.SUMPOP/+d.count;
        d.PCTSODA = d.SUMSODA/+d.count;
        d.PCTCOKE = d.SUMCOKE/+d.count;
        d.PCTOTHER = d.SUMOTHER/+d.count;
        d.lat = +d.lat;
        d.lon = +d.lon;
        d.count = +d.count;
      });

      /*
      svg.append("g").selectAll("circle")
          .data(points
            .filter(d => projection([+d.lon,+d.lat])) // filter anything where proj fails
            .filter(d => d.zip != 92122 && d.zip != 77069 && d.zip != 82401) // filter some bad data
          )
        .enter()
          .append("circle")
          .attr("r", function(d) {
            return d.count / 10;
          })
          .attr("fill", function(d) {
            return cmyk(d);
          })
          .attr("cx", function(d) {
            return projection([+d.lon,+d.lat])[0];
          })
          .attr("cy", function(d) {
            return projection([+d.lon,+d.lat])[1];
          })
          //.on("mouseover", d => {
          //  console.log(d.zip);
          //});
      */


      svg.append("g")
          .attr("class", "hexbins")
          .attr("clip-path", "url(#us-clip)") // clip to the shape of the us
        .selectAll("path")
          .data(hexbin(points))
        .enter().append("path")
          .attr("class", "hexagon")
          .attr("d", function(d) { return hexbin.hexagon(); })
          .attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; })
          .attr("fill", function(d) {
            var arrayvalues = Array.from(d);
            d.PCTPOP = d3.sum(arrayvalues, i => i.SUMPOP)/d3.sum(arrayvalues, i => i.count);
            d.PCTSODA = d3.sum(arrayvalues, i => i.SUMSODA)/d3.sum(arrayvalues, i => i.count);
            d.PCTCOKE = d3.sum(arrayvalues, i => i.SUMCOKE)/d3.sum(arrayvalues, i => i.count);
            d.PCTOTHER = d3.sum(arrayvalues, i => i.SUMOTHER)/d3.sum(arrayvalues, i => i.count);
            return cmyk(d);
          });

      //var topology = topojson.topology();



      // Add the us outline again just for clipping
      svg.append("clipPath").datum(topojson.feature(us, us.objects.land))
        .attr("id", "us-clip")
        .append("path")
        .attr("d", path);

      // Add the shapes of states on top, to have outlines.
      svg.append("path").datum(topojson.mesh(us, us.objects.states, function(a, b) {
        return a.id !== b.id;
      })).attr("class", "states").attr("d", path);

    });


  </script>
</body>

d3-hexbin.v0.2.min.js

// https://github.com/d3/d3-hexbin Version 0.2.2. Copyright 2017 Mike Bostock.
!function(n,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t(n.d3=n.d3||{})}(this,function(n){"use strict";function t(n){return n[0]}function r(n){return n[1]}var e=Math.PI/3,u=[0,e,2*e,3*e,4*e,5*e],o=function(){function n(n){var t,r={},e=[],u=n.length;for(t=0;t<u;++t)if(!isNaN(i=+d.call(null,o=n[t],t,n))&&!isNaN(c=+p.call(null,o,t,n))){var o,i,c,s=Math.round(c/=f),h=Math.round(i=i/a-(1&s)/2),l=c-s;if(3*Math.abs(l)>1){var v=i-h,M=h+(i<h?-1:1)/2,x=s+(c<s?-1:1),g=i-M,m=c-x;v*v+l*l>g*g+m*m&&(h=M+(1&s?1:-1)/2,s=x)}var y=h+"-"+s,j=r[y];j?j.push(o):(e.push(j=r[y]=[o]),j.x=(h+(1&s)/2)*a,j.y=s*f)}return e}function o(n){var t=0,r=0;return u.map(function(e){var u=Math.sin(e)*n,o=-Math.cos(e)*n,i=u-t,a=o-r;return t=u,r=o,[i,a]})}var i,a,f,c=0,s=0,h=1,l=1,d=t,p=r;return n.hexagon=function(n){return"m"+o(null==n?i:+n).join("l")+"z"},n.centers=function(){for(var n=[],t=Math.round(s/f),r=Math.round(c/a),e=t*f;e<l+i;e+=f,++t)for(var u=r*a+(1&t)*a/2;u<h+a/2;u+=a)n.push([u,e]);return n},n.mesh=function(){var t=o(i).slice(0,4).join("l");return n.centers().map(function(n){return"M"+n+"m"+t}).join("")},n.x=function(t){return arguments.length?(d=t,n):d},n.y=function(t){return arguments.length?(p=t,n):p},n.radius=function(t){return arguments.length?(i=+t,a=2*i*Math.sin(e),f=1.5*i,n):i},n.size=function(t){return arguments.length?(c=s=0,h=+t[0],l=+t[1],n):[h-c,l-s]},n.extent=function(t){return arguments.length?(c=+t[0][0],s=+t[0][1],h=+t[1][0],l=+t[1][1],n):[[c,s],[h,l]]},n.radius(1)};n.hexbin=o,Object.defineProperty(n,"__esModule",{value:!0})});

topojson.v0.min.js

topojson=function(){function t(t,e){function n(e){var n=t.arcs[e],r=n[0],o=[0,0];return n.forEach(function(t){o[0]+=t[0],o[1]+=t[1]}),[r,o]}var r={},o={},a={};e.forEach(function(t){var e=n(t);(r[e[0]]||(r[e[0]]=[])).push(t),(r[e[1]]||(r[e[1]]=[])).push(~t)}),e.forEach(function(t){var e,r,i=n(t),c=i[0],s=i[1];if(e=a[c])if(delete a[e.end],e.push(t),e.end=s,r=o[s]){delete o[r.start];var u=r===e?e:e.concat(r);o[u.start=e.start]=a[u.end=r.end]=u}else if(r=a[s]){delete o[r.start],delete a[r.end];var u=e.concat(r.map(function(t){return~t}).reverse());o[u.start=e.start]=a[u.end=r.start]=u}else o[e.start]=a[e.end]=e;else if(e=o[s])if(delete o[e.start],e.unshift(t),e.start=c,r=a[c]){delete a[r.end];var f=r===e?e:r.concat(e);o[f.start=r.start]=a[f.end=e.end]=f}else if(r=o[c]){delete o[r.start],delete a[r.end];var f=r.map(function(t){return~t}).reverse().concat(e);o[f.start=r.end]=a[f.end=e.end]=f}else o[e.start]=a[e.end]=e;else if(e=o[c])if(delete o[e.start],e.unshift(~t),e.start=s,r=a[s]){delete a[r.end];var f=r===e?e:r.concat(e);o[f.start=r.start]=a[f.end=e.end]=f}else if(r=o[s]){delete o[r.start],delete a[r.end];var f=r.map(function(t){return~t}).reverse().concat(e);o[f.start=r.end]=a[f.end=e.end]=f}else o[e.start]=a[e.end]=e;else if(e=a[s])if(delete a[e.end],e.push(~t),e.end=c,r=a[c]){delete o[r.start];var u=r===e?e:e.concat(r);o[u.start=e.start]=a[u.end=r.end]=u}else if(r=o[c]){delete o[r.start],delete a[r.end];var u=e.concat(r.map(function(t){return~t}).reverse());o[u.start=e.start]=a[u.end=r.start]=u}else o[e.start]=a[e.end]=e;else e=[t],o[e.start=c]=a[e.end=s]=e});var i=[];for(var c in a)i.push(a[c]);return i}function e(e,r,o){function a(t){0>t&&(t=~t),(l[t]||(l[t]=[])).push(f)}function i(t){t.forEach(a)}function c(t){t.forEach(i)}function s(t){"GeometryCollection"===t.type?t.geometries.forEach(s):t.type in d&&(f=t,d[t.type](t.arcs))}var u=[];if(arguments.length>1){var f,l=[],d={LineString:i,MultiLineString:c,Polygon:c,MultiPolygon:function(t){t.forEach(c)}};s(r),l.forEach(3>arguments.length?function(t,e){u.push([e])}:function(t,e){o(t[0],t[t.length-1])&&u.push([e])})}else for(var p=0,h=e.arcs.length;h>p;++p)u.push([p]);return n(e,{type:"MultiLineString",arcs:t(e,u)})}function n(t,e){function n(t,e){e.length&&e.pop();for(var n,o=h[0>t?~t:t],a=0,i=o.length,c=0,s=0;i>a;++a)e.push([(c+=(n=o[a])[0])*f+d,(s+=n[1])*l+p]);0>t&&r(e,i)}function o(t){return[t[0]*f+d,t[1]*l+p]}function a(t){for(var e=[],r=0,o=t.length;o>r;++r)n(t[r],e);return 2>e.length&&e.push(e[0]),e}function i(t){for(var e=a(t);4>e.length;)e.push(e[0]);return e}function c(t){return t.map(i)}function s(t){var e=t.type,n="GeometryCollection"===e?{type:e,geometries:t.geometries.map(s)}:e in v?{type:e,coordinates:v[e](t)}:{type:null};return"id"in t&&(n.id=t.id),"properties"in t&&(n.properties=t.properties),n}var u=t.transform,f=u.scale[0],l=u.scale[1],d=u.translate[0],p=u.translate[1],h=t.arcs,v={Point:function(t){return o(t.coordinates)},MultiPoint:function(t){return t.coordinates.map(o)},LineString:function(t){return a(t.arcs)},MultiLineString:function(t){return t.arcs.map(a)},Polygon:function(t){return c(t.arcs)},MultiPolygon:function(t){return t.arcs.map(c)}};return s(e)}function r(t,e){for(var n,r=t.length,o=r-e;--r>o;)n=t[o],t[o++]=t[r],t[r]=n}function o(t,e){for(var n=0,r=t.length;r>n;){var o=n+r>>>1;e>t[o]?n=o+1:r=o}return n}function a(t){function e(t,e){t.forEach(function(t){0>t&&(t=~t);var n=a[t]||(a[t]=[]);n[e]||(n.forEach(function(t){var n,r;r=o(n=i[e],t),n[r]!==t&&n.splice(r,0,t),r=o(n=i[t],e),n[r]!==e&&n.splice(r,0,e)}),n[e]=e)})}function n(t,n){t.forEach(function(t){e(t,n)})}function r(t,e){"GeometryCollection"===t.type?t.geometries.forEach(function(t){r(t,e)}):t.type in c&&c[t.type](t.arcs,e)}var a=[],i=t.map(function(){return[]}),c={LineString:e,MultiLineString:n,Polygon:n,MultiPolygon:function(t,e){t.forEach(function(t){n(t,e)})}};return t.forEach(r),i}return{version:"0.0.32",mesh:e,object:n,neighbors:a}}();