[ Index ] |
PHP Cross Reference of Unnamed Project |
[Summary view] [Print] [Text view]
1 /* 2 YUI 3.17.2 (build 9c3c78e) 3 Copyright 2014 Yahoo! Inc. All rights reserved. 4 Licensed under the BSD License. 5 http://yuilibrary.com/license/ 6 */ 7 8 YUI.add('series-pie', function (Y, NAME) { 9 10 /** 11 * Provides functionality for creating a pie series. 12 * 13 * @module charts 14 * @submodule series-pie 15 */ 16 /** 17 * PieSeries visualizes data as a circular chart divided into wedges which represent data as a 18 * percentage of a whole. 19 * 20 * @class PieSeries 21 * @constructor 22 * @extends SeriesBase 23 * @uses Plots 24 * @param {Object} config (optional) Configuration parameters. 25 * @submodule series-pie 26 */ 27 var CONFIG = Y.config, 28 DOCUMENT = CONFIG.doc, 29 _getClassName = Y.ClassNameManager.getClassName, 30 SERIES_MARKER = _getClassName("seriesmarker"); 31 Y.PieSeries = Y.Base.create("pieSeries", Y.SeriesBase, [Y.Plots], { 32 /** 33 * Image map used for interactivity when rendered with canvas. 34 * 35 * @property _map 36 * @type HTMLElement 37 * @private 38 */ 39 _map: null, 40 41 /** 42 * Image used for image map when rendered with canvas. 43 * 44 * @property _image 45 * @type HTMLElement 46 * @private 47 */ 48 _image: null, 49 50 /** 51 * Creates or updates the image map when rendered with canvas. 52 * 53 * @method _setMap 54 * @private 55 */ 56 _setMap: function() 57 { 58 var id = "pieHotSpotMapi_" + Math.round(100000 * Math.random()), 59 graph = this.get("graph"), 60 graphic, 61 cb, 62 areaNode; 63 if(graph) 64 { 65 cb = graph.get("contentBox"); 66 } 67 else 68 { 69 graphic = this.get("graphic"); 70 cb = graphic.get("node"); 71 } 72 if(this._image) 73 { 74 cb.removeChild(this._image); 75 while(this._areaNodes && this._areaNodes.length > 0) 76 { 77 areaNode = this._areaNodes.shift(); 78 this._map.removeChild(areaNode); 79 } 80 cb.removeChild(this._map); 81 } 82 this._image = DOCUMENT.createElement("img"); 83 this._image.src = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAYAAAABCAYAAAD9yd/wAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSB" + 84 "JbWFnZVJlYWR5ccllPAAAABJJREFUeNpiZGBgSGPAAgACDAAIkABoFyloZQAAAABJRU5ErkJggg=="; 85 cb.appendChild(this._image); 86 this._image.style.position = "absolute"; 87 this._image.style.left = "0px"; 88 this._image.style.top = "0px"; 89 this._image.setAttribute("usemap", "#" + id); 90 this._image.style.zIndex = 3; 91 this._image.style.opacity = 0; 92 this._image.setAttribute("alt", "imagemap"); 93 this._map = DOCUMENT.createElement("map"); 94 cb.appendChild(this._map); 95 this._map.setAttribute("name", id); 96 this._map.setAttribute("id", id); 97 this._areaNodes = []; 98 }, 99 100 /** 101 * Storage for `categoryDisplayName` attribute. 102 * 103 * @property _categoryDisplayName 104 * @private 105 */ 106 _categoryDisplayName: null, 107 108 /** 109 * Storage for `valueDisplayName` attribute. 110 * 111 * @property _valueDisplayName 112 * @private 113 */ 114 _valueDisplayName: null, 115 116 /** 117 * Adds event listeners. 118 * 119 * @method addListeners 120 * @private 121 */ 122 addListeners: function() 123 { 124 var categoryAxis = this.get("categoryAxis"), 125 valueAxis = this.get("valueAxis"); 126 if(categoryAxis) 127 { 128 categoryAxis.after("dataReady", Y.bind(this._categoryDataChangeHandler, this)); 129 categoryAxis.after("dataUpdate", Y.bind(this._categoryDataChangeHandler, this)); 130 } 131 if(valueAxis) 132 { 133 valueAxis.after("dataReady", Y.bind(this._valueDataChangeHandler, this)); 134 valueAxis.after("dataUpdate", Y.bind(this._valueDataChangeHandler, this)); 135 } 136 this.after("categoryAxisChange", this.categoryAxisChangeHandler); 137 this.after("valueAxisChange", this.valueAxisChangeHandler); 138 this._stylesChangeHandle = this.after("stylesChange", this._updateHandler); 139 this._visibleChangeHandle = this.after("visibleChange", this._handleVisibleChange); 140 }, 141 142 /** 143 * Draws the series. 144 * 145 * @method validate 146 * @private 147 */ 148 validate: function() 149 { 150 this.draw(); 151 this._renderered = true; 152 }, 153 154 /** 155 * Event handler for the categoryAxisChange event. 156 * 157 * @method _categoryAxisChangeHandler 158 * @param {Object} e Event object. 159 * @private 160 */ 161 _categoryAxisChangeHandler: function() 162 { 163 var categoryAxis = this.get("categoryAxis"); 164 categoryAxis.after("dataReady", Y.bind(this._categoryDataChangeHandler, this)); 165 categoryAxis.after("dataUpdate", Y.bind(this._categoryDataChangeHandler, this)); 166 }, 167 168 /** 169 * Event handler for the valueAxisChange event. 170 * 171 * @method _valueAxisChangeHandler 172 * @param {Object} e Event object. 173 * @private 174 */ 175 _valueAxisChangeHandler: function() 176 { 177 var valueAxis = this.get("valueAxis"); 178 valueAxis.after("dataReady", Y.bind(this._valueDataChangeHandler, this)); 179 valueAxis.after("dataUpdate", Y.bind(this._valueDataChangeHandler, this)); 180 }, 181 182 /** 183 * Constant used to generate unique id. 184 * 185 * @property GUID 186 * @type String 187 * @private 188 */ 189 GUID: "pieseries", 190 191 /** 192 * Event handler for categoryDataChange event. 193 * 194 * @method _categoryDataChangeHandler 195 * @param {Object} event Event object. 196 * @private 197 */ 198 _categoryDataChangeHandler: function() 199 { 200 if(this._rendered && this.get("categoryKey") && this.get("valueKey")) 201 { 202 this.draw(); 203 } 204 }, 205 206 /** 207 * Event handler for valueDataChange event. 208 * 209 * @method _valueDataChangeHandler 210 * @param {Object} event Event object. 211 * @private 212 */ 213 _valueDataChangeHandler: function() 214 { 215 if(this._rendered && this.get("categoryKey") && this.get("valueKey")) 216 { 217 this.draw(); 218 } 219 }, 220 221 /** 222 * Returns the sum of all values for the series. 223 * 224 * @method getTotalValues 225 * @return Number 226 */ 227 getTotalValues: function() 228 { 229 var total = this.get("valueAxis").getTotalByKey(this.get("valueKey")); 230 return total; 231 }, 232 233 /** 234 * Draws the series. Overrides the base implementation. 235 * 236 * @method draw 237 * @protected 238 */ 239 draw: function() 240 { 241 var w = this.get("width"), 242 h = this.get("height"); 243 if(isFinite(w) && isFinite(h) && w > 0 && h > 0) 244 { 245 this._rendered = true; 246 if(this._drawing) 247 { 248 this._callLater = true; 249 return; 250 } 251 this._drawing = true; 252 this._callLater = false; 253 this.drawSeries(); 254 this._drawing = false; 255 if(this._callLater) 256 { 257 this.draw(); 258 } 259 else 260 { 261 this.fire("drawingComplete"); 262 } 263 } 264 }, 265 266 /** 267 * Draws the markers 268 * 269 * @method drawPlots 270 * @protected 271 */ 272 drawPlots: function() 273 { 274 var values = this.get("valueAxis").getDataByKey(this.get("valueKey")).concat(), 275 totalValue = 0, 276 itemCount = values.length, 277 styles = this.get("styles").marker, 278 fillColors = styles.fill.colors, 279 fillAlphas = styles.fill.alphas || ["1"], 280 borderColors = styles.border.colors, 281 borderWeights = [styles.border.weight], 282 borderAlphas = [styles.border.alpha], 283 tbw = borderWeights.concat(), 284 tbc = borderColors.concat(), 285 tba = borderAlphas.concat(), 286 tfc, 287 tfa, 288 padding = styles.padding, 289 graphic = this.get("graphic"), 290 minDimension = Math.min(graphic.get("width"), graphic.get("height")), 291 w = minDimension - (padding.left + padding.right), 292 h = minDimension - (padding.top + padding.bottom), 293 startAngle = -90, 294 halfWidth = w / 2, 295 halfHeight = h / 2, 296 radius = Math.min(halfWidth, halfHeight), 297 i = 0, 298 value, 299 angle = 0, 300 lc, 301 la, 302 lw, 303 wedgeStyle, 304 marker, 305 graphOrder = this.get("graphOrder") || 0, 306 isCanvas = Y.Graphic.NAME === "canvasGraphic"; 307 for(; i < itemCount; ++i) 308 { 309 value = parseFloat(values[i]); 310 311 values.push(value); 312 if(!isNaN(value)) 313 { 314 totalValue += value; 315 } 316 } 317 318 tfc = fillColors ? fillColors.concat() : null; 319 tfa = fillAlphas ? fillAlphas.concat() : null; 320 this._createMarkerCache(); 321 if(isCanvas) 322 { 323 this._setMap(); 324 this._image.width = w; 325 this._image.height = h; 326 } 327 for(i = 0; i < itemCount; i++) 328 { 329 value = values[i]; 330 if(totalValue === 0) 331 { 332 angle = 360 / values.length; 333 } 334 else 335 { 336 angle = 360 * (value / totalValue); 337 } 338 if(tfc && tfc.length < 1) 339 { 340 tfc = fillColors.concat(); 341 } 342 if(tfa && tfa.length < 1) 343 { 344 tfa = fillAlphas.concat(); 345 } 346 if(tbw && tbw.length < 1) 347 { 348 tbw = borderWeights.concat(); 349 } 350 if(tbw && tbc.length < 1) 351 { 352 tbc = borderColors.concat(); 353 } 354 if(tba && tba.length < 1) 355 { 356 tba = borderAlphas.concat(); 357 } 358 lw = tbw ? tbw.shift() : null; 359 lc = tbc ? tbc.shift() : null; 360 la = tba ? tba.shift() : null; 361 startAngle += angle; 362 wedgeStyle = { 363 border: { 364 color:lc, 365 weight:lw, 366 alpha:la 367 }, 368 fill: { 369 color:tfc ? tfc.shift() : this._getDefaultColor(i, "slice"), 370 alpha:tfa ? tfa.shift() : null 371 }, 372 type: "pieslice", 373 arc: angle, 374 radius: radius, 375 startAngle: startAngle, 376 cx: halfWidth, 377 cy: halfHeight, 378 width: w, 379 height: h 380 }; 381 marker = this.getMarker(wedgeStyle, graphOrder, i); 382 if(isCanvas) 383 { 384 this._addHotspot(wedgeStyle, graphOrder, i); 385 } 386 } 387 this._clearMarkerCache(); 388 }, 389 390 /** 391 * @protected 392 * 393 * Method used by `styles` setter. Overrides base implementation. 394 * 395 * @method _setStyles 396 * @param {Object} newStyles Hash of properties to update. 397 * @return Object 398 */ 399 _setStyles: function(val) 400 { 401 if(!val.marker) 402 { 403 val = {marker:val}; 404 } 405 val = this._parseMarkerStyles(val); 406 return Y.PieSeries.superclass._mergeStyles.apply(this, [val, this._getDefaultStyles()]); 407 }, 408 409 /** 410 * Adds an interactive map when rendering in canvas. 411 * 412 * @method _addHotspot 413 * @param {Object} cfg Object containing data used to draw the hotspot 414 * @param {Number} seriesIndex Index of series in the `seriesCollection`. 415 * @param {Number} index Index of the marker using the hotspot. 416 * @private 417 */ 418 _addHotspot: function(cfg, seriesIndex, index) 419 { 420 var areaNode = DOCUMENT.createElement("area"), 421 i = 1, 422 x = cfg.cx, 423 y = cfg.cy, 424 arc = cfg.arc, 425 startAngle = cfg.startAngle - arc, 426 endAngle = cfg.startAngle, 427 radius = cfg.radius, 428 ax = x + Math.cos(startAngle / 180 * Math.PI) * radius, 429 ay = y + Math.sin(startAngle / 180 * Math.PI) * radius, 430 bx = x + Math.cos(endAngle / 180 * Math.PI) * radius, 431 by = y + Math.sin(endAngle / 180 * Math.PI) * radius, 432 numPoints = Math.floor(arc/10) - 1, 433 divAngle = (arc/(Math.floor(arc/10)) / 180) * Math.PI, 434 angleCoord = Math.atan((ay - y)/(ax - x)), 435 pts = x + ", " + y + ", " + ax + ", " + ay, 436 cosAng, 437 sinAng, 438 multDivAng; 439 for(i = 1; i <= numPoints; ++i) 440 { 441 multDivAng = divAngle * i; 442 cosAng = Math.cos(angleCoord + multDivAng); 443 sinAng = Math.sin(angleCoord + multDivAng); 444 if(startAngle <= 90) 445 { 446 pts += ", " + (x + (radius * Math.cos(angleCoord + (divAngle * i)))); 447 pts += ", " + (y + (radius * Math.sin(angleCoord + (divAngle * i)))); 448 } 449 else 450 { 451 pts += ", " + (x - (radius * Math.cos(angleCoord + (divAngle * i)))); 452 pts += ", " + (y - (radius * Math.sin(angleCoord + (divAngle * i)))); 453 } 454 } 455 pts += ", " + bx + ", " + by; 456 pts += ", " + x + ", " + y; 457 this._map.appendChild(areaNode); 458 areaNode.setAttribute("class", SERIES_MARKER); 459 areaNode.setAttribute("id", "hotSpot_" + seriesIndex + "_" + index); 460 areaNode.setAttribute("shape", "polygon"); 461 areaNode.setAttribute("coords", pts); 462 this._areaNodes.push(areaNode); 463 464 }, 465 466 /** 467 * Resizes and positions markers based on a mouse interaction. 468 * 469 * @method updateMarkerState 470 * @param {String} type state of the marker 471 * @param {Number} i index of the marker 472 * @protected 473 */ 474 updateMarkerState: function(type, i) 475 { 476 if(this._markers[i]) 477 { 478 var state = this._getState(type), 479 markerStyles, 480 indexStyles, 481 marker = this._markers[i], 482 styles = this.get("styles").marker; 483 markerStyles = state === "off" || !styles[state] ? styles : styles[state]; 484 indexStyles = this._mergeStyles(markerStyles, {}); 485 indexStyles.fill.color = indexStyles.fill.colors[i % indexStyles.fill.colors.length]; 486 indexStyles.fill.alpha = indexStyles.fill.alphas[i % indexStyles.fill.alphas.length]; 487 marker.set(indexStyles); 488 } 489 }, 490 491 /** 492 * Creates a shape to be used as a marker. 493 * 494 * @method _createMarker 495 * @param {Object} styles Hash of style properties. 496 * @return Shape 497 * @private 498 */ 499 _createMarker: function(styles) 500 { 501 var graphic = this.get("graphic"), 502 marker, 503 cfg = this._copyObject(styles); 504 marker = graphic.addShape(cfg); 505 marker.addClass(SERIES_MARKER); 506 return marker; 507 }, 508 509 /** 510 * Creates a cache of markers for reuse. 511 * 512 * @method _createMarkerCache 513 * @private 514 */ 515 _clearMarkerCache: function() 516 { 517 var len = this._markerCache.length, 518 i = 0, 519 marker; 520 for(; i < len; ++i) 521 { 522 marker = this._markerCache[i]; 523 if(marker) 524 { 525 marker.destroy(); 526 } 527 } 528 this._markerCache = []; 529 }, 530 531 /** 532 * Gets the default style values for the markers. 533 * 534 * @method _getPlotDefaults 535 * @return Object 536 * @private 537 */ 538 _getPlotDefaults: function() 539 { 540 var defs = { 541 padding:{ 542 top: 0, 543 left: 0, 544 right: 0, 545 bottom: 0 546 }, 547 fill:{ 548 alphas:["1"] 549 }, 550 border: { 551 weight: 0, 552 alpha: 1 553 } 554 }; 555 defs.fill.colors = this._defaultSliceColors; 556 defs.border.colors = this._defaultBorderColors; 557 return defs; 558 } 559 }, { 560 ATTRS: { 561 /** 562 * Read-only attribute indicating the type of series. 563 * 564 * @attribute type 565 * @type String 566 * @default pie 567 */ 568 type: { 569 value: "pie" 570 }, 571 572 /** 573 * Order of this instance of this `type`. 574 * 575 * @attribute order 576 * @type Number 577 */ 578 order: {}, 579 580 /** 581 * Reference to the `Graph` in which the series is drawn into. 582 * 583 * @attribute graph 584 * @type Graph 585 */ 586 graph: {}, 587 588 /** 589 * Reference to the `Axis` instance used for assigning 590 * category values to the graph. 591 * 592 * @attribute categoryAxis 593 * @type Axis 594 */ 595 categoryAxis: { 596 value: null, 597 598 validator: function(value) 599 { 600 return value !== this.get("categoryAxis"); 601 } 602 }, 603 604 /** 605 * Reference to the `Axis` instance used for assigning 606 * series values to the graph. 607 * 608 * @attribute categoryAxis 609 * @type Axis 610 */ 611 valueAxis: { 612 value: null, 613 614 validator: function(value) 615 { 616 return value !== this.get("valueAxis"); 617 } 618 }, 619 620 /** 621 * Indicates which array to from the hash of value arrays in 622 * the category `Axis` instance. 623 * 624 * @attribute categoryKey 625 * @type String 626 */ 627 categoryKey: { 628 value: null, 629 630 validator: function(value) 631 { 632 return value !== this.get("categoryKey"); 633 } 634 }, 635 /** 636 * Indicates which array to from the hash of value arrays in 637 * the value `Axis` instance. 638 * 639 * @attribute valueKey 640 * @type String 641 */ 642 valueKey: { 643 value: null, 644 645 validator: function(value) 646 { 647 return value !== this.get("valueKey"); 648 } 649 }, 650 651 /** 652 * Name used for for displaying category data 653 * 654 * @attribute categoryDisplayName 655 * @type String 656 */ 657 categoryDisplayName: { 658 setter: function(val) 659 { 660 this._categoryDisplayName = val; 661 return val; 662 }, 663 664 getter: function() 665 { 666 return this._categoryDisplayName || this.get("categoryKey"); 667 } 668 }, 669 670 /** 671 * Name used for for displaying value data 672 * 673 * @attribute valueDisplayName 674 * @type String 675 */ 676 valueDisplayName: { 677 setter: function(val) 678 { 679 this._valueDisplayName = val; 680 return val; 681 }, 682 683 getter: function() 684 { 685 return this._valueDisplayName || this.get("valueKey"); 686 } 687 }, 688 689 /** 690 * @attribute slices 691 * @type Array 692 * @private 693 */ 694 slices: null 695 696 /** 697 * Style properties used for drawing markers. This attribute is inherited from `MarkerSeries`. Below are the default 698 * values: 699 * <dl> 700 * <dt>fill</dt><dd>A hash containing the following values: 701 * <dl> 702 * <dt>colors</dt><dd>An array of colors to be used for the marker fills. The color for each marker is 703 * retrieved from the array below:<br/> 704 * `["#66007f", "#a86f41", "#295454", "#996ab2", "#e8cdb7", "#90bdbd","#000000","#c3b8ca", "#968373", "#678585"]` 705 * </dd> 706 * <dt>alphas</dt><dd>An array of alpha references (Number from 0 to 1) indicating the opacity of each marker 707 * fill. The default value is [1].</dd> 708 * </dl> 709 * </dd> 710 * <dt>border</dt><dd>A hash containing the following values: 711 * <dl> 712 * <dt>color</dt><dd>An array of colors to be used for the marker borders. The color for each marker is 713 * retrieved from the array below:<br/> 714 * `["#205096", "#b38206", "#000000", "#94001e", "#9d6fa0", "#e55b00", "#5e85c9", "#adab9e", "#6ac291", "#006457"]` 715 * <dt>alpha</dt><dd>Number from 0 to 1 indicating the opacity of the marker border. The default value is 1.</dd> 716 * <dt>weight</dt><dd>Number indicating the width of the border. The default value is 1.</dd> 717 * </dl> 718 * </dd> 719 * <dt>over</dt><dd>hash containing styles for markers when highlighted by a `mouseover` event. The default 720 * values for each style is null. When an over style is not set, the non-over value will be used. For example, 721 * the default value for `marker.over.fill.color` is equivalent to `marker.fill.color`.</dd> 722 * </dl> 723 * 724 * @attribute styles 725 * @type Object 726 */ 727 } 728 }); 729 730 731 }, '3.17.2', {"requires": ["series-base", "series-plot-util"]});
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Thu Aug 11 10:00:09 2016 | Cross-referenced by PHPXref 0.7.1 |