Total Complexity | 90 |
Complexity/F | 3.21 |
Lines of Code | 817 |
Function Count | 28 |
Duplicated Lines | 0 |
Ratio | 0 % |
Changes | 28 | ||
Bugs | 2 | Features | 1 |
Complex classes like src/markerfactory.js often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
1 | function compact(array) { |
||
2 | let index = -1, |
||
3 | length = array ? array.length : 0, |
||
4 | resIndex = 0, |
||
5 | result = []; |
||
6 | |||
7 | while (++index < length) { |
||
8 | let value = array[index]; |
||
9 | if (value) { |
||
10 | result[resIndex++] = value; |
||
11 | } |
||
12 | } |
||
13 | return result; |
||
14 | } |
||
15 | |||
16 | function padHex(str_in) { |
||
17 | if (('' + str_in).length === 1) { |
||
18 | return '0' + String(str_in); |
||
19 | } else { |
||
20 | return String(str_in); |
||
21 | } |
||
22 | } |
||
23 | |||
24 | const defaults = { |
||
25 | h: 1, |
||
26 | s: 78, // constant saturation |
||
27 | l: 63, // constant luminance |
||
28 | a: 1 |
||
29 | }; |
||
30 | |||
31 | function hslaString(hslcolor) { |
||
32 | if (hslcolor.a) { |
||
33 | return 'hsla(' + hslcolor.h + ',' + hslcolor.s + '%,' + hslcolor.l + '%,' + hslcolor.a + ')'; |
||
34 | } |
||
35 | return 'hsl(' + hslcolor.h + ',' + hslcolor.s + '%,' + hslcolor.l + '%)'; |
||
36 | } |
||
37 | |||
38 | function rgbaString(hexcolor) { |
||
39 | if (hexcolor.a) { |
||
40 | return 'rgba(' + hexcolor.r + ',' + hexcolor.g + ',' + hexcolor.b + ',' + hexcolor.a + ')'; |
||
41 | } |
||
42 | return 'rgb(' + hexcolor.r + ',' + hexcolor.g + ',' + hexcolor.b + ')'; |
||
43 | } |
||
44 | |||
45 | function getColor(val, range) { |
||
46 | defaults.h = Math.floor((360 / range) * val); |
||
47 | return hslaString(defaults); |
||
48 | } |
||
49 | |||
50 | function getColor1() { |
||
51 | const defaults1 = { |
||
52 | h: 1, |
||
53 | s: 78, // constant saturation |
||
54 | l: 33, // constant luminance |
||
55 | a: 1 |
||
56 | }; |
||
57 | return hslaString(defaults1); |
||
58 | } |
||
59 | |||
60 | function parseHalf(foo) { |
||
61 | return parseInt(foo / 2, 10); |
||
62 | } |
||
63 | |||
64 | |||
65 | function darken(stringcolor, factor) { |
||
66 | const darkercolor = {}; |
||
67 | if (!factor) { |
||
68 | factor = 1; |
||
69 | } |
||
70 | if (stringcolor.fillColor.indexOf('rgb') !== -1) { |
||
71 | darkercolor.r = factor * parseHalf(stringcolor.r); |
||
72 | darkercolor.g = factor * parseHalf(stringcolor.g); |
||
73 | darkercolor.b = factor * parseHalf(stringcolor.b); |
||
74 | darkercolor.a = 0.99; |
||
75 | darkercolor.fillColor = rgbaString(darkercolor); |
||
76 | } else if (stringcolor.fillColor.indexOf('hsl') !== -1) { |
||
77 | darkercolor.h = stringcolor.h; |
||
78 | darkercolor.s = stringcolor.s; |
||
79 | darkercolor.l = factor * stringcolor.l - 30; |
||
80 | darkercolor.fillColor = hslaString(darkercolor); |
||
81 | } |
||
82 | |||
83 | return darkercolor; |
||
84 | } |
||
85 | |||
86 | |||
87 | function parseHex(hexstring, opacity, darkenfactor) { |
||
88 | let hexcolor = { |
||
89 | hex: hexstring |
||
90 | }; |
||
91 | darkenfactor = darkenfactor || 1; |
||
92 | |||
93 | hexstring = hexstring.replace('#', ''); |
||
94 | if (hexstring.length === 3) { |
||
95 | hexstring = hexstring[0] + hexstring[0] + hexstring[1] + hexstring[1] + hexstring[2] + hexstring[2]; |
||
96 | } |
||
97 | if (isNaN(parseFloat(opacity, 10))) { |
||
98 | opacity = 1; |
||
99 | } |
||
100 | |||
101 | hexcolor.r = parseInt(darkenfactor * (parseInt(hexstring.substring(0, 2), 16)), 10); |
||
102 | hexcolor.g = parseInt(darkenfactor * (parseInt(hexstring.substring(2, 4), 16)), 10); |
||
103 | hexcolor.b = parseInt(darkenfactor * (parseInt(hexstring.substring(4, 6), 16)), 10); |
||
104 | hexcolor.a = opacity; |
||
105 | hexcolor.fillColor = rgbaString(hexcolor); |
||
106 | hexcolor.strokeColor = [ |
||
107 | 'rgba(' + parseHalf(hexcolor.r), |
||
108 | parseHalf(hexcolor.g), |
||
109 | parseHalf(hexcolor.b), hexcolor.a + ')' |
||
110 | ].join(','); |
||
111 | hexcolor.rgb = hexcolor.fillColor; |
||
112 | return hexcolor; |
||
113 | } |
||
114 | |||
115 | |||
116 | function parseHSL(hslstring, opacity) { |
||
117 | let hslcolor = {}, |
||
118 | hslcolor_stroke = {}, |
||
119 | hslparts = compact(hslstring.split(/hsla?\(|,|\)|%/)); |
||
120 | |||
121 | if (hslparts[3] === undefined) { |
||
122 | hslparts[3] = 1; |
||
123 | } |
||
124 | if (isNaN(parseFloat(opacity, 10))) { |
||
125 | opacity = 1; |
||
126 | } |
||
127 | |||
128 | hslcolor.h = hslcolor_stroke.h = parseFloat(hslparts[0], 10); |
||
129 | hslcolor.s = hslcolor_stroke.s = parseFloat(hslparts[1], 10); |
||
130 | hslcolor.l = parseFloat(hslparts[2], 10); |
||
131 | hslcolor.a = hslcolor_stroke.a = parseFloat(opacity * hslparts[3], 10); |
||
132 | hslcolor_stroke.l = parseInt(hslcolor.l / 2, 10); |
||
133 | |||
134 | |||
135 | hslcolor.fillColor = hslaString(hslcolor); |
||
136 | hslcolor.strokeColor = hslaString(hslcolor_stroke); |
||
137 | hslcolor.hsl = hslcolor.fillColor; |
||
138 | return hslcolor; |
||
139 | } |
||
140 | |||
141 | function parseRGB(rgbstring, opacity, darkenfactor) { |
||
142 | let rgbcolor = {}, |
||
143 | rgbparts = compact(rgbstring.split(/rgba?\(|,|\)/)); |
||
144 | |||
145 | darkenfactor = darkenfactor || 1; |
||
146 | |||
147 | if (rgbparts[3] === undefined) { |
||
148 | rgbparts[3] = 1; |
||
149 | } |
||
150 | |||
151 | if (isNaN(parseFloat(opacity, 10))) { |
||
152 | opacity = 1; |
||
153 | } |
||
154 | |||
155 | rgbcolor.r = parseInt(darkenfactor * (parseInt(rgbparts[0], 10) % 256), 10); |
||
156 | rgbcolor.g = parseInt(darkenfactor * (parseInt(rgbparts[1], 10) % 256), 10); |
||
157 | rgbcolor.b = parseInt(darkenfactor * (parseInt(rgbparts[2], 10) % 256), 10); |
||
158 | rgbcolor.a = parseFloat(opacity * rgbparts[3], 10); |
||
159 | rgbcolor.fillColor = rgbaString(rgbcolor); |
||
160 | rgbcolor.strokeColor = 'rgba(' + rgbcolor.r / 2 + ',' + rgbcolor.g / 2 + ',' + rgbcolor.b / 2 + ',' + rgbcolor.a + ')'; |
||
161 | rgbcolor.rgb = rgbcolor.fillColor; |
||
162 | return rgbcolor; |
||
163 | } |
||
164 | |||
165 | function toDecColor(stringcolor) { |
||
166 | let parsedcolor = {}; |
||
167 | if (!stringcolor) { |
||
168 | parsedcolor.fillColor = 'rgba(100,250,50,0.99)'; |
||
169 | } else if (stringcolor.indexOf('rgb') !== -1) { |
||
170 | parsedcolor = parseRGB(stringcolor); |
||
171 | } else if (stringcolor.indexOf('hsl') !== -1) { |
||
172 | parsedcolor = parseHSL(stringcolor); |
||
173 | } else { |
||
174 | parsedcolor = parseHex(stringcolor); |
||
175 | } |
||
176 | |||
177 | return parsedcolor; |
||
178 | } |
||
179 | |||
180 | |||
181 | function getColors(options) { |
||
182 | let color0, color1; |
||
183 | if (options.index !== undefined && options.count > 0) { |
||
184 | color0 = getColor(options.index, options.count); |
||
185 | color1 = getColor1(); |
||
186 | } else { |
||
187 | let deccolor = toDecColor(options.color); |
||
188 | color0 = deccolor.fillColor; |
||
189 | color1 = darken(deccolor).fillColor; |
||
190 | } |
||
191 | return [color0, color1]; |
||
192 | } |
||
193 | |||
194 | |||
195 | function rgbToHSL(r, g, b, a) { |
||
196 | r = (r % 256) / 255; |
||
197 | g = (g % 256) / 255; |
||
198 | b = (b % 256) / 255; |
||
199 | if (a === undefined) { |
||
200 | a = 1; |
||
201 | } |
||
202 | let max = Math.max(r, g, b), |
||
203 | min = Math.min(r, g, b); |
||
204 | let h, s, l = (max + min) / 2; |
||
205 | |||
206 | if (max === min) { |
||
207 | h = s = 0; // achromatic |
||
208 | } else { |
||
209 | let d = max - min; |
||
210 | s = l > 0.5 ? d / (2 - max - min) : d / (max + min); |
||
211 | switch (max) { |
||
212 | case r: |
||
|
|||
213 | h = (g - b) / d + (g < b ? 6 : 0); |
||
214 | break; |
||
215 | case g: |
||
216 | h = (b - r) / d + 2; |
||
217 | break; |
||
218 | case b: |
||
219 | h = (r - g) / d + 4; |
||
220 | break; |
||
221 | default: |
||
222 | h = 0; |
||
223 | break; |
||
224 | } |
||
225 | |||
226 | h /= 6; |
||
227 | } |
||
228 | let hsl = { |
||
229 | h: Math.round(360 * h), |
||
230 | s: Math.round(100 * s), |
||
231 | l: Math.round(100 * l), |
||
232 | a: Math.round(100 * a) / 100 |
||
233 | }; |
||
234 | |||
235 | hsl.fillColor = hslaString(hsl); |
||
236 | |||
237 | return hsl; |
||
238 | } |
||
239 | |||
240 | function hue2rgb(p, q, t) { |
||
241 | if (t < 0) { |
||
242 | t += 1; |
||
243 | } |
||
244 | if (t > 1) { |
||
245 | t -= 1; |
||
246 | } |
||
247 | if (t < 1 / 6) { |
||
248 | return p + (q - p) * 6 * t; |
||
249 | } |
||
250 | if (t < 1 / 2) { |
||
251 | return q; |
||
252 | } |
||
253 | if (t < 2 / 3) { |
||
254 | return p + (q - p) * (2 / 3 - t) * 6; |
||
255 | } |
||
256 | return p; |
||
257 | } |
||
258 | |||
259 | function hslToRGB(h, s, l, a, darkenfactor) { |
||
260 | let r, g, b; |
||
261 | |||
262 | darkenfactor = darkenfactor || 1; |
||
263 | h = parseFloat(h, 10) / 360; |
||
264 | s = parseFloat(s, 10) / 100; |
||
265 | l = parseFloat(l, 10) / 100; |
||
266 | if (a === undefined) { |
||
267 | a = 1; |
||
268 | } |
||
269 | if (s === 0) { |
||
270 | r = g = b = l; // achromatic |
||
271 | } else { |
||
272 | |||
273 | |||
274 | let q = l < 0.5 ? l * (1 + s) : l + s - l * s; |
||
275 | let p = 2 * l - q; |
||
276 | r = hue2rgb(p, q, h + 1 / 3); |
||
277 | g = hue2rgb(p, q, h); |
||
278 | b = hue2rgb(p, q, h - 1 / 3); |
||
279 | } |
||
280 | |||
281 | if (a === undefined) { |
||
282 | a = 1; |
||
283 | } |
||
284 | |||
285 | let rgb = { |
||
286 | r: Math.round(r * 255 * darkenfactor), |
||
287 | g: Math.round(g * 255 * darkenfactor), |
||
288 | b: Math.round(b * 255 * darkenfactor), |
||
289 | a: parseFloat(a, 10) |
||
290 | }; |
||
291 | |||
292 | rgb.fillColor = rgbaString(rgb); |
||
293 | |||
294 | return rgb; |
||
295 | |||
296 | } |
||
297 | |||
298 | |||
299 | function IconObject(canvas, markerOpts) { |
||
300 | this.url = canvas.toDataURL(); |
||
301 | this.fillColor = canvas.fillColor; |
||
302 | this.markerOpts = markerOpts; |
||
303 | Object.assign(this, markerOpts); |
||
304 | return this; |
||
305 | }; |
||
306 | IconObject.prototype.toJSON = function () { |
||
307 | return { |
||
308 | url: null, |
||
309 | markerOpts: this.markerOpts |
||
310 | }; |
||
311 | }; |
||
312 | |||
313 | function createTextMarker(theoptions) { |
||
314 | |||
315 | const generateCanvas = function (options) { |
||
316 | let canvas = document.createElement("canvas"); |
||
317 | let ancho = 30, |
||
318 | alto = 40; |
||
319 | canvas.width = ancho + 18; |
||
320 | canvas.height = alto; |
||
321 | let x = canvas.width / 2, |
||
322 | y = canvas.height - 2, |
||
323 | radius = ancho / 2, |
||
324 | angulo = 0.6; |
||
325 | |||
326 | let font = "'" + options.font + "'" || 'Arial'; |
||
327 | let fontsize = options.fontsize || 11; |
||
328 | |||
329 | let context = canvas.getContext("2d"); |
||
330 | |||
331 | context.clearRect(0, 0, canvas.width, canvas.height); |
||
332 | |||
333 | let radius0 = 2 * radius, |
||
334 | cx = x + 0.95 * radius0, |
||
335 | cy = y + 0.45 * radius0; |
||
336 | |||
337 | let grad = context.createLinearGradient(0, 0, 0, canvas.height), |
||
338 | colors = getColors(options), |
||
339 | color0 = colors[0], |
||
340 | color1 = colors[1]; |
||
341 | |||
342 | grad.addColorStop(0, color0); |
||
343 | grad.addColorStop(1, color1); |
||
344 | |||
345 | context.fillStyle = grad; |
||
346 | context.strokeStyle = 'rgba(200,200,200,0.7)'; |
||
347 | |||
348 | context.beginPath(); |
||
349 | |||
350 | //arco izquierdo |
||
351 | context.arc(cx - 1, cy, radius0, 9 * Math.PI / 8, -6 * Math.PI / 8, false); |
||
352 | |||
353 | // arco superior |
||
354 | context.arc(x, (y - 7) / 2, radius, angulo, Math.PI - angulo, true); |
||
355 | |||
356 | //arco derecho |
||
357 | context.arc(2 * x - cx + 1, cy, radius0, -0.95 * Math.PI / 3, -Math.PI / 8, false); |
||
358 | context.fill(); |
||
359 | context.stroke(); |
||
360 | |||
361 | context.beginPath(); |
||
362 | context.arc(x, 0.40 * y, 2 * radius / 3, 0, 2 * Math.PI, false); |
||
363 | context.fillStyle = 'white'; |
||
364 | context.fill(); |
||
365 | |||
366 | context.beginPath(); |
||
367 | |||
368 | // Render Label |
||
369 | //context.font = "11pt Arial"; |
||
370 | context.font = fontsize + "pt " + font; |
||
371 | context.textBaseline = "top"; |
||
372 | |||
373 | let textWidth = context.measureText(options.label); |
||
374 | |||
375 | if (textWidth.width > ancho || String(options.label).length > 3) { |
||
376 | context.rect(x - 2 - textWidth.width / 2, y - 30, x - 2 + textWidth.width / 2, y - 23); |
||
377 | context.fillStyle = '#F7F0F0'; |
||
378 | context.fill(); |
||
379 | context.stroke(); |
||
380 | } |
||
381 | |||
382 | context.fillStyle = "black"; |
||
383 | context.strokeStyle = "black"; |
||
384 | // centre the text. |
||
385 | context.fillText(options.label, 1 + Math.floor((canvas.width / 2) - (textWidth.width / 2)), 8); |
||
386 | |||
387 | return canvas; |
||
388 | |||
389 | }; |
||
390 | theoptions.scale = theoptions.scale || 0.75; |
||
391 | let markerCanvas = generateCanvas(theoptions), |
||
392 | markerOpts = {}; |
||
393 | |||
394 | theoptions.type = 'textmarker'; |
||
395 | |||
396 | Object.assign(markerOpts, theoptions); |
||
397 | |||
398 | if (window && window.google && window.google.maps) { |
||
399 | Object.assign(markerOpts, { |
||
400 | size: new google.maps.Size(48, 40), |
||
401 | origin: new google.maps.Point(0, 0), |
||
402 | anchor: new google.maps.Point(24 * theoptions.scale, 40 * theoptions.scale), |
||
403 | scaledSize: new google.maps.Size(48 * theoptions.scale, 40 * theoptions.scale) |
||
404 | }); |
||
405 | } |
||
406 | let iconObj = new IconObject(markerCanvas, markerOpts); |
||
407 | |||
408 | return iconObj; |
||
409 | } |
||
410 | |||
411 | |||
412 | function createClusterIcon(theoptions) { |
||
413 | |||
414 | const generateClusterCanvas = function (options) { |
||
415 | let canvas = options.canvas || document.createElement("canvas"), |
||
416 | anchorX = 27, |
||
417 | anchorY = 53, |
||
418 | radius = (anchorX - 9), |
||
419 | angulo = 1.1, |
||
420 | font = options.font || 'fontello', |
||
421 | fontsize = options.fontsize || 14, |
||
1 ignored issue
–
show
|
|||
422 | context = canvas.getContext("2d"), |
||
423 | grad = context.createLinearGradient(0, 0, 0, anchorY); |
||
424 | |||
425 | canvas.width = anchorX * 2; |
||
426 | canvas.height = anchorY + 1; |
||
427 | |||
428 | let colors = getColors(options), |
||
429 | color0 = colors[0], |
||
430 | color1 = colors[1]; |
||
431 | |||
432 | |||
433 | context.clearRect(0, 0, canvas.width, canvas.height); |
||
434 | context.moveTo(anchorX, anchorY); |
||
435 | |||
436 | let labelvalue = parseInt(options.label, 10); |
||
437 | if (labelvalue < 10) { |
||
438 | color1 = 'orange'; |
||
439 | fontsize = 14; |
||
440 | } else if (labelvalue < 30) { |
||
441 | color1 = 'red'; |
||
442 | fontsize = 15; |
||
443 | } else { |
||
444 | color1 = 'purple'; |
||
445 | fontsize = 16; |
||
446 | } |
||
447 | if (labelvalue > 99) { |
||
448 | radius = radius + 3; |
||
449 | context.setLineDash([5, 5]); |
||
450 | context.beginPath(); |
||
451 | context.arc(anchorX, 2 + (0.50 * anchorY), (radius + 7), 0, 2 * Math.PI, false); |
||
452 | context.fillStyle = 'transparent'; |
||
453 | context.strokeStyle = color1; |
||
454 | context.lineWidth = 2; |
||
455 | context.fill(); |
||
456 | context.stroke(); |
||
457 | } |
||
458 | |||
459 | context.setLineDash([5, 5]); |
||
460 | context.beginPath(); |
||
461 | context.arc(anchorX, 2 + (0.50 * anchorY), (radius + 2), 0, 2 * Math.PI, false); |
||
462 | context.fillStyle = 'transparent'; |
||
463 | context.strokeStyle = color1; |
||
464 | context.lineWidth = 2; |
||
465 | context.fill(); |
||
466 | context.stroke(); |
||
467 | |||
468 | // Círculo blanco |
||
469 | context.setLineDash([5, 0]); |
||
470 | context.beginPath(); |
||
471 | context.arc(anchorX, 2 + (0.50 * anchorY), (radius - 3), 0, 2 * Math.PI, false); |
||
472 | context.fillStyle = 'white'; |
||
473 | context.strokeStyle = color1; |
||
474 | context.lineWidth = 4; |
||
475 | context.fill(); |
||
476 | context.stroke(); |
||
477 | |||
478 | context.beginPath(); |
||
479 | |||
480 | context.font = 'normal normal normal ' + fontsize + 'px ' + font; |
||
481 | console.log('context font', context.font); |
||
482 | context.fillStyle = '#333'; |
||
483 | context.textBaseline = "top"; |
||
484 | |||
485 | |||
486 | let textWidth = context.measureText(options.label), |
||
487 | text_x = options.label, |
||
488 | label_x = Math.floor((canvas.width / 2) - (textWidth.width / 2)), |
||
489 | label_y = 1 + Math.floor(canvas.height / 2 - fontsize / 2); |
||
490 | |||
491 | // centre the text. |
||
492 | context.fillText(text_x, label_x, label_y); |
||
493 | |||
494 | return canvas; |
||
495 | |||
496 | }; |
||
497 | theoptions.scale = theoptions.scale || 1; |
||
498 | let markerCanvas = generateClusterCanvas(theoptions), |
||
499 | markerOpts = {}, |
||
500 | scale = theoptions.scale; |
||
501 | |||
502 | Object.assign(markerOpts, theoptions); |
||
503 | |||
504 | if (window && window.google && window.google.maps) { |
||
505 | Object.assign(markerOpts, { |
||
506 | size: new google.maps.Size(54, 48), |
||
507 | origin: new google.maps.Point(0, 0), |
||
508 | anchor: new google.maps.Point(27 * scale, 24 * scale), |
||
509 | scaledSize: new google.maps.Size(54 * scale, 48 * scale) |
||
510 | }); |
||
511 | } |
||
512 | |||
513 | let iconObj = new IconObject(markerCanvas, markerOpts); |
||
514 | |||
515 | return iconObj; |
||
516 | } |
||
517 | |||
518 | function createFatMarkerIcon(theoptions) { |
||
519 | |||
520 | const generateFatCanvas = function (options) { |
||
521 | let canvas = options.canvas || document.createElement("canvas"), |
||
522 | anchorX = 27, |
||
523 | anchorY = 53, |
||
524 | radius = (anchorX - 9), |
||
525 | angulo = 1.1, |
||
526 | font = options.font || 'fontello', |
||
527 | fontsize = options.fontsize || 14, |
||
528 | context = canvas.getContext("2d"), |
||
529 | grad = context.createLinearGradient(0, 0, 0, anchorY); |
||
530 | |||
531 | canvas.width = anchorX * 2; |
||
532 | canvas.height = anchorY + 1; |
||
533 | |||
534 | let colors = getColors(options), |
||
535 | color0 = colors[0], |
||
536 | color1 = colors[1]; |
||
537 | |||
538 | context.clearRect(0, 0, canvas.width, canvas.height); |
||
539 | |||
540 | grad.addColorStop(0, color0); |
||
541 | grad.addColorStop(1, color1); |
||
542 | |||
543 | context.fillStyle = grad; |
||
544 | context.strokeStyle = color1; |
||
545 | context.beginPath(); |
||
546 | |||
547 | context.moveTo(anchorX, anchorY); |
||
548 | |||
549 | // arco superior |
||
550 | context.arc(anchorX, 2 + (0.50 * anchorY), radius, angulo, Math.PI - angulo, true); |
||
551 | |||
552 | //punta inferior |
||
553 | context.lineTo(anchorX, anchorY); |
||
554 | |||
555 | context.fill(); |
||
556 | context.stroke(); |
||
557 | |||
558 | // Círculo blanco |
||
559 | context.beginPath(); |
||
560 | context.arc(anchorX, 2 + (0.50 * anchorY), (radius - 3), 0, 2 * Math.PI, false); |
||
561 | context.fillStyle = 'white'; |
||
562 | context.fill(); |
||
563 | |||
564 | context.beginPath(); |
||
565 | |||
566 | context.font = 'normal normal normal ' + fontsize + 'px ' + font; |
||
567 | //console.log('context font', context.font); |
||
568 | context.fillStyle = color1; |
||
569 | context.textBaseline = "top"; |
||
570 | |||
571 | let textWidth = context.measureText(options.unicodelabel), |
||
572 | text_x = options.unicodelabel, |
||
573 | label_x = Math.floor((canvas.width / 2) - (textWidth.width / 2)), |
||
574 | label_y = 1 + Math.floor(canvas.height / 2 - fontsize / 2); |
||
575 | |||
576 | // centre the text. |
||
577 | context.fillText(text_x, label_x, label_y); |
||
578 | canvas.fillColor = color0; |
||
579 | return canvas; |
||
580 | }; |
||
581 | |||
582 | let scale = theoptions.scale || 1, |
||
583 | markerCanvas = generateFatCanvas(theoptions), |
||
584 | markerOpts = {}; |
||
585 | |||
586 | theoptions.type = 'fatmarker'; |
||
587 | |||
588 | Object.assign(markerOpts, theoptions); |
||
589 | |||
590 | if (window && window.google && window.google.maps) { |
||
591 | Object.assign(markerOpts, { |
||
592 | size: new google.maps.Size(54, 48), |
||
593 | origin: new google.maps.Point(0, 0), |
||
594 | anchor: new google.maps.Point(21 * scale, 36 * scale), |
||
595 | scaledSize: new google.maps.Size(42 * scale, 36 * scale), |
||
596 | scale: scale |
||
597 | }); |
||
598 | } |
||
599 | let iconObj = new IconObject(markerCanvas, markerOpts); |
||
600 | return iconObj; |
||
601 | } |
||
602 | |||
603 | function createTransparentMarkerIcon(theoptions) { |
||
604 | |||
605 | const generateTransparentCanvas = function (options) { |
||
606 | let text_x, |
||
607 | canvas = options.canvas || document.createElement("canvas"), |
||
608 | context = canvas.getContext("2d"), |
||
609 | font = options.font || 'fontello', |
||
610 | fontsize = options.fontsize || 26; |
||
611 | |||
612 | canvas.width = 54; |
||
613 | canvas.height = 48; |
||
614 | context.clearRect(0, 0, canvas.width, canvas.height); |
||
615 | |||
616 | let colors = getColors(options), |
||
617 | color0 = colors[0], |
||
618 | color1 = colors[1]; |
||
619 | context.beginPath(); |
||
620 | |||
621 | if (options.shadow) { |
||
622 | |||
623 | context.font = 'normal normal normal ' + fontsize + 'px ' + font; |
||
624 | |||
625 | context.textBaseline = "top"; |
||
626 | let textWidth = context.measureText(options.unicodelabel); |
||
627 | text_x = Math.floor((canvas.width / 2) - (textWidth.width / 2)); |
||
628 | |||
629 | context.shadowOffsetX = -2; |
||
630 | context.shadowOffsetY = -2; |
||
631 | context.shadowBlur = 0; |
||
632 | |||
633 | context.fillStyle = '#FFFFFF'; |
||
634 | context.shadowColor = '#666666'; |
||
635 | |||
636 | context.fillText(options.unicodelabel, text_x - 4, 2); |
||
637 | context.fillText(options.unicodelabel, text_x, 5); |
||
638 | context.fillStyle = color0; |
||
639 | context.fillText(options.unicodelabel, text_x + 4, 8); |
||
640 | |||
641 | context.strokeStyle = '#FFFFFF'; |
||
642 | context.strokeText(options.unicodelabel, text_x + 4, 8); |
||
643 | |||
644 | } else { |
||
645 | |||
646 | context.font = 'normal normal normal ' + (fontsize - 3) + 'px ' + font; |
||
647 | |||
648 | context.textBaseline = "top"; |
||
649 | let textmetric = context.measureText(options.unicodelabel); |
||
650 | text_x = Math.floor((canvas.width / 2) - (textmetric.width / 2)); |
||
651 | |||
652 | //console.debug('textmetric', textmetric); |
||
653 | |||
654 | context.shadowOffsetX = 2; |
||
655 | context.shadowOffsetY = 2; |
||
656 | context.shadowBlur = 0; |
||
657 | context.shadowColor = '#FFFFFF'; |
||
658 | context.fillStyle = color0; |
||
659 | context.fillText(options.unicodelabel, text_x + 1, 6); |
||
660 | |||
661 | context.shadowOffsetX = 2; |
||
662 | context.shadowOffsetY = 2; |
||
663 | context.shadowBlur = 1; |
||
664 | context.shadowColor = '#FFFFFF'; |
||
665 | context.strokeStyle = color1; |
||
666 | context.strokeText(options.unicodelabel, text_x + 1, 6); |
||
667 | |||
668 | } |
||
669 | |||
670 | canvas.fillColor = color0; |
||
671 | |||
672 | return canvas; |
||
673 | |||
674 | }; |
||
675 | |||
676 | theoptions.scale = theoptions.scale || 1; |
||
677 | theoptions.fontsize = theoptions.fontsize || 26; |
||
678 | |||
679 | let markerCanvas = generateTransparentCanvas(theoptions), |
||
680 | markerOpts = {}; |
||
681 | |||
682 | let scale = theoptions.scale; |
||
683 | /*if (theoptions.shadow) { |
||
684 | scale = 0.9 * scale; |
||
685 | }*/ |
||
686 | theoptions.type = 'transparent'; |
||
687 | |||
688 | Object.assign(markerOpts, theoptions); |
||
689 | |||
690 | if (window.google && window.google.maps) { |
||
691 | Object.assign(markerOpts, { |
||
692 | size: new google.maps.Size(54 * scale, 48 * scale), |
||
693 | origin: new google.maps.Point(0, 0), |
||
694 | anchor: new google.maps.Point(27 * scale, 24 * scale), |
||
695 | scaledSize: new google.maps.Size(54 * scale, 48 * scale) |
||
696 | }); |
||
697 | } |
||
698 | let iconObj = new IconObject(markerCanvas, markerOpts); |
||
699 | |||
700 | return iconObj; |
||
701 | }; |
||
702 | |||
703 | |||
704 | const MarkerFactory = { |
||
705 | createTransparentMarkerIcon: createTransparentMarkerIcon, |
||
706 | createFatMarkerIcon: createFatMarkerIcon, |
||
707 | createTextMarker: createTextMarker, |
||
708 | /** |
||
709 | * Receives a color string rgb(a), hsl(a) or hex, returns its components |
||
710 | * in rgba and hsla, with optional transparency |
||
711 | * plus a darkened version (default is half of each RGB component) and a |
||
712 | * |
||
713 | * @param {string} somecolor - A color string in rgb(a), hsl(a) or hex format |
||
714 | * @param {Number} [opacity=1] - Opacity to apply to the color |
||
715 | * @param {Number} [darkenfactor=1] - How much darker should the resulting color be |
||
716 | * |
||
717 | * @return {Object} input color parsed and modified as requested |
||
718 | */ |
||
719 | parseColorString: function (somecolor, opacity, darkenfactor) { |
||
720 | let parsedcolor = { |
||
721 | original: somecolor |
||
722 | }, |
||
723 | hsl, rgb; |
||
724 | |||
725 | darkenfactor = darkenfactor || 1; |
||
726 | opacity = opacity || 1; |
||
727 | |||
728 | if (somecolor.indexOf('hsl') !== -1) { |
||
729 | hsl = parseHSL(somecolor, opacity); |
||
730 | rgb = hslToRGB(hsl.h, hsl.s, hsl.l, hsl.a, darkenfactor); |
||
731 | |||
732 | } else if (somecolor.indexOf('rgb') !== -1) { |
||
733 | rgb = parseRGB(somecolor, opacity, darkenfactor); |
||
734 | } else { |
||
735 | rgb = parseHex(somecolor, opacity, darkenfactor); |
||
736 | } |
||
737 | |||
738 | |||
739 | hsl = rgbToHSL(rgb.r, rgb.g, rgb.b, rgb.a); |
||
740 | |||
741 | |||
742 | parsedcolor.hsl = { |
||
743 | h: hsl.h, |
||
744 | s: hsl.s, |
||
745 | l: hsl.l, |
||
746 | a: hsl.a |
||
747 | }; |
||
748 | parsedcolor.rgb = { |
||
749 | r: rgb.r, |
||
750 | g: rgb.g, |
||
751 | b: rgb.b, |
||
752 | a: rgb.a |
||
753 | }; |
||
754 | |||
755 | |||
756 | parsedcolor.fillColor = rgb.fillColor; |
||
757 | parsedcolor.rgba = rgb.fillColor; |
||
758 | parsedcolor.hsla = hsl.fillColor; |
||
759 | parsedcolor.strokeColor = rgb.strokeColor; |
||
760 | parsedcolor.hex = ['#', padHex(rgb.r.toString(16)), padHex(rgb.g.toString(16)), padHex(rgb.b.toString(16))].join(''); |
||
761 | return parsedcolor; |
||
762 | }, |
||
763 | /** |
||
764 | * Generates an google maps marker (or an image as dataurl from the given options) |
||
765 | * |
||
766 | * @param {Object} options The options |
||
767 | * @return {Object} { description_of_the_return_value } |
||
768 | */ |
||
769 | autoIcon: function (options) { |
||
770 | |||
771 | if (typeof (options) !== 'object') { |
||
772 | console.warn('autoIcon expects an object as its only parameter'); |
||
773 | return null; |
||
774 | } |
||
775 | |||
776 | options.label = String(options.label || 'A'); |
||
777 | options.color = options.color || '#FF0000'; |
||
778 | |||
779 | // unless explicitly set to false, the icon doesn't have a marker-like wrapper |
||
780 | if (options.transparent_background === undefined) { |
||
781 | options.transparent_background = true; |
||
782 | } |
||
783 | |||
784 | if (options.label.length === 4 || options.label.substring(0, 2) === '0x') { |
||
785 | |||
786 | |||
787 | options.font = options.font || 'fontello'; |
||
788 | options.label = (options.label || 'e836').slice(-4); |
||
789 | options.unicodelabel = String.fromCharCode('0x' + options.label); |
||
790 | options.scale = options.scale || 1; |
||
791 | |||
792 | if (options.transparent_background) { |
||
793 | console.log('createTransparentMarkerIcon', options.font); |
||
794 | return MarkerFactory.createTransparentMarkerIcon(options); |
||
795 | } else { |
||
796 | console.log('createFatMarkerIcon', options.font); |
||
797 | return MarkerFactory.createFatMarkerIcon(options); |
||
798 | } |
||
799 | } else if (options.shadow) { |
||
800 | return createClusterIcon(options); |
||
801 | } else { |
||
802 | options.scale = options.scale || 0.75; |
||
803 | options.label = String(options.label || 'A'); |
||
804 | options.fontsize = options.fontsize || 11; |
||
805 | options.font = options.font || 'Arial'; |
||
806 | // This is text I should print literally |
||
807 | return MarkerFactory.createTextMarker(options); |
||
808 | } |
||
809 | |||
810 | } |
||
811 | }; |
||
1 ignored issue
–
show
|
|||
812 | |||
813 | |||
814 | export { |
||
815 | MarkerFactory |
||
816 | }; |
||
817 | export default MarkerFactory; |
This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.
To learn more about declaring variables in Javascript, see the MDN.