-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathheatmap.js
211 lines (172 loc) · 5.73 KB
/
heatmap.js
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
//UI Elements
const INPUT_BOX = document.querySelector( ".heatmap-input" ) ;
const HEATMAP_DISPLAY = document.querySelector( "#heatmap-display" ) ;
//A function to populate a plotData
//object with the right postcodes for the UK
//from a mapData object
function setupPostcodes( plotData , mapData ) {
var postcodes = mapData.getAllPostcodes() ;
var len , i ;
for( len = postcodes.length , i=0 ; i<len ; i++ ) {
plotData[ postcodes[i] ] = 0 ;
}
}
//Finds the first number in a text string
function locateFirstNumber( textString ) {
var firstIndex = 100 ;
var i , index ;
for( i=0 ; i<10 ; i++ ) {
index = textString.search( i.toString() ) ;
if( index > 0 && index < firstIndex ) {
firstIndex = index ;
}
}
return firstIndex ;
}
//Takes the raw input data, parses in
//then adds the data to the plotData
function parseTextData( dataIn , plotData ) {
//Local copy of the input data
//to do whatever we want with
var textData = String( dataIn ).replace( /\n/g , ";" ) ;
//Indices of points of interest in data
var startIndex, endIndex ;
//Temporary postcode and associated values
var postcode , value ;
//While there is another entry
while( textData.search( ";" ) > 0 ) {
/*
Everything before the first comma
should be the postcode for the
current entry
*/
startIndex = textData.search( "," ) ;
postcode = textData.slice( 0 , startIndex ) ;
/*
Find the first number in the string
which will be just after the first
letters of the postcode
*/
endIndex = locateFirstNumber( postcode ) ;
//Get first letters of postcode
if( endIndex !== 100 ) {
postcode = postcode.slice( 0 , endIndex ) ;
}
/*
Convert it to upper case for
compatibility with inbuilt list
*/
postcode = postcode.toUpperCase() ;
//Next, find the first semicolon
endIndex = textData.search( ";" ) ;
//Up to this is the value we want
//to add to this postcode region
value = textData.slice( startIndex+1 , endIndex ) ;
console.log( postcode , value ) ;
//Add the value to the plotData
plotData[ postcode ] += Number( value ) ;
//Get rid of the postcode/value pair
//that was just read in
textData = textData.slice( endIndex+1 ) ;
}
}
//Find the minimum and maximum values
//for a given object in format
//{ key1 : number1 , key2 : number2 , ... }
function getMinimumMaximum( object ) {
var minimum = object[ Object.keys( object )[0] ] ;
var maximum = object[ Object.keys( object )[0] ] ;
for ( entry in object ) {
if ( object[ entry ] < minimum ) {
minimum = object[ entry ] ;
} else if ( object[ entry ] > maximum ) {
maximum = object[ entry ] ;
}
}
return [ minimum , maximum ] ;
}
//Takes in an array [ r , g , b ]
//and output a string that can be used
//in a fill attribute as a colour
function formatrgbString( rgbArray ) {
var stringOut = "rgb(" ;
stringOut += rgbArray[0] + "," ;
stringOut += rgbArray[1] + "," ;
stringOut += rgbArray[2] + ")" ;
return stringOut ;
}
function plotHeatMap() {
//Create an object containing all of
//the path and postcode data
var mapData = new MapData ;
//Create an object containing
//all the colour map dataIn
var colourMap = new ColourMap ;
//The data that is to be plotted
var plotData = new Object ;
//Setup an object with all the postcodes
//but zero values next to them
setupPostcodes( plotData , mapData ) ;
//Grab the data from the input box
var dataIn = INPUT_BOX.value ;
//Add the values to the plot data
parseTextData( dataIn , plotData ) ;
var extrema = getMinimumMaximum( plotData ) ;
//Rescale & get colours for each data point
for ( var postcode in plotData ) {
plotData[ postcode ] = ( plotData[ postcode ] - extrema[0] ) / ( extrema[1] - extrema[0] ) ;
plotData[ postcode ] = [ plotData[ postcode ] ,
colourMap.getInterpolatedColour( plotData[ postcode ] , "Heat Basic" ) ] ;
}
//Add paths to the SVG for each postcode
for ( var postcode in plotData ) {
//Create the new path element
var addPath = document.createElementNS( "http://www.w3.org/2000/svg" , "path" ) ;
//Get the id for this postcode's path
addPath.setAttribute( "id" , mapData.getIdFromPostcode( postcode ) ) ;
//Set the colours
addPath.setAttribute( "stroke" , "black" ) ;
addPath.setAttribute( "fill" , formatrgbString( plotData[ postcode ][1] ) ) ;
//Set the points in the path from the map data
addPath.setAttribute( "d" , mapData.getPointsFromPostcode( postcode ) ) ;
//Push the new path into the SVG
HEATMAP_DISPLAY.appendChild( addPath ) ;
}
//Make the thing re-render
HEATMAP_DISPLAY.style.visibility = "hidden" ;
HEATMAP_DISPLAY.style.visibility = "visible " ;
}
/*
//Get input data from the input box
//var dataIn = "cb1 1gh,10;ab12lk,5;E11JK,1;" ;
//Colour data for each postcode plotted
var colourData = new Object ;
//Create an object containing
//all the colour map dataIn
var colourMap = new ColourMap ;
//Minimum and maximum values to be plotted
var minimumValue , maximumValue ;
//Used for an iterator
var postcode ;
//Take the input data and
//add the values to the plotData
parseTextData( dataIn , plotData ) ;
//Get the maximum and minimum values
//that will be plotted
maximumValue = 0 ;
for ( postcode in plotData ) {
if( plotData[ postcode ] > maximumValue ) {
maximumValue = plotData[ postcode ] ;
}
}
minimumValue = maximumValue ;
for ( postcode in plotData ) {
if( plotData[ postcode ] < minimumValue ) {
minimumValue = plotData[ postcode ] ;
}
}
//Get colours for each data point
for ( postcode in plotData ) {
colourData[ postcode ] = colourMap.getInterpolatedColour( plotData[ postcode ] , minimumValue , maximumValue , "Heat Basic" ) ;
}
*/