/** * echarts图表类:饼图 * * @desc echarts基于Canvas,纯Javascript图表库,提供直观,生动,可交互,可个性化定制的数据统计图表。 * @author Kener (@Kener-林峰, linzhifeng@baidu.com) * */ define(function(require) { /** * 构造函数 * @param {Object} messageCenter echart消息中心 * @param {ZRender} zr zrender实例 * @param {Object} series 数据 * @param {Object} component 组件 */ function Pie(ecConfig, messageCenter, zr, option, component){ // 基类装饰 var ComponentBase = require('../component/base'); ComponentBase.call(this, ecConfig, zr); // 可计算特性装饰 var CalculableBase = require('./calculableBase'); CalculableBase.call(this, zr, option); var ecData = require('../util/ecData'); var zrMath = require('zrender/tool/math'); var zrUtil = require('zrender/tool/util'); var zrColor = require('zrender/tool/color'); var self = this; self.type = ecConfig.CHART_TYPE_PIE; var series; // 共享数据源,不要修改跟自己无关的项 var _zlevelBase = self.getZlevelBase(); var _selectedMode; var _selected = {}; function _buildShape() { var legend = component.legend; self.selectedMap = {}; _selected = {}; var center; var radius; var pieCase; // 饼图箱子 _selectedMode = false; var serieName; for (var i = 0, l = series.length; i < l; i++) { if (series[i].type == ecConfig.CHART_TYPE_PIE) { series[i] = self.reformOption(series[i]); serieName = series[i].name || ''; // 系列图例开关 self.selectedMap[serieName] = legend ? legend.isSelected(serieName) : true; if (!self.selectedMap[serieName]) { continue; } center = self.parseCenter(series[i].center); radius = self.parseRadius(series[i].radius); _selectedMode = _selectedMode || series[i].selectedMode; _selected[i] = []; if (self.deepQuery([series[i], option], 'calculable')) { pieCase = { shape : radius[0] <= 10 ? 'circle' : 'ring', zlevel : _zlevelBase, hoverable : false, style : { x : center[0], // 圆心横坐标 y : center[1], // 圆心纵坐标 // 圆环内外半径 r0 : radius[0] <= 10 ? 0 : radius[0] - 10, r : radius[1] + 10, brushType : 'stroke', lineWidth: 1, strokeColor : series[i].calculableHolderColor || ecConfig.calculableHolderColor } }; ecData.pack(pieCase, series[i], i, undefined, -1); self.setCalculable(pieCase); self.shapeList.push(pieCase); } _buildSinglePie(i); self.buildMark( series[i], i, component ); } } for (var i = 0, l = self.shapeList.length; i < l; i++) { self.shapeList[i].id = zr.newShapeId(self.type); zr.addShape(self.shapeList[i]); } } /** * 构建单个饼图 * * @param {number} seriesIndex 系列索引 */ function _buildSinglePie(seriesIndex) { var serie = series[seriesIndex]; var data = serie.data; var legend = component.legend; var itemName; var totalSelected = 0; // 迭代累计选中且非0个数 var totalSelectedValue0 = 0; // 迭代累计选中0只个数 var totalValue = 0; // 迭代累计 var maxValue = Number.NEGATIVE_INFINITY; // 计算需要显示的个数和总值 for (var i = 0, l = data.length; i < l; i++) { itemName = data[i].name; if (legend){ self.selectedMap[itemName] = legend.isSelected(itemName); } else { self.selectedMap[itemName] = true; } if (self.selectedMap[itemName]) { if (+data[i].value !== 0) { totalSelected++; } else { totalSelectedValue0++; } totalValue += +data[i].value; maxValue = Math.max(maxValue, +data[i].value); } } var percent = 100; var lastPercent; // 相邻细角度优化 var lastAddRadius = 0; var clockWise = serie.clockWise; var startAngle = serie.startAngle.toFixed(2) - 0; var endAngle; var minAngle = serie.minAngle || 0.01; // #bugfixed var totalAngle = 360 - (minAngle * totalSelected) - 0.01 * totalSelectedValue0; var defaultColor; var roseType = serie.roseType; var radius; var r0; // 扇形内半径 var r1; // 扇形外半径 for (var i = 0, l = data.length; i < l; i++){ itemName = data[i].name; if (!self.selectedMap[itemName]) { continue; } // 默认颜色策略 if (legend) { // 有图例则从图例中获取颜色定义 defaultColor = legend.getColor(itemName); } else { // 全局颜色定义 defaultColor = zr.getColor(i); } lastPercent = percent; percent = data[i].value / totalValue; if (roseType != 'area') { endAngle = clockWise ? (startAngle - percent * totalAngle - (percent !== 0 ? minAngle : 0.01)) : (percent * totalAngle + startAngle + (percent !== 0 ? minAngle : 0.01)); } else { endAngle = clockWise ? (startAngle - 360 / l) : (360 / l + startAngle); } endAngle = endAngle.toFixed(2) - 0; percent = (percent * 100).toFixed(2); radius = self.parseRadius(serie.radius); r0 = +radius[0]; r1 = +radius[1]; if (roseType == 'radius') { r1 = data[i].value / maxValue * (r1 - r0) * 0.8 + (r1 - r0) * 0.2 + r0; } else if (roseType == 'area') { r1 = Math.sqrt(data[i].value / maxValue) * (r1 - r0) + r0; } if (clockWise) { var temp; temp = startAngle; startAngle = endAngle; endAngle = temp; } // 当前小角度需要检查前一个是否也是小角度,如果是得调整长度,不能完全避免,但能大大降低覆盖概率 if (i > 0 && percent < 4 // 约15度 && lastPercent < 4 && _needLabel(serie, data[i], false) && self.deepQuery( [data[i], serie], 'itemStyle.normal.label.position' ) != 'center' ) { // 都小就延长,前小后大就缩短 lastAddRadius += (percent < 4 ? 20 : -20); } else { lastAddRadius = 0; } _buildItem( seriesIndex, i, percent, lastAddRadius, // 相邻最小角度优化 data[i].selected, r0, r1, startAngle, endAngle, defaultColor ); if (!clockWise) { startAngle = endAngle; } } } /** * 构建单个扇形及指标 */ function _buildItem( seriesIndex, dataIndex, percent, lastAddRadius, isSelected, r0, r1, startAngle, endAngle, defaultColor ) { // 扇形 var sector = _getSector( seriesIndex, dataIndex, percent, isSelected, r0, r1, startAngle, endAngle, defaultColor ); // 图形需要附加的私有数据 ecData.pack( sector, series[seriesIndex], seriesIndex, series[seriesIndex].data[dataIndex], dataIndex, series[seriesIndex].data[dataIndex].name, percent ); sector._lastAddRadius = lastAddRadius; self.shapeList.push(sector); // 文本标签,需要显示则会有返回 var label = _getLabel( seriesIndex, dataIndex, percent, lastAddRadius, startAngle, endAngle, defaultColor, false ); if (label) { label._dataIndex = dataIndex; self.shapeList.push(label); } // 文本标签视觉引导线,需要显示则会有返回 var labelLine = _getLabelLine( seriesIndex, dataIndex, lastAddRadius, r0, r1, startAngle, endAngle, defaultColor, false ); if (labelLine) { labelLine._dataIndex = dataIndex; self.shapeList.push(labelLine); } } /** * 构建扇形 */ function _getSector( seriesIndex, dataIndex, percent, isSelected, r0, r1, startAngle, endAngle, defaultColor ) { var serie = series[seriesIndex]; var data = serie.data[dataIndex]; var queryTarget = [data, serie]; var center = self.parseCenter(serie.center); // 多级控制 var normal = self.deepMerge( queryTarget, 'itemStyle.normal' ) || {}; var emphasis = self.deepMerge( queryTarget, 'itemStyle.emphasis' ) || {}; var normalColor = normal.color || defaultColor; var emphasisColor = emphasis.color || (typeof normalColor == 'string' ? zrColor.lift(normalColor, -0.2) : normalColor ); var sector = { shape : 'sector', // 扇形 zlevel : _zlevelBase, clickable : true, style : { x : center[0], // 圆心横坐标 y : center[1], // 圆心纵坐标 r0 : r0, // 圆环内半径 r : r1, // 圆环外半径 startAngle : startAngle, endAngle : endAngle, brushType : 'both', color : normalColor, lineWidth : normal.borderWidth, strokeColor : normal.borderColor, lineJoin: 'round' }, highlightStyle : { color : emphasisColor, strokeColor : 'rgba(0,0,0,0)', lineWidth : emphasis.borderWidth, strokeColor : emphasis.borderColor, lineJoin: 'round' }, _seriesIndex : seriesIndex, _dataIndex : dataIndex }; if (isSelected) { var midAngle = ((sector.style.startAngle + sector.style.endAngle) / 2) .toFixed(2) - 0; sector.style._hasSelected = true; sector.style._x = sector.style.x; sector.style._y = sector.style.y; var offset = self.query(serie, 'selectedOffset'); sector.style.x += zrMath.cos(midAngle, true) * offset; sector.style.y -= zrMath.sin(midAngle, true) * offset; _selected[seriesIndex][dataIndex] = true; } else { _selected[seriesIndex][dataIndex] = false; } if (_selectedMode) { sector.onclick = self.shapeHandler.onclick; } if (self.deepQuery([data, serie, option], 'calculable')) { self.setCalculable(sector); sector.draggable = true; } // “normal下不显示,emphasis显示”添加事件响应 if (_needLabel(serie, data, true) // emphasis下显示文本 || _needLabelLine(serie, data, true) // emphasis下显示引导线 ) { sector.onmouseover = self.shapeHandler.onmouseover; } return sector; } /** * 需要显示则会有返回构建好的shape,否则返回undefined */ function _getLabel( seriesIndex, dataIndex, percent, lastAddRadius, startAngle, endAngle, defaultColor, isEmphasis ) { var serie = series[seriesIndex]; var data = serie.data[dataIndex]; // 特定状态下是否需要显示文本标签 if (!_needLabel(serie, data, isEmphasis)) { return; } var status = isEmphasis ? 'emphasis' : 'normal'; // serie里有默认配置,放心大胆的用! var itemStyle = zrUtil.merge( zrUtil.clone(data.itemStyle) || {}, serie.itemStyle, { 'overwrite' : false, 'recursive' : true } ); // label配置 var labelControl = itemStyle[status].label; var textStyle = labelControl.textStyle || {}; var center = self.parseCenter(serie.center); var centerX = center[0]; // 圆心横坐标 var centerY = center[1]; // 圆心纵坐标 var x; var y; var midAngle = ((endAngle + startAngle) / 2 + 360) % 360; // 中值 var radius = self.parseRadius(serie.radius); // 标签位置半径 var textAlign; var textBaseline = 'middle'; if (labelControl.position == 'center') { // center显示 radius = radius[1]; x = centerX; y = centerY; textAlign = 'center'; } else if (labelControl.position == 'inner'){ // 内部显示 radius = (radius[0] + radius[1]) / 2 + lastAddRadius; x = Math.round( centerX + radius * zrMath.cos(midAngle, true) ); y = Math.round( centerY - radius * zrMath.sin(midAngle, true) ); defaultColor = '#fff'; textAlign = 'center'; } else { // 外部显示,默认 labelControl.position == 'outer') radius = radius[1] - (-itemStyle[status].labelLine.length) //- (-textStyle.fontSize) + lastAddRadius; x = centerX + radius * zrMath.cos(midAngle, true); y = centerY - radius * zrMath.sin(midAngle, true); textAlign = (midAngle >= 90 && midAngle <= 270) ? 'right' : 'left'; } if (labelControl.position != 'center' && labelControl.position != 'inner' ) { x += textAlign == 'left' ? 20 : -20; } data.__labelX = x - (textAlign == 'left' ? 5 : -5); data.__labelY = y; return { shape : 'text', zlevel : _zlevelBase + 1, hoverable : false, style : { x : x, y : y, color : textStyle.color || defaultColor, text : _getLabelText( seriesIndex, dataIndex, percent, status ), textAlign : textStyle.align || textAlign, textBaseline : textStyle.baseline || textBaseline, textFont : self.getFont(textStyle) }, highlightStyle : { brushType : 'fill' }, _seriesIndex : seriesIndex, _dataIndex : dataIndex }; } /** * 根据lable.format计算label text */ function _getLabelText(seriesIndex, dataIndex, percent, status) { var serie = series[seriesIndex]; var data = serie.data[dataIndex]; var formatter = self.deepQuery( [data, serie], 'itemStyle.' + status + '.label.formatter' ); if (formatter) { if (typeof formatter == 'function') { return formatter( serie.name, data.name, data.value, percent ); } else if (typeof formatter == 'string') { formatter = formatter.replace('{a}','{a0}') .replace('{b}','{b0}') .replace('{c}','{c0}') .replace('{d}','{d0}'); formatter = formatter.replace('{a0}', serie.name) .replace('{b0}', data.name) .replace('{c0}', data.value) .replace('{d0}', percent); return formatter; } } else { return data.name; } } /** * 需要显示则会有返回构建好的shape,否则返回undefined */ function _getLabelLine( seriesIndex, dataIndex, lastAddRadius, r0, r1, startAngle, endAngle, defaultColor, isEmphasis ) { var serie = series[seriesIndex]; var data = serie.data[dataIndex]; // 特定状态下是否需要显示文本标签 if (_needLabelLine(serie, data, isEmphasis)) { var status = isEmphasis ? 'emphasis' : 'normal'; // serie里有默认配置,放心大胆的用! var itemStyle = zrUtil.merge( zrUtil.clone(data.itemStyle) || {}, serie.itemStyle, { 'overwrite' : false, 'recursive' : true } ); // labelLine配置 var labelLineControl = itemStyle[status].labelLine; var lineStyle = labelLineControl.lineStyle || {}; var center = self.parseCenter(serie.center); var centerX = center[0]; // 圆心横坐标 var centerY = center[1]; // 圆心纵坐标 // 视觉引导线起点半径 var midRadius = r1; // 视觉引导线终点半径 var maxRadius = self.parseRadius(serie.radius)[1] - (-labelLineControl.length) + lastAddRadius; var midAngle = ((endAngle + startAngle) / 2) % 360; // 角度中值 var cosValue = zrMath.cos(midAngle, true); var sinValue = zrMath.sin(midAngle, true); // 三角函数缓存已在zrender/tool/math中做了 return { shape : 'brokenLine', zlevel : _zlevelBase + 1, hoverable : false, style : { pointList : [ [ centerX + midRadius * cosValue, centerY - midRadius * sinValue ], [ centerX + maxRadius * cosValue, centerY - maxRadius * sinValue ], [ data.__labelX, data.__labelY ] ], //xStart : centerX + midRadius * cosValue, //yStart : centerY - midRadius * sinValue, //xEnd : centerX + maxRadius * cosValue, //yEnd : centerY - maxRadius * sinValue, strokeColor : lineStyle.color || defaultColor, lineType : lineStyle.type, lineWidth : lineStyle.width }, _seriesIndex : seriesIndex, _dataIndex : dataIndex }; } else { return; } } /** * 返回特定状态(normal or emphasis)下是否需要显示label标签文本 * @param {Object} serie * @param {Object} data * @param {boolean} isEmphasis true is 'emphasis' and false is 'normal' */ function _needLabel(serie, data, isEmphasis) { return self.deepQuery( [data, serie], 'itemStyle.' + (isEmphasis ? 'emphasis' : 'normal') + '.label.show' ); } /** * 返回特定状态(normal or emphasis)下是否需要显示labelLine标签视觉引导线 * @param {Object} serie * @param {Object} data * @param {boolean} isEmphasis true is 'emphasis' and false is 'normal' */ function _needLabelLine(serie, data, isEmphasis) { return self.deepQuery( [data, serie], 'itemStyle.' + (isEmphasis ? 'emphasis' : 'normal') +'.labelLine.show' ); } /** * 参数修正&默认值赋值,重载基类方法 * @param {Object} opt 参数 */ function reformOption(opt) { // 常用方法快捷方式 var _merge = zrUtil.merge; opt = _merge( opt || {}, ecConfig.pie, { 'overwrite' : false, 'recursive' : true } ); // 通用字体设置 opt.itemStyle.normal.label.textStyle = _merge( opt.itemStyle.normal.label.textStyle || {}, ecConfig.textStyle, { 'overwrite' : false, 'recursive' : true } ); opt.itemStyle.emphasis.label.textStyle = _merge( opt.itemStyle.emphasis.label.textStyle || {}, ecConfig.textStyle, { 'overwrite' : false, 'recursive' : true } ); return opt; } /** * 构造函数默认执行的初始化方法,也用于创建实例后动态修改 * @param {Object} newSeries * @param {Object} newComponent */ function init(newOption, newComponent) { component = newComponent; refresh(newOption); } /** * 刷新 */ function refresh(newOption) { if (newOption) { option = newOption; series = option.series; } self.clear(); _buildShape(); } /** * 动态数据增加动画 * 心跳效果 function addDataAnimation(params) { var aniMap = {}; // seriesIndex索引参数 for (var i = 0, l = params.length; i < l; i++) { aniMap[params[i][0]] = params[i]; } var x; var y; var r; var seriesIndex; for (var i = self.shapeList.length - 1; i >= 0; i--) { seriesIndex = ecData.get(self.shapeList[i], 'seriesIndex'); if (aniMap[seriesIndex]) { if (self.shapeList[i].shape == 'sector' || self.shapeList[i].shape == 'circle' || self.shapeList[i].shape == 'ring' ) { r = self.shapeList[i].style.r; zr.animate(self.shapeList[i].id, 'style') .when( 300, {r : r * 0.9} ) .when( 500, {r : r} ) .start(); } } } } */ /** * 动态数据增加动画 */ function addDataAnimation(params) { var aniMap = {}; // seriesIndex索引参数 for (var i = 0, l = params.length; i < l; i++) { aniMap[params[i][0]] = params[i]; } // 构建新的饼图匹配差异做动画 var sectorMap = {}; var textMap = {}; var lineMap = {}; var backupShapeList = zrUtil.clone(self.shapeList); self.shapeList = []; var seriesIndex; var isHead; var dataGrow; var deltaIdxMap = {}; // 修正新增数据后会对dataIndex产生错位匹配 for (var i = 0, l = params.length; i < l; i++) { seriesIndex = params[i][0]; isHead = params[i][2]; dataGrow = params[i][3]; if (series[seriesIndex] && series[seriesIndex].type == ecConfig.CHART_TYPE_PIE ) { if (isHead) { if (!dataGrow) { sectorMap[ seriesIndex + '_' + series[seriesIndex].data.length ] = 'delete'; } deltaIdxMap[seriesIndex] = 1; } else { if (!dataGrow) { sectorMap[seriesIndex + '_-1'] = 'delete'; deltaIdxMap[seriesIndex] = -1; } else { deltaIdxMap[seriesIndex] = 0; } } _buildSinglePie(seriesIndex); } } var dataIndex; var key; for (var i = 0, l = self.shapeList.length; i < l; i++) { seriesIndex = self.shapeList[i]._seriesIndex; dataIndex = self.shapeList[i]._dataIndex; key = seriesIndex + '_' + dataIndex; // map映射让n*n变n switch (self.shapeList[i].shape) { case 'sector' : sectorMap[key] = self.shapeList[i]; break; case 'text' : textMap[key] = self.shapeList[i]; break; case 'line' : lineMap[key] = self.shapeList[i]; break; } } self.shapeList = []; var targeSector; for (var i = 0, l = backupShapeList.length; i < l; i++) { seriesIndex = backupShapeList[i]._seriesIndex; if (aniMap[seriesIndex]) { dataIndex = backupShapeList[i]._dataIndex + deltaIdxMap[seriesIndex]; key = seriesIndex + '_' + dataIndex; targeSector = sectorMap[key]; if (!targeSector) { continue; } if (backupShapeList[i].shape == 'sector') { if (targeSector != 'delete') { // 原有扇形 zr.animate(backupShapeList[i].id, 'style') .when( 400, { startAngle : targeSector.style.startAngle, endAngle : targeSector.style.endAngle } ) .start(); } else { // 删除的扇形 zr.animate(backupShapeList[i].id, 'style') .when( 400, deltaIdxMap[seriesIndex] < 0 ? { endAngle : backupShapeList[i].style.startAngle } : { startAngle : backupShapeList[i].style.endAngle } ) .start(); } } else if (backupShapeList[i].shape == 'text' || backupShapeList[i].shape == 'line' ) { if (targeSector == 'delete') { // 删除逻辑一样 zr.delShape(backupShapeList[i].id); } else { // 懒得新建变量了,借用一下 switch (backupShapeList[i].shape) { case 'text': targeSector = textMap[key]; zr.animate(backupShapeList[i].id, 'style') .when( 400, { x :targeSector.style.x, y :targeSector.style.y } ) .start(); break; case 'line': targeSector = lineMap[key]; zr.animate(backupShapeList[i].id, 'style') .when( 400, { xStart:targeSector.style.xStart, yStart:targeSector.style.yStart, xEnd : targeSector.style.xEnd, yEnd : targeSector.style.yEnd } ) .start(); break; } } } } } self.shapeList = backupShapeList; } /** * 动画设定 */ function animation() { var duration = self.query(option, 'animationDuration'); var easing = self.query(option, 'animationEasing'); var x; var y; var r0; var r; var serie; var dataIndex; for (var i = 0, l = self.shapeList.length; i < l; i++) { if (self.shapeList[i].shape == 'sector' || self.shapeList[i].shape == 'circle' || self.shapeList[i].shape == 'ring' ) { x = self.shapeList[i].style.x; y = self.shapeList[i].style.y; r0 = self.shapeList[i].style.r0; r = self.shapeList[i].style.r; zr.modShape( self.shapeList[i].id, { rotation : [Math.PI*2, x, y], style : { r0 : 0, r : 0 } }, true ); serie = ecData.get(self.shapeList[i], 'series'); dataIndex = ecData.get(self.shapeList[i], 'dataIndex'); zr.animate(self.shapeList[i].id, 'style') .when( (self.query(serie,'animationDuration') || duration) + dataIndex * 10, { r0 : r0, r : r } ) .start('QuinticOut'); zr.animate(self.shapeList[i].id, '') .when( (self.query(serie,'animationDuration') || duration) + dataIndex * 100, {rotation : [0, x, y]} ) .start( self.query(serie, 'animationEasing') || easing ); } else if (!self.shapeList[i]._mark){ dataIndex = self.shapeList[i]._dataIndex; zr.modShape( self.shapeList[i].id, { scale : [0, 0, x, y] }, true ); zr.animate(self.shapeList[i].id, '') .when( duration + dataIndex * 100, {scale : [1, 1, x, y]} ) .start('QuinticOut'); } } self.animationMark(duration, easing); } function onclick(param) { if (!self.isClick || !param.target) { // 没有在当前实例上发生点击直接返回 return; } var offset; // 偏移 var target = param.target; var style = target.style; var seriesIndex = ecData.get(target, 'seriesIndex'); var dataIndex = ecData.get(target, 'dataIndex'); for (var i = 0, len = self.shapeList.length; i < len; i++) { if (self.shapeList[i].id == target.id) { seriesIndex = ecData.get(target, 'seriesIndex'); dataIndex = ecData.get(target, 'dataIndex'); // 当前点击的 if (!style._hasSelected) { var midAngle = ((style.startAngle + style.endAngle) / 2) .toFixed(2) - 0; target.style._hasSelected = true; _selected[seriesIndex][dataIndex] = true; target.style._x = target.style.x; target.style._y = target.style.y; offset = self.query( series[seriesIndex], 'selectedOffset' ); target.style.x += zrMath.cos(midAngle, true) * offset; target.style.y -= zrMath.sin(midAngle, true) * offset; } else { // 复位 target.style.x = target.style._x; target.style.y = target.style._y; target.style._hasSelected = false; _selected[seriesIndex][dataIndex] = false; } zr.modShape(target.id, target); } else if (self.shapeList[i].style._hasSelected && _selectedMode == 'single' ) { seriesIndex = ecData.get(self.shapeList[i], 'seriesIndex'); dataIndex = ecData.get(self.shapeList[i], 'dataIndex'); // 单选模式下需要取消其他已经选中的 self.shapeList[i].style.x = self.shapeList[i].style._x; self.shapeList[i].style.y = self.shapeList[i].style._y; self.shapeList[i].style._hasSelected = false; _selected[seriesIndex][dataIndex] = false; zr.modShape( self.shapeList[i].id, self.shapeList[i] ); } } messageCenter.dispatch( ecConfig.EVENT.PIE_SELECTED, param.event, {selected : _selected} ); zr.refresh(); } /** * 数据项被拖拽进来, 重载基类方法 */ function ondrop(param, status) { if (!self.isDrop || !param.target) { // 没有在当前实例上发生拖拽行为则直接返回 return; } var target = param.target; // 拖拽安放目标 var dragged = param.dragged; // 当前被拖拽的图形对象 var seriesIndex = ecData.get(target, 'seriesIndex'); var dataIndex = ecData.get(target, 'dataIndex'); var data; var legend = component.legend; if (dataIndex == -1) { // 落到pieCase上,数据被拖拽进某个饼图,增加数据 data = { value : ecData.get(dragged, 'value'), name : ecData.get(dragged, 'name') }; // 修饼图数值不为负值 if (data.value < 0) { data.value = 0; } series[seriesIndex].data.push(data); legend && legend.add( data.name, dragged.style.color || dragged.style.strokeColor ); } else { // 落到sector上,数据被拖拽到某个数据项上,数据修改 var accMath = require('../util/accMath'); data = series[seriesIndex].data[dataIndex]; legend && legend.del(data.name); data.name += option.nameConnector + ecData.get(dragged, 'name'); data.value = accMath.accAdd( data.value, ecData.get(dragged, 'value') ); legend && legend.add( data.name, dragged.style.color || dragged.style.strokeColor ); } // 别status = {}赋值啊!! status.dragIn = status.dragIn || true; // 处理完拖拽事件后复位 self.isDrop = false; return; } /** * 数据项被拖拽出去,重载基类方法 */ function ondragend(param, status) { if (!self.isDragend || !param.target) { // 没有在当前实例上发生拖拽行为则直接返回 return; } var target = param.target; // 被拖拽图形元素 var seriesIndex = ecData.get(target, 'seriesIndex'); var dataIndex = ecData.get(target, 'dataIndex'); // 被拖拽的图形是饼图sector,删除被拖拽走的数据 component.legend && component.legend.del( series[seriesIndex].data[dataIndex].name ); series[seriesIndex].data.splice(dataIndex, 1); // 别status = {}赋值啊!! status.dragOut = true; status.needRefresh = true; // 处理完拖拽事件后复位 self.isDragend = false; return; } /** * 输出动态视觉引导线 */ self.shapeHandler.onmouseover = function(param) { var shape = param.target; var seriesIndex = ecData.get(shape, 'seriesIndex'); var dataIndex = ecData.get(shape, 'dataIndex'); var percent = ecData.get(shape, 'special'); var lastAddRadius = shape._lastAddRadius; var startAngle = shape.style.startAngle; var endAngle = shape.style.endAngle; var defaultColor = shape.highlightStyle.color; // 文本标签,需要显示则会有返回 var label = _getLabel( seriesIndex, dataIndex, percent, lastAddRadius, startAngle, endAngle, defaultColor, true ); if (label) { zr.addHoverShape(label); } // 文本标签视觉引导线,需要显示则会有返回 var labelLine = _getLabelLine( seriesIndex, dataIndex, lastAddRadius, shape.style.r0, shape.style.r, startAngle, endAngle, defaultColor, true ); if (labelLine) { zr.addHoverShape(labelLine); } }; self.reformOption = reformOption; // 重载基类方法 self.animation = animation; // 接口方法 self.init = init; self.refresh = refresh; self.addDataAnimation = addDataAnimation; self.onclick = onclick; self.ondrop = ondrop; self.ondragend = ondragend; init(option, component); } // 图表注册 require('../chart').define('pie', Pie); return Pie; });