-
Notifications
You must be signed in to change notification settings - Fork 0
/
canvasRender.js
196 lines (175 loc) · 6.31 KB
/
canvasRender.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
var canvases = document.querySelectorAll('canvas');
// const monthNames = ["January", "February", "March", "April", "May", "June",
// "July", "August", "September", "October", "November", "December"
// ];
//converts full object data from server into {x: mm/yyyy, y: Number} objects
function getPoints(items) {
let points= datePoints.map(a => {
return {...a}
});
if (typeof items.payload !== 'undefined') {
for (let item of items.payload) {
const workingDate = new Date(item[items.searchProperty])
const monthYear = `${workingDate.getMonth() + 1}/${workingDate.getFullYear()}`;
let workingPoint = points.find(point => point.x === monthYear);
workingPoint.y ++;
}
}
return points;
};
// Returns the max Y value in our data list
function getMaxY(data) {
var max = 0;
for(var i = 0; i < data.length; i ++) {
if(data[i].y > max) {
max = data[i].y;
}
}
max += 5 - max % 5;
return max;
}
/* Removes objects from combined data where month matches, in order to draw only one copy of that
month on the X axis */
function removeDuplicates(originalArray, objKey) {
var trimmedArray = [];
var values = [];
var value;
for(var i = 0; i < originalArray.length; i++) {
value = originalArray[i][objKey];
if(values.indexOf(value) === -1) {
trimmedArray.push(originalArray[i]);
values.push(value);
}
}
return trimmedArray;
};
/* compare two arrays and if there are any missing months in either array, add them with a y value of 0, then sortby month/year */
function equalize(arr1, arr2) {
let newArr = arr2.reduce(function (result, obj2) {
if (arr1.some(obj1 => obj1['x'] === obj2['x'])) {
return result;
}
return [...result, {'x' : obj2['x'], 'y':0}];
}, arr1);
newArr.sort(function (a, b) {
a = a.x.split('/');
b = b.x.split('/')
return new Date(a[1], a[0], 1) - new Date(b[1], b[0], 1)
});
return newArr;
};
function renderCanvas(canvas, data) {
console.log('drawing on canvas');
const colors = ['indigo','blue','green','orange','purple','teal','fuschia'];
canvas.width = canvas.parentNode.parentElement.clientWidth;
if(canvas.getContext) {
var topPadding = 5;
var xPadding = 30;
var yPadding = 30;
var legendWidth = (data[0].label.length * 4);
var xLength = canvas.width - yPadding - legendWidth;
var yLength = canvas.height - xPadding;
var pointsArr = [];
data.forEach(function (obj) {
pointsArr.push(getPoints(obj));
});
for (let i = 0; i < pointsArr.length -1 ; i++) {
pointsArr[i] = equalize(pointsArr[i], pointsArr[i+1]);
};
var combinedData = Array.prototype.concat.apply([], pointsArr);
combinedData.sort(function(a,b) {
return new Date(a.created) - new Date(b.created)
});
var filteredPoints = removeDuplicates(combinedData, 'x');
/* cuts X axis into a number of sections double the number of points */
var xSpacing = xLength / (filteredPoints.length * 2);
var yMax = getMaxY(combinedData);
//draw Y and X axes
var ctx = canvas.getContext('2d');
ctx.clearRect( 0, 0, ctx.canvas.width, ctx.canvas.height);
ctx.font = 'italic 8pt sans-serif';
ctx.beginPath();
ctx.lineWidth = 6;
ctx.moveTo(yPadding,0);
ctx.lineTo(yPadding,yLength + topPadding);
ctx.lineTo(xLength - legendWidth,yLength + topPadding);
ctx.stroke();
ctx.closePath();
// Return the y pixel for a graph point
function getYPixel(val) {
return yLength - ((yLength / yMax) * (val));
}
// Return the y pixel for a graph point
function getXPixel(val) {
return ((xSpacing + yPadding) + (xSpacing * (2 * val)))
}
function drawLine(points, color, legendVal) {
/* move one xSpacing out from y Axis */
ctx.moveTo(yPadding + xSpacing, getYPixel(points[0].y));
ctx.beginPath();
ctx.fillStyle=color;
ctx.strokeStyle=color;
points.forEach((point) => {
const x = getXPixel(points.indexOf(point));
const y = (getYPixel(point.y)) ;
ctx.lineWidth = 2;
ctx.lineTo(x,y);
ctx.closePath();
ctx.stroke();
ctx.beginPath();
ctx.arc(x,y,5,0,360,false);
ctx.fillText(point.y, x + 15, y - 15);
ctx.closePath();
ctx.fill();
ctx.moveTo(x,y);
});
ctx.fillText(legendVal, xLength + legendWidth, getYPixel(points[points.length-1].y));
}
// Draw the X value texts
for(var i = 0; i < filteredPoints.length; i ++) {
ctx.fillText(filteredPoints[i].x, getXPixel(i) - (xSpacing * .25), yLength + xPadding);
}
// Draw the Y value texts
ctx.textAlign = "right"
ctx.textBaseline = "middle";
var increment = 10;
if (yMax < 5) {
increment = 1;
} else if (yMax < 10) {
increment = 2;
} else if (yMax < 25) {
increment = 4;
} else if (yMax < 50) {
increment = 5;
} else if (yMax > 100) {
increment = 10;
} else if (yMax >= 150) {
increment = 15;
}
for(var i = 0; i <= yMax; i += increment) {
if (i === yMax) {
ctx.fillText(i, xPadding - 10, getYPixel(i) + topPadding);
} else {
ctx.fillText(i, xPadding - 10, getYPixel(i));
}
};
pointsArr.forEach(function (points) {
drawLine(points, colors[pointsArr.indexOf(points)], data[pointsArr.indexOf(points)].label);
});
}
};
NodeList.prototype.indexOf = Array.prototype.indexOf
canvases.forEach((canvas) => {
renderCanvas(
canvas,
graphDatasets[canvases.indexOf(canvas)]
);
});
window.addEventListener('resize', function () {
canvases.forEach((canvas) => {
renderCanvas(
canvas,
graphDatasets[canvases.indexOf(canvas)]
);
});
});