Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 1
YUI.add('series-fill-util', function (Y, NAME) {
2
 
3
/**
4
 * Provides functionality for drawing fills in a series.
5
 *
6
 * @module charts
7
 * @submodule series-fill-util
8
 */
9
var Y_Lang = Y.Lang;
10
 
11
/**
12
 * Utility class used for drawing area fills.
13
 *
14
 * @class Fills
15
 * @constructor
16
 * @submodule series-fill-util
17
 */
18
function Fills() {}
19
 
20
Fills.ATTRS = {
21
    area: {
22
        getter: function()
23
        {
24
            return this._defaults || this._getAreaDefaults();
25
        },
26
 
27
        setter: function(val)
28
        {
29
            var defaults = this._defaults || this._getAreaDefaults();
30
            this._defaults = Y.merge(defaults, val);
31
        }
32
    }
33
};
34
 
35
Fills.prototype = {
36
    /**
37
     * Returns a path shape used for drawing fills.
38
     *
39
     * @method _getPath
40
     * @return Path
41
     * @private
42
     */
43
    _getPath: function()
44
    {
45
        var path = this._path;
46
        if(!path)
47
        {
48
            path = this.get("graphic").addShape({type:"path"});
49
            this._path = path;
50
        }
51
        return path;
52
    },
53
 
54
    /**
55
     * Toggles visibility
56
     *
57
     * @method _toggleVisible
58
     * @param {Boolean} visible indicates visibilitye
59
     * @private
60
     */
61
    _toggleVisible: function(visible)
62
    {
63
        if(this._path)
64
        {
65
            this._path.set("visible", visible);
66
        }
67
    },
68
 
69
    /**
70
     * Draws fill
71
     *
72
     * @method drawFill
73
     * @param {Array} xcoords The x-coordinates for the series.
74
     * @param {Array} ycoords The y-coordinates for the series.
75
     * @protected
76
     */
77
    drawFill: function(xcoords, ycoords)
78
    {
79
        if(xcoords.length < 1)
80
        {
81
            return;
82
        }
83
        var isNumber = Y_Lang.isNumber,
84
            len = xcoords.length,
85
            firstX = xcoords[0],
86
            firstY = ycoords[0],
87
            lastValidX = firstX,
88
            lastValidY = firstY,
89
            nextX,
90
            nextY,
91
            pointValid,
92
            noPointsRendered = true,
93
            i = 0,
94
            styles = this.get("styles").area,
95
            path = this._getPath(),
96
            color = styles.color || this._getDefaultColor(this.get("graphOrder"), "slice");
97
        path.clear();
98
        path.set("fill", {
99
            color: color,
100
            opacity: styles.alpha
101
        });
102
        path.set("stroke", {weight: 0});
103
        for(; i < len; i = ++i)
104
        {
105
            nextX = xcoords[i];
106
            nextY = ycoords[i];
107
            pointValid = isNumber(nextX) && isNumber(nextY);
108
            if(!pointValid)
109
            {
110
                continue;
111
            }
112
            if(noPointsRendered)
113
            {
114
                this._firstValidX = nextX;
115
                this._firstValidY = nextY;
116
                noPointsRendered = false;
117
                path.moveTo(nextX, nextY);
118
            }
119
            else
120
            {
121
                path.lineTo(nextX, nextY);
122
            }
123
            lastValidX = nextX;
124
            lastValidY = nextY;
125
        }
126
        this._lastValidX = lastValidX;
127
        this._lastValidY = lastValidY;
128
        path.end();
129
    },
130
 
131
    /**
132
     * Draws a fill for a spline
133
     *
134
     * @method drawAreaSpline
135
     * @protected
136
     */
137
    drawAreaSpline: function()
138
    {
139
        if(this.get("xcoords").length < 1)
140
        {
141
            return;
142
        }
143
        var xcoords = this.get("xcoords"),
144
            ycoords = this.get("ycoords"),
145
            curvecoords = this.getCurveControlPoints(xcoords, ycoords),
146
            len = curvecoords.length,
147
            cx1,
148
            cx2,
149
            cy1,
150
            cy2,
151
            x,
152
            y,
153
            i = 0,
154
            firstX = xcoords[0],
155
            firstY = ycoords[0],
156
            styles = this.get("styles").area,
157
            path = this._getPath(),
158
            color = styles.color || this._getDefaultColor(this.get("graphOrder"), "slice");
159
        path.set("fill", {
160
            color: color,
161
            opacity: styles.alpha
162
        });
163
        path.set("stroke", {weight: 0});
164
        path.moveTo(firstX, firstY);
165
        for(; i < len; i = ++i)
166
        {
167
            x = curvecoords[i].endx;
168
            y = curvecoords[i].endy;
169
            cx1 = curvecoords[i].ctrlx1;
170
            cx2 = curvecoords[i].ctrlx2;
171
            cy1 = curvecoords[i].ctrly1;
172
            cy2 = curvecoords[i].ctrly2;
173
            path.curveTo(cx1, cy1, cx2, cy2, x, y);
174
        }
175
        if(this.get("direction") === "vertical")
176
        {
177
            path.lineTo(this._leftOrigin, y);
178
            path.lineTo(this._leftOrigin, firstY);
179
        }
180
        else
181
        {
182
            path.lineTo(x, this._bottomOrigin);
183
            path.lineTo(firstX, this._bottomOrigin);
184
        }
185
        path.lineTo(firstX, firstY);
186
        path.end();
187
    },
188
 
189
    /**
190
     * Draws a a stacked area spline
191
     *
192
     * @method drawStackedAreaSpline
193
     * @protected
194
     */
195
    drawStackedAreaSpline: function()
196
    {
197
        if(this.get("xcoords").length < 1)
198
        {
199
            return;
200
        }
201
        var xcoords = this.get("xcoords"),
202
            ycoords = this.get("ycoords"),
203
            curvecoords,
204
            order = this.get("order"),
205
            seriesCollection = this.get("seriesTypeCollection"),
206
            prevXCoords,
207
            prevYCoords,
208
            len,
209
            cx1,
210
            cx2,
211
            cy1,
212
            cy2,
213
            x,
214
            y,
215
            i = 0,
216
            firstX,
217
            firstY,
218
            styles = this.get("styles").area,
219
            path = this._getPath(),
220
            color = styles.color || this._getDefaultColor(this.get("graphOrder"), "slice");
221
        firstX = xcoords[0];
222
        firstY = ycoords[0];
223
        curvecoords = this.getCurveControlPoints(xcoords, ycoords);
224
        len = curvecoords.length;
225
        path.set("fill", {
226
            color: color,
227
            opacity: styles.alpha
228
        });
229
        path.set("stroke", {weight: 0});
230
        path.moveTo(firstX, firstY);
231
        for(; i < len; i = ++i)
232
        {
233
            x = curvecoords[i].endx;
234
            y = curvecoords[i].endy;
235
            cx1 = curvecoords[i].ctrlx1;
236
            cx2 = curvecoords[i].ctrlx2;
237
            cy1 = curvecoords[i].ctrly1;
238
            cy2 = curvecoords[i].ctrly2;
239
            path.curveTo(cx1, cy1, cx2, cy2, x, y);
240
        }
241
        if(order > 0)
242
        {
243
            prevXCoords = seriesCollection[order - 1].get("xcoords").concat().reverse();
244
            prevYCoords = seriesCollection[order - 1].get("ycoords").concat().reverse();
245
            curvecoords = this.getCurveControlPoints(prevXCoords, prevYCoords);
246
            i = 0;
247
            len = curvecoords.length;
248
            path.lineTo(prevXCoords[0], prevYCoords[0]);
249
            for(; i < len; i = ++i)
250
            {
251
                x = curvecoords[i].endx;
252
                y = curvecoords[i].endy;
253
                cx1 = curvecoords[i].ctrlx1;
254
                cx2 = curvecoords[i].ctrlx2;
255
                cy1 = curvecoords[i].ctrly1;
256
                cy2 = curvecoords[i].ctrly2;
257
                path.curveTo(cx1, cy1, cx2, cy2, x, y);
258
            }
259
        }
260
        else
261
        {
262
            if(this.get("direction") === "vertical")
263
            {
264
                path.lineTo(this._leftOrigin, ycoords[ycoords.length-1]);
265
                path.lineTo(this._leftOrigin, firstY);
266
            }
267
            else
268
            {
269
                path.lineTo(xcoords[xcoords.length-1], this._bottomOrigin);
270
                path.lineTo(firstX, this._bottomOrigin);
271
            }
272
 
273
        }
274
        path.lineTo(firstX, firstY);
275
        path.end();
276
    },
277
 
278
    /**
279
     * Storage for default area styles.
280
     *
281
     * @property _defaults
282
     * @type Object
283
     * @private
284
     */
285
    _defaults: null,
286
 
287
    /**
288
     * Concatenates coordinate array with correct coordinates for closing an area fill.
289
     *
290
     * @method _getClosingPoints
291
     * @return Array
292
     * @protected
293
     */
294
    _getClosingPoints: function()
295
    {
296
        var xcoords = this.get("xcoords").concat(),
297
            ycoords = this.get("ycoords").concat(),
298
            firstValidIndex,
299
            lastValidIndex;
300
        if(this.get("direction") === "vertical")
301
        {
302
            lastValidIndex = this._getLastValidIndex(xcoords);
303
            firstValidIndex = this._getFirstValidIndex(xcoords);
304
            ycoords.push(ycoords[lastValidIndex]);
305
            ycoords.push(ycoords[firstValidIndex]);
306
            xcoords.push(this._leftOrigin);
307
            xcoords.push(this._leftOrigin);
308
        }
309
        else
310
        {
311
            lastValidIndex = this._getLastValidIndex(ycoords);
312
            firstValidIndex = this._getFirstValidIndex(ycoords);
313
            xcoords.push(xcoords[lastValidIndex]);
314
            xcoords.push(xcoords[firstValidIndex]);
315
            ycoords.push(this._bottomOrigin);
316
            ycoords.push(this._bottomOrigin);
317
        }
318
        xcoords.push(xcoords[0]);
319
        ycoords.push(ycoords[0]);
320
        return [xcoords, ycoords];
321
    },
322
 
323
    /**
324
     * Returns the order of the series closest to the current series that has a valid value for the current index.
325
     *
326
     * @method _getHighestValidOrder
327
     * @param {Array} seriesCollection Array of series of a given type.
328
     * @param {Number} index Index of the series item.
329
     * @param {Number} order Index of the the series in the seriesCollection
330
     * @param {String} direction Indicates the direction of the series
331
     * @return Number
332
     * @private
333
     */
334
    _getHighestValidOrder: function(seriesCollection, index, order, direction)
335
    {
336
        var coords = direction === "vertical" ? "stackedXCoords" : "stackedYCoords",
337
            coord;
338
        while(isNaN(coord) && order > -1)
339
        {
340
          order = order - 1;
341
          if(order > -1)
342
          {
343
            coord = seriesCollection[order].get(coords)[index];
344
          }
345
        }
346
        return order;
347
    },
348
 
349
    /**
350
     * Returns an array containing the x and y coordinates for a given series and index.
351
     *
352
     * @method _getCoordsByOrderAndIndex
353
     * @param {Array} seriesCollection Array of series of a given type.
354
     * @param {Number} index Index of the series item.
355
     * @param {Number} order Index of the the series in the seriesCollection
356
     * @param {String} direction Indicates the direction of the series
357
     * @return Array
358
     * @private
359
     */
360
    _getCoordsByOrderAndIndex: function(seriesCollection, index, order, direction)
361
    {
362
        var xcoord,
363
            ycoord;
364
        if(direction === "vertical")
365
        {
366
            xcoord = order < 0 ? this._leftOrigin : seriesCollection[order].get("stackedXCoords")[index];
367
            ycoord = this.get("stackedYCoords")[index];
368
        }
369
        else
370
        {
371
            xcoord = this.get("stackedXCoords")[index];
372
            ycoord = order < 0 ? this._bottomOrigin : seriesCollection[order].get("stackedYCoords")[index];
373
        }
374
        return [xcoord, ycoord];
375
    },
376
 
377
    /**
378
     * Concatenates coordinate array with the correct coordinates for closing an area stack.
379
     *
380
     * @method _getStackedClosingPoints
381
     * @return Array
382
     * @protected
383
     */
384
    _getStackedClosingPoints: function()
385
    {
386
        var order = this.get("order"),
387
            direction = this.get("direction"),
388
            seriesCollection = this.get("seriesTypeCollection"),
389
            firstValidIndex,
390
            lastValidIndex,
391
            xcoords = this.get("stackedXCoords"),
392
            ycoords = this.get("stackedYCoords"),
393
            limit,
394
            previousSeries,
395
            previousSeriesFirstValidIndex,
396
            previousSeriesLastValidIndex,
397
            previousXCoords,
398
            previousYCoords,
399
            coords,
400
            closingXCoords,
401
            closingYCoords,
402
            currentIndex,
403
            highestValidOrder,
404
            oldOrder;
405
        if(order < 1)
406
        {
407
          return this._getClosingPoints();
408
        }
409
 
410
        previousSeries = seriesCollection[order - 1];
411
        previousXCoords = previousSeries.get("stackedXCoords").concat();
412
        previousYCoords = previousSeries.get("stackedYCoords").concat();
413
        if(direction === "vertical")
414
        {
415
            firstValidIndex = this._getFirstValidIndex(xcoords);
416
            lastValidIndex = this._getLastValidIndex(xcoords);
417
            previousSeriesFirstValidIndex = previousSeries._getFirstValidIndex(previousXCoords);
418
            previousSeriesLastValidIndex = previousSeries._getLastValidIndex(previousXCoords);
419
        }
420
        else
421
        {
422
            firstValidIndex = this._getFirstValidIndex(ycoords);
423
            lastValidIndex = this._getLastValidIndex(ycoords);
424
            previousSeriesFirstValidIndex = previousSeries._getFirstValidIndex(previousYCoords);
425
            previousSeriesLastValidIndex = previousSeries._getLastValidIndex(previousYCoords);
426
        }
427
        if(previousSeriesLastValidIndex >= firstValidIndex && previousSeriesFirstValidIndex <= lastValidIndex)
428
        {
429
            previousSeriesFirstValidIndex = Math.max(firstValidIndex, previousSeriesFirstValidIndex);
430
            previousSeriesLastValidIndex = Math.min(lastValidIndex, previousSeriesLastValidIndex);
431
            previousXCoords = previousXCoords.slice(previousSeriesFirstValidIndex, previousSeriesLastValidIndex + 1);
432
            previousYCoords = previousYCoords.slice(previousSeriesFirstValidIndex, previousSeriesLastValidIndex + 1);
433
            limit = previousSeriesFirstValidIndex;
434
        }
435
        else
436
        {
437
            limit = lastValidIndex;
438
        }
439
 
440
        closingXCoords = [xcoords[firstValidIndex]];
441
        closingYCoords = [ycoords[firstValidIndex]];
442
        currentIndex = firstValidIndex;
443
        while((isNaN(highestValidOrder) || highestValidOrder < order - 1) && currentIndex <= limit)
444
        {
445
            oldOrder = highestValidOrder;
446
            highestValidOrder = this._getHighestValidOrder(seriesCollection, currentIndex, order, direction);
447
            if(!isNaN(oldOrder) && highestValidOrder > oldOrder)
448
            {
449
                coords = this._getCoordsByOrderAndIndex(seriesCollection, currentIndex, oldOrder, direction);
450
                closingXCoords.push(coords[0]);
451
                closingYCoords.push(coords[1]);
452
            }
453
            coords = this._getCoordsByOrderAndIndex(seriesCollection, currentIndex, highestValidOrder, direction);
454
            closingXCoords.push(coords[0]);
455
            closingYCoords.push(coords[1]);
456
            currentIndex = currentIndex + 1;
457
        }
458
        if(previousXCoords &&
459
            previousXCoords.length > 0 &&
460
            previousSeriesLastValidIndex > firstValidIndex &&
461
            previousSeriesFirstValidIndex < lastValidIndex)
462
        {
463
            closingXCoords = closingXCoords.concat(previousXCoords);
464
            closingYCoords = closingYCoords.concat(previousYCoords);
465
            highestValidOrder = order -1;
466
        }
467
        currentIndex = Math.max(firstValidIndex, previousSeriesLastValidIndex);
468
        order = order - 1;
469
        highestValidOrder = NaN;
470
        while(currentIndex <= lastValidIndex)
471
        {
472
            oldOrder = highestValidOrder;
473
            highestValidOrder = this._getHighestValidOrder(seriesCollection, currentIndex, order, direction);
474
            if(!isNaN(oldOrder))
475
            {
476
                if(highestValidOrder > oldOrder)
477
                {
478
                    coords = this._getCoordsByOrderAndIndex(seriesCollection, currentIndex, oldOrder, direction);
479
                    closingXCoords.push(coords[0]);
480
                    closingYCoords.push(coords[1]);
481
                }
482
                else if(highestValidOrder < oldOrder)
483
                {
484
                    coords = this._getCoordsByOrderAndIndex(seriesCollection, currentIndex - 1, highestValidOrder, direction);
485
                    closingXCoords.push(coords[0]);
486
                    closingYCoords.push(coords[1]);
487
                }
488
            }
489
            coords = this._getCoordsByOrderAndIndex(seriesCollection, currentIndex, highestValidOrder, direction);
490
            closingXCoords.push(coords[0]);
491
            closingYCoords.push(coords[1]);
492
            currentIndex = currentIndex + 1;
493
        }
494
 
495
        closingXCoords.reverse();
496
        closingYCoords.reverse();
497
        return [xcoords.concat(closingXCoords), ycoords.concat(closingYCoords)];
498
    },
499
 
500
    /**
501
     * Returns default values for area styles.
502
     *
503
     * @method _getAreaDefaults
504
     * @return Object
505
     * @private
506
     */
507
    _getAreaDefaults: function()
508
    {
509
        return {
510
        };
511
    }
512
};
513
Y.augment(Fills, Y.Attribute);
514
Y.Fills = Fills;
515
 
516
 
517
}, '3.18.1');