forked from scottcheng/bj-air-vis
-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.jade
216 lines (175 loc) · 9.48 KB
/
index.jade
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
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
!!!
html
head
title Visualization of Beijing Air Pollution
meta(charset='utf-8')
meta(name='author', content='Scott Cheng')
meta(name='description', content='Visualization of the intensity distribution of several major pollutants in Beijing over two weeks')
link(href='style.css', rel='stylesheet')
link(rel='canonical', href='http://scottcheng.github.com/bj-air-vis/')
body
header
.content
h1
| Visualization of Beijing
span.color Air
| Pollution
p.author
| By
a(href='http://scottcheng.com/') Scott Cheng
section#vis
.content
#loading Loading...
#stations
#map-wrapper
svg.map
#station
h2#station-name
#radial-wrapper
svg.radial
#tiles-wrapper
svg.tiles
#pollutant-selector
#ix-hint
p Try clicking a dot on the map, a layer in the stacked area chart, or a pollutant name on the bottom.
section#write-up
.content
p This interactive visualization demonstrates the intensity distribution of several major pollutants in Beijing during October 17 and October 30, 2012.
p
| This is one of
a(href='http://vis.pku.edu.cn/wiki/public_course/visclass_f12/assignment/a02/chengye/start') my
a(href='http://vis.pku.edu.cn/wiki/public_course/visclass_f12/assignment/a02/start') course assignments
| in the
a(href='http://vis.pku.edu.cn/wiki/public_course/visclass_f12/start') fall 2012 Visualization course
| at Peking University. Data is sourced from the
a(href='http://www.bjmemc.com.cn/g356.aspx') Beijing Municipal Environmental Monitoring Center website
| .
h2#data Data
p
| The data that I have are hourly samples at 27 monitor stations over 14 days. In each record, there are concentration values of four types of pollutants (SO
sub 2
| , NO
sub 2
| , PM
sub 2.5
| , PM
sub 10
| ). Some of these values are missing in certain records.
p
| In order to draw the map, I also extracted the following spatial data from
a(href='http://www.bjmemc.com.cn/g356.aspx') here
| :
ul
li Rouge outline of Beijing (I know it looks kinda unprofessional, but it’s sufficient to serve my purpose)
li Coordinates of each monitor station
h2#visualization Visualization
p I aim to clarify the following aspects of the data with this visualization:
ul
li Which part of the city is more heavily polluted than others.
li Which part of the city suffer from the highest intensity of a given type of pollutant.
li What time in a day is the air most polluted in Beijing.
li What time in a day is the air most polluted, for a given place and / or a given type of pollutant.
p My design consists of three interrelated sections:
ul
li
b Map
| Map is best for encoding locations. Users can easily compare on the map which parts of the city suffers from more serious pollution than others.
li
b Stacked Radial Area Chart
| Encode time (24 hours) in a circle, and stack the concentration of each pollutant by hour. From this chart, users can see the trend of pollution intensity in a day (both on a by-pollutant basis and of all pollutants), and a rough level of overall pollution at a certain monitor station.
li
b Tile Chart
| A 14*24 table, where each cell displays the pollution concentration during a given hour in a given day. This is closest to the raw data.
h2#visuals Visuals
h3#colors Colors
p
| I use
span(style='color:rgb(65, 171, 93)') four
span(style='color:rgb(128, 125, 186)') colors
span(style='color:rgb(239, 59, 44)') to
span(style='color:rgb(241, 105, 19)') encode
| the four types of pollutants,
span(style='color:rgb(66, 146, 198)') another
| color for the overall pollution, and some
span(style='color:rgb(189, 189, 189)') greys
| for legends and text. All the colors are taken from
a(href='http://colorbrewer2.org/') ColorBrewer
| – it’s
i really
| good!
h3#transitions Transitions
p Every visual change in this visualization is eased with transition. Speaking of which, it is only recently that I realized why transition feels much more comfortable than sudden changes: because sudden changes are unnatural! Nothing in the real world can change its size, position or color in an instant.
p Did you notice that everything animated in when you first open this page, instead of just show up? The colors fade from white to blue, and the circles grow outwards.
h2#interaction Interaction
p There are two dimensions to select / filter in this visualization: station and pollutant.
p You can select a station by clicking on the corresponding circle on the map, or select “all stations” by clicking on the rest of the map. When a station is selected, the two charts on the right display data sampled at that monitor station; otherwise, they display mean value of all stations.
p You can select a type of pollutant by clicking on the pollutant name on the bottom, or by clicking on the corresponding circular area in the stacked area chart. When a pollutant type is selected, the map and the tiles only display data of that specific pollutant, and the corresponding layer in the area chart is highlighted; otherwise, the map and the tiles display aggregate value of all pollutants.
h2#abandoned What My Visualization Does Not Have
p Besides what I have implemented, I also had the following initial designs which I abandoned, in order to simplify the visualization and avoid distractions.
ul
li Split up each tile into four smaller tiles, each representing a type of pollutant. This is distracting because the value of different pollutants are less comparable. For example, SO2 value seems always lower than the rest pollutants, given the time and station.
li For each monitor station on the map, somehow encode the time-series value, for example stacked radial area charts.
h2#lessons Lessons Learned
ul
li Design the data structure with extra care before anything else, and everything else would be a breeze. Modifying data structure later on is pain.
li The most complicated visualization, or a chart with the largest amount of information, is not necessarily the best choice. Too much information can be confusing and distracting. Instead, it is usually a good idea to break down the data into logical groups, present one group at a time, and let the user explore the rest through interaction.
h2#next What Next?
p
| Fork the
a(href='https://github.com/scottcheng/bj-air-vis') GitHub repo
| , or
| grab the
a(href='https://github.com/scottcheng/bj-air-vis/archive/gh-pages.zip') source
| ! I’m fairly new to D3, and I’m open to any criticism and / or comments on my code.
//- p
| Check out
a(href='http://scottcheng.com/projects') my other projects
| !
footer
.content
p
| Copyright © 2012
a(href='http://scottcheng.com/') Scott Cheng
br
| Proudly powered by
a(href='http://d3js.org/') D3.js
#social
.social-button-wrapper
.g-plusone(data-size='medium', data-annotation='none')
.social-button-wrapper
a.twitter-share-button(
href='https://twitter.com/share',
data-url='http://scottcheng.github.com/bj-air-vis/',
data-counturl='http://scottcheng.github.com/bj-air-vis/',
data-count='none'
) Tweet
.social-button-wrapper
iframe(
src='http://ghbtns.com/github-btn.html?user=scottcheng&repo=bj-air-vis&type=fork',
allowtransparency='true',
frameborder='0',
scrolling='0',
width='53px',
height='20px'
)
script(src='lib/d3.v2.min.js')
script(src='lib/colorbrewer.js')
script(src='air-vis.js')
script
// twitter button
!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="http://platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");
// google +1 button
(function() {
var po = document.createElement('script'); po.type = 'text/javascript'; po.async = true;
po.src = 'https://apis.google.com/js/plusone.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(po, s);
})();
// ga
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-33401065-2']);
_gaq.push(['_trackPageview']);
(function() {
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
})();