2303 |
02 Apr 14 |
olle |
1 |
/** |
2303 |
02 Apr 14 |
olle |
* Draws box plot in a canvas context of percentile data |
2303 |
02 Apr 14 |
olle |
* supplied as a JSON object. |
2303 |
02 Apr 14 |
olle |
4 |
*/ |
2401 |
06 May 14 |
olle |
function createGraphPlot(boxPlotJsonObject, canvas, draw_area_wdt, draw_area_hgt, draw_scale_factor, viewType, storageIntervalInSeconds) |
2401 |
06 May 14 |
olle |
6 |
{ |
2401 |
06 May 14 |
olle |
var ctx = canvas.getContext('2d'); |
2401 |
06 May 14 |
olle |
8 |
|
2401 |
06 May 14 |
olle |
draw_area_wdt *= draw_scale_factor; |
2401 |
06 May 14 |
olle |
draw_area_hgt *= draw_scale_factor; |
2401 |
06 May 14 |
olle |
11 |
|
2401 |
06 May 14 |
olle |
ctx.clearRect(0, 0, draw_area_wdt, draw_area_hgt); |
2401 |
06 May 14 |
olle |
// Reserve area for scale and titles |
4526 |
19 Jun 17 |
nicklas |
var headerTitleHgt = 60 * draw_scale_factor; |
4525 |
15 Jun 17 |
nicklas |
var drect_xoff = 70 * draw_scale_factor; |
4526 |
19 Jun 17 |
nicklas |
var drect_yoff = 70 * draw_scale_factor; |
2401 |
06 May 14 |
olle |
var header_text_top_off = 5 * draw_scale_factor; |
4525 |
15 Jun 17 |
nicklas |
var text_axis_off = 5 * draw_scale_factor; |
2401 |
06 May 14 |
olle |
// Calculate remaining plot area |
2401 |
06 May 14 |
olle |
var drect_w = draw_area_wdt - 2*drect_xoff; |
4525 |
15 Jun 17 |
nicklas |
var drect_h = draw_area_hgt - drect_yoff - headerTitleHgt; |
2401 |
06 May 14 |
olle |
22 |
|
2401 |
06 May 14 |
olle |
// Font sizes |
2401 |
06 May 14 |
olle |
var base_font_size = 11 * draw_scale_factor; // 11px scaled |
2401 |
06 May 14 |
olle |
var header1_font_size = base_font_size + 5 * draw_scale_factor; // 16px scaled |
2401 |
06 May 14 |
olle |
var header2_font_size = base_font_size + 4 * draw_scale_factor; // 15px scaled |
2401 |
06 May 14 |
olle |
var top_right_font_size = base_font_size + 1 * draw_scale_factor; // 12px scaled |
2401 |
06 May 14 |
olle |
var top_left_font_size = base_font_size; // 11px scaled |
2401 |
06 May 14 |
olle |
var y_title_font_size = header2_font_size; // 15px scaled |
2401 |
06 May 14 |
olle |
var y_scale_font_size = base_font_size; // 11px scaled |
2401 |
06 May 14 |
olle |
var x_scale_font_size = base_font_size; // 11px scaled |
2401 |
06 May 14 |
olle |
32 |
|
2401 |
06 May 14 |
olle |
// Draw rectangle enclosing plot area |
2401 |
06 May 14 |
olle |
ctx.strokeStyle = "#000000"; |
2401 |
06 May 14 |
olle |
ctx.strokeRect(fixCoordinate(ctx, drect_xoff), fixCoordinate(ctx, drect_yoff), Math.floor(drect_w), Math.floor(drect_h)); |
2401 |
06 May 14 |
olle |
// Add top header title |
2401 |
06 May 14 |
olle |
var headerTitleTop = getJSONData(boxPlotJsonObject, 'headerTitleTop'); |
2401 |
06 May 14 |
olle |
drawHeaderTitleTopCenter(headerTitleTop, header1_font_size, header_text_top_off, ctx, drect_xoff, drect_yoff, drect_w, drect_h); |
2401 |
06 May 14 |
olle |
// Add top plot title |
2401 |
06 May 14 |
olle |
var titleTop = getJSONData(boxPlotJsonObject, 'titleTop'); |
2401 |
06 May 14 |
olle |
drawTitleTopCenter(titleTop, header2_font_size, text_axis_off, ctx, drect_xoff, drect_yoff, drect_w, drect_h); |
2401 |
06 May 14 |
olle |
// Add bottom plot title |
2401 |
06 May 14 |
olle |
var titleBottom = getJSONData(boxPlotJsonObject, 'titleBottom'); |
2401 |
06 May 14 |
olle |
drawTitleBottomCenter(titleBottom, header2_font_size, text_axis_off, ctx, drect_xoff, drect_yoff, drect_w, drect_h); |
2401 |
06 May 14 |
olle |
// Add plot top right sub-title |
2401 |
06 May 14 |
olle |
var subTitleRight = getJSONData(boxPlotJsonObject, 'subTitleRight'); |
2401 |
06 May 14 |
olle |
drawSubTitleTopRight(subTitleRight, top_right_font_size, text_axis_off, ctx, drect_xoff, drect_yoff, drect_w, drect_h); |
2401 |
06 May 14 |
olle |
// Add plot top left sub-titles |
2401 |
06 May 14 |
olle |
var subTitleLeft01 = getJSONData(boxPlotJsonObject, 'subTitleLeft01'); |
2401 |
06 May 14 |
olle |
var subTitleLeft02 = getJSONData(boxPlotJsonObject, 'subTitleLeft02'); |
2401 |
06 May 14 |
olle |
var subTitleLeft03 = getJSONData(boxPlotJsonObject, 'subTitleLeft03'); |
2401 |
06 May 14 |
olle |
drawSubTitleTopLeft(subTitleLeft01, 0, top_left_font_size, text_axis_off, ctx, drect_xoff, drect_yoff, drect_w, drect_h); |
2401 |
06 May 14 |
olle |
drawSubTitleTopLeft(subTitleLeft02, 1, top_left_font_size, text_axis_off, ctx, drect_xoff, drect_yoff, drect_w, drect_h); |
2401 |
06 May 14 |
olle |
drawSubTitleTopLeft(subTitleLeft03, 2, top_left_font_size, text_axis_off, ctx, drect_xoff, drect_yoff, drect_w, drect_h); |
2401 |
06 May 14 |
olle |
// Add y-axis left title |
2401 |
06 May 14 |
olle |
var yAxisTitleLeft = getJSONData(boxPlotJsonObject, 'yAxisTitleLeft'); |
4525 |
15 Jun 17 |
nicklas |
drawTitleYLeft(yAxisTitleLeft, y_title_font_size, ctx, drect_xoff-45*draw_scale_factor, drect_yoff, drect_w, drect_h); |
2401 |
06 May 14 |
olle |
// Add y-axis right title |
2401 |
06 May 14 |
olle |
var yAxisTitleRight = getJSONData(boxPlotJsonObject, 'yAxisTitleRight'); |
4525 |
15 Jun 17 |
nicklas |
drawTitleYRight(yAxisTitleRight, y_title_font_size, ctx, drect_xoff+45*draw_scale_factor, drect_yoff, drect_w, drect_h); |
2401 |
06 May 14 |
olle |
// Calculate y-axis data value limits |
2401 |
06 May 14 |
olle |
var minDataValue = calculateMinDataValueSimple(boxPlotJsonObject); |
2401 |
06 May 14 |
olle |
var maxDataValue = calculateMaxDataValueSimple(boxPlotJsonObject); |
2401 |
06 May 14 |
olle |
if (viewType == 'overviewDisplay') |
2401 |
06 May 14 |
olle |
65 |
{ |
2401 |
06 May 14 |
olle |
// Calculate min and max values for variables 'v1' and 'v3', respectively |
2401 |
06 May 14 |
olle |
minDataValue = calculateMinDataValueSimple2(boxPlotJsonObject); |
2401 |
06 May 14 |
olle |
maxDataValue = calculateMaxDataValueSimple2(boxPlotJsonObject); |
2401 |
06 May 14 |
olle |
69 |
} |
2401 |
06 May 14 |
olle |
// Calculate scale marker array |
2401 |
06 May 14 |
olle |
var numTicks = 7; |
2401 |
06 May 14 |
olle |
var scaleMarkerArr = calculateScaleMarkerArray(minDataValue, maxDataValue, numTicks); |
2401 |
06 May 14 |
olle |
// Add 2% buffer below min value and 5% buffer above max value |
2401 |
06 May 14 |
olle |
var dataValueRange = maxDataValue - minDataValue; |
2401 |
06 May 14 |
olle |
var min_y = minDataValue - 0.02*dataValueRange; |
2401 |
06 May 14 |
olle |
var max_y = maxDataValue + 0.05*dataValueRange; |
2401 |
06 May 14 |
olle |
// Trim scale marker array to only include values inside range |
2401 |
06 May 14 |
olle |
var trimmedScaleMarkerArr = trimScaleMarkerArray(scaleMarkerArr, min_y, max_y); |
2401 |
06 May 14 |
olle |
// Add small spacing buffer in pixels below and above value area |
2401 |
06 May 14 |
olle |
var min_yoff = 5 * draw_scale_factor; |
2401 |
06 May 14 |
olle |
var max_yoff = 5 * draw_scale_factor; |
2401 |
06 May 14 |
olle |
// Select number of decimals for scale marker text |
2401 |
06 May 14 |
olle |
// Select number of decimals to get one decimal digit different from 0, up to 3 decimals |
2401 |
06 May 14 |
olle |
var numberOfDecimals = 0; |
2401 |
06 May 14 |
olle |
for (i=0; i < trimmedScaleMarkerArr.length; i++) |
2401 |
06 May 14 |
olle |
86 |
{ |
2401 |
06 May 14 |
olle |
var scaleValueTmp = trimmedScaleMarkerArr[i]; |
2401 |
06 May 14 |
olle |
// Round scale value to 3 decimals (to make e.g. 2.99999993 -> 3.000) |
2401 |
06 May 14 |
olle |
scaleValueTmp = scaleValueTmp.toFixed(3); |
2401 |
06 May 14 |
olle |
var decimalPart = scaleValueTmp - Math.floor(scaleValueTmp); |
2401 |
06 May 14 |
olle |
if (decimalPart >= 0.05) |
2401 |
06 May 14 |
olle |
92 |
{ |
2401 |
06 May 14 |
olle |
if (numberOfDecimals == 0 || numberOfDecimals > 1) |
2401 |
06 May 14 |
olle |
94 |
{ |
2401 |
06 May 14 |
olle |
numberOfDecimals = 1; |
2401 |
06 May 14 |
olle |
96 |
} |
2401 |
06 May 14 |
olle |
97 |
} |
2401 |
06 May 14 |
olle |
else if (decimalPart >= 0.005) |
2401 |
06 May 14 |
olle |
99 |
{ |
2401 |
06 May 14 |
olle |
if (numberOfDecimals == 0 || numberOfDecimals > 2) |
2401 |
06 May 14 |
olle |
101 |
{ |
2401 |
06 May 14 |
olle |
numberOfDecimals = 2; |
2401 |
06 May 14 |
olle |
103 |
} |
2401 |
06 May 14 |
olle |
104 |
} |
2401 |
06 May 14 |
olle |
else if (decimalPart >= 0.0005) |
2401 |
06 May 14 |
olle |
106 |
{ |
2401 |
06 May 14 |
olle |
if (numberOfDecimals == 0 || numberOfDecimals > 3) |
2401 |
06 May 14 |
olle |
108 |
{ |
2401 |
06 May 14 |
olle |
numberOfDecimals = 3; |
2401 |
06 May 14 |
olle |
110 |
} |
2401 |
06 May 14 |
olle |
111 |
} |
2401 |
06 May 14 |
olle |
112 |
} |
2401 |
06 May 14 |
olle |
// Draw y-axis left scale markers with values |
2401 |
06 May 14 |
olle |
var scaleValue; |
2401 |
06 May 14 |
olle |
var markerText; |
2401 |
06 May 14 |
olle |
for (i=0; i < trimmedScaleMarkerArr.length; i++) |
2401 |
06 May 14 |
olle |
117 |
{ |
2401 |
06 May 14 |
olle |
scaleValue = trimmedScaleMarkerArr[i]; |
2401 |
06 May 14 |
olle |
markerText = scaleValue.toFixed(numberOfDecimals); |
2401 |
06 May 14 |
olle |
drawScaleMarkerYLeft(scaleValue, y_scale_font_size, markerText, min_y, max_y, min_yoff, max_yoff, ctx, drect_xoff, drect_yoff, drect_w, drect_h); |
2401 |
06 May 14 |
olle |
121 |
} |
2401 |
06 May 14 |
olle |
// Find number of data points in graph plot |
2401 |
06 May 14 |
olle |
var dataPointsTot = 0; |
2401 |
06 May 14 |
olle |
for (var i in boxPlotJsonObject.percentileData) |
2401 |
06 May 14 |
olle |
125 |
{ |
2401 |
06 May 14 |
olle |
dataPointsTot++; |
2401 |
06 May 14 |
olle |
127 |
} |
2401 |
06 May 14 |
olle |
// Set time delay to identify missing data points |
4526 |
19 Jun 17 |
nicklas |
var max_minutes_between_consequitive_data_points = 15; |
2401 |
06 May 14 |
olle |
if (storageIntervalInSeconds > 0) |
2401 |
06 May 14 |
olle |
131 |
{ |
2401 |
06 May 14 |
olle |
var storageIntervalInMinutes = storageIntervalInSeconds/60; |
4526 |
19 Jun 17 |
nicklas |
max_minutes_between_consequitive_data_points = Math.max(5, 3*storageIntervalInMinutes); |
2401 |
06 May 14 |
olle |
134 |
} |
2401 |
06 May 14 |
olle |
// Draw data values as line graph |
2401 |
06 May 14 |
olle |
var min_x = 0; |
2401 |
06 May 14 |
olle |
var max_x = 24*60; |
4526 |
19 Jun 17 |
nicklas |
if (viewType == 'last24hours') |
2401 |
06 May 14 |
olle |
139 |
{ |
4526 |
19 Jun 17 |
nicklas |
max_x = 25*60; |
4526 |
19 Jun 17 |
nicklas |
141 |
} |
4526 |
19 Jun 17 |
nicklas |
else if (viewType == 'weeklyDisplay') |
4526 |
19 Jun 17 |
nicklas |
143 |
{ |
2401 |
06 May 14 |
olle |
max_x = 7*max_x; |
2401 |
06 May 14 |
olle |
145 |
} |
2401 |
06 May 14 |
olle |
else if (viewType == 'overviewDisplay') |
2401 |
06 May 14 |
olle |
147 |
{ |
2401 |
06 May 14 |
olle |
// Set max_x to number of minutes between first midnight and midnight of last day with data |
2401 |
06 May 14 |
olle |
var num_data_points = boxPlotJsonObject.percentileData.length; |
2401 |
06 May 14 |
olle |
if (num_data_points > 0) |
2401 |
06 May 14 |
olle |
151 |
{ |
2401 |
06 May 14 |
olle |
// Name of last data point is number of minutes since midnight of day for first point |
2531 |
26 Jun 14 |
olle |
var num_minutes_since_first_midnight = boxPlotJsonObject.latestPeriodName; |
2401 |
06 May 14 |
olle |
var num_full_days_since_first_midnight = Math.floor(num_minutes_since_first_midnight/(24*60)); |
2401 |
06 May 14 |
olle |
var days_to_add = 1; |
2401 |
06 May 14 |
olle |
if (num_minutes_since_first_midnight % (24*60) == 0) |
2401 |
06 May 14 |
olle |
157 |
{ |
2401 |
06 May 14 |
olle |
days_to_add = 0; |
2401 |
06 May 14 |
olle |
159 |
} |
2401 |
06 May 14 |
olle |
// Set max_x to number of minutes between first midnight and midnight of last day with data |
2401 |
06 May 14 |
olle |
max_x = (num_full_days_since_first_midnight + days_to_add)*24*60; |
2401 |
06 May 14 |
olle |
162 |
} |
2401 |
06 May 14 |
olle |
else |
2401 |
06 May 14 |
olle |
164 |
{ |
2401 |
06 May 14 |
olle |
max_x = 7*max_x; |
2401 |
06 May 14 |
olle |
166 |
} |
2401 |
06 May 14 |
olle |
max_minutes_between_consequitive_data_points = 1.5*60*24; |
2401 |
06 May 14 |
olle |
168 |
} |
2401 |
06 May 14 |
olle |
// Draw graph |
2401 |
06 May 14 |
olle |
var x_old = 0; |
2401 |
06 May 14 |
olle |
var y_min_value_old = 0; |
2401 |
06 May 14 |
olle |
var y_mean_value_old = 0; |
2401 |
06 May 14 |
olle |
var y_max_value_old = 0; |
2401 |
06 May 14 |
olle |
for (var i in boxPlotJsonObject.percentileData) |
2401 |
06 May 14 |
olle |
175 |
{ |
2401 |
06 May 14 |
olle |
var name = boxPlotJsonObject.percentileData[i].name; |
2401 |
06 May 14 |
olle |
var numItems = boxPlotJsonObject.percentileData[i].numItems; |
2401 |
06 May 14 |
olle |
var v1 = boxPlotJsonObject.percentileData[i].v1; |
2401 |
06 May 14 |
olle |
var v2 = boxPlotJsonObject.percentileData[i].v2; |
2401 |
06 May 14 |
olle |
var v3 = boxPlotJsonObject.percentileData[i].v3; |
2401 |
06 May 14 |
olle |
var v4 = boxPlotJsonObject.percentileData[i].v4; |
2401 |
06 May 14 |
olle |
var v5 = boxPlotJsonObject.percentileData[i].v5; |
2401 |
06 May 14 |
olle |
// Draw graph plot line segment |
2401 |
06 May 14 |
olle |
x1 = x_old; |
2401 |
06 May 14 |
olle |
y1_min_value = y_min_value_old; |
2401 |
06 May 14 |
olle |
y1_mean_value = y_mean_value_old; |
2401 |
06 May 14 |
olle |
y1_max_value = y_max_value_old; |
2401 |
06 May 14 |
olle |
x2 = name; |
2401 |
06 May 14 |
olle |
y2_min_value = v1; |
2401 |
06 May 14 |
olle |
y2_mean_value = v2; |
2401 |
06 May 14 |
olle |
y2_max_value = v3; |
2401 |
06 May 14 |
olle |
var x_pad = 10 * draw_scale_factor; |
2401 |
06 May 14 |
olle |
// Draw line segments starting after second data point |
2401 |
06 May 14 |
olle |
if (i > 0) |
2401 |
06 May 14 |
olle |
195 |
{ |
2401 |
06 May 14 |
olle |
// Skip line segments containing missing data points |
2401 |
06 May 14 |
olle |
if ((x2 - x1) <= max_minutes_between_consequitive_data_points) |
2401 |
06 May 14 |
olle |
198 |
{ |
2401 |
06 May 14 |
olle |
// Draw line segment |
2401 |
06 May 14 |
olle |
drawGraphPlotLineSegment(x1, y1_min_value, x2, y2_min_value, min_x, max_x, min_y, max_y, min_yoff, max_yoff, x_pad, ctx, drect_xoff, drect_yoff, drect_w, drect_h, draw_scale_factor, 2); |
2401 |
06 May 14 |
olle |
drawGraphPlotLineSegment(x1, y1_mean_value, x2, y2_mean_value, min_x, max_x, min_y, max_y, min_yoff, max_yoff, x_pad, ctx, drect_xoff, drect_yoff, drect_w, drect_h, draw_scale_factor, 3); |
2401 |
06 May 14 |
olle |
drawGraphPlotLineSegment(x1, y1_max_value, x2, y2_max_value, min_x, max_x, min_y, max_y, min_yoff, max_yoff, x_pad, ctx, drect_xoff, drect_yoff, drect_w, drect_h, draw_scale_factor, 2); |
2401 |
06 May 14 |
olle |
//drawGraphPlotLineSegmentY(x1, y1, x2, y2, x_min, x_max, y_min, y_max, min_off, max_off, x_pad, context, xoff, yoff, wdt, hgt, draw_scale_factor, linewidth); |
2401 |
06 May 14 |
olle |
204 |
} |
2401 |
06 May 14 |
olle |
else |
2401 |
06 May 14 |
olle |
206 |
{ |
2401 |
06 May 14 |
olle |
// Draw single data point |
2401 |
06 May 14 |
olle |
drawGraphPlotDataPoint(x2, y2_min_value, min_x, max_x, min_y, max_y, min_yoff, max_yoff, x_pad, ctx, drect_xoff, drect_yoff, drect_w, drect_h, draw_scale_factor); |
2401 |
06 May 14 |
olle |
drawGraphPlotDataPoint(x2, y2_mean_value, min_x, max_x, min_y, max_y, min_yoff, max_yoff, x_pad, ctx, drect_xoff, drect_yoff, drect_w, drect_h, draw_scale_factor); |
2401 |
06 May 14 |
olle |
drawGraphPlotDataPoint(x2, y2_max_value, min_x, max_x, min_y, max_y, min_yoff, max_yoff, x_pad, ctx, drect_xoff, drect_yoff, drect_w, drect_h, draw_scale_factor); |
2401 |
06 May 14 |
olle |
211 |
} |
2401 |
06 May 14 |
olle |
212 |
} |
2401 |
06 May 14 |
olle |
x_old = x2; |
2401 |
06 May 14 |
olle |
y_min_value_old = y2_min_value; |
2401 |
06 May 14 |
olle |
y_mean_value_old = y2_mean_value; |
2401 |
06 May 14 |
olle |
y_max_value_old = y2_max_value; |
2401 |
06 May 14 |
olle |
217 |
} |
2401 |
06 May 14 |
olle |
// Draw graph for mean day values |
2401 |
06 May 14 |
olle |
x_old = 0; |
2401 |
06 May 14 |
olle |
y_old = 0; |
2401 |
06 May 14 |
olle |
for (var i in boxPlotJsonObject.percentileData) |
2401 |
06 May 14 |
olle |
222 |
{ |
2401 |
06 May 14 |
olle |
var name = boxPlotJsonObject.percentileData[i].name; |
2401 |
06 May 14 |
olle |
var numItems = boxPlotJsonObject.percentileData[i].numItems; |
2401 |
06 May 14 |
olle |
var v1 = boxPlotJsonObject.percentileData[i].v1; |
2401 |
06 May 14 |
olle |
var v2 = boxPlotJsonObject.percentileData[i].v2; |
2401 |
06 May 14 |
olle |
var v3 = boxPlotJsonObject.percentileData[i].v3; |
2401 |
06 May 14 |
olle |
var v4 = boxPlotJsonObject.percentileData[i].v4; |
2401 |
06 May 14 |
olle |
var v5 = boxPlotJsonObject.percentileData[i].v5; |
2401 |
06 May 14 |
olle |
// Draw graph plot line segment |
2401 |
06 May 14 |
olle |
x1 = x_old; |
2401 |
06 May 14 |
olle |
y1 = y_old; |
2401 |
06 May 14 |
olle |
x2 = name; |
2401 |
06 May 14 |
olle |
y2 = v2; |
2401 |
06 May 14 |
olle |
var x_pad = 10 * draw_scale_factor; |
2401 |
06 May 14 |
olle |
// Draw line segments starting after second data point |
2401 |
06 May 14 |
olle |
if (i > 0) |
2401 |
06 May 14 |
olle |
238 |
{ |
2401 |
06 May 14 |
olle |
// Skip line segments containing missing data points |
2401 |
06 May 14 |
olle |
if ((x2 - x1) <= max_minutes_between_consequitive_data_points) |
2401 |
06 May 14 |
olle |
241 |
{ |
2401 |
06 May 14 |
olle |
// Draw line segment |
2401 |
06 May 14 |
olle |
drawGraphPlotLineSegment(x1, y1, x2, y2, min_x, max_x, min_y, max_y, min_yoff, max_yoff, x_pad, ctx, drect_xoff, drect_yoff, drect_w, drect_h, draw_scale_factor, 3); |
2401 |
06 May 14 |
olle |
//drawGraphPlotLineSegmentY(x1, y1, x2, y2, x_min, x_max, y_min, y_max, min_off, max_off, x_pad, context, xoff, yoff, wdt, hgt, draw_scale_factor, linewidth); |
2401 |
06 May 14 |
olle |
245 |
} |
2401 |
06 May 14 |
olle |
else |
2401 |
06 May 14 |
olle |
247 |
{ |
2401 |
06 May 14 |
olle |
// Draw single data point |
2401 |
06 May 14 |
olle |
drawGraphPlotDataPoint(x2, y2, min_x, max_x, min_y, max_y, min_yoff, max_yoff, x_pad, ctx, drect_xoff, drect_yoff, drect_w, drect_h, draw_scale_factor); |
2401 |
06 May 14 |
olle |
250 |
} |
2401 |
06 May 14 |
olle |
251 |
} |
2401 |
06 May 14 |
olle |
x_old = x2; |
2401 |
06 May 14 |
olle |
y_old = y2; |
2401 |
06 May 14 |
olle |
254 |
} |
2401 |
06 May 14 |
olle |
// Draw x-axis bottom scale markers |
4526 |
19 Jun 17 |
nicklas |
if (viewType == 'last24hours') |
2401 |
06 May 14 |
olle |
257 |
{ |
4526 |
19 Jun 17 |
nicklas |
var startHour = new Date().getHours(); |
4526 |
19 Jun 17 |
nicklas |
for (var j = 0; j < 26; j++) |
4526 |
19 Jun 17 |
nicklas |
260 |
{ |
4526 |
19 Jun 17 |
nicklas |
hourStr = (j+startHour) % 24; |
4526 |
19 Jun 17 |
nicklas |
if (hourStr < 10) |
4526 |
19 Jun 17 |
nicklas |
263 |
{ |
4526 |
19 Jun 17 |
nicklas |
hourStr = '0' + hourStr; |
4526 |
19 Jun 17 |
nicklas |
265 |
} |
4526 |
19 Jun 17 |
nicklas |
drawGraphPlotBoxScaleMarkerXBottom(j, 26, hourStr, x_scale_font_size, x_pad, ctx, drect_xoff, drect_yoff, drect_w, drect_h); |
4526 |
19 Jun 17 |
nicklas |
// Draw dotted vertical lines at x axis bottom scale marker values |
4526 |
19 Jun 17 |
nicklas |
var min_xoff = x_pad; |
4526 |
19 Jun 17 |
nicklas |
var max_xoff = x_pad; |
4526 |
19 Jun 17 |
nicklas |
drawDottedLineX(j, 0, 25, min_xoff, max_xoff, ctx, drect_xoff, drect_yoff, drect_w, drect_h); |
4526 |
19 Jun 17 |
nicklas |
271 |
} |
4526 |
19 Jun 17 |
nicklas |
272 |
} |
4526 |
19 Jun 17 |
nicklas |
else if (viewType == 'dailyDisplay') |
4526 |
19 Jun 17 |
nicklas |
274 |
{ |
2401 |
06 May 14 |
olle |
for (var j = 0; j < 25; j++) |
2401 |
06 May 14 |
olle |
276 |
{ |
2401 |
06 May 14 |
olle |
hourStr = j; |
2401 |
06 May 14 |
olle |
if (j < 10) |
2401 |
06 May 14 |
olle |
279 |
{ |
2401 |
06 May 14 |
olle |
hourStr = '0' + hourStr; |
2401 |
06 May 14 |
olle |
281 |
} |
2401 |
06 May 14 |
olle |
drawGraphPlotBoxScaleMarkerXBottom(j, 25, hourStr, x_scale_font_size, x_pad, ctx, drect_xoff, drect_yoff, drect_w, drect_h); |
2401 |
06 May 14 |
olle |
// Draw dotted vertical lines at x axis bottom scale marker values |
2401 |
06 May 14 |
olle |
var min_xoff = x_pad; |
2401 |
06 May 14 |
olle |
var max_xoff = x_pad; |
2401 |
06 May 14 |
olle |
drawDottedLineX(j, 0, 24, min_xoff, max_xoff, ctx, drect_xoff, drect_yoff, drect_w, drect_h); |
2401 |
06 May 14 |
olle |
287 |
} |
2401 |
06 May 14 |
olle |
288 |
} |
2401 |
06 May 14 |
olle |
else if (viewType == 'weeklyDisplay') |
2401 |
06 May 14 |
olle |
290 |
{ |
2401 |
06 May 14 |
olle |
var jsonDayInWeekString = boxPlotJsonObject.dayInWeekString; |
2401 |
06 May 14 |
olle |
for (var j = 0; j < 8; j++) |
2401 |
06 May 14 |
olle |
293 |
{ |
2401 |
06 May 14 |
olle |
dayIndexStr = j; |
2401 |
06 May 14 |
olle |
if (j < 10) |
2401 |
06 May 14 |
olle |
296 |
{ |
2401 |
06 May 14 |
olle |
dayIndexStr = '0' + dayIndexStr; |
2401 |
06 May 14 |
olle |
298 |
} |
2401 |
06 May 14 |
olle |
var dayInWeekStr = jsonDayInWeekString[dayIndexStr]; |
2401 |
06 May 14 |
olle |
drawGraphPlotBoxScaleMarkerXBottom(j, 8, dayInWeekStr, x_scale_font_size, x_pad, ctx, drect_xoff, drect_yoff, drect_w, drect_h); |
2401 |
06 May 14 |
olle |
// Draw dotted vertical lines at x axis bottom scale marker values |
2401 |
06 May 14 |
olle |
var min_xoff = x_pad; |
2401 |
06 May 14 |
olle |
var max_xoff = x_pad; |
2401 |
06 May 14 |
olle |
drawDottedLineX(j, 0, 7, min_xoff, max_xoff, ctx, drect_xoff, drect_yoff, drect_w, drect_h); |
2401 |
06 May 14 |
olle |
305 |
} |
2401 |
06 May 14 |
olle |
306 |
} |
2401 |
06 May 14 |
olle |
else if (viewType == 'overviewDisplay') |
2401 |
06 May 14 |
olle |
308 |
{ |
2401 |
06 May 14 |
olle |
var jsonDayInWeekString = boxPlotJsonObject.dayInWeekString; |
2401 |
06 May 14 |
olle |
var numMarkerStrings = jsonDayInWeekString.numMarkers; |
2401 |
06 May 14 |
olle |
for (var j = 0; j < numMarkerStrings; j++) |
2401 |
06 May 14 |
olle |
312 |
{ |
2401 |
06 May 14 |
olle |
dayIndexStr = j; |
2401 |
06 May 14 |
olle |
if (j < 10) |
2401 |
06 May 14 |
olle |
315 |
{ |
2401 |
06 May 14 |
olle |
dayIndexStr = '0' + dayIndexStr; |
2401 |
06 May 14 |
olle |
317 |
} |
2401 |
06 May 14 |
olle |
if (j < 100) |
2401 |
06 May 14 |
olle |
319 |
{ |
2401 |
06 May 14 |
olle |
dayIndexStr = '0' + dayIndexStr; |
2401 |
06 May 14 |
olle |
321 |
} |
2401 |
06 May 14 |
olle |
if (j < 1000) |
2401 |
06 May 14 |
olle |
323 |
{ |
2401 |
06 May 14 |
olle |
dayIndexStr = '0' + dayIndexStr; |
2401 |
06 May 14 |
olle |
325 |
} |
2401 |
06 May 14 |
olle |
var dayInWeekStr = jsonDayInWeekString[dayIndexStr]; |
2401 |
06 May 14 |
olle |
if (dayInWeekStr != null) |
2401 |
06 May 14 |
olle |
328 |
{ |
2401 |
06 May 14 |
olle |
drawGraphPlotBoxScaleMarkerXBottom(j, numMarkerStrings, dayInWeekStr, x_scale_font_size, x_pad, ctx, drect_xoff, drect_yoff, drect_w, drect_h); |
2401 |
06 May 14 |
olle |
// Draw dotted vertical lines at x axis bottom scale marker values |
2401 |
06 May 14 |
olle |
var min_xoff = x_pad; |
2401 |
06 May 14 |
olle |
var max_xoff = x_pad; |
2401 |
06 May 14 |
olle |
drawDottedLineX(j, 0, numMarkerStrings - 1, min_xoff, max_xoff, ctx, drect_xoff, drect_yoff, drect_w, drect_h); |
2401 |
06 May 14 |
olle |
334 |
} |
2401 |
06 May 14 |
olle |
335 |
} |
2401 |
06 May 14 |
olle |
336 |
} |
2401 |
06 May 14 |
olle |
// Draw y-axis right scale markers with values and horizontal dotted guide lines |
2401 |
06 May 14 |
olle |
for (var i in boxPlotJsonObject.valueGuideLinesY) |
2401 |
06 May 14 |
olle |
339 |
{ |
2401 |
06 May 14 |
olle |
if (boxPlotJsonObject.valueGuideLinesY[i] != null) |
2401 |
06 May 14 |
olle |
341 |
{ |
2401 |
06 May 14 |
olle |
var value = boxPlotJsonObject.valueGuideLinesY[i].value; |
2401 |
06 May 14 |
olle |
var valueText = boxPlotJsonObject.valueGuideLinesY[i].text; |
2401 |
06 May 14 |
olle |
// Draw y-axis right scale markers with values |
2401 |
06 May 14 |
olle |
drawScaleMarkerYRight(value, valueText, y_scale_font_size, min_y, max_y, min_yoff, max_yoff, ctx, drect_xoff, drect_yoff, drect_w, drect_h); |
2401 |
06 May 14 |
olle |
// Draw dotted horizontal lines at y axis right scale marker values |
2401 |
06 May 14 |
olle |
drawDottedLineY(value, min_y, max_y, min_yoff, max_yoff, ctx, drect_xoff, drect_yoff, drect_w, drect_h); |
2401 |
06 May 14 |
olle |
348 |
} |
2401 |
06 May 14 |
olle |
349 |
} |
2401 |
06 May 14 |
olle |
350 |
} |
2401 |
06 May 14 |
olle |
351 |
|
2401 |
06 May 14 |
olle |
352 |
/** |
2401 |
06 May 14 |
olle |
* Draws box plot in a canvas context of percentile data |
2401 |
06 May 14 |
olle |
* supplied as a JSON object. |
2401 |
06 May 14 |
olle |
355 |
*/ |
2303 |
02 Apr 14 |
olle |
function createBoxPlot(boxPlotJsonObject, canvas, draw_area_wdt, draw_area_hgt, draw_scale_factor) |
2303 |
02 Apr 14 |
olle |
357 |
{ |
2303 |
02 Apr 14 |
olle |
var ctx = canvas.getContext('2d'); |
2303 |
02 Apr 14 |
olle |
359 |
|
2303 |
02 Apr 14 |
olle |
draw_area_wdt *= draw_scale_factor; |
2303 |
02 Apr 14 |
olle |
draw_area_hgt *= draw_scale_factor; |
2303 |
02 Apr 14 |
olle |
362 |
|
2303 |
02 Apr 14 |
olle |
ctx.clearRect(0, 0, draw_area_wdt, draw_area_hgt); |
2303 |
02 Apr 14 |
olle |
// Reserve area for scale and titles |
2303 |
02 Apr 14 |
olle |
var headerTitleHgt = 25 * draw_scale_factor; |
2303 |
02 Apr 14 |
olle |
var drect_xoff = 60 * draw_scale_factor; |
2303 |
02 Apr 14 |
olle |
var drect_yoff = 70 * draw_scale_factor + headerTitleHgt; |
2303 |
02 Apr 14 |
olle |
var header_text_top_off = 5 * draw_scale_factor; |
2303 |
02 Apr 14 |
olle |
var text_axis_off = 40 * draw_scale_factor; |
2303 |
02 Apr 14 |
olle |
// Calculate remaining plot area |
2303 |
02 Apr 14 |
olle |
var drect_w = draw_area_wdt - 2*drect_xoff; |
2303 |
02 Apr 14 |
olle |
var drect_h = draw_area_hgt - 2*drect_yoff; |
2303 |
02 Apr 14 |
olle |
373 |
|
2303 |
02 Apr 14 |
olle |
// Font sizes |
2303 |
02 Apr 14 |
olle |
var base_font_size = 11 * draw_scale_factor; // 11px scaled |
2303 |
02 Apr 14 |
olle |
var header1_font_size = base_font_size + 5 * draw_scale_factor; // 16px scaled |
2303 |
02 Apr 14 |
olle |
var header2_font_size = base_font_size + 4 * draw_scale_factor; // 15px scaled |
2303 |
02 Apr 14 |
olle |
var top_right_font_size = base_font_size + 1 * draw_scale_factor; // 12px scaled |
2303 |
02 Apr 14 |
olle |
var top_left_font_size = base_font_size; // 11px scaled |
2303 |
02 Apr 14 |
olle |
var y_title_font_size = header2_font_size; // 15px scaled |
2303 |
02 Apr 14 |
olle |
var y_scale_font_size = base_font_size; // 11px scaled |
2303 |
02 Apr 14 |
olle |
var x_scale_font_size = base_font_size; // 11px scaled |
2303 |
02 Apr 14 |
olle |
383 |
|
2303 |
02 Apr 14 |
olle |
// Draw rectangle enclosing plot area |
2303 |
02 Apr 14 |
olle |
ctx.strokeStyle = "#000000"; |
2303 |
02 Apr 14 |
olle |
ctx.strokeRect(fixCoordinate(ctx, drect_xoff), fixCoordinate(ctx, drect_yoff), Math.floor(drect_w), Math.floor(drect_h)); |
2303 |
02 Apr 14 |
olle |
// Add top header title |
2303 |
02 Apr 14 |
olle |
var headerTitleTop = getJSONData(boxPlotJsonObject, 'headerTitleTop'); |
2303 |
02 Apr 14 |
olle |
drawHeaderTitleTopCenter(headerTitleTop, header1_font_size, header_text_top_off, ctx, drect_xoff, drect_yoff, drect_w, drect_h); |
2303 |
02 Apr 14 |
olle |
// Add top plot title |
2303 |
02 Apr 14 |
olle |
var titleTop = getJSONData(boxPlotJsonObject, 'titleTop'); |
2303 |
02 Apr 14 |
olle |
drawTitleTopCenter(titleTop, header2_font_size, text_axis_off, ctx, drect_xoff, drect_yoff, drect_w, drect_h); |
2303 |
02 Apr 14 |
olle |
// Add bottom plot title |
2303 |
02 Apr 14 |
olle |
var titleBottom = getJSONData(boxPlotJsonObject, 'titleBottom'); |
2303 |
02 Apr 14 |
olle |
drawTitleBottomCenter(titleBottom, header2_font_size, text_axis_off, ctx, drect_xoff, drect_yoff, drect_w, drect_h); |
2303 |
02 Apr 14 |
olle |
// Add plot top right sub-title |
2303 |
02 Apr 14 |
olle |
var subTitleRight = getJSONData(boxPlotJsonObject, 'subTitleRight'); |
2303 |
02 Apr 14 |
olle |
drawSubTitleTopRight(subTitleRight, top_right_font_size, text_axis_off, ctx, drect_xoff, drect_yoff, drect_w, drect_h); |
2303 |
02 Apr 14 |
olle |
// Add plot top left sub-titles |
2303 |
02 Apr 14 |
olle |
var subTitleLeft01 = getJSONData(boxPlotJsonObject, 'subTitleLeft01'); |
2303 |
02 Apr 14 |
olle |
var subTitleLeft02 = getJSONData(boxPlotJsonObject, 'subTitleLeft02'); |
2303 |
02 Apr 14 |
olle |
var subTitleLeft03 = getJSONData(boxPlotJsonObject, 'subTitleLeft03'); |
2303 |
02 Apr 14 |
olle |
drawSubTitleTopLeft(subTitleLeft01, 0, top_left_font_size, text_axis_off, ctx, drect_xoff, drect_yoff, drect_w, drect_h); |
2303 |
02 Apr 14 |
olle |
drawSubTitleTopLeft(subTitleLeft02, 1, top_left_font_size, text_axis_off, ctx, drect_xoff, drect_yoff, drect_w, drect_h); |
2303 |
02 Apr 14 |
olle |
drawSubTitleTopLeft(subTitleLeft03, 2, top_left_font_size, text_axis_off, ctx, drect_xoff, drect_yoff, drect_w, drect_h); |
2303 |
02 Apr 14 |
olle |
// Add y-axis left title |
2303 |
02 Apr 14 |
olle |
var yAxisTitleLeft = getJSONData(boxPlotJsonObject, 'yAxisTitleLeft'); |
2303 |
02 Apr 14 |
olle |
drawTitleYLeft(yAxisTitleLeft, y_title_font_size, ctx, drect_xoff-35*draw_scale_factor, drect_yoff, drect_w, drect_h); |
2303 |
02 Apr 14 |
olle |
// Add y-axis right title |
2303 |
02 Apr 14 |
olle |
var yAxisTitleRight = getJSONData(boxPlotJsonObject, 'yAxisTitleRight'); |
2303 |
02 Apr 14 |
olle |
drawTitleYRight(yAxisTitleRight, y_title_font_size, ctx, drect_xoff+35*draw_scale_factor, drect_yoff, drect_w, drect_h); |
2303 |
02 Apr 14 |
olle |
// Calculate y-axis data value limits |
2303 |
02 Apr 14 |
olle |
var minDataValue = calculateMinDataValue(boxPlotJsonObject); |
2303 |
02 Apr 14 |
olle |
var maxDataValue = calculateMaxDataValue(boxPlotJsonObject); |
2303 |
02 Apr 14 |
olle |
// Calculate scale marker array |
2303 |
02 Apr 14 |
olle |
var numTicks = 7; |
2303 |
02 Apr 14 |
olle |
var scaleMarkerArr = calculateScaleMarkerArray(minDataValue, maxDataValue, numTicks); |
2303 |
02 Apr 14 |
olle |
// Add 2% buffer below min value and 5% buffer above max value |
2303 |
02 Apr 14 |
olle |
var dataValueRange = maxDataValue - minDataValue; |
2303 |
02 Apr 14 |
olle |
var min_y = minDataValue - 0.02*dataValueRange; |
2303 |
02 Apr 14 |
olle |
var max_y = maxDataValue + 0.05*dataValueRange; |
2303 |
02 Apr 14 |
olle |
// Trim scale marker array to only include values inside range |
2303 |
02 Apr 14 |
olle |
var trimmedScaleMarkerArr = trimScaleMarkerArray(scaleMarkerArr, min_y, max_y); |
2303 |
02 Apr 14 |
olle |
// Add small spacing buffer in pixels below and above value area |
2303 |
02 Apr 14 |
olle |
var min_yoff = 5 * draw_scale_factor; |
2303 |
02 Apr 14 |
olle |
var max_yoff = 5 * draw_scale_factor; |
2303 |
02 Apr 14 |
olle |
// Select number of decimals for scale marker text |
2303 |
02 Apr 14 |
olle |
// Select number of decimals to get one decimal digit different from 0, up to 3 decimals |
2303 |
02 Apr 14 |
olle |
var numberOfDecimals = 0; |
2303 |
02 Apr 14 |
olle |
for (i=0; i < trimmedScaleMarkerArr.length; i++) |
2303 |
02 Apr 14 |
olle |
431 |
{ |
2303 |
02 Apr 14 |
olle |
var scaleValueTmp = trimmedScaleMarkerArr[i]; |
2303 |
02 Apr 14 |
olle |
// Round scale value to 3 decimals (to make e.g. 2.99999993 -> 3.000) |
2303 |
02 Apr 14 |
olle |
scaleValueTmp = scaleValueTmp.toFixed(3); |
2303 |
02 Apr 14 |
olle |
var decimalPart = scaleValueTmp - Math.floor(scaleValueTmp); |
2303 |
02 Apr 14 |
olle |
if (decimalPart >= 0.05) |
2303 |
02 Apr 14 |
olle |
437 |
{ |
2303 |
02 Apr 14 |
olle |
if (numberOfDecimals == 0 || numberOfDecimals > 1) |
2303 |
02 Apr 14 |
olle |
439 |
{ |
2303 |
02 Apr 14 |
olle |
numberOfDecimals = 1; |
2303 |
02 Apr 14 |
olle |
441 |
} |
2303 |
02 Apr 14 |
olle |
442 |
} |
2303 |
02 Apr 14 |
olle |
else if (decimalPart >= 0.005) |
2303 |
02 Apr 14 |
olle |
444 |
{ |
2303 |
02 Apr 14 |
olle |
if (numberOfDecimals == 0 || numberOfDecimals > 2) |
2303 |
02 Apr 14 |
olle |
446 |
{ |
2303 |
02 Apr 14 |
olle |
numberOfDecimals = 2; |
2303 |
02 Apr 14 |
olle |
448 |
} |
2303 |
02 Apr 14 |
olle |
449 |
} |
2303 |
02 Apr 14 |
olle |
else if (decimalPart >= 0.0005) |
2303 |
02 Apr 14 |
olle |
451 |
{ |
2303 |
02 Apr 14 |
olle |
if (numberOfDecimals == 0 || numberOfDecimals > 3) |
2303 |
02 Apr 14 |
olle |
453 |
{ |
2303 |
02 Apr 14 |
olle |
numberOfDecimals = 3; |
2303 |
02 Apr 14 |
olle |
455 |
} |
2303 |
02 Apr 14 |
olle |
456 |
} |
2303 |
02 Apr 14 |
olle |
457 |
} |
2303 |
02 Apr 14 |
olle |
// Draw y-axis left scale markers with values |
2303 |
02 Apr 14 |
olle |
var scaleValue; |
2303 |
02 Apr 14 |
olle |
var markerText; |
2303 |
02 Apr 14 |
olle |
for (i=0; i < trimmedScaleMarkerArr.length; i++) |
2303 |
02 Apr 14 |
olle |
462 |
{ |
2303 |
02 Apr 14 |
olle |
scaleValue = trimmedScaleMarkerArr[i]; |
2303 |
02 Apr 14 |
olle |
markerText = scaleValue.toFixed(numberOfDecimals); |
2303 |
02 Apr 14 |
olle |
drawScaleMarkerYLeft(scaleValue, y_scale_font_size, markerText, min_y, max_y, min_yoff, max_yoff, ctx, drect_xoff, drect_yoff, drect_w, drect_h); |
2303 |
02 Apr 14 |
olle |
466 |
} |
2303 |
02 Apr 14 |
olle |
// Find number of boxes in box plot |
2303 |
02 Apr 14 |
olle |
var boxNumTot = 0; |
2303 |
02 Apr 14 |
olle |
for (var i in boxPlotJsonObject.percentileData) |
2303 |
02 Apr 14 |
olle |
470 |
{ |
2303 |
02 Apr 14 |
olle |
boxNumTot++; |
2303 |
02 Apr 14 |
olle |
472 |
} |
2303 |
02 Apr 14 |
olle |
// Draw box plot boxes |
2303 |
02 Apr 14 |
olle |
for (var i in boxPlotJsonObject.percentileData) |
2303 |
02 Apr 14 |
olle |
475 |
{ |
2303 |
02 Apr 14 |
olle |
var boxNum = i; |
2303 |
02 Apr 14 |
olle |
var name = boxPlotJsonObject.percentileData[i].name; |
2303 |
02 Apr 14 |
olle |
var numItems = boxPlotJsonObject.percentileData[i].numItems; |
2303 |
02 Apr 14 |
olle |
var v1 = boxPlotJsonObject.percentileData[i].v1; |
2303 |
02 Apr 14 |
olle |
var v2 = boxPlotJsonObject.percentileData[i].v2; |
2303 |
02 Apr 14 |
olle |
var v3 = boxPlotJsonObject.percentileData[i].v3; |
2303 |
02 Apr 14 |
olle |
var v4 = boxPlotJsonObject.percentileData[i].v4; |
2303 |
02 Apr 14 |
olle |
var v5 = boxPlotJsonObject.percentileData[i].v5; |
2303 |
02 Apr 14 |
olle |
// Draw box plot box |
2303 |
02 Apr 14 |
olle |
var x_pad = 10 * draw_scale_factor; |
2303 |
02 Apr 14 |
olle |
drawBoxPlotBoxY(boxNum, boxNumTot, v1, v2, v3, v4, v5, min_y, max_y, min_yoff, max_yoff, x_pad, ctx, drect_xoff, drect_yoff, drect_w, drect_h, draw_scale_factor); |
2303 |
02 Apr 14 |
olle |
drawBoxPlotBoxScaleMarkerXBottom(boxNum, boxNumTot, name, x_scale_font_size, x_pad, ctx, drect_xoff, drect_yoff, drect_w, drect_h); |
2303 |
02 Apr 14 |
olle |
drawBoxPlotBoxScaleMarkerXTop(boxNum, boxNumTot, numItems, x_scale_font_size, x_pad, ctx, drect_xoff, drect_yoff, drect_w, drect_h); |
2303 |
02 Apr 14 |
olle |
489 |
} |
2303 |
02 Apr 14 |
olle |
// Draw y-axis right scale markers with values and horizontal dotted guide lines |
2303 |
02 Apr 14 |
olle |
for (var i in boxPlotJsonObject.valueGuideLinesY) |
2303 |
02 Apr 14 |
olle |
492 |
{ |
2303 |
02 Apr 14 |
olle |
if (boxPlotJsonObject.valueGuideLinesY[i] != null) |
2303 |
02 Apr 14 |
olle |
494 |
{ |
2303 |
02 Apr 14 |
olle |
var value = boxPlotJsonObject.valueGuideLinesY[i].value; |
2303 |
02 Apr 14 |
olle |
var valueText = boxPlotJsonObject.valueGuideLinesY[i].text; |
2303 |
02 Apr 14 |
olle |
// Draw y-axis right scale markers with values |
2303 |
02 Apr 14 |
olle |
drawScaleMarkerYRight(value, valueText, y_scale_font_size, min_y, max_y, min_yoff, max_yoff, ctx, drect_xoff, drect_yoff, drect_w, drect_h); |
2303 |
02 Apr 14 |
olle |
// Draw dotted horizontal lines at y axis right scale marker values |
2303 |
02 Apr 14 |
olle |
drawDottedLineY(value, min_y, max_y, min_yoff, max_yoff, ctx, drect_xoff, drect_yoff, drect_w, drect_h); |
2303 |
02 Apr 14 |
olle |
501 |
} |
2303 |
02 Apr 14 |
olle |
502 |
} |
2303 |
02 Apr 14 |
olle |
503 |
} |
2303 |
02 Apr 14 |
olle |
504 |
|
2303 |
02 Apr 14 |
olle |
505 |
/** |
2303 |
02 Apr 14 |
olle |
* Calculate min data value for percentiles in box plot JSON object. |
2303 |
02 Apr 14 |
olle |
507 |
*/ |
2303 |
02 Apr 14 |
olle |
function calculateMinDataValue(boxPlotJsonObject) |
2303 |
02 Apr 14 |
olle |
509 |
{ |
2303 |
02 Apr 14 |
olle |
// Find number of boxes in box plot |
2303 |
02 Apr 14 |
olle |
var boxNumTot = 0; |
2303 |
02 Apr 14 |
olle |
for (var i in boxPlotJsonObject.percentileData) |
2303 |
02 Apr 14 |
olle |
513 |
{ |
2303 |
02 Apr 14 |
olle |
boxNumTot++; |
2303 |
02 Apr 14 |
olle |
515 |
} |
2303 |
02 Apr 14 |
olle |
// Calculate min percentile value |
2303 |
02 Apr 14 |
olle |
var minValue = 1000000000; |
2303 |
02 Apr 14 |
olle |
for (var i in boxPlotJsonObject.percentileData) |
2303 |
02 Apr 14 |
olle |
519 |
{ |
2303 |
02 Apr 14 |
olle |
var boxNum = i; |
2303 |
02 Apr 14 |
olle |
var v1 = boxPlotJsonObject.percentileData[i].v1; |
2303 |
02 Apr 14 |
olle |
var v5 = boxPlotJsonObject.percentileData[i].v5; |
2303 |
02 Apr 14 |
olle |
if (v1 < minValue) |
2303 |
02 Apr 14 |
olle |
524 |
{ |
2303 |
02 Apr 14 |
olle |
minValue = v1; |
2303 |
02 Apr 14 |
olle |
526 |
} |
2303 |
02 Apr 14 |
olle |
if (v5 < minValue) |
2303 |
02 Apr 14 |
olle |
528 |
{ |
2303 |
02 Apr 14 |
olle |
minValue = v5; |
2303 |
02 Apr 14 |
olle |
530 |
} |
2303 |
02 Apr 14 |
olle |
531 |
} |
2303 |
02 Apr 14 |
olle |
return minValue; |
2303 |
02 Apr 14 |
olle |
533 |
} |
2303 |
02 Apr 14 |
olle |
534 |
|
2303 |
02 Apr 14 |
olle |
535 |
/** |
2303 |
02 Apr 14 |
olle |
* Calculate max data value for percentiles in box plot JSON object. |
2303 |
02 Apr 14 |
olle |
537 |
*/ |
2303 |
02 Apr 14 |
olle |
function calculateMaxDataValue(boxPlotJsonObject) |
2303 |
02 Apr 14 |
olle |
539 |
{ |
2303 |
02 Apr 14 |
olle |
// Find number of boxes in box plot |
2303 |
02 Apr 14 |
olle |
var boxNumTot = 0; |
2303 |
02 Apr 14 |
olle |
for (var i in boxPlotJsonObject.percentileData) |
2303 |
02 Apr 14 |
olle |
543 |
{ |
2303 |
02 Apr 14 |
olle |
boxNumTot++; |
2303 |
02 Apr 14 |
olle |
545 |
} |
2303 |
02 Apr 14 |
olle |
// Calculate max percentile value |
2303 |
02 Apr 14 |
olle |
var maxValue = -1; |
2303 |
02 Apr 14 |
olle |
for (var i in boxPlotJsonObject.percentileData) |
2303 |
02 Apr 14 |
olle |
549 |
{ |
2303 |
02 Apr 14 |
olle |
var boxNum = i; |
2303 |
02 Apr 14 |
olle |
var v1 = boxPlotJsonObject.percentileData[i].v1; |
2303 |
02 Apr 14 |
olle |
var v5 = boxPlotJsonObject.percentileData[i].v5; |
2303 |
02 Apr 14 |
olle |
if (v1 > maxValue) |
2303 |
02 Apr 14 |
olle |
554 |
{ |
2303 |
02 Apr 14 |
olle |
maxValue = v1; |
2303 |
02 Apr 14 |
olle |
556 |
} |
2303 |
02 Apr 14 |
olle |
if (v5 > maxValue) |
2303 |
02 Apr 14 |
olle |
558 |
{ |
2303 |
02 Apr 14 |
olle |
maxValue = v5; |
2303 |
02 Apr 14 |
olle |
560 |
} |
2303 |
02 Apr 14 |
olle |
561 |
} |
2303 |
02 Apr 14 |
olle |
return maxValue; |
2303 |
02 Apr 14 |
olle |
563 |
} |
2303 |
02 Apr 14 |
olle |
564 |
|
2303 |
02 Apr 14 |
olle |
565 |
/** |
2401 |
06 May 14 |
olle |
* Calculate min data value for graph plot JSON object. |
2401 |
06 May 14 |
olle |
567 |
*/ |
2401 |
06 May 14 |
olle |
function calculateMinDataValueSimple(boxPlotJsonObject) |
2401 |
06 May 14 |
olle |
569 |
{ |
2401 |
06 May 14 |
olle |
// Find number of boxes in box plot |
2401 |
06 May 14 |
olle |
var boxNumTot = 0; |
2401 |
06 May 14 |
olle |
for (var i in boxPlotJsonObject.percentileData) |
2401 |
06 May 14 |
olle |
573 |
{ |
2401 |
06 May 14 |
olle |
boxNumTot++; |
2401 |
06 May 14 |
olle |
575 |
} |
2401 |
06 May 14 |
olle |
// Calculate min percentile value |
2401 |
06 May 14 |
olle |
var minValue = 1000000000; |
2401 |
06 May 14 |
olle |
for (var i in boxPlotJsonObject.percentileData) |
2401 |
06 May 14 |
olle |
579 |
{ |
2401 |
06 May 14 |
olle |
var boxNum = i; |
2401 |
06 May 14 |
olle |
var v3 = boxPlotJsonObject.percentileData[i].v3; |
2401 |
06 May 14 |
olle |
if (v3 < minValue) |
2401 |
06 May 14 |
olle |
583 |
{ |
2401 |
06 May 14 |
olle |
minValue = v3; |
2401 |
06 May 14 |
olle |
585 |
} |
2401 |
06 May 14 |
olle |
586 |
} |
2401 |
06 May 14 |
olle |
return minValue; |
2401 |
06 May 14 |
olle |
588 |
} |
2401 |
06 May 14 |
olle |
589 |
|
2401 |
06 May 14 |
olle |
590 |
/** |
2401 |
06 May 14 |
olle |
* Calculate max data value for graph plot JSON object. |
2401 |
06 May 14 |
olle |
592 |
*/ |
2401 |
06 May 14 |
olle |
function calculateMaxDataValueSimple(boxPlotJsonObject) |
2401 |
06 May 14 |
olle |
594 |
{ |
2401 |
06 May 14 |
olle |
// Find number of boxes in box plot |
2401 |
06 May 14 |
olle |
var boxNumTot = 0; |
2401 |
06 May 14 |
olle |
for (var i in boxPlotJsonObject.percentileData) |
2401 |
06 May 14 |
olle |
598 |
{ |
2401 |
06 May 14 |
olle |
boxNumTot++; |
2401 |
06 May 14 |
olle |
600 |
} |
2401 |
06 May 14 |
olle |
// Calculate max percentile value |
2401 |
06 May 14 |
olle |
var maxValue = -1; |
2401 |
06 May 14 |
olle |
for (var i in boxPlotJsonObject.percentileData) |
2401 |
06 May 14 |
olle |
604 |
{ |
2401 |
06 May 14 |
olle |
var boxNum = i; |
2401 |
06 May 14 |
olle |
var v3 = boxPlotJsonObject.percentileData[i].v3; |
2401 |
06 May 14 |
olle |
if (v3 > maxValue) |
2401 |
06 May 14 |
olle |
608 |
{ |
2401 |
06 May 14 |
olle |
maxValue = v3; |
2401 |
06 May 14 |
olle |
610 |
} |
2401 |
06 May 14 |
olle |
611 |
} |
2401 |
06 May 14 |
olle |
return maxValue; |
2401 |
06 May 14 |
olle |
613 |
} |
2401 |
06 May 14 |
olle |
614 |
|
2401 |
06 May 14 |
olle |
615 |
/** |
2401 |
06 May 14 |
olle |
* Calculate min data value for graph plot JSON object. |
2401 |
06 May 14 |
olle |
* Minimum value for variable v1. |
2401 |
06 May 14 |
olle |
618 |
*/ |
2401 |
06 May 14 |
olle |
function calculateMinDataValueSimple2(boxPlotJsonObject) |
2401 |
06 May 14 |
olle |
620 |
{ |
2401 |
06 May 14 |
olle |
// Find number of boxes in box plot |
2401 |
06 May 14 |
olle |
var boxNumTot = 0; |
2401 |
06 May 14 |
olle |
for (var i in boxPlotJsonObject.percentileData) |
2401 |
06 May 14 |
olle |
624 |
{ |
2401 |
06 May 14 |
olle |
boxNumTot++; |
2401 |
06 May 14 |
olle |
626 |
} |
2401 |
06 May 14 |
olle |
// Calculate min percentile value |
2401 |
06 May 14 |
olle |
var minValue = 1000000000; |
2401 |
06 May 14 |
olle |
for (var i in boxPlotJsonObject.percentileData) |
2401 |
06 May 14 |
olle |
630 |
{ |
2401 |
06 May 14 |
olle |
var boxNum = i; |
2401 |
06 May 14 |
olle |
var v1 = boxPlotJsonObject.percentileData[i].v1; |
2401 |
06 May 14 |
olle |
if (v1 < minValue) |
2401 |
06 May 14 |
olle |
634 |
{ |
2401 |
06 May 14 |
olle |
minValue = v1; |
2401 |
06 May 14 |
olle |
636 |
} |
2401 |
06 May 14 |
olle |
637 |
} |
2401 |
06 May 14 |
olle |
return minValue; |
2401 |
06 May 14 |
olle |
639 |
} |
2401 |
06 May 14 |
olle |
640 |
|
2401 |
06 May 14 |
olle |
641 |
/** |
2401 |
06 May 14 |
olle |
* Calculate max data value for graph plot JSON object. |
2401 |
06 May 14 |
olle |
* Maximum value for variable v3. |
2401 |
06 May 14 |
olle |
644 |
*/ |
2401 |
06 May 14 |
olle |
function calculateMaxDataValueSimple2(boxPlotJsonObject) |
2401 |
06 May 14 |
olle |
646 |
{ |
2401 |
06 May 14 |
olle |
// Find number of boxes in box plot |
2401 |
06 May 14 |
olle |
var maxValue = calculateMaxDataValueSimple(boxPlotJsonObject); |
2401 |
06 May 14 |
olle |
return maxValue; |
2401 |
06 May 14 |
olle |
650 |
} |
2401 |
06 May 14 |
olle |
651 |
|
2401 |
06 May 14 |
olle |
652 |
/** |
2303 |
02 Apr 14 |
olle |
* Draws centered top header title in a canvas context, using coordinates |
2303 |
02 Apr 14 |
olle |
* where x increases to the right and y increases upwards, |
2303 |
02 Apr 14 |
olle |
* and where the offsets are added automatically. |
2303 |
02 Apr 14 |
olle |
656 |
*/ |
2303 |
02 Apr 14 |
olle |
function drawHeaderTitleTopCenter(text, font_size, text_top_off, context, xoff, yoff, wdt, hgt) |
2303 |
02 Apr 14 |
olle |
658 |
{ |
2303 |
02 Apr 14 |
olle |
// Add centered top header title |
2303 |
02 Apr 14 |
olle |
context.font = font_size + 'px sans-serif'; |
2303 |
02 Apr 14 |
olle |
context.textBaseline = 'top'; |
2303 |
02 Apr 14 |
olle |
context.textAlign="center"; |
2303 |
02 Apr 14 |
olle |
context.fillText(text, xoff + wdt/2, text_top_off); |
2303 |
02 Apr 14 |
olle |
664 |
} |
2303 |
02 Apr 14 |
olle |
665 |
|
2303 |
02 Apr 14 |
olle |
666 |
/** |
2303 |
02 Apr 14 |
olle |
* Draws centered top title in a canvas context, using coordinates |
2303 |
02 Apr 14 |
olle |
* where x increases to the right and y increases upwards, |
2303 |
02 Apr 14 |
olle |
* and where the offsets are added automatically. |
2303 |
02 Apr 14 |
olle |
670 |
*/ |
2303 |
02 Apr 14 |
olle |
function drawTitleTopCenter(text, font_size, text_axis_off, context, xoff, yoff, wdt, hgt) |
2303 |
02 Apr 14 |
olle |
672 |
{ |
2303 |
02 Apr 14 |
olle |
// Add centered top title |
2303 |
02 Apr 14 |
olle |
var text_axis_yoff = -text_axis_off; |
2303 |
02 Apr 14 |
olle |
context.font = font_size + 'px sans-serif'; |
2303 |
02 Apr 14 |
olle |
context.textBaseline = 'bottom'; |
2303 |
02 Apr 14 |
olle |
context.textAlign="center"; |
2303 |
02 Apr 14 |
olle |
context.fillText(text, xoff + wdt/2, yoff + text_axis_yoff); |
2303 |
02 Apr 14 |
olle |
679 |
} |
2303 |
02 Apr 14 |
olle |
680 |
|
2303 |
02 Apr 14 |
olle |
681 |
/** |
2303 |
02 Apr 14 |
olle |
* Draws centered bottom title in a canvas context, using coordinates |
2303 |
02 Apr 14 |
olle |
* where x increases to the right and y increases upwards, |
2303 |
02 Apr 14 |
olle |
* and where the offsets are added automatically. |
2303 |
02 Apr 14 |
olle |
685 |
*/ |
2303 |
02 Apr 14 |
olle |
function drawTitleBottomCenter(text, font_size, text_axis_off, context, xoff, yoff, wdt, hgt) |
2303 |
02 Apr 14 |
olle |
687 |
{ |
2303 |
02 Apr 14 |
olle |
// Add centered bottom title |
2303 |
02 Apr 14 |
olle |
var text_axis_yoff = text_axis_off; |
2303 |
02 Apr 14 |
olle |
context.font = font_size + 'px sans-serif'; |
2303 |
02 Apr 14 |
olle |
context.textBaseline = 'top'; |
2303 |
02 Apr 14 |
olle |
context.textAlign="center"; |
2303 |
02 Apr 14 |
olle |
context.fillText(text, xoff + wdt/2, yoff + hgt + text_axis_yoff); |
2303 |
02 Apr 14 |
olle |
694 |
} |
2303 |
02 Apr 14 |
olle |
695 |
|
2303 |
02 Apr 14 |
olle |
696 |
/** |
2303 |
02 Apr 14 |
olle |
* Draws right-aligned top sub-title in a canvas context, using coordinates |
2303 |
02 Apr 14 |
olle |
* where x increases to the right and y increases upwards, |
2303 |
02 Apr 14 |
olle |
* and where the offsets are added automatically. |
2303 |
02 Apr 14 |
olle |
700 |
*/ |
2303 |
02 Apr 14 |
olle |
function drawSubTitleTopRight(text, font_size, text_axis_off, context, xoff, yoff, wdt, hgt) |
2303 |
02 Apr 14 |
olle |
702 |
{ |
2303 |
02 Apr 14 |
olle |
// Add right-aligned top title |
2303 |
02 Apr 14 |
olle |
var text_axis_yoff = -text_axis_off; |
2303 |
02 Apr 14 |
olle |
context.font = font_size + 'px sans-serif'; |
2303 |
02 Apr 14 |
olle |
context.textBaseline = 'bottom'; |
2303 |
02 Apr 14 |
olle |
context.textAlign="right"; |
2303 |
02 Apr 14 |
olle |
context.fillText(text, xoff + wdt, yoff + text_axis_yoff); |
2303 |
02 Apr 14 |
olle |
709 |
} |
2303 |
02 Apr 14 |
olle |
710 |
|
2303 |
02 Apr 14 |
olle |
711 |
/** |
2303 |
02 Apr 14 |
olle |
* Draws left-aligned top sub-title in a canvas context, using coordinates |
2303 |
02 Apr 14 |
olle |
* where x increases to the right and y increases upwards, |
2303 |
02 Apr 14 |
olle |
* and where the offsets are added automatically. |
2303 |
02 Apr 14 |
olle |
715 |
*/ |
2303 |
02 Apr 14 |
olle |
function drawSubTitleTopLeft(text, sub_title_num, font_size, text_axis_off, context, xoff, yoff, wdt, hgt) |
2303 |
02 Apr 14 |
olle |
717 |
{ |
2303 |
02 Apr 14 |
olle |
// Add left-aligned top title |
2303 |
02 Apr 14 |
olle |
var text_axis_yoff = -text_axis_off; |
2303 |
02 Apr 14 |
olle |
//var text_yoff = 35 - 11*(2 - sub_title_num); |
2303 |
02 Apr 14 |
olle |
var text_yoff = yoff + text_axis_yoff - (font_size+1)*(2 - sub_title_num); |
2303 |
02 Apr 14 |
olle |
context.font = font_size + 'px sans-serif'; |
2303 |
02 Apr 14 |
olle |
context.textBaseline = 'bottom'; |
2303 |
02 Apr 14 |
olle |
context.textAlign="left"; |
2303 |
02 Apr 14 |
olle |
context.fillText(text, xoff, text_yoff); |
2303 |
02 Apr 14 |
olle |
726 |
} |
2303 |
02 Apr 14 |
olle |
727 |
|
2303 |
02 Apr 14 |
olle |
728 |
/** |
2401 |
06 May 14 |
olle |
* Draws line segment between two data points. |
2401 |
06 May 14 |
olle |
730 |
*/ |
2401 |
06 May 14 |
olle |
function drawGraphPlotLineSegment(x1, y1, x2, y2, x_min, x_max, y_min, y_max, min_off, max_off, x_pad, context, xoff, yoff, wdt, hgt, draw_scale_factor, linewidth) |
2401 |
06 May 14 |
olle |
732 |
{ |
2401 |
06 May 14 |
olle |
// Calculate value offsets |
2401 |
06 May 14 |
olle |
var eff_hgt = hgt - min_off - max_off; |
2401 |
06 May 14 |
olle |
var eff_wdt = wdt - 2*x_pad; |
2401 |
06 May 14 |
olle |
var x_range = x_max - x_min; |
2401 |
06 May 14 |
olle |
var y_range = y_max - y_min; |
2401 |
06 May 14 |
olle |
var x1_xoff = x_pad + eff_wdt*((x1 - x_min)/x_range); |
2401 |
06 May 14 |
olle |
var x2_xoff = x_pad + eff_wdt*((x2 - x_min)/x_range); |
2401 |
06 May 14 |
olle |
var y1_yoff = min_off + eff_hgt*((y1 - y_min)/y_range); |
2401 |
06 May 14 |
olle |
var y2_yoff = min_off + eff_hgt*((y2 - y_min)/y_range); |
2401 |
06 May 14 |
olle |
// Draw graph line between (x1, y1) and (x2, y2) (thick) |
2401 |
06 May 14 |
olle |
context.lineWidth = linewidth; |
2401 |
06 May 14 |
olle |
context.beginPath(); |
2401 |
06 May 14 |
olle |
drawLine(x1_xoff, y1_yoff, x2_xoff, y2_yoff, context, xoff, yoff, wdt, hgt); |
2401 |
06 May 14 |
olle |
context.stroke(); |
2401 |
06 May 14 |
olle |
747 |
} |
2401 |
06 May 14 |
olle |
748 |
|
2401 |
06 May 14 |
olle |
749 |
/** |
2401 |
06 May 14 |
olle |
* Draws a data point. |
2401 |
06 May 14 |
olle |
751 |
*/ |
2401 |
06 May 14 |
olle |
function drawGraphPlotDataPoint(x, y, x_min, x_max, y_min, y_max, min_off, max_off, x_pad, context, xoff, yoff, wdt, hgt, draw_scale_factor) |
2401 |
06 May 14 |
olle |
753 |
{ |
2401 |
06 May 14 |
olle |
// Calculate value offsets |
2401 |
06 May 14 |
olle |
var eff_hgt = hgt - min_off - max_off; |
2401 |
06 May 14 |
olle |
var eff_wdt = wdt - 2*x_pad; |
2401 |
06 May 14 |
olle |
var x_range = x_max - x_min; |
2401 |
06 May 14 |
olle |
var y_range = y_max - y_min; |
2401 |
06 May 14 |
olle |
var x_xoff = x_pad + eff_wdt*((x - x_min)/x_range); |
2401 |
06 May 14 |
olle |
var y_yoff = min_off + eff_hgt*((y - y_min)/y_range); |
2401 |
06 May 14 |
olle |
// Draw graph line data point at (x1, y1) (thick) |
2401 |
06 May 14 |
olle |
context.lineWidth = 3; |
2401 |
06 May 14 |
olle |
context.beginPath(); |
2401 |
06 May 14 |
olle |
drawPoint(x_xoff, y_yoff, context, xoff, yoff, wdt, hgt); |
2401 |
06 May 14 |
olle |
context.stroke(); |
2401 |
06 May 14 |
olle |
766 |
} |
2401 |
06 May 14 |
olle |
767 |
|
2401 |
06 May 14 |
olle |
768 |
/** |
2401 |
06 May 14 |
olle |
* Draws x-axis bottom scale marker with text in a canvas context |
2401 |
06 May 14 |
olle |
* for a graph plot box, using coordinates where x increases to the right |
2401 |
06 May 14 |
olle |
* and y increases upwards, and where the offsets are added automatically. |
2401 |
06 May 14 |
olle |
772 |
*/ |
2401 |
06 May 14 |
olle |
function drawGraphPlotBoxScaleMarkerXBottom(markerNum, markerNumTot, value, font_size, x_pad, context, xoff, yoff, wdt, hgt) |
2401 |
06 May 14 |
olle |
774 |
{ |
2401 |
06 May 14 |
olle |
// Calculate box width |
2401 |
06 May 14 |
olle |
var width_per_marker = (wdt - 2*x_pad)/(markerNumTot - 1); |
2401 |
06 May 14 |
olle |
// Reserve 20% as space between boxes |
2401 |
06 May 14 |
olle |
//var box_pad = width_per_box/10; |
2401 |
06 May 14 |
olle |
//var box_wdt = width_per_box*4/5; |
2401 |
06 May 14 |
olle |
// Calculate marker center offset |
2401 |
06 May 14 |
olle |
//var marker_xmin = x_pad + markerNum*width_per_box + box_pad; |
2401 |
06 May 14 |
olle |
var marker_xcenter = x_pad + markerNum*width_per_marker; |
2401 |
06 May 14 |
olle |
//var box_xmax = box_xmin + box_wdt; |
2401 |
06 May 14 |
olle |
// Draw scale marker |
2401 |
06 May 14 |
olle |
var marker_len = font_size; |
2401 |
06 May 14 |
olle |
context.lineWidth = 1; |
2401 |
06 May 14 |
olle |
context.beginPath(); |
2401 |
06 May 14 |
olle |
drawLine(marker_xcenter, 0, marker_xcenter, -marker_len, context, xoff, yoff, wdt, hgt); |
2401 |
06 May 14 |
olle |
context.stroke(); |
2401 |
06 May 14 |
olle |
// Draw scale marker value |
2401 |
06 May 14 |
olle |
var value_text = '' + value; |
2401 |
06 May 14 |
olle |
var text_axis_yoff = 1.5*font_size; |
2401 |
06 May 14 |
olle |
var text_marker_xoff = font_size / 2; |
2401 |
06 May 14 |
olle |
context.save(); |
2401 |
06 May 14 |
olle |
context.font = font_size + 'px sans-serif'; |
2401 |
06 May 14 |
olle |
context.textBaseline = 'bottom'; |
2401 |
06 May 14 |
olle |
context.translate(xoff + marker_xcenter + text_marker_xoff, yoff + hgt + text_axis_yoff); |
2401 |
06 May 14 |
olle |
context.rotate(-Math.PI/2); |
2401 |
06 May 14 |
olle |
context.textAlign = "right"; |
2401 |
06 May 14 |
olle |
context.fillText(value_text, 0, 0); |
2401 |
06 May 14 |
olle |
context.restore(); |
2401 |
06 May 14 |
olle |
802 |
} |
2401 |
06 May 14 |
olle |
803 |
|
2401 |
06 May 14 |
olle |
804 |
/** |
2303 |
02 Apr 14 |
olle |
* Draws vertical box plot box with five percentiles. |
2303 |
02 Apr 14 |
olle |
* Box numbers starts from 0 at the left. |
2303 |
02 Apr 14 |
olle |
807 |
*/ |
2303 |
02 Apr 14 |
olle |
function drawBoxPlotBoxY(boxNum, boxNumTot, v1, v2, v3, v4, v5, min, max, min_off, max_off, x_pad, context, xoff, yoff, wdt, hgt, draw_scale_factor) |
2303 |
02 Apr 14 |
olle |
809 |
{ |
2303 |
02 Apr 14 |
olle |
// Calculate value offsets |
2303 |
02 Apr 14 |
olle |
var eff_hgt = hgt - min_off - max_off; |
2303 |
02 Apr 14 |
olle |
var value_range = max - min; |
2303 |
02 Apr 14 |
olle |
var v1_yoff = min_off + eff_hgt*((v1 - min)/value_range); |
2303 |
02 Apr 14 |
olle |
var v2_yoff = min_off + eff_hgt*((v2 - min)/value_range); |
2303 |
02 Apr 14 |
olle |
var v3_yoff = min_off + eff_hgt*((v3 - min)/value_range); |
2303 |
02 Apr 14 |
olle |
var v4_yoff = min_off + eff_hgt*((v4 - min)/value_range); |
2303 |
02 Apr 14 |
olle |
var v5_yoff = min_off + eff_hgt*((v5 - min)/value_range); |
2303 |
02 Apr 14 |
olle |
// Calculate box width |
2303 |
02 Apr 14 |
olle |
var width_per_box = (wdt - 2*x_pad)/boxNumTot; |
2303 |
02 Apr 14 |
olle |
// Reserve 20% as space between boxes |
2303 |
02 Apr 14 |
olle |
var box_pad = width_per_box/10; |
2303 |
02 Apr 14 |
olle |
var box_wdt = width_per_box*4/5; |
2303 |
02 Apr 14 |
olle |
// Calculate box min, center, and max offsets |
2303 |
02 Apr 14 |
olle |
var box_xmin = x_pad + boxNum*width_per_box + box_pad; |
2303 |
02 Apr 14 |
olle |
var box_xcenter = box_xmin + box_wdt/2; |
2303 |
02 Apr 14 |
olle |
var box_xmax = box_xmin + box_wdt; |
2303 |
02 Apr 14 |
olle |
// Draw box rectangle |
2303 |
02 Apr 14 |
olle |
drawRect(box_xmin, v2_yoff, box_wdt, v4_yoff - v2_yoff, context, xoff, yoff, wdt, hgt); |
2303 |
02 Apr 14 |
olle |
// Draw median line (thick) |
2303 |
02 Apr 14 |
olle |
context.lineWidth = 3; |
2303 |
02 Apr 14 |
olle |
context.beginPath(); |
2303 |
02 Apr 14 |
olle |
drawLine(box_xmin, v3_yoff, box_xmax, v3_yoff, context, xoff, yoff, wdt, hgt); |
2303 |
02 Apr 14 |
olle |
context.stroke(); |
2303 |
02 Apr 14 |
olle |
// Draw line between first percentile and box (dashed line) |
2303 |
02 Apr 14 |
olle |
context.lineWidth = 1; |
2303 |
02 Apr 14 |
olle |
context.beginPath(); |
2303 |
02 Apr 14 |
olle |
//drawLine(box_xcenter, v1_yoff, box_xcenter, v2_yoff, context, xoff, yoff, wdt, hgt); |
2303 |
02 Apr 14 |
olle |
var dash_size = 5 * draw_scale_factor; |
2303 |
02 Apr 14 |
olle |
drawDashedLineVertical(box_xcenter, v1_yoff, v2_yoff, context, xoff, yoff, wdt, hgt, dash_size, dash_size); |
2303 |
02 Apr 14 |
olle |
// Draw short horizontal line at end of line |
2303 |
02 Apr 14 |
olle |
drawLine(box_xcenter - box_wdt/4, v1_yoff, box_xcenter + box_wdt/4, v1_yoff, context, xoff, yoff, wdt, hgt); |
2303 |
02 Apr 14 |
olle |
context.stroke(); |
2303 |
02 Apr 14 |
olle |
// Draw line between box and fifth percentile (dashed line) |
2303 |
02 Apr 14 |
olle |
context.lineWidth = 1; |
2303 |
02 Apr 14 |
olle |
context.beginPath(); |
2303 |
02 Apr 14 |
olle |
//drawLine(box_xcenter, v4_yoff, box_xcenter, v5_yoff, context, xoff, yoff, wdt, hgt); |
2303 |
02 Apr 14 |
olle |
drawDashedLineVertical(box_xcenter, v4_yoff, v5_yoff, context, xoff, yoff, wdt, hgt, dash_size, dash_size); |
2303 |
02 Apr 14 |
olle |
// Draw short horizontal line at end of line |
2303 |
02 Apr 14 |
olle |
drawLine(box_xcenter - box_wdt/4, v5_yoff, box_xcenter + box_wdt/4, v5_yoff, context, xoff, yoff, wdt, hgt); |
2303 |
02 Apr 14 |
olle |
context.stroke(); |
2303 |
02 Apr 14 |
olle |
851 |
} |
2303 |
02 Apr 14 |
olle |
852 |
|
2303 |
02 Apr 14 |
olle |
853 |
/** |
2303 |
02 Apr 14 |
olle |
* Draws x-axis bottom scale marker with text in a canvas context |
2303 |
02 Apr 14 |
olle |
* for a box plot box, using coordinates where x increases to the right |
2303 |
02 Apr 14 |
olle |
* and y increases upwards, and where the offsets are added automatically. |
2303 |
02 Apr 14 |
olle |
857 |
*/ |
2303 |
02 Apr 14 |
olle |
function drawBoxPlotBoxScaleMarkerXBottom(boxNum, boxNumTot, value, font_size, x_pad, context, xoff, yoff, wdt, hgt) |
2303 |
02 Apr 14 |
olle |
859 |
{ |
2303 |
02 Apr 14 |
olle |
// Calculate box width |
2303 |
02 Apr 14 |
olle |
var width_per_box = (wdt - 2*x_pad)/boxNumTot; |
2303 |
02 Apr 14 |
olle |
// Reserve 20% as space between boxes |
2303 |
02 Apr 14 |
olle |
var box_pad = width_per_box/10; |
2303 |
02 Apr 14 |
olle |
var box_wdt = width_per_box*4/5; |
2303 |
02 Apr 14 |
olle |
// Calculate box min, center, and max offsets |
2303 |
02 Apr 14 |
olle |
var box_xmin = x_pad + boxNum*width_per_box + box_pad; |
2303 |
02 Apr 14 |
olle |
var box_xcenter = box_xmin + box_wdt/2; |
2303 |
02 Apr 14 |
olle |
var box_xmax = box_xmin + box_wdt; |
2303 |
02 Apr 14 |
olle |
// Draw scale marker |
2303 |
02 Apr 14 |
olle |
var marker_len = font_size; |
2303 |
02 Apr 14 |
olle |
context.lineWidth = 1; |
2303 |
02 Apr 14 |
olle |
context.beginPath(); |
2303 |
02 Apr 14 |
olle |
drawLine(box_xcenter, 0, box_xcenter, -marker_len, context, xoff, yoff, wdt, hgt); |
2303 |
02 Apr 14 |
olle |
context.stroke(); |
2303 |
02 Apr 14 |
olle |
// Draw scale marker value |
2303 |
02 Apr 14 |
olle |
var value_text = '' + value; |
2303 |
02 Apr 14 |
olle |
var text_axis_yoff = 1.5*font_size; |
2303 |
02 Apr 14 |
olle |
var text_marker_xoff = font_size / 2; |
2303 |
02 Apr 14 |
olle |
context.save(); |
2303 |
02 Apr 14 |
olle |
context.font = font_size + 'px sans-serif'; |
2303 |
02 Apr 14 |
olle |
context.textBaseline = 'bottom'; |
2303 |
02 Apr 14 |
olle |
context.translate(xoff + box_xcenter + text_marker_xoff, yoff + hgt + text_axis_yoff); |
2303 |
02 Apr 14 |
olle |
context.rotate(-Math.PI/2); |
2303 |
02 Apr 14 |
olle |
context.textAlign = "right"; |
2303 |
02 Apr 14 |
olle |
context.fillText(value_text, 0, 0); |
2303 |
02 Apr 14 |
olle |
context.restore(); |
2303 |
02 Apr 14 |
olle |
887 |
} |
2303 |
02 Apr 14 |
olle |
888 |
|
2303 |
02 Apr 14 |
olle |
889 |
/** |
2303 |
02 Apr 14 |
olle |
* Draws x-axis top scale marker with text in a canvas context |
2303 |
02 Apr 14 |
olle |
* for a box plot box, using coordinates where x increases to the right |
2303 |
02 Apr 14 |
olle |
* and y increases upwards, and where the offsets are added automatically. |
2303 |
02 Apr 14 |
olle |
893 |
*/ |
2303 |
02 Apr 14 |
olle |
function drawBoxPlotBoxScaleMarkerXTop(boxNum, boxNumTot, value, font_size, x_pad, context, xoff, yoff, wdt, hgt) |
2303 |
02 Apr 14 |
olle |
895 |
{ |
2303 |
02 Apr 14 |
olle |
// Calculate box width |
2303 |
02 Apr 14 |
olle |
var width_per_box = (wdt - 2*x_pad)/boxNumTot; |
2303 |
02 Apr 14 |
olle |
// Reserve 20% as space between boxes |
2303 |
02 Apr 14 |
olle |
var box_pad = width_per_box/10; |
2303 |
02 Apr 14 |
olle |
var box_wdt = width_per_box*4/5; |
2303 |
02 Apr 14 |
olle |
// Calculate box min, center, and max offsets |
2303 |
02 Apr 14 |
olle |
var box_xmin = x_pad + boxNum*width_per_box + box_pad; |
2303 |
02 Apr 14 |
olle |
var box_xcenter = box_xmin + box_wdt/2; |
2303 |
02 Apr 14 |
olle |
var box_xmax = box_xmin + box_wdt; |
2303 |
02 Apr 14 |
olle |
// Draw scale marker |
2303 |
02 Apr 14 |
olle |
var marker_len = font_size; |
2303 |
02 Apr 14 |
olle |
context.lineWidth = 1; |
2303 |
02 Apr 14 |
olle |
context.beginPath(); |
2303 |
02 Apr 14 |
olle |
drawLine(box_xcenter, hgt, box_xcenter, hgt + marker_len, context, xoff, yoff, wdt, hgt); |
2303 |
02 Apr 14 |
olle |
context.stroke(); |
2303 |
02 Apr 14 |
olle |
// Draw scale marker value |
2303 |
02 Apr 14 |
olle |
var value_text = '' + value; |
2303 |
02 Apr 14 |
olle |
var text_axis_yoff = 1.5*font_size; |
2303 |
02 Apr 14 |
olle |
var text_marker_xoff = font_size / 2; |
2303 |
02 Apr 14 |
olle |
context.save(); |
2303 |
02 Apr 14 |
olle |
context.font = font_size + 'px sans-serif'; |
2303 |
02 Apr 14 |
olle |
context.textBaseline = 'bottom'; |
2303 |
02 Apr 14 |
olle |
context.translate(xoff + box_xcenter + text_marker_xoff, yoff - text_axis_yoff); |
2303 |
02 Apr 14 |
olle |
context.rotate(-Math.PI/2); |
2303 |
02 Apr 14 |
olle |
context.textAlign = "left"; |
2303 |
02 Apr 14 |
olle |
context.fillText(value_text, 0, 0); |
2303 |
02 Apr 14 |
olle |
context.restore(); |
2303 |
02 Apr 14 |
olle |
923 |
} |
2303 |
02 Apr 14 |
olle |
924 |
|
2303 |
02 Apr 14 |
olle |
925 |
/** |
2303 |
02 Apr 14 |
olle |
* Draws y-axis left scale marker with text in a canvas context, using coordinates |
2303 |
02 Apr 14 |
olle |
* where x increases to the right and y increases upwards, |
2303 |
02 Apr 14 |
olle |
* and where the offsets are added automatically. |
2303 |
02 Apr 14 |
olle |
929 |
*/ |
2303 |
02 Apr 14 |
olle |
function drawScaleMarkerYLeft(value, font_size, markerText, min, max, min_off, max_off, context, xoff, yoff, wdt, hgt) |
2303 |
02 Apr 14 |
olle |
931 |
{ |
2303 |
02 Apr 14 |
olle |
var eff_hgt = hgt - min_off - max_off; |
2303 |
02 Apr 14 |
olle |
var value_range = max - min; |
2303 |
02 Apr 14 |
olle |
var marker_yoff = min_off + eff_hgt*((value - min)/value_range); |
2303 |
02 Apr 14 |
olle |
var marker_len = font_size; |
2303 |
02 Apr 14 |
olle |
// Draw scale marker |
2303 |
02 Apr 14 |
olle |
context.lineWidth = 1; |
2303 |
02 Apr 14 |
olle |
context.beginPath(); |
2303 |
02 Apr 14 |
olle |
drawLine(0, marker_yoff, -marker_len, marker_yoff, context, xoff, yoff, wdt, hgt); |
2303 |
02 Apr 14 |
olle |
context.stroke(); |
2303 |
02 Apr 14 |
olle |
// Draw scale marker value |
2303 |
02 Apr 14 |
olle |
var value_text = '' + markerText; |
2303 |
02 Apr 14 |
olle |
var text_axis_xoff = -1.5*font_size; |
2303 |
02 Apr 14 |
olle |
var text_marker_yoff = -font_size / 2; |
2303 |
02 Apr 14 |
olle |
context.font = font_size+'px sans-serif'; |
2303 |
02 Apr 14 |
olle |
context.textBaseline = 'bottom'; |
2303 |
02 Apr 14 |
olle |
context.textAlign="right"; |
2303 |
02 Apr 14 |
olle |
drawText(value_text, text_axis_xoff, marker_yoff + text_marker_yoff, context, xoff, yoff, wdt, hgt); |
2303 |
02 Apr 14 |
olle |
949 |
} |
2303 |
02 Apr 14 |
olle |
950 |
|
2303 |
02 Apr 14 |
olle |
951 |
/** |
2303 |
02 Apr 14 |
olle |
* Draws y-axis right scale marker with text in a canvas context, using coordinates |
2303 |
02 Apr 14 |
olle |
* where x increases to the right and y increases upwards, |
2303 |
02 Apr 14 |
olle |
* and where the offsets are added automatically. |
2303 |
02 Apr 14 |
olle |
955 |
*/ |
2303 |
02 Apr 14 |
olle |
function drawScaleMarkerYRight(value, markerText, font_size, min, max, min_off, max_off, context, xoff, yoff, wdt, hgt) |
2303 |
02 Apr 14 |
olle |
957 |
{ |
2303 |
02 Apr 14 |
olle |
var eff_hgt = hgt - min_off - max_off; |
2303 |
02 Apr 14 |
olle |
var value_range = max - min; |
2303 |
02 Apr 14 |
olle |
var marker_yoff = min_off + eff_hgt*((value - min)/value_range); |
2303 |
02 Apr 14 |
olle |
var marker_len = font_size; |
2303 |
02 Apr 14 |
olle |
// Draw scale marker |
2303 |
02 Apr 14 |
olle |
context.lineWidth = 1; |
2303 |
02 Apr 14 |
olle |
context.beginPath(); |
2303 |
02 Apr 14 |
olle |
drawLine(wdt, marker_yoff, wdt + marker_len, marker_yoff, context, xoff, yoff, wdt, hgt); |
2303 |
02 Apr 14 |
olle |
context.stroke(); |
2303 |
02 Apr 14 |
olle |
// Draw scale marker value |
2303 |
02 Apr 14 |
olle |
var value_text = '' + markerText; |
2303 |
02 Apr 14 |
olle |
var text_axis_xoff = font_size * 1.5; |
2303 |
02 Apr 14 |
olle |
var text_marker_yoff = -font_size / 2; |
2303 |
02 Apr 14 |
olle |
context.font = font_size + 'px sans-serif'; |
2303 |
02 Apr 14 |
olle |
context.textBaseline = 'bottom'; |
2303 |
02 Apr 14 |
olle |
context.textAlign="left"; |
2303 |
02 Apr 14 |
olle |
drawText(value_text, wdt + text_axis_xoff, marker_yoff + text_marker_yoff, context, xoff, yoff, wdt, hgt); |
2303 |
02 Apr 14 |
olle |
975 |
} |
2303 |
02 Apr 14 |
olle |
976 |
|
2303 |
02 Apr 14 |
olle |
977 |
/** |
2401 |
06 May 14 |
olle |
* Draws dotted line for x-value in a canvas context, using coordinates |
2401 |
06 May 14 |
olle |
* where x increases to the right and y increases upwards, |
2401 |
06 May 14 |
olle |
* and where the offsets are added automatically. |
2401 |
06 May 14 |
olle |
981 |
*/ |
2401 |
06 May 14 |
olle |
function drawDottedLineX(value, min, max, min_off, max_off, context, xoff, yoff, wdt, hgt) |
2401 |
06 May 14 |
olle |
983 |
{ |
2401 |
06 May 14 |
olle |
var eff_wdt = wdt - min_off - max_off; |
2401 |
06 May 14 |
olle |
var value_range = max - min; |
2401 |
06 May 14 |
olle |
var line_xoff = min_off + eff_wdt*((value - min)/value_range); |
2401 |
06 May 14 |
olle |
// Draw dotted line for x-value |
2401 |
06 May 14 |
olle |
context.lineWidth = 1; |
2401 |
06 May 14 |
olle |
context.beginPath(); |
2401 |
06 May 14 |
olle |
drawDottedLineVertical(line_xoff, 0, hgt, context, xoff, yoff, wdt, hgt); |
2401 |
06 May 14 |
olle |
context.stroke(); |
2401 |
06 May 14 |
olle |
992 |
} |
2401 |
06 May 14 |
olle |
993 |
|
2401 |
06 May 14 |
olle |
994 |
/** |
2303 |
02 Apr 14 |
olle |
* Draws dotted line for y-value in a canvas context, using coordinates |
2303 |
02 Apr 14 |
olle |
* where x increases to the right and y increases upwards, |
2303 |
02 Apr 14 |
olle |
* and where the offsets are added automatically. |
2303 |
02 Apr 14 |
olle |
998 |
*/ |
2303 |
02 Apr 14 |
olle |
function drawDottedLineY(value, min, max, min_off, max_off, context, xoff, yoff, wdt, hgt) |
2303 |
02 Apr 14 |
olle |
1000 |
{ |
2303 |
02 Apr 14 |
olle |
var eff_hgt = hgt - min_off - max_off; |
2303 |
02 Apr 14 |
olle |
var value_range = max - min; |
2303 |
02 Apr 14 |
olle |
var line_yoff = min_off + eff_hgt*((value - min)/value_range); |
2303 |
02 Apr 14 |
olle |
// Draw dotted line for y-value |
2303 |
02 Apr 14 |
olle |
context.lineWidth = 1; |
2303 |
02 Apr 14 |
olle |
context.beginPath(); |
2303 |
02 Apr 14 |
olle |
drawDottedLineHorizontal(0, wdt, line_yoff, context, xoff, yoff, wdt, hgt); |
2303 |
02 Apr 14 |
olle |
context.stroke(); |
2303 |
02 Apr 14 |
olle |
1009 |
} |
2303 |
02 Apr 14 |
olle |
1010 |
|
2303 |
02 Apr 14 |
olle |
1011 |
/** |
2303 |
02 Apr 14 |
olle |
* Draws y-axis left scale title in a canvas context, using coordinates |
2303 |
02 Apr 14 |
olle |
* where x increases to the right and y increases upwards, |
2303 |
02 Apr 14 |
olle |
* and where the offsets are added automatically. |
2303 |
02 Apr 14 |
olle |
1015 |
*/ |
2303 |
02 Apr 14 |
olle |
function drawTitleYLeft(title, font_size, context, xoff, yoff, wdt, hgt) |
2303 |
02 Apr 14 |
olle |
1017 |
{ |
2303 |
02 Apr 14 |
olle |
// Add y axis title |
2303 |
02 Apr 14 |
olle |
context.save(); |
2303 |
02 Apr 14 |
olle |
context.font = font_size + 'px sans-serif'; |
2303 |
02 Apr 14 |
olle |
context.textBaseline = 'bottom'; |
2303 |
02 Apr 14 |
olle |
context.translate(xoff, yoff + hgt/2); |
2303 |
02 Apr 14 |
olle |
context.rotate(-Math.PI/2); |
2303 |
02 Apr 14 |
olle |
context.textAlign = "center"; |
2303 |
02 Apr 14 |
olle |
context.fillText(title, 0, 0); |
2303 |
02 Apr 14 |
olle |
context.restore(); |
2303 |
02 Apr 14 |
olle |
1027 |
} |
2303 |
02 Apr 14 |
olle |
1028 |
|
2303 |
02 Apr 14 |
olle |
1029 |
/** |
2303 |
02 Apr 14 |
olle |
* Draws y-axis right scale title in a canvas context, using coordinates |
2303 |
02 Apr 14 |
olle |
* where x increases to the right and y increases upwards, |
2303 |
02 Apr 14 |
olle |
* and where the offsets are added automatically. |
2303 |
02 Apr 14 |
olle |
1033 |
*/ |
2303 |
02 Apr 14 |
olle |
function drawTitleYRight(title, font_size, context, xoff, yoff, wdt, hgt) |
2303 |
02 Apr 14 |
olle |
1035 |
{ |
2303 |
02 Apr 14 |
olle |
// Add y axis title |
2303 |
02 Apr 14 |
olle |
context.save(); |
2303 |
02 Apr 14 |
olle |
context.font = font_size + 'px sans-serif'; |
2303 |
02 Apr 14 |
olle |
context.textBaseline = 'top'; |
2303 |
02 Apr 14 |
olle |
context.translate(xoff + wdt, yoff + hgt/2); |
2303 |
02 Apr 14 |
olle |
context.rotate(-Math.PI/2); |
2303 |
02 Apr 14 |
olle |
context.textAlign = "center"; |
2303 |
02 Apr 14 |
olle |
context.fillText(title, 0, 0); |
2303 |
02 Apr 14 |
olle |
context.restore(); |
2303 |
02 Apr 14 |
olle |
1045 |
} |
2303 |
02 Apr 14 |
olle |
1046 |
|
2303 |
02 Apr 14 |
olle |
1047 |
/** |
2303 |
02 Apr 14 |
olle |
* Draws a rectangle in a canvas context, using coordinates |
2303 |
02 Apr 14 |
olle |
* where x increases to the right and y increases upwards, |
2303 |
02 Apr 14 |
olle |
* and where the offsets are added automatically. |
2303 |
02 Apr 14 |
olle |
* Rectangle input is given as coordinates for lower left corner |
2303 |
02 Apr 14 |
olle |
* and rectangle width and height. |
2303 |
02 Apr 14 |
olle |
1053 |
*/ |
2303 |
02 Apr 14 |
olle |
function drawRect(x, y, rect_wdt, rect_hgt, context, xoff, yoff, wdt, hgt) |
2303 |
02 Apr 14 |
olle |
1055 |
{ |
2303 |
02 Apr 14 |
olle |
var x_with_offset = fixCoordinate(context, x + xoff); |
2303 |
02 Apr 14 |
olle |
var y_with_offset = fixCoordinate(context, yoff + hgt - y - rect_hgt); |
2303 |
02 Apr 14 |
olle |
// Draw box rectangle |
2303 |
02 Apr 14 |
olle |
context.strokeStyle = "#000000"; |
2303 |
02 Apr 14 |
olle |
context.strokeRect(x_with_offset, y_with_offset, Math.floor(rect_wdt), Math.floor(rect_hgt)); |
2303 |
02 Apr 14 |
olle |
1061 |
} |
2303 |
02 Apr 14 |
olle |
1062 |
|
2303 |
02 Apr 14 |
olle |
1063 |
/** |
2303 |
02 Apr 14 |
olle |
* Draws a line in a canvas context, using coordinates |
2303 |
02 Apr 14 |
olle |
* where x increases to the right and y increases upwards, |
2303 |
02 Apr 14 |
olle |
* and where the offsets are added automatically. |
2303 |
02 Apr 14 |
olle |
1067 |
*/ |
2303 |
02 Apr 14 |
olle |
function drawLine(x1, y1, x2, y2, context, xoff, yoff, wdt, hgt) |
2303 |
02 Apr 14 |
olle |
1069 |
{ |
2303 |
02 Apr 14 |
olle |
var x1_with_offset = fixCoordinate(context, x1 + xoff); |
2303 |
02 Apr 14 |
olle |
var x2_with_offset = fixCoordinate(context, x2 + xoff); |
2303 |
02 Apr 14 |
olle |
var y1_with_offset = fixCoordinate(context, yoff + hgt - y1); |
2303 |
02 Apr 14 |
olle |
var y2_with_offset = fixCoordinate(context, yoff + hgt - y2); |
2303 |
02 Apr 14 |
olle |
context.moveTo(x1_with_offset, y1_with_offset); |
2303 |
02 Apr 14 |
olle |
context.lineTo(x2_with_offset, y2_with_offset); |
2303 |
02 Apr 14 |
olle |
1076 |
} |
2303 |
02 Apr 14 |
olle |
1077 |
|
2303 |
02 Apr 14 |
olle |
1078 |
/** |
2303 |
02 Apr 14 |
olle |
* Draws a dashed vertical line in a canvas context, using coordinates |
2303 |
02 Apr 14 |
olle |
* where x increases to the right and y increases upwards, |
2303 |
02 Apr 14 |
olle |
* and where the offsets are added automatically. |
2303 |
02 Apr 14 |
olle |
1082 |
*/ |
2303 |
02 Apr 14 |
olle |
function drawDashedLineVertical(x, y1, y2, context, xoff, yoff, wdt, hgt, dash_size, space_size) |
2303 |
02 Apr 14 |
olle |
1084 |
{ |
2303 |
02 Apr 14 |
olle |
var sign = 1; |
2303 |
02 Apr 14 |
olle |
if (y1 > y2) |
2303 |
02 Apr 14 |
olle |
1087 |
{ |
2303 |
02 Apr 14 |
olle |
sign = -1; |
2303 |
02 Apr 14 |
olle |
1089 |
} |
2303 |
02 Apr 14 |
olle |
var y = y1; |
2303 |
02 Apr 14 |
olle |
var y_new; |
2303 |
02 Apr 14 |
olle |
while (sign*(y2 - y) > 0) |
2303 |
02 Apr 14 |
olle |
1093 |
{ |
2303 |
02 Apr 14 |
olle |
y_new = y + sign*dash_size; |
2303 |
02 Apr 14 |
olle |
if (sign*y_new > sign*y2) |
2303 |
02 Apr 14 |
olle |
1096 |
{ |
2303 |
02 Apr 14 |
olle |
y_new = y2; |
2303 |
02 Apr 14 |
olle |
1098 |
} |
2303 |
02 Apr 14 |
olle |
drawLine(x, y, x, y_new, context, xoff, yoff, wdt, hgt); |
2303 |
02 Apr 14 |
olle |
y = y_new + sign*space_size; |
2303 |
02 Apr 14 |
olle |
1101 |
} |
2303 |
02 Apr 14 |
olle |
1102 |
} |
2303 |
02 Apr 14 |
olle |
1103 |
|
2303 |
02 Apr 14 |
olle |
1104 |
/** |
2303 |
02 Apr 14 |
olle |
* Draws a dotted horizontal line in a canvas context, using coordinates |
2303 |
02 Apr 14 |
olle |
* where x increases to the right and y increases upwards, |
2303 |
02 Apr 14 |
olle |
* and where the offsets are added automatically. |
2303 |
02 Apr 14 |
olle |
1108 |
*/ |
2303 |
02 Apr 14 |
olle |
function drawDottedLineHorizontal(x1, x2, y, context, xoff, yoff, wdt, hgt) |
2303 |
02 Apr 14 |
olle |
1110 |
{ |
2303 |
02 Apr 14 |
olle |
var dash_step1 = 2; |
2303 |
02 Apr 14 |
olle |
var space_step1 = 4; |
2303 |
02 Apr 14 |
olle |
var sign = 1; |
2303 |
02 Apr 14 |
olle |
if (x1 > x2) |
2303 |
02 Apr 14 |
olle |
1115 |
{ |
2303 |
02 Apr 14 |
olle |
sign = -1; |
2303 |
02 Apr 14 |
olle |
1117 |
} |
2303 |
02 Apr 14 |
olle |
var x = x1; |
2303 |
02 Apr 14 |
olle |
var x_new; |
2303 |
02 Apr 14 |
olle |
while (sign*(x2 - x) > 0) |
2303 |
02 Apr 14 |
olle |
1121 |
{ |
2303 |
02 Apr 14 |
olle |
x_new = x + sign*dash_step1; |
2303 |
02 Apr 14 |
olle |
if (sign*x_new > sign*x2) |
2303 |
02 Apr 14 |
olle |
1124 |
{ |
2303 |
02 Apr 14 |
olle |
x_new = x2; |
2303 |
02 Apr 14 |
olle |
1126 |
} |
2303 |
02 Apr 14 |
olle |
drawLine(x, y, x_new, y, context, xoff, yoff, wdt, hgt); |
2303 |
02 Apr 14 |
olle |
x = x_new + sign*space_step1; |
2303 |
02 Apr 14 |
olle |
1129 |
} |
2303 |
02 Apr 14 |
olle |
1130 |
} |
2303 |
02 Apr 14 |
olle |
1131 |
|
2303 |
02 Apr 14 |
olle |
1132 |
/** |
2401 |
06 May 14 |
olle |
* Draws a dotted vertical line in a canvas context, using coordinates |
2401 |
06 May 14 |
olle |
* where x increases to the right and y increases upwards, |
2401 |
06 May 14 |
olle |
* and where the offsets are added automatically. |
2401 |
06 May 14 |
olle |
1136 |
*/ |
2401 |
06 May 14 |
olle |
function drawDottedLineVertical(x, y1, y2, context, xoff, yoff, wdt, hgt) |
2401 |
06 May 14 |
olle |
1138 |
{ |
2401 |
06 May 14 |
olle |
var dash_step1 = 2; |
2401 |
06 May 14 |
olle |
var space_step1 = 4; |
2401 |
06 May 14 |
olle |
drawDashedLineVertical(x, y1, y2, context, xoff, yoff, wdt, hgt, dash_step1, space_step1); |
2401 |
06 May 14 |
olle |
1142 |
} |
2401 |
06 May 14 |
olle |
1143 |
|
2401 |
06 May 14 |
olle |
1144 |
/** |
2401 |
06 May 14 |
olle |
* Draws a point in a canvas context, using coordinates |
2401 |
06 May 14 |
olle |
* where x increases to the right and y increases upwards, |
2401 |
06 May 14 |
olle |
* and where the offsets are added automatically. |
2401 |
06 May 14 |
olle |
1148 |
*/ |
2401 |
06 May 14 |
olle |
function drawPoint(x, y, context, xoff, yoff, wdt, hgt) |
2401 |
06 May 14 |
olle |
1150 |
{ |
2401 |
06 May 14 |
olle |
var x_with_offset = fixCoordinate(context, x + xoff); |
2401 |
06 May 14 |
olle |
var y_with_offset = fixCoordinate(context, yoff + hgt - y); |
2401 |
06 May 14 |
olle |
// Draw a point as a rectangle with sides 1 pixel in length |
2401 |
06 May 14 |
olle |
context.fillRect(x_with_offset, y_with_offset, 1, 1); |
2401 |
06 May 14 |
olle |
1155 |
} |
2401 |
06 May 14 |
olle |
1156 |
|
2401 |
06 May 14 |
olle |
1157 |
/** |
2303 |
02 Apr 14 |
olle |
* Draws text in a canvas context, using coordinates |
2303 |
02 Apr 14 |
olle |
* where x increases to the right and y increases upwards, |
2303 |
02 Apr 14 |
olle |
* and where the offsets are added automatically. |
2303 |
02 Apr 14 |
olle |
1161 |
*/ |
2303 |
02 Apr 14 |
olle |
function drawText(text, x1, y1, context, xoff, yoff, wdt, hgt) |
2303 |
02 Apr 14 |
olle |
1163 |
{ |
2303 |
02 Apr 14 |
olle |
var x1_with_offset = fixCoordinate(context, x1 + xoff); |
2303 |
02 Apr 14 |
olle |
var y1_with_offset = fixCoordinate(context, yoff + hgt - y1); |
2303 |
02 Apr 14 |
olle |
context.fillText(text, x1_with_offset, y1_with_offset); |
2303 |
02 Apr 14 |
olle |
1167 |
} |
2303 |
02 Apr 14 |
olle |
1168 |
|
2303 |
02 Apr 14 |
olle |
1169 |
/** |
2303 |
02 Apr 14 |
olle |
* Calculates an array of values for y-axis scale markers (ticks), |
2303 |
02 Apr 14 |
olle |
* given the min and max values of the data, and the numbers |
2303 |
02 Apr 14 |
olle |
* of markers (optional). |
2303 |
02 Apr 14 |
olle |
1173 |
* |
2303 |
02 Apr 14 |
olle |
* Based on PHP example on |
2303 |
02 Apr 14 |
olle |
* http://stackoverflow.com/questions/326679/choosing-an-attractive-linear-scale-for-a-graphs-y-axis |
2303 |
02 Apr 14 |
olle |
* but with modified behavior for step size < 1. |
2303 |
02 Apr 14 |
olle |
1177 |
*/ |
2303 |
02 Apr 14 |
olle |
function calculateScaleMarkerArray(minDataValue, maxDataValue, numTicks) |
2303 |
02 Apr 14 |
olle |
1179 |
{ |
2303 |
02 Apr 14 |
olle |
if (numTicks == null || numTicks <= 0) |
2303 |
02 Apr 14 |
olle |
1181 |
{ |
2303 |
02 Apr 14 |
olle |
numTicks = 10; |
2303 |
02 Apr 14 |
olle |
1183 |
} |
2303 |
02 Apr 14 |
olle |
// Adjust ticks if needed |
2303 |
02 Apr 14 |
olle |
if (numTicks < 2) |
2303 |
02 Apr 14 |
olle |
1186 |
{ |
2303 |
02 Apr 14 |
olle |
numTicks = 2; |
2303 |
02 Apr 14 |
olle |
1188 |
} |
2303 |
02 Apr 14 |
olle |
else if (numTicks > 2) |
2303 |
02 Apr 14 |
olle |
1190 |
{ |
2303 |
02 Apr 14 |
olle |
numTicks -= 2; |
2303 |
02 Apr 14 |
olle |
1192 |
} |
2303 |
02 Apr 14 |
olle |
1193 |
|
2303 |
02 Apr 14 |
olle |
// If min and max are identical, then adjust these values. |
2303 |
02 Apr 14 |
olle |
if (minDataValue == maxDataValue) |
2303 |
02 Apr 14 |
olle |
1196 |
{ |
2303 |
02 Apr 14 |
olle |
minDataValue = minDataValue - 10; |
2303 |
02 Apr 14 |
olle |
maxDataValue = maxDataValue + 10; |
2303 |
02 Apr 14 |
olle |
1199 |
} |
2303 |
02 Apr 14 |
olle |
1200 |
|
2303 |
02 Apr 14 |
olle |
// Determine range |
2303 |
02 Apr 14 |
olle |
var range = maxDataValue - minDataValue; |
2303 |
02 Apr 14 |
olle |
// Get raw step value |
2303 |
02 Apr 14 |
olle |
var tempStep = range/numTicks; |
2303 |
02 Apr 14 |
olle |
// Calculate pretty step value |
2303 |
02 Apr 14 |
olle |
var mag = Math.floor(Math.log(tempStep)/Math.log(10) + 0.001); |
2303 |
02 Apr 14 |
olle |
var magPow = Math.pow(10, mag); |
2303 |
02 Apr 14 |
olle |
if (magPow >= 1) |
2303 |
02 Apr 14 |
olle |
1209 |
{ |
2303 |
02 Apr 14 |
olle |
magPow = Math.floor(magPow + 0.001); |
2303 |
02 Apr 14 |
olle |
1211 |
} |
2303 |
02 Apr 14 |
olle |
var magMsd = Math.floor(tempStep/magPow + 0.5); |
2303 |
02 Apr 14 |
olle |
var stepSize = magMsd*magPow; |
2303 |
02 Apr 14 |
olle |
// Correction for stepSize < 1000 |
2303 |
02 Apr 14 |
olle |
if (stepSize < 1000) |
2303 |
02 Apr 14 |
olle |
1216 |
{ |
2303 |
02 Apr 14 |
olle |
if (stepSize >= 750) |
2303 |
02 Apr 14 |
olle |
1218 |
{ |
2303 |
02 Apr 14 |
olle |
stepSize = 1000; |
2303 |
02 Apr 14 |
olle |
1220 |
} |
2303 |
02 Apr 14 |
olle |
else if (stepSize >= 250) |
2303 |
02 Apr 14 |
olle |
1222 |
{ |
2303 |
02 Apr 14 |
olle |
stepSize = 500; |
2303 |
02 Apr 14 |
olle |
1224 |
} |
2303 |
02 Apr 14 |
olle |
else if (stepSize >= 75) |
2303 |
02 Apr 14 |
olle |
1226 |
{ |
2303 |
02 Apr 14 |
olle |
stepSize = 100; |
2303 |
02 Apr 14 |
olle |
1228 |
} |
2303 |
02 Apr 14 |
olle |
else if (stepSize >= 25) |
2303 |
02 Apr 14 |
olle |
1230 |
{ |
2303 |
02 Apr 14 |
olle |
stepSize = 50; |
2303 |
02 Apr 14 |
olle |
1232 |
} |
2303 |
02 Apr 14 |
olle |
else if (stepSize >= 7.5) |
2303 |
02 Apr 14 |
olle |
1234 |
{ |
2303 |
02 Apr 14 |
olle |
stepSize = 10; |
2303 |
02 Apr 14 |
olle |
1236 |
} |
2303 |
02 Apr 14 |
olle |
else if (stepSize >= 2.5) |
2303 |
02 Apr 14 |
olle |
1238 |
{ |
2303 |
02 Apr 14 |
olle |
stepSize = 5; |
2303 |
02 Apr 14 |
olle |
1240 |
} |
2303 |
02 Apr 14 |
olle |
else if (stepSize >= 0.75) |
2303 |
02 Apr 14 |
olle |
1242 |
{ |
2303 |
02 Apr 14 |
olle |
stepSize = 1; |
2303 |
02 Apr 14 |
olle |
1244 |
} |
2303 |
02 Apr 14 |
olle |
else if (stepSize >= 0.25) |
2303 |
02 Apr 14 |
olle |
1246 |
{ |
2303 |
02 Apr 14 |
olle |
stepSize = 0.5; |
2303 |
02 Apr 14 |
olle |
1248 |
} |
2303 |
02 Apr 14 |
olle |
else if (stepSize >= 0.075) |
2303 |
02 Apr 14 |
olle |
1250 |
{ |
2303 |
02 Apr 14 |
olle |
stepSize = 0.1; |
2303 |
02 Apr 14 |
olle |
1252 |
} |
2303 |
02 Apr 14 |
olle |
else if (stepSize >= 0.025) |
2303 |
02 Apr 14 |
olle |
1254 |
{ |
2303 |
02 Apr 14 |
olle |
stepSize = 0.05; |
2303 |
02 Apr 14 |
olle |
1256 |
} |
2303 |
02 Apr 14 |
olle |
else if (stepSize >= 0.0075) |
2303 |
02 Apr 14 |
olle |
1258 |
{ |
2303 |
02 Apr 14 |
olle |
stepSize = 0.01; |
2303 |
02 Apr 14 |
olle |
1260 |
} |
2303 |
02 Apr 14 |
olle |
else if (stepSize >= 0.0025) |
2303 |
02 Apr 14 |
olle |
1262 |
{ |
2303 |
02 Apr 14 |
olle |
stepSize = 0.005; |
2303 |
02 Apr 14 |
olle |
1264 |
} |
2303 |
02 Apr 14 |
olle |
else if (stepSize >= 0.00075) |
2303 |
02 Apr 14 |
olle |
1266 |
{ |
2303 |
02 Apr 14 |
olle |
stepSize = 0.001; |
2303 |
02 Apr 14 |
olle |
1268 |
} |
2303 |
02 Apr 14 |
olle |
else if (stepSize >= 0.00025) |
2303 |
02 Apr 14 |
olle |
1270 |
{ |
2303 |
02 Apr 14 |
olle |
stepSize = 0.0005; |
2303 |
02 Apr 14 |
olle |
1272 |
} |
2303 |
02 Apr 14 |
olle |
else if (stepSize >= 0.000075) |
2303 |
02 Apr 14 |
olle |
1274 |
{ |
2303 |
02 Apr 14 |
olle |
stepSize = 0.0001; |
2303 |
02 Apr 14 |
olle |
1276 |
} |
2303 |
02 Apr 14 |
olle |
1277 |
} |
2303 |
02 Apr 14 |
olle |
1278 |
|
2303 |
02 Apr 14 |
olle |
// Build y label array |
2303 |
02 Apr 14 |
olle |
// Lower and upper bounds calculations |
2303 |
02 Apr 14 |
olle |
var lowerBound = stepSize*Math.floor(minDataValue/stepSize); |
2303 |
02 Apr 14 |
olle |
var upperBound = stepSize*Math.ceil(maxDataValue/stepSize); |
2303 |
02 Apr 14 |
olle |
// Build array |
2303 |
02 Apr 14 |
olle |
var tickValuesArr = []; |
2303 |
02 Apr 14 |
olle |
var value = lowerBound; |
2303 |
02 Apr 14 |
olle |
var i = 0; |
2303 |
02 Apr 14 |
olle |
tickValuesArr[i] = value; |
2303 |
02 Apr 14 |
olle |
value += stepSize; |
2303 |
02 Apr 14 |
olle |
while(value <= upperBound) |
2303 |
02 Apr 14 |
olle |
1290 |
{ |
2303 |
02 Apr 14 |
olle |
i++; |
2303 |
02 Apr 14 |
olle |
tickValuesArr[i] = value; |
2303 |
02 Apr 14 |
olle |
value += stepSize; |
2303 |
02 Apr 14 |
olle |
1294 |
} |
2303 |
02 Apr 14 |
olle |
return tickValuesArr; |
2303 |
02 Apr 14 |
olle |
1296 |
} |
2303 |
02 Apr 14 |
olle |
1297 |
|
2303 |
02 Apr 14 |
olle |
1298 |
/** |
2303 |
02 Apr 14 |
olle |
* Trims an array of values for y-axis scale markers (ticks), |
2303 |
02 Apr 14 |
olle |
* to only include values in given value range. |
2303 |
02 Apr 14 |
olle |
1301 |
*/ |
2303 |
02 Apr 14 |
olle |
function trimScaleMarkerArray(origTickValuesArr, minValue, maxValue) |
2303 |
02 Apr 14 |
olle |
1303 |
{ |
2303 |
02 Apr 14 |
olle |
// Build trimmed y label array |
2303 |
02 Apr 14 |
olle |
var tickValuesArr = []; |
2303 |
02 Apr 14 |
olle |
var value; |
2303 |
02 Apr 14 |
olle |
var k = 0; |
2303 |
02 Apr 14 |
olle |
for (i=0; i < origTickValuesArr.length; i++) |
2303 |
02 Apr 14 |
olle |
1309 |
{ |
2303 |
02 Apr 14 |
olle |
value = origTickValuesArr[i]; |
2303 |
02 Apr 14 |
olle |
if (value >= minValue && value <= maxValue) |
2303 |
02 Apr 14 |
olle |
1312 |
{ |
2303 |
02 Apr 14 |
olle |
// Add value to trimmed array |
2303 |
02 Apr 14 |
olle |
tickValuesArr[k] = value; |
2303 |
02 Apr 14 |
olle |
k++; |
2303 |
02 Apr 14 |
olle |
1316 |
} |
2303 |
02 Apr 14 |
olle |
1317 |
} |
2303 |
02 Apr 14 |
olle |
return tickValuesArr; |
2303 |
02 Apr 14 |
olle |
1319 |
} |
2303 |
02 Apr 14 |
olle |
1320 |
|
2303 |
02 Apr 14 |
olle |
1321 |
/* |
2303 |
02 Apr 14 |
olle |
Fixes a plotting coordinate by aligning it so that anti-aliasing |
2303 |
02 Apr 14 |
olle |
is avoided. For 1-pixel line widths the coordate should alway be a |
2303 |
02 Apr 14 |
olle |
half-value, eg. 1.5, 10.5, etc. |
2303 |
02 Apr 14 |
olle |
1325 |
*/ |
2303 |
02 Apr 14 |
olle |
function fixCoordinate(context, value) |
2303 |
02 Apr 14 |
olle |
1327 |
{ |
2303 |
02 Apr 14 |
olle |
return Math.floor(value) + (context.lineWidth % 2) / 2; |
2303 |
02 Apr 14 |
olle |
1329 |
} |
2989 |
02 Dec 14 |
olle |
1330 |
|
2989 |
02 Dec 14 |
olle |
1331 |
/** |
2989 |
02 Dec 14 |
olle |
* Returns value for a JSON object given a key. |
2989 |
02 Dec 14 |
olle |
* If the JSON object or the value for the key is `null`, |
2989 |
02 Dec 14 |
olle |
* an empty string is returned. |
2989 |
02 Dec 14 |
olle |
1335 |
*/ |
2989 |
02 Dec 14 |
olle |
function getJSONData(jsonObject, key) |
2989 |
02 Dec 14 |
olle |
1337 |
{ |
2989 |
02 Dec 14 |
olle |
var data = labenvdbstat.getJSONData(jsonObject, key, ''); |
2989 |
02 Dec 14 |
olle |
return data; |
2989 |
02 Dec 14 |
olle |
1340 |
} |
2989 |
02 Dec 14 |
olle |
1341 |
|
2989 |
02 Dec 14 |
olle |
1342 |
/** |
2989 |
02 Dec 14 |
olle |
* Returns value for a JSON object given a key. |
2989 |
02 Dec 14 |
olle |
* If the JSON object or the value for the key is `null`, |
2989 |
02 Dec 14 |
olle |
* an the given default choice string is returned. |
2989 |
02 Dec 14 |
olle |
1346 |
*/ |
2989 |
02 Dec 14 |
olle |
function getJSONData(jsonObject, key, defaultChoice) |
2989 |
02 Dec 14 |
olle |
1348 |
{ |
2989 |
02 Dec 14 |
olle |
var data = defaultChoice; |
2989 |
02 Dec 14 |
olle |
if (jsonObject != null) |
2989 |
02 Dec 14 |
olle |
1351 |
{ |
2989 |
02 Dec 14 |
olle |
if (jsonObject[key] != null) |
2989 |
02 Dec 14 |
olle |
1353 |
{ |
2989 |
02 Dec 14 |
olle |
data = jsonObject[key]; |
2989 |
02 Dec 14 |
olle |
1355 |
} |
2989 |
02 Dec 14 |
olle |
1356 |
} |
2989 |
02 Dec 14 |
olle |
return data; |
2989 |
02 Dec 14 |
olle |
1358 |
} |
2989 |
02 Dec 14 |
olle |
1359 |
|
2303 |
02 Apr 14 |
olle |
1360 |
|