AutorÃa | Ultima modificación | Ver Log |
YUI.add('series-pie', function (Y, NAME) {/*** Provides functionality for creating a pie series.** @module charts* @submodule series-pie*//*** PieSeries visualizes data as a circular chart divided into wedges which represent data as a* percentage of a whole.** @class PieSeries* @constructor* @extends SeriesBase* @uses Plots* @param {Object} config (optional) Configuration parameters.* @submodule series-pie*/var CONFIG = Y.config,DOCUMENT = CONFIG.doc,_getClassName = Y.ClassNameManager.getClassName,SERIES_MARKER = _getClassName("seriesmarker");Y.PieSeries = Y.Base.create("pieSeries", Y.SeriesBase, [Y.Plots], {/*** Image map used for interactivity when rendered with canvas.** @property _map* @type HTMLElement* @private*/_map: null,/*** Image used for image map when rendered with canvas.** @property _image* @type HTMLElement* @private*/_image: null,/*** Creates or updates the image map when rendered with canvas.** @method _setMap* @private*/_setMap: function(){var id = "pieHotSpotMapi_" + Math.round(100000 * Math.random()),graph = this.get("graph"),graphic,cb,areaNode;if(graph){cb = graph.get("contentBox");}else{graphic = this.get("graphic");cb = graphic.get("node");}if(this._image){cb.removeChild(this._image);while(this._areaNodes && this._areaNodes.length > 0){areaNode = this._areaNodes.shift();this._map.removeChild(areaNode);}cb.removeChild(this._map);}this._image = DOCUMENT.createElement("img");this._image.src = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAYAAAABCAYAAAD9yd/wAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSB" +"JbWFnZVJlYWR5ccllPAAAABJJREFUeNpiZGBgSGPAAgACDAAIkABoFyloZQAAAABJRU5ErkJggg==";cb.appendChild(this._image);this._image.style.position = "absolute";this._image.style.left = "0px";this._image.style.top = "0px";this._image.setAttribute("usemap", "#" + id);this._image.style.zIndex = 3;this._image.style.opacity = 0;this._image.setAttribute("alt", "imagemap");this._map = DOCUMENT.createElement("map");cb.appendChild(this._map);this._map.setAttribute("name", id);this._map.setAttribute("id", id);this._areaNodes = [];},/*** Storage for `categoryDisplayName` attribute.** @property _categoryDisplayName* @private*/_categoryDisplayName: null,/*** Storage for `valueDisplayName` attribute.** @property _valueDisplayName* @private*/_valueDisplayName: null,/*** Adds event listeners.** @method addListeners* @private*/addListeners: function(){var categoryAxis = this.get("categoryAxis"),valueAxis = this.get("valueAxis");if(categoryAxis){categoryAxis.after("dataReady", Y.bind(this._categoryDataChangeHandler, this));categoryAxis.after("dataUpdate", Y.bind(this._categoryDataChangeHandler, this));}if(valueAxis){valueAxis.after("dataReady", Y.bind(this._valueDataChangeHandler, this));valueAxis.after("dataUpdate", Y.bind(this._valueDataChangeHandler, this));}this.after("categoryAxisChange", this.categoryAxisChangeHandler);this.after("valueAxisChange", this.valueAxisChangeHandler);this._stylesChangeHandle = this.after("stylesChange", this._updateHandler);this._visibleChangeHandle = this.after("visibleChange", this._handleVisibleChange);},/*** Draws the series.** @method validate* @private*/validate: function(){this.draw();this._renderered = true;},/*** Event handler for the categoryAxisChange event.** @method _categoryAxisChangeHandler* @param {Object} e Event object.* @private*/_categoryAxisChangeHandler: function(){var categoryAxis = this.get("categoryAxis");categoryAxis.after("dataReady", Y.bind(this._categoryDataChangeHandler, this));categoryAxis.after("dataUpdate", Y.bind(this._categoryDataChangeHandler, this));},/*** Event handler for the valueAxisChange event.** @method _valueAxisChangeHandler* @param {Object} e Event object.* @private*/_valueAxisChangeHandler: function(){var valueAxis = this.get("valueAxis");valueAxis.after("dataReady", Y.bind(this._valueDataChangeHandler, this));valueAxis.after("dataUpdate", Y.bind(this._valueDataChangeHandler, this));},/*** Constant used to generate unique id.** @property GUID* @type String* @private*/GUID: "pieseries",/*** Event handler for categoryDataChange event.** @method _categoryDataChangeHandler* @param {Object} event Event object.* @private*/_categoryDataChangeHandler: function(){if(this._rendered && this.get("categoryKey") && this.get("valueKey")){this.draw();}},/*** Event handler for valueDataChange event.** @method _valueDataChangeHandler* @param {Object} event Event object.* @private*/_valueDataChangeHandler: function(){if(this._rendered && this.get("categoryKey") && this.get("valueKey")){this.draw();}},/*** Returns the sum of all values for the series.** @method getTotalValues* @return Number*/getTotalValues: function(){var total = this.get("valueAxis").getTotalByKey(this.get("valueKey"));return total;},/*** Draws the series. Overrides the base implementation.** @method draw* @protected*/draw: function(){var w = this.get("width"),h = this.get("height");if(isFinite(w) && isFinite(h) && w > 0 && h > 0){this._rendered = true;if(this._drawing){this._callLater = true;return;}this._drawing = true;this._callLater = false;this.drawSeries();this._drawing = false;if(this._callLater){this.draw();}else{this.fire("drawingComplete");}}},/*** Draws the markers** @method drawPlots* @protected*/drawPlots: function(){var values = this.get("valueAxis").getDataByKey(this.get("valueKey")).concat(),totalValue = 0,itemCount = values.length,styles = this.get("styles").marker,fillColors = styles.fill.colors,fillAlphas = styles.fill.alphas || ["1"],borderColors = styles.border.colors,borderWeights = [styles.border.weight],borderAlphas = [styles.border.alpha],tbw = borderWeights.concat(),tbc = borderColors.concat(),tba = borderAlphas.concat(),tfc,tfa,padding = styles.padding,graphic = this.get("graphic"),minDimension = Math.min(graphic.get("width"), graphic.get("height")),w = minDimension - (padding.left + padding.right),h = minDimension - (padding.top + padding.bottom),startAngle = -90,halfWidth = w / 2,halfHeight = h / 2,radius = Math.min(halfWidth, halfHeight),i = 0,value,angle = 0,lc,la,lw,wedgeStyle,marker,graphOrder = this.get("graphOrder") || 0,isCanvas = Y.Graphic.NAME === "canvasGraphic";for(; i < itemCount; ++i){value = parseFloat(values[i]);values.push(value);if(!isNaN(value)){totalValue += value;}}tfc = fillColors ? fillColors.concat() : null;tfa = fillAlphas ? fillAlphas.concat() : null;this._createMarkerCache();if(isCanvas){this._setMap();this._image.width = w;this._image.height = h;}for(i = 0; i < itemCount; i++){value = values[i];if(totalValue === 0){angle = 360 / values.length;}else{angle = 360 * (value / totalValue);}if(tfc && tfc.length < 1){tfc = fillColors.concat();}if(tfa && tfa.length < 1){tfa = fillAlphas.concat();}if(tbw && tbw.length < 1){tbw = borderWeights.concat();}if(tbw && tbc.length < 1){tbc = borderColors.concat();}if(tba && tba.length < 1){tba = borderAlphas.concat();}lw = tbw ? tbw.shift() : null;lc = tbc ? tbc.shift() : null;la = tba ? tba.shift() : null;startAngle += angle;wedgeStyle = {border: {color:lc,weight:lw,alpha:la},fill: {color:tfc ? tfc.shift() : this._getDefaultColor(i, "slice"),alpha:tfa ? tfa.shift() : null},type: "pieslice",arc: angle,radius: radius,startAngle: startAngle,cx: halfWidth,cy: halfHeight,width: w,height: h};marker = this.getMarker(wedgeStyle, graphOrder, i);if(isCanvas){this._addHotspot(wedgeStyle, graphOrder, i);}}this._clearMarkerCache();},/*** @protected** Method used by `styles` setter. Overrides base implementation.** @method _setStyles* @param {Object} newStyles Hash of properties to update.* @return Object*/_setStyles: function(val){if(!val.marker){val = {marker:val};}val = this._parseMarkerStyles(val);return Y.PieSeries.superclass._mergeStyles.apply(this, [val, this._getDefaultStyles()]);},/*** Adds an interactive map when rendering in canvas.** @method _addHotspot* @param {Object} cfg Object containing data used to draw the hotspot* @param {Number} seriesIndex Index of series in the `seriesCollection`.* @param {Number} index Index of the marker using the hotspot.* @private*/_addHotspot: function(cfg, seriesIndex, index){var areaNode = DOCUMENT.createElement("area"),i = 1,x = cfg.cx,y = cfg.cy,arc = cfg.arc,startAngle = cfg.startAngle - arc,endAngle = cfg.startAngle,radius = cfg.radius,ax = x + Math.cos(startAngle / 180 * Math.PI) * radius,ay = y + Math.sin(startAngle / 180 * Math.PI) * radius,bx = x + Math.cos(endAngle / 180 * Math.PI) * radius,by = y + Math.sin(endAngle / 180 * Math.PI) * radius,numPoints = Math.floor(arc/10) - 1,divAngle = (arc/(Math.floor(arc/10)) / 180) * Math.PI,angleCoord = Math.atan((ay - y)/(ax - x)),pts = x + ", " + y + ", " + ax + ", " + ay,cosAng,sinAng,multDivAng;for(i = 1; i <= numPoints; ++i){multDivAng = divAngle * i;cosAng = Math.cos(angleCoord + multDivAng);sinAng = Math.sin(angleCoord + multDivAng);if(startAngle <= 90){pts += ", " + (x + (radius * Math.cos(angleCoord + (divAngle * i))));pts += ", " + (y + (radius * Math.sin(angleCoord + (divAngle * i))));}else{pts += ", " + (x - (radius * Math.cos(angleCoord + (divAngle * i))));pts += ", " + (y - (radius * Math.sin(angleCoord + (divAngle * i))));}}pts += ", " + bx + ", " + by;pts += ", " + x + ", " + y;this._map.appendChild(areaNode);areaNode.setAttribute("class", SERIES_MARKER);areaNode.setAttribute("id", "hotSpot_" + seriesIndex + "_" + index);areaNode.setAttribute("shape", "polygon");areaNode.setAttribute("coords", pts);this._areaNodes.push(areaNode);},/*** Resizes and positions markers based on a mouse interaction.** @method updateMarkerState* @param {String} type state of the marker* @param {Number} i index of the marker* @protected*/updateMarkerState: function(type, i){if(this._markers[i]){var state = this._getState(type),markerStyles,indexStyles,marker = this._markers[i],styles = this.get("styles").marker;markerStyles = state === "off" || !styles[state] ? styles : styles[state];indexStyles = this._mergeStyles(markerStyles, {});indexStyles.fill.color = indexStyles.fill.colors[i % indexStyles.fill.colors.length];indexStyles.fill.alpha = indexStyles.fill.alphas[i % indexStyles.fill.alphas.length];marker.set(indexStyles);}},/*** Creates a shape to be used as a marker.** @method _createMarker* @param {Object} styles Hash of style properties.* @return Shape* @private*/_createMarker: function(styles){var graphic = this.get("graphic"),marker,cfg = this._copyObject(styles);marker = graphic.addShape(cfg);marker.addClass(SERIES_MARKER);return marker;},/*** Creates a cache of markers for reuse.** @method _createMarkerCache* @private*/_clearMarkerCache: function(){var len = this._markerCache.length,i = 0,marker;for(; i < len; ++i){marker = this._markerCache[i];if(marker){marker.destroy();}}this._markerCache = [];},/*** Gets the default style values for the markers.** @method _getPlotDefaults* @return Object* @private*/_getPlotDefaults: function(){var defs = {padding:{top: 0,left: 0,right: 0,bottom: 0},fill:{alphas:["1"]},border: {weight: 0,alpha: 1}};defs.fill.colors = this._defaultSliceColors;defs.border.colors = this._defaultBorderColors;return defs;}}, {ATTRS: {/*** Read-only attribute indicating the type of series.** @attribute type* @type String* @default pie*/type: {value: "pie"},/*** Order of this instance of this `type`.** @attribute order* @type Number*/order: {},/*** Reference to the `Graph` in which the series is drawn into.** @attribute graph* @type Graph*/graph: {},/*** Reference to the `Axis` instance used for assigning* category values to the graph.** @attribute categoryAxis* @type Axis*/categoryAxis: {value: null,validator: function(value){return value !== this.get("categoryAxis");}},/*** Reference to the `Axis` instance used for assigning* series values to the graph.** @attribute categoryAxis* @type Axis*/valueAxis: {value: null,validator: function(value){return value !== this.get("valueAxis");}},/*** Indicates which array to from the hash of value arrays in* the category `Axis` instance.** @attribute categoryKey* @type String*/categoryKey: {value: null,validator: function(value){return value !== this.get("categoryKey");}},/*** Indicates which array to from the hash of value arrays in* the value `Axis` instance.** @attribute valueKey* @type String*/valueKey: {value: null,validator: function(value){return value !== this.get("valueKey");}},/*** Name used for for displaying category data** @attribute categoryDisplayName* @type String*/categoryDisplayName: {setter: function(val){this._categoryDisplayName = val;return val;},getter: function(){return this._categoryDisplayName || this.get("categoryKey");}},/*** Name used for for displaying value data** @attribute valueDisplayName* @type String*/valueDisplayName: {setter: function(val){this._valueDisplayName = val;return val;},getter: function(){return this._valueDisplayName || this.get("valueKey");}},/*** @attribute slices* @type Array* @private*/slices: null/*** Style properties used for drawing markers. This attribute is inherited from `MarkerSeries`. Below are the default* values:* <dl>* <dt>fill</dt><dd>A hash containing the following values:* <dl>* <dt>colors</dt><dd>An array of colors to be used for the marker fills. The color for each marker is* retrieved from the array below:<br/>* `["#66007f", "#a86f41", "#295454", "#996ab2", "#e8cdb7", "#90bdbd","#000000","#c3b8ca", "#968373", "#678585"]`* </dd>* <dt>alphas</dt><dd>An array of alpha references (Number from 0 to 1) indicating the opacity of each marker* fill. The default value is [1].</dd>* </dl>* </dd>* <dt>border</dt><dd>A hash containing the following values:* <dl>* <dt>color</dt><dd>An array of colors to be used for the marker borders. The color for each marker is* retrieved from the array below:<br/>* `["#205096", "#b38206", "#000000", "#94001e", "#9d6fa0", "#e55b00", "#5e85c9", "#adab9e", "#6ac291", "#006457"]`* <dt>alpha</dt><dd>Number from 0 to 1 indicating the opacity of the marker border. The default value is 1.</dd>* <dt>weight</dt><dd>Number indicating the width of the border. The default value is 1.</dd>* </dl>* </dd>* <dt>over</dt><dd>hash containing styles for markers when highlighted by a `mouseover` event. The default* values for each style is null. When an over style is not set, the non-over value will be used. For example,* the default value for `marker.over.fill.color` is equivalent to `marker.fill.color`.</dd>* </dl>** @attribute styles* @type Object*/}});}, '3.18.1', {"requires": ["series-base", "series-plot-util"]});