Skip to content

Instantly share code, notes, and snippets.

@Mbrownshoes
Last active March 14, 2018 19:58
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Mbrownshoes/5e36771400038b0c861c6617c622c5f7 to your computer and use it in GitHub Desktop.
Save Mbrownshoes/5e36771400038b0c861c6617c622c5f7 to your computer and use it in GitHub Desktop.
Display the source blob
Display the rendered blob
Raw
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
<!DOCTYPE html>
<met charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1">
<!-- <script type="text/javascript" src="https://unipear.api.gov.bc.ca/v1/bcgov/"></script>
<script type="text/javascript">
unippear({
"headerContainer": "#wrapper",
"footerContainer": "#wrapper"
});
</script> -->
<!-- Latest compiled and minified CSS -->
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/bootstrap-table/1.11.0/bootstrap-table.min.css">
<!-- Optional theme -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap-theme.min.css">
<script src="https://code.jquery.com/jquery-3.1.1.min.js" integrity="sha256-hVVnYaiADRTO2PzUGmuLJr8BLUSjGIZsDYGmIJLv2b8=" crossorigin="anonymous"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
<!-- Latest compiled and minified CSS -->
<!-- <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css"> -->
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/bootstrap-table/1.11.0/bootstrap-table.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-table/1.11.0/extensions/filter-control/bootstrap-table-filter-control.js"></script>
<style>
#map {
/* width: 960px;
height: 600px;*/
background: #fff;
margin-top: 40px;
}
:root {
--accent-color: #E8336D;
}
#provinces {
fill: #ddd;
cursor: pointer;
}
#label{
font-size: 20px;
/*color: white;*/
text-align: left;
}
#prov-borders {
stroke: #fff;
stroke-linejoin: round;
}
.bubble {
/*opacity: 1;*/
/*stroke: #fff;*/
stroke-width: .1px;
/*z-index: 1000;*/
}
.route {
fill: none;
/*stroke: #000;*/
/*stroke-width: 3px;*/
/*stroke-linecap: round;*/
/*opacity: 1;*/
/*stroke-dasharray: 12,8,4,8/*;*/
}
.annotation path {
stroke: var(--accent-color);
fill: none;
}
.annotation path.connector-arrow{
fill: var(--accent-color);
}
.annotation text {
fill: var(--accent-color);
}
.annotation-note-title {
font-weight: bold;
}
.tooltip {
position: absolute;
display: none;
min-width: 80px;
height: auto;
background: none repeat scroll 0 0 #ffffff;
border: 1px solid #6F257F;
padding: 14px;
text-align: center;
}
#arrow{
marker: 'red';
}
</style>
<body>
<script src="//d3js.org/d3.v4.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/topojson/1.6.19/topojson.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>
<script src="http://d3js.org/queue.v1.min.js"></script>
<script src="d3-annotation.min.js"></script>
<div id="wrapper" class="hfeed">
<div class="container">
<!-- <svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="960" height="500"> -->
<!-- <defs>
<path id="arrow" d="M-5,0 L-15,15 L15,0 L-15,-15 Z"/>
</defs> -->
<!-- </svg> -->
<!-- <div class="col-lg-8">
<select id="year">
<option value="2017 Q2" selected>2017 Q2</option>
</select>
</div> -->
<div id="nav-container">
<!-- <div class="nav left">left</div> -->
<div id="yearDropdown"></div>
<!-- <div class="nav right">right</div> -->
</div>
<div class="map" id="map"></div>
<div class="col-md-12">
</div>
</div>
</div>
<script src="main.js"></script>
<!-- <script>
margin = {
top: 20,
right: 20,
bottom: 30,
left: 50
};
var width = 960,
height = 500
var projection = d3.geoConicConformal()
.rotate([98, 0])
.center([0, 60])
.parallels([-10, 85.5])
.scale(1400)
var svg = d3.select(".map")
.append("svg")
.attr("width", width)
.attr("height", height);
var path = d3.geoPath()
.projection(projection);
var line_path = d3.geoPath()
.projection(null);
var radius = d3.scaleSqrt()
.domain([0, 3600])
.range([0, 50]);
var line_size = d3.scaleLinear()
.domain([32, 14103])
.range([2, 30])
var migration, test, net;
var line_data = [];
g = svg.append("g")
var defs = svg.append('svg:defs');
defs.append('svg:marker')
.attr('id', 'end-arrow')
.attr('viewBox', '0 -5 10 10')
.attr('refX', 0)
.attr('refY', 0)
.attr('stroke', 'none')
.attr('markerWidth', 9)
.attr('markerHeight', 3)
.attr("markerUnits", "strokeWidth")
.attr('orient', 'auto')
.append('svg:path')
.attr('d', 'M0,-5L10,0L0,5')
.attr('fill', '#3f51b5');
var defs = svg.append('svg:defs');
defs.append('svg:marker')
.attr('id', 'end-arrow-neg')
.attr('stroke', 'none')
.attr('viewBox', '0 -5 10 10')
.attr('refX', 0)
.attr('refY', 0)
.attr('markerWidth', 9)
.attr('markerHeight', 3)
.attr("markerUnits", "strokeWidth")
.attr('orient', 'auto')
.append('svg:path')
.attr('d', 'M0,-5L10,0L0,5')
.attr('fill', '#D32F2F');
// https://stackoverflow.com/questions/11121465/scaling-an-arrowhead-on-a-d3-force-layout-link-marker
// svg.append("defs").append("pattern")
// .attr('id','myPattern')
// .attr('markerWidth', 16)
// .attr('markerHeight', 16)
// .attr('patternUnits',"userSpaceOnUse")
// .append('path')
// .attr('fill','none')
// .attr('stroke','#335553')
// .attr('stroke-width','3')
// .attr('d','M-5,0 L-15,15 L15,0 L-15,-15 Z');
d3.json("can_no_projs.json", function(error, canada) {
if (error) throw error;
g.append("g")
.attr("id", "provinces")
.selectAll("path")
.data(topojson.feature(canada, canada.objects.cangeo).features)
.enter()
.append("path")
.attr("d", path)
.attr("id", "prov-borders")
.attr('fill', function(d) {
if (d.properties.PRENAME == 'British Columbia') {
return 'orange'
}
// console.log(d.properties.PRENAME)
})
tot = 0
var int, alldata, yearMenu;
var currYear = '2017 Q2'
d3.csv("Quarterly_2017.csv", function(error, dat) {
test = dat
alldata = dat
var yr = d3.map(alldata, function(d) {
return d.time_period;
}).keys()
// console.log(yr)
// yr.forEach(function(d){
// var option = $('<option />').text(d);
// $("#year").append(option);
// })
yearMenu = d3.select("#yearDropdown");
yearMenu
.append("select")
.attr("id", "locationMenu")
.selectAll("option")
.data(yr)
.enter()
.append("option")
.attr("value", function(d, i) {
return d;
})
.text(function(d) {
return d;
});
// migration = alldata.filter(function(d) {
// return d.time_period == currYear;
// })
update(alldata, currYear);
})
function update(migration, currYear) {
migration = alldata.filter(function(d) {
return d.time_period == currYear;
})
d3.selectAll('.route').remove()
d3.selectAll('.annotation-group').remove()
// $('#orders-table').bootstrapTable("destroy");
migration.forEach(function(d) {
d.net = Number(d.Origin) - Number(d.Destination)
if (d.Province != 'International') {
tot += d['Origin'] - d['Destination']
} else {
int = d['Origin'] - d['Destination']
}
})
flow_dat = topojson.feature(canada, canada.objects.cangeo).features
flow_dat.forEach(function(d) {
// define where arrow start/ends in other provinces
cen = line_path.centroid(d)
if (d.properties.PRENAME == 'Alberta') {
cen[0] += 1
cen[1] = cen[1] - 3.2
}
if (d.properties.PRENAME == 'Saskatchewan') {
cen[1] = cen[1] - 1.2
console.log(cen)
}
if (d.properties.PRENAME == 'Manitoba') {
cen[1] = cen[1] - 2.2
console.log(cen)
}
if (d.properties.PRENAME == 'New Brunswick') {
cen[1] = cen[1] - 1
}
if (d.properties.PRENAME == 'Nunavut') {
cen[1] = cen[1] - 5
cen[0] += -6
}
// console.log(line_path.centroid(d))
line_data.push({
prov: d.properties,
coords: cen
})
})
// console.log(flow_dat)
yearMenu.on('change', function() {
var currYear = d3.select(this)
.select('select')
.property('value');
// console.log(currYear)
update(alldata, currYear)
})
// var tooltip = d3.select("body").append("div")
// .attr("class", "tooltip")
// .style("opacity", 0);
var tooltip = d3.select("body").append("div").attr("class", "tooltip").style("opacity", 0);;
route_path = g.selectAll(".route")
// .data(migration.filter(function(d) {
// return d.Province != 'International';
// }))
.data(migration)
.enter()
.append("path")
.attr("class", "route")
.attr('d', function(d, i) {
line_data.forEach(function(j) {
// console.log(ii)
if (j.prov.PRENAME == d.Province) {
d.coords = j.coords
}
if (d.Province == 'International') {
d.coords = [-139.75635246400601, 53.75809690349844]
}
})
// console.log(d)
d.net = Number(d.Origin) - Number(d.Destination)
// define the location for arrow to start/end in bc here
bc_coords = [-122.75635246400601, 54.75809690349844];
if (d.Province == 'Nunavut') {
bc_coords = [-122.75635246400601, 57.75809690349844]
} else if (d.Province == 'Alberta') {
bc_coords = [-121.245605, 52.263570]
} else if (d.Province == 'Yukon') {
bc_coords = [-130.417969, 59.562099]
} else if (d.Province == 'Saskatchewan') {
bc_coords = [-121.394922, 53.469826]
} else if (d.Province == 'Manitoba') {
bc_coords = [-121.146484, 54.262016]
} else if (d.Province == 'Northwest Territories') {
bc_coords = [-122.167969, 59.462099]
} else if (d.Province == 'Newfoundland and Labrador') {
bc_coords = [-122.146484, 56.386543]
} else if (d.Province == 'International') {
bc_coords = [-138.346484, 53.76543]
} else if (d.Province == 'Quebec') {
bc_coords = [-122.046484, 55.586543]
}
if (d.net < 0) {
return path({
type: "LineString",
coordinates: [
bc_coords,
// [-122.75635246400601, 54.75809690349844], // BC
d.coords
]
})
// }
} else {
// if (d.Province == 'Alberta') {
return path({
type: "LineString",
coordinates: [
d.coords, bc_coords // BC
]
})
// }
}
})
// .style("stroke-dasharray", ("5, 3"))
.attr("stroke", function(d, i) {
// console.log(d.Destination)
if (Number(d.Origin) - Number(d.Destination) > 0) {
return "#3f51b5";
} else {
return "#D32F2F";
}
})
.style("stroke-width", function(d) {
// console.log(Math.abs((Number(d.Origin) - Number(d.Destination))))
return line_size(Math.abs((Number(d.Origin) - Number(d.Destination))));
})
.style("opacity", .8)
.transition()
.duration(2000)
.attrTween("stroke-dasharray", function() {
var len = this.getTotalLength();
return function(t) {
return (d3.interpolateString("0," + len, len + ",0"))(t)
};
}).attr("marker-end", function(d) {
// console.log(d)
if (d.net > 0) {
return "url(#end-arrow)"
} else {
return "url(#end-arrow-neg)"
}
})
// annotation
const type = d3.annotationCallout
const annotations = [{
type: d3.annotationCustomType(
d3.annotationCallout, {
"className": "custom",
"note": {
"lineType": "horizontal",
"align": "middle"
}
}),
note: {
label: "moved to BC from outside Canada",
title: int
},
//can use x, y directly instead of data
x: 118,
y: 250.02,
dy: 157,
dx: 42
},
{
note: {
label: "moved to BC from other provinces",
title: tot
},
//can use x, y directly instead of data
x: 245,
y: 343.02,
dy: 87,
dx: 23
}
]
const parseTime = d3.timeParse("%d-%b-%y")
const timeFormat = d3.timeFormat("%d-%b-%y")
//Skipping setting domains for sake of example
const x = d3.scaleTime().range([0, 800])
const y = d3.scaleLinear().range([300, 0])
const makeAnnotations = d3.annotation()
// .editMode(true)
.type(type)
//accessors & accessorsInverse not needed
//if using x, y in annotations JSON
// .accessors({
// x: d => x(parseTime(d.date)),
// y: d => y(d.close)
// })
// .accessorsInverse({
// date: d => timeFormat(x.invert(d.x)),
// close: d => y.invert(d.y)
// })
.annotations(annotations)
d3.select("svg")
.append("g")
.attr("class", "annotation-group")
.call(makeAnnotations)
// d3.selectAll('route').remove()
}
})
console.log(migration)
Province Destination Origin time_period
Newfoundland and Labrador 98 228 2017 Q2
Prince Edward Island 117 100 2017 Q2
Nova Scotia 594 510 2017 Q2
New Brunswick 348 182 2017 Q2
Quebec 1259 1291 2017 Q2
Ontario 5694 5596 2017 Q2
Manitoba 645 1392 2017 Q2
Saskatchewan 886 1735 2017 Q2
Alberta 7197 10711 2017 Q2
Yukon 78 202 2017 Q2
Northwest Territories 74 120 2017 Q2
Nunavut 52 9 2017 Q2
International 14103 2017 Q2
Newfoundland and Labrador 98 228 2017 Q3
Prince Edward Island 317 500 2017 Q3
Nova Scotia 594 710 2017 Q3
New Brunswick 348 782 2017 Q3
Quebec 1259 1291 2017 Q3
Ontario 5694 5596 2017 Q3
Manitoba 645 1392 2017 Q3
Saskatchewan 886 1735 2017 Q3
Alberta 11197 10711 2017 Q3
Yukon 78 202 2017 Q3
Northwest Territories 74 120 2017 Q3
Nunavut 52 9 2017 Q3
International 10103 2017 Q3
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment