Skip to content

Commit b516dda

Browse files
committed
Debug timeline
1 parent 4ee5326 commit b516dda

File tree

5 files changed

+210
-90
lines changed

5 files changed

+210
-90
lines changed
File renamed without changes.
File renamed without changes.

main-map.html

+6-6
Original file line numberDiff line numberDiff line change
@@ -27,19 +27,19 @@
2727
<head>
2828
<meta charset="utf-8">
2929
<script src="https://d3js.org/d3.v4.js"></script>
30-
<script src="https://d3js.org/d3-geo-projection.v2.min.js"></script>
3130
<script src="https://www.w3schools.com/lib/w3data.js"></script>
3231
<link rel="stylesheet" href="https://unpkg.com/[email protected]/dist/leaflet.css" integrity="sha512-xwE/Az9zrjBIphAcBb3F6JVqxf46+CDLwfLMHloNu6KEQCAWi6HcDUbeOfBIptF7tcCzusKFjFw2yuvEpDL9wQ==" crossorigin=""/>
3332
<script src="https://unpkg.com/[email protected]/dist/leaflet.js" integrity="sha512-nMMmRyTVoLYqjP9hrbed9S+FzjZHW5gY1TWCHA5ckwXZBadntCNs8kEqAWdrb9O7rxbCaA4lKTIWjDXZxflOcA==" crossorigin=""></script>
3433
<script src="https://unpkg.com/[email protected]/dist/leaflet.js" integrity="sha512-gZwIG9x3wUXg2hdXF6+rVkLF/0Vi9U8D2Ntg4Ga5I5BZpVkVxlJWbSQtXPSiUTtC0TjtGOmxa1AJPuV0CPthew==" crossorigin=""></script>
3534
<style>
3635
body {margin: 0;}
37-
#mapid { height: 100vh; width: 100vw;}
36+
#mapid { height: 50vh; width: 50vw;}
3837
</style>
3938
</head>
4039
<body>
4140
<div id="mapid"></div>
42-
<script type="text/javascript" src="hs-severity.json"></script>
43-
<script type="text/javascript" src="main-map.js"></script>
44-
<div id="timeline-container" href="/transition-flash-research/transition_flash.html"></div>
45-
</body>
41+
<div id="timeline-container"></div>
42+
</body>
43+
44+
<script type="text/javascript" src="hs-severity.json"></script>
45+
<script type="text/javascript" src="main-map.js"></script>

main-map.js

+203-84
Original file line numberDiff line numberDiff line change
@@ -1,92 +1,211 @@
1-
// mapid is the id of the div where the map will appear
2-
var map = L
3-
.map('mapid')
4-
.setView([40.730610, -73.935242], 11); // center position + zoom
5-
6-
// Add background to map (many diff options: https://leaflet-extras.github.io/leaflet-providers/preview/)
7-
L.tileLayer(
8-
'https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}{r}.png', {
9-
attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors &copy; <a href="https://carto.com/attributions">CARTO</a>',
10-
subdomains: 'abcd',
11-
maxZoom: 19
12-
}).addTo(map);
13-
14-
// Add a svg layer to the map
15-
L.svg().addTo(map);
16-
17-
// Create color palettes
18-
var violation = {
19-
true: "red",
20-
false: "green"
21-
}
1+
makeMap();
222

23-
// Plot map
24-
d3.json("hs-severity.json", function(data) {
25-
26-
d3.select("#mapid")
27-
.select("svg")
28-
.selectAll("myCircle")
29-
.data(data)
30-
.enter()
31-
.append("circle")
32-
.attr("cx", function(d){ return map.latLngToLayerPoint([d.la, d.lo]).x })
33-
.attr("cy", function(d){ return map.latLngToLayerPoint([d.la, d.lo]).y })
34-
.attr("r", function(d) {
35-
if(d.s == 0) {
36-
return (d.s /3) + 5;
37-
}
38-
else {
39-
return (d.s ** (1/3)) * 4;
40-
}
41-
}) // change this to correlate with severity
42-
.style("fill", function(d) {
43-
return violation[d.v];
44-
})
45-
.attr("stroke", false)
46-
.attr("fill-opacity", .8)
47-
48-
// Function that update circle position if something change
49-
function update() {
50-
d3.selectAll("circle")
51-
.attr("cx", function(d){ return map.latLngToLayerPoint([d.la, d.lo]).x })
52-
.attr("cy", function(d){ return map.latLngToLayerPoint([d.la, d.lo]).y })
3+
function makeMap() {
4+
// mapid is the id of the div where the map will appear
5+
var map = L
6+
.map('mapid')
7+
.setView([40.730610, -73.935242], 11); // center position + zoom
8+
9+
// Add background to map (many diff options: https://leaflet-extras.github.io/leaflet-providers/preview/)
10+
L.tileLayer(
11+
'https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}{r}.png', {
12+
attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors &copy; <a href="https://carto.com/attributions">CARTO</a>',
13+
subdomains: 'abcd',
14+
maxZoom: 19
15+
}).addTo(map);
16+
17+
// Add a svg layer to the map
18+
L.svg().addTo(map);
19+
20+
// Create color palettes
21+
var violation = {
22+
true: "red",
23+
false: "green"
5324
}
5425

55-
//add brush to timeline, hook to callback
56-
var brush = d3.svg.brush()
57-
.x(x);
58-
.on("brush", function(){ brushCallback(brush, data);})
59-
.extent([new Date("7/1/2014"), new Date("8/1/2014")]); // initial value
26+
// Plot map + parse data
27+
d3.json("hs-severity.json", function(data) {
28+
29+
d3.select("#mapid")
30+
.select("svg")
31+
.selectAll("myCircle")
32+
.data(data)
33+
.enter()
34+
.append("circle")
35+
.attr("cx", function(d){ return map.latLngToLayerPoint([d.la, d.lo]).x })
36+
.attr("cy", function(d){ return map.latLngToLayerPoint([d.la, d.lo]).y })
37+
.attr("r", function(d) {
38+
if(d.s == 0) {
39+
return (d.s /3) + 5;
40+
}
41+
else {
42+
return (d.s ** (1/3)) * 4;
43+
}
44+
}) // change this to correlate with severity
45+
.style("fill", function(d) {
46+
return violation[d.v];
47+
})
48+
.attr("stroke", false)
49+
.attr("fill-opacity", .8)
50+
51+
52+
// data parsing
53+
var parseMonthDayYear = d3.timeFormat("%d-%b"); // d3.utcParse() // fix this
54+
55+
var dataForTimeline = [],
56+
dateToCrimeCount = {};
6057

61-
slider.append("g")
58+
data.forEach(function(d, idx) {
59+
60+
d.a = parseMonthDayYear(new Date(d.a)) ;
61+
// d.created_at = parseMonthDayYear(d.created_at);
62+
if (!dateToCrimeCount[d.a]) {
63+
var dataCount = [d.t, 1];
64+
dateToCrimeCount[d.a] = dataCount;
65+
}
66+
dateToCrimeCount[d.a][0] += d.t;
67+
dateToCrimeCount[d.a][1] += 1;
68+
69+
});
70+
71+
Object.keys(dateToCrimeCount).forEach(function(time) {
72+
dateToCrimeCount[time] = dateToCrimeCount[time][0] / dateToCrimeCount[time][1];
73+
dataForTimeline.push({ TIME: new Date(time), TEMP: dateToCrimeCount[time] });
74+
});
75+
dataForTimeline.sort(function(a,b) { return a.TIME - b.TIME; });
76+
77+
makeTimeline(data, dataForTimeline);
78+
//makeLegend();
79+
80+
})
81+
82+
// If the user change the map (zoom or drag), update circle position:
83+
map.on("moveend", update)
84+
85+
}
86+
87+
// Creates the event timeline and sets up callbacks for brush changes
88+
function makeTimeline(dataForMap, dataForTimeline) {
89+
90+
var margin = { top: 10, right: 10, bottom: 20, left: 25 },
91+
width = 600 - margin.left - margin.right,
92+
height = 80 - margin.top - margin.bottom;
93+
94+
var timelineSvg = d3.select("#timeline-container").append("svg")
95+
.attr("width", width + margin.left + margin.right)
96+
.attr("height", height + margin.top + margin.bottom);
97+
98+
var timeline = timelineSvg.append("g")
99+
.attr("class", "timeline")
100+
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
101+
102+
var x = d3.scaleTime()
103+
.domain(d3.extent(dataForTimeline.map(function(d) { return d.TIME; })))
104+
.range([0, width]);
105+
106+
var y = d3.scaleLinear()
107+
.domain(d3.extent(dataForTimeline.map(function(d) { return d.TEMP; })))
108+
.range([height, 0]);
109+
110+
var xAxis = d3.axisBottom()
111+
.scale(x);
112+
113+
var yAxis = d3.axisLeft()
114+
.scale(y);
115+
116+
var area = d3.area()
117+
.x(function(d) { return x(d.TIME); })
118+
.y0(height)
119+
.y1(function(d) { return y(d.TEMP); });
120+
121+
timeline.append("path")
122+
.datum(dataForTimeline)
123+
.attr("class", "area")
124+
.attr("d", area);
125+
126+
timeline.append("g")
127+
.attr("class", "x axis")
128+
.attr("transform", "translate(0," + height + ")")
129+
.call(xAxis);
130+
131+
timeline.append("g")
132+
.attr("class", "y axis")
133+
.call(yAxis);
134+
135+
timeline.append("text")
136+
.attr("transform", "rotate(-90)")
137+
.attr("dy", "1em")
138+
.style("text-anchor", "end")
139+
.text("Temperature");
140+
141+
// Add brush to timeline, hook up to callback
142+
var brush = d3.brushX()
143+
.on("brush", function() { brushCallback(brush, dataForMap); });
144+
145+
timeline.append("g")
62146
.attr("class", "x brush")
63147
.call(brush)
64-
.selectAll("rect")
65-
.attr("y", "-10")
66-
.attr("height", height + 10);
67-
68-
brush.event(slider.select('g,x.brush')); //dispatches a single brush event
69-
70-
});
71-
72-
// Called whenever the timeline brush range (extent) is updated
73-
// Filters the map data to those points that fall within the selected timeline range
74-
function brushCallback(d3.slider().brush, data) {
75-
if (brush.empty()) {
76-
update([]);
77-
} else {
78-
var newDateRange = brush.extent(),
79-
filteredData = [];
80-
81-
data.forEach(function(d) {
82-
if (d.TIME >= newDateRange[0] && d.TIME <= newDateRange[1]) {
83-
filteredData.push(d);
84-
}
85-
});
86-
update(filteredData);
87-
}
148+
.selectAll("rect")
149+
.append("rect")
150+
.attr("y", -6)
151+
.attr("height", height + 7);
152+
153+
//console.log(d3.)
154+
//brush.event(timeline.select('g.x.brush')); // dispatches a single brush event
88155
}
89156

90-
// If the user change the map (zoom or drag), update circle position:
91-
map.on("moveend", update)
92-
})
157+
// this part isn't working
158+
function brushCallback(brush, dataForMap) {
159+
if (d3.event.selection == null) {
160+
updateMapPoints([]);
161+
} else {
162+
var newDateRange = brush.extent(),
163+
filteredData = [];
164+
165+
dataForMap.forEach(function(d) {
166+
if (d.TIME >= newDateRange[0] && d.TIME <= newDateRange[1]) {
167+
filteredData.push(d);
168+
}
169+
});
170+
updateMapPoints(filteredData);
171+
console.log(filteredData);
172+
}
173+
}
174+
175+
// Updates the points displayed on the map, to those in the passed data array
176+
function updateMapPoints(data) {
177+
/*
178+
var circles = mapSvg.selectAll("circle").data(data, function(d) { return d.TIME + d.TOT; });
179+
180+
circles // update existing points
181+
.on("mouseover", tipMouseover)
182+
.on("mouseout", tipMouseout)
183+
.attr("fill", function(d) { return colorScale(d.CR); })
184+
.attr("cx", function(d) { return projection([+d.longitude, +d.latitude])[0]; })
185+
.attr("cy", function(d) { return projection([+d.longitude, +d.latitude])[1]; })
186+
.attr("r", function(d) { return radiusScale(+d.TOT); });
187+
188+
circles.enter().append("circle") // new entering points
189+
.on("mouseover", tipMouseover)
190+
.on("mouseout", tipMouseout)
191+
.attr("fill", function(d) { return colorScale(d.CR); })
192+
.attr("cx", function(d) { return projection([+d.longitude, +d.latitude])[0]; })
193+
.attr("cy", function(d) { return projection([+d.longitude, +d.latitude])[1]; })
194+
.attr("r", 0)
195+
.transition()
196+
.duration(500)
197+
.attr("r", function(d) { return radiusScale(+d.TOT); });
198+
199+
circles.exit() // exiting points
200+
.attr("r", function(d) { return radiusScale(+d.TOT); })
201+
.transition()
202+
.duration(500)
203+
.attr("r", 0).remove();
204+
*/
205+
};
206+
207+
function update() {
208+
d3.selectAll("circle")
209+
.attr("cx", function(d){ return map.latLngToLayerPoint([d.la, d.lo]).x })
210+
.attr("cy", function(d){ return map.latLngToLayerPoint([d.la, d.lo]).y })
211+
};

map-data.json

+1
Large diffs are not rendered by default.

0 commit comments

Comments
 (0)