-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.html
179 lines (156 loc) · 7.12 KB
/
index.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
<!DOCTYPE html>
<head>
<style>
.states {
stroke-width: 0.5;
stroke-linejoin: round;
stroke-linecap: round;
}
.points {
fill: #ffa600;
stroke-width: .5;
}
.main {
stroke: #000;
fill: none;
}
.nation {
fill: #003f5c;
stroke-width: 1;
}
.tooltip {
position: absolute;
text-align: center;
width: auto;
height: auto;
padding: 2px;
font: 10px sans-serif;
background: lightsteelblue;
border: 0px;
border-radius: 8px;
pointer-events: none;
}
</style>
</head>
<body>
<svg class="main"></svg>
</body>
<script src="https://d3js.org/d3.v5.js"></script>
<script src="https://d3js.org/d3-array.v1.min.js"></script>
<script src="https://d3js.org/d3-geo.v1.min.js"></script>
<script src="https://d3js.org/d3-fetch.v1.min.js"></script>
<script src="https://unpkg.com/topojson-client@3"></script>
<script>
// define tooltip object
var tooltip = d3.select('body')
.append('div')
.attr('class', 'tooltip')
.style('opacity', 0);
// basic steps for creating a map
// 1. Create a projection function
// 2. Create a path function
// 3. Get GEOJson object as data, and draw map using the path function
var width = 960;
var height = 600;
// create projection. projections are functions that take geo locations (lat, long), and return cartesian coordinates
// there are many of them but I am using Albers' equal area conic projection. Essentially maps the sphere (globe) onto a cone and then unrolls the cone onto a plane
// the TopoJson of the U.S. comes pre-projected in Albers. We use this same projection for the points on the map
var albersProjection = d3.geoAlbersUsa()
// configure the projection for a 960x600 viewport
.scale(1280)
.translate([width / 2, height / 2]);
// create path. paths are functions that translate GEOJson features into svg path data
// GEOJson is a json format for representing geographical features, like Point, MultiPoint, LineString, MultiLineString, Polygon, MultiPolygon
// the path function can handle all the GEOJson features
// specify the projection that should be used to translate the geo locations from the GEOJson to cartesian coordinates
// http://bl.ocks.org/michellechandra/0b2ce4923dc9b5809922
// http://bl.ocks.org/phil-pedruco/7745589
// https://bl.ocks.org/mbostock/raw/4090846/us.json
// https://d3js.org/us-10m.v1.json
// select svg element and specify width and height
var svg = d3.select('svg')
.attr('width', width)
.attr('height', height);
var path = d3.geoPath();
d3.json('https://jacks-bush.github.io/mtb_project/combined.json').then(function (usData) {
// TopoJSON is an extension of GeoJSON that includes topology. Rather than representing geometries discretely,
// geometries are stitched together from shared line segments called arcs.
// draw the outline of the us
svg.append('g')
.append('path')
.attr('class', 'nation')
.attr('d', path(topojson.feature(usData, usData.objects.nation)));
// draw all the states
// add a wrapper element for the state path element
svg.append('g')
// add a single path element
.append('path')
// add only one data point, which is a GeoJson MultiLineString geometry object
// topojson.mesh
.datum(topojson.mesh(usData, usData.objects.states), function (a, b) { return a !== b; })
// get a selection of all the data points (states) that have no corresponding DOM element
// the path function takes the GeoJson data and translates it into svg path data
.attr('class', 'states')
.attr('d', path);
// get the list of GeoJson features from the TopoJson
var pointsData = topojson.feature(usData, usData.objects.points).features
// create a selector with the rideData bound to g elements
var featuredRides = svg.append('g')
.attr('text-anchor', 'middle')
.attr('font-family', 'sans-serif')
.attr('font-size', '10')
// define the selector to which we will join data
.selectAll('g')
// pointsData is a list of GeoJson features
.data(pointsData)
// joins wrapper elements to match all of the unbound data points defined in the data() function above
// this should append a wrapper g element for each ride in the list
.join('g')
.attr('transform', function (d) { return 'translate(' + d.geometry.coordinates + ')' });
// add the circle element.
featuredRides.append('circle')
.attr('class', 'points')
.attr('r', 3)
// add mouseover event listener
.on('mouseover', function (d, i) {
tooltip
// set text of tooltip
.html(d.properties.name + '</br>' + d.properties.city + ',' + d.properties.state + '</br>#' + d.properties.position)
// set position
.style('left', d3.event.pageX + 'px')
.style('top', d3.event.pageY + 'px')
// transition tooltip to .85 opacity
.transition()
.duration(200)
.style('opacity', .75);
})
// add mouseout event listener
.on('mouseout', function (d) {
// transition the opacity back to 0
tooltip.transition()
.duration(200)
.style('opacity', 0);
});
// add the label
// featuredRides.append('text')
// .attr('y', -6)
// .text(function (d) { return d.name; });
// .attr('cx', function (d) { return albersProjection([d.long, d.lat])[0] })
// .attr('cy', function (d) { return albersProjection([d.long, d.lat])[1] });
// d3.select('svg')
// // add a wrapper element
// .append('g')
// // define the selector to which we will join data.
// .selectAll('path')
// // join topojson feature data for us states
// .data(topojson.feature(usData, usData.objects.states).features)
// // get a selection of all the data points (states) that have no corresponding DOM element
// .enter()
// // now add a path element for each state in the selection
// // this returns a new selection of all the path elements that were just added
// .append('path')
// // major magic going on here. we're adding a d attribute and passing in the path function defined above
// // the path function takes the GeoJson data and translates it into svg path data
// .attr('d', d3.geoPath());
});
</script>