5659 lines
		
	
	
		
			190 KiB
		
	
	
	
		
			JavaScript
		
	
	
			
		
		
	
	
			5659 lines
		
	
	
		
			190 KiB
		
	
	
	
		
			JavaScript
		
	
	
| /*
 | ||
|  * uCharts v1.9.3.20190922
 | ||
|  * uni-app平台高性能跨全端图表,支持H5、APP、小程序(微信/支付宝/百度/头条/QQ/360)
 | ||
|  * Copyright (c) 2019 QIUN秋云 https://www.ucharts.cn All rights reserved.
 | ||
|  * Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
 | ||
|  * 
 | ||
|  * uCharts官方网站
 | ||
|  * https://www.uCharts.cn
 | ||
|  * 
 | ||
|  * 开源地址:
 | ||
|  * https://gitee.com/uCharts/uCharts
 | ||
|  * 
 | ||
|  * uni-app插件市场地址:
 | ||
|  * http://ext.dcloud.net.cn/plugin?id=271
 | ||
|  * 
 | ||
|  */
 | ||
| 
 | ||
| 'use strict';
 | ||
| 
 | ||
| var config = {
 | ||
|   yAxisWidth: 15,
 | ||
|   yAxisSplit: 5,
 | ||
|   xAxisHeight: 15,
 | ||
|   xAxisLineHeight: 15,
 | ||
|   legendHeight: 15,
 | ||
|   yAxisTitleWidth: 15,
 | ||
|   padding: [10, 10, 10, 10],
 | ||
|   pixelRatio: 1,
 | ||
|   rotate: false,
 | ||
|   columePadding: 3,
 | ||
|   fontSize: 13,
 | ||
|   //dataPointShape: ['diamond', 'circle', 'triangle', 'rect'],
 | ||
|   dataPointShape: ['circle', 'circle', 'circle', 'circle'],
 | ||
|   colors: ['#1890ff', '#2fc25b', '#facc14', '#f04864', '#8543e0', '#90ed7d'],
 | ||
|   pieChartLinePadding: 15,
 | ||
|   pieChartTextPadding: 5,
 | ||
|   xAxisTextPadding: 3,
 | ||
|   titleColor: '#333333',
 | ||
|   titleFontSize: 20,
 | ||
|   subtitleColor: '#999999',
 | ||
|   subtitleFontSize: 15,
 | ||
|   toolTipPadding: 3,
 | ||
|   toolTipBackground: '#000000',
 | ||
|   toolTipOpacity: 0.7,
 | ||
|   toolTipLineHeight: 20,
 | ||
|   radarLabelTextMargin: 15,
 | ||
|   gaugeLabelTextMargin: 15
 | ||
| };
 | ||
| 
 | ||
| let assign = function (target, ...varArgs) {
 | ||
|     if (target == null) {
 | ||
|         throw new TypeError('Cannot convert undefined or null to object');
 | ||
|     }
 | ||
|     if (!varArgs || varArgs.length <= 0) {
 | ||
|         return target;
 | ||
|     }
 | ||
|     // 深度合并对象
 | ||
|     function deepAssign(obj1, obj2) {
 | ||
|         for (let key in obj2) {
 | ||
|             obj1[key] = obj1[key] && obj1[key].toString() === "[object Object]" ?
 | ||
|                 deepAssign(obj1[key], obj2[key]) : obj1[key] = obj2[key];
 | ||
|         }
 | ||
|         return obj1;
 | ||
|     }
 | ||
| 
 | ||
|     varArgs.forEach(val => {
 | ||
|         target = deepAssign(target, val);
 | ||
|     });
 | ||
|     return target;
 | ||
| };
 | ||
| 
 | ||
| var util = {
 | ||
|   toFixed: function toFixed(num, limit) {
 | ||
|     limit = limit || 2;
 | ||
|     if (this.isFloat(num)) {
 | ||
|       num = num.toFixed(limit);
 | ||
|     }
 | ||
|     return num;
 | ||
|   },
 | ||
|   isFloat: function isFloat(num) {
 | ||
|     return num % 1 !== 0;
 | ||
|   },
 | ||
|   approximatelyEqual: function approximatelyEqual(num1, num2) {
 | ||
|     return Math.abs(num1 - num2) < 1e-10;
 | ||
|   },
 | ||
|   isSameSign: function isSameSign(num1, num2) {
 | ||
|     return Math.abs(num1) === num1 && Math.abs(num2) === num2 || Math.abs(num1) !== num1 && Math.abs(num2) !== num2;
 | ||
|   },
 | ||
|   isSameXCoordinateArea: function isSameXCoordinateArea(p1, p2) {
 | ||
|     return this.isSameSign(p1.x, p2.x);
 | ||
|   },
 | ||
|   isCollision: function isCollision(obj1, obj2) {
 | ||
|     obj1.end = {};
 | ||
|     obj1.end.x = obj1.start.x + obj1.width;
 | ||
|     obj1.end.y = obj1.start.y - obj1.height;
 | ||
|     obj2.end = {};
 | ||
|     obj2.end.x = obj2.start.x + obj2.width;
 | ||
|     obj2.end.y = obj2.start.y - obj2.height;
 | ||
|     var flag = obj2.start.x > obj1.end.x || obj2.end.x < obj1.start.x || obj2.end.y > obj1.start.y || obj2.start.y < obj1.end.y;
 | ||
|     return !flag;
 | ||
|   }
 | ||
| };
 | ||
| 
 | ||
| //兼容H5点击事件
 | ||
| function getH5Offset(e) {
 | ||
|   e.mp = {
 | ||
|     changedTouches: []
 | ||
|   };
 | ||
|   e.mp.changedTouches.push({
 | ||
|     x: e.offsetX,
 | ||
|     y: e.offsetY
 | ||
|   });
 | ||
|   return e;
 | ||
| }
 | ||
| 
 | ||
| // hex 转 rgba
 | ||
| function hexToRgb(hexValue, opc) {
 | ||
|   var rgx = /^#?([a-f\d])([a-f\d])([a-f\d])$/i;
 | ||
|   var hex = hexValue.replace(rgx, function(m, r, g, b) {
 | ||
|     return r + r + g + g + b + b;
 | ||
|   });
 | ||
|   var rgb = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
 | ||
|   var r = parseInt(rgb[1], 16);
 | ||
|   var g = parseInt(rgb[2], 16);
 | ||
|   var b = parseInt(rgb[3], 16);
 | ||
|   return 'rgba(' + r + ',' + g + ',' + b + ',' + opc + ')';
 | ||
| }
 | ||
| 
 | ||
| function findRange(num, type, limit) {
 | ||
|   if (isNaN(num)) {
 | ||
|     throw new Error('[uCharts] unvalid series data!');
 | ||
|   }
 | ||
|   limit = limit || 10;
 | ||
|   type = type ? type : 'upper';
 | ||
|   var multiple = 1;
 | ||
|   while (limit < 1) {
 | ||
|     limit *= 10;
 | ||
|     multiple *= 10;
 | ||
|   }
 | ||
|   if (type === 'upper') {
 | ||
|     num = Math.ceil(num * multiple);
 | ||
|   } else {
 | ||
|     num = Math.floor(num * multiple);
 | ||
|   }
 | ||
|   while (num % limit !== 0) {
 | ||
|     if (type === 'upper') {
 | ||
|       num++;
 | ||
|     } else {
 | ||
|       num--;
 | ||
|     }
 | ||
|   }
 | ||
|   return num / multiple;
 | ||
| }
 | ||
| 
 | ||
| function calCandleMA(dayArr, nameArr, colorArr, kdata) {
 | ||
|   let seriesTemp = [];
 | ||
|   for (let k = 0; k < dayArr.length; k++) {
 | ||
|     let seriesItem = {
 | ||
|       data: [],
 | ||
|       name: nameArr[k],
 | ||
|       color: colorArr[k]
 | ||
|     };
 | ||
|     for (let i = 0, len = kdata.length; i < len; i++) {
 | ||
|       if (i < dayArr[k]) {
 | ||
|         seriesItem.data.push(null);
 | ||
|         continue;
 | ||
|       }
 | ||
|       let sum = 0;
 | ||
|       for (let j = 0; j < dayArr[k]; j++) {
 | ||
|         sum += kdata[i - j][1];
 | ||
|       }
 | ||
|       seriesItem.data.push(+(sum / dayArr[k]).toFixed(3));
 | ||
|     }
 | ||
|     seriesTemp.push(seriesItem);
 | ||
|   }
 | ||
|   return seriesTemp;
 | ||
| }
 | ||
| 
 | ||
| function calValidDistance(self,distance, chartData, config, opts) {
 | ||
|   var dataChartAreaWidth = opts.width - opts.area[1] - opts.area[3];
 | ||
|   var dataChartWidth = chartData.eachSpacing * (opts.chartData.xAxisData.xAxisPoints.length-1);
 | ||
|   var validDistance = distance;
 | ||
|   if (distance >= 0) {
 | ||
|     validDistance = 0;
 | ||
| 		self.event.trigger('scrollLeft');
 | ||
|   } else if (Math.abs(distance) >= dataChartWidth - dataChartAreaWidth) {
 | ||
|     validDistance = dataChartAreaWidth - dataChartWidth;
 | ||
| 		self.event.trigger('scrollRight');
 | ||
|   }
 | ||
|   return validDistance;
 | ||
| }
 | ||
| 
 | ||
| function isInAngleRange(angle, startAngle, endAngle) {
 | ||
|   function adjust(angle) {
 | ||
|     while (angle < 0) {
 | ||
|       angle += 2 * Math.PI;
 | ||
|     }
 | ||
|     while (angle > 2 * Math.PI) {
 | ||
|       angle -= 2 * Math.PI;
 | ||
|     }
 | ||
|     return angle;
 | ||
|   }
 | ||
|   angle = adjust(angle);
 | ||
|   startAngle = adjust(startAngle);
 | ||
|   endAngle = adjust(endAngle);
 | ||
|   if (startAngle > endAngle) {
 | ||
|     endAngle += 2 * Math.PI;
 | ||
|     if (angle < startAngle) {
 | ||
|       angle += 2 * Math.PI;
 | ||
|     }
 | ||
|   }
 | ||
|   return angle >= startAngle && angle <= endAngle;
 | ||
| }
 | ||
| 
 | ||
| function calRotateTranslate(x, y, h) {
 | ||
|   var xv = x;
 | ||
|   var yv = h - y;
 | ||
|   var transX = xv + (h - yv - xv) / Math.sqrt(2);
 | ||
|   transX *= -1;
 | ||
|   var transY = (h - yv) * (Math.sqrt(2) - 1) - (h - yv - xv) / Math.sqrt(2);
 | ||
|   return {
 | ||
|     transX: transX,
 | ||
|     transY: transY
 | ||
|   };
 | ||
| }
 | ||
| 
 | ||
| function createCurveControlPoints(points, i) {
 | ||
| 
 | ||
|   function isNotMiddlePoint(points, i) {
 | ||
|     if (points[i - 1] && points[i + 1]) {
 | ||
|       return points[i].y >= Math.max(points[i - 1].y, points[i + 1].y) || points[i].y <= Math.min(points[i - 1].y,points[i + 1].y);
 | ||
|     } else {
 | ||
|       return false;
 | ||
|     }
 | ||
|   }
 | ||
| 	function isNotMiddlePointX(points, i) {
 | ||
| 	  if (points[i - 1] && points[i + 1]) {
 | ||
| 	    return points[i].x >= Math.max(points[i - 1].x, points[i + 1].x) || points[i].x <= Math.min(points[i - 1].x,points[i + 1].x);
 | ||
| 	  } else {
 | ||
| 	    return false;
 | ||
| 	  }
 | ||
| 	}
 | ||
|   var a = 0.2;
 | ||
|   var b = 0.2;
 | ||
|   var pAx = null;
 | ||
|   var pAy = null;
 | ||
|   var pBx = null;
 | ||
|   var pBy = null;
 | ||
|   if (i < 1) {
 | ||
|     pAx = points[0].x + (points[1].x - points[0].x) * a;
 | ||
|     pAy = points[0].y + (points[1].y - points[0].y) * a;
 | ||
|   } else {
 | ||
|     pAx = points[i].x + (points[i + 1].x - points[i - 1].x) * a;
 | ||
|     pAy = points[i].y + (points[i + 1].y - points[i - 1].y) * a;
 | ||
|   }
 | ||
| 
 | ||
|   if (i > points.length - 3) {
 | ||
|     var last = points.length - 1;
 | ||
|     pBx = points[last].x - (points[last].x - points[last - 1].x) * b;
 | ||
|     pBy = points[last].y - (points[last].y - points[last - 1].y) * b;
 | ||
|   } else {
 | ||
|     pBx = points[i + 1].x - (points[i + 2].x - points[i].x) * b;
 | ||
|     pBy = points[i + 1].y - (points[i + 2].y - points[i].y) * b;
 | ||
|   }
 | ||
|   if (isNotMiddlePoint(points, i + 1)) {
 | ||
|     pBy = points[i + 1].y;
 | ||
|   }
 | ||
|   if (isNotMiddlePoint(points, i)) {
 | ||
|     pAy = points[i].y;
 | ||
|   }
 | ||
| 	if (isNotMiddlePointX(points, i + 1)) {
 | ||
| 	  pBx = points[i + 1].x;
 | ||
| 	}
 | ||
| 	if (isNotMiddlePointX(points, i)) {
 | ||
| 	  pAx = points[i].x;
 | ||
| 	}
 | ||
| 	if (pAy >= Math.max(points[i].y, points[i + 1].y) || pAy <= Math.min(points[i].y, points[i + 1].y)) {
 | ||
| 	pAy = points[i].y;
 | ||
| 	}
 | ||
| 	if (pBy >= Math.max(points[i].y, points[i + 1].y) || pBy <= Math.min(points[i].y, points[i + 1].y)) {
 | ||
| 	pBy = points[i + 1].y;
 | ||
| 	}
 | ||
| 	if (pAx >= Math.max(points[i].x, points[i + 1].x) || pAx <= Math.min(points[i].x, points[i + 1].x)) {
 | ||
| 	pAx = points[i].x;
 | ||
| 	}
 | ||
| 	if (pBx >= Math.max(points[i].x, points[i + 1].x) || pBx <= Math.min(points[i].x, points[i + 1].x)) {
 | ||
| 	pBx = points[i + 1].x;
 | ||
| 	}
 | ||
|   return {
 | ||
|     ctrA: {
 | ||
|       x: pAx,
 | ||
|       y: pAy
 | ||
|     },
 | ||
|     ctrB: {
 | ||
|       x: pBx,
 | ||
|       y: pBy
 | ||
|     }
 | ||
|   };
 | ||
| }
 | ||
| 
 | ||
| function convertCoordinateOrigin(x, y, center) {
 | ||
|   return {
 | ||
|     x: center.x + x,
 | ||
|     y: center.y - y
 | ||
|   };
 | ||
| }
 | ||
| 
 | ||
| function avoidCollision(obj, target) {
 | ||
|   if (target) {
 | ||
|     // is collision test
 | ||
|     while (util.isCollision(obj, target)) {
 | ||
|       if (obj.start.x > 0) {
 | ||
|         obj.start.y--;
 | ||
|       } else if (obj.start.x < 0) {
 | ||
|         obj.start.y++;
 | ||
|       } else {
 | ||
|         if (obj.start.y > 0) {
 | ||
|           obj.start.y++;
 | ||
|         } else {
 | ||
|           obj.start.y--;
 | ||
|         }
 | ||
|       }
 | ||
|     }
 | ||
|   }
 | ||
|   return obj;
 | ||
| }
 | ||
| 
 | ||
| function fillSeries(series, opts, config) {
 | ||
|   var index = 0;
 | ||
|   return series.map(function(item) {
 | ||
|     if (!item.color) {
 | ||
|       item.color = config.colors[index];
 | ||
|       index = (index + 1) % config.colors.length;
 | ||
|     }
 | ||
|     if (!item.index) {
 | ||
|       item.index = 0;
 | ||
|     }
 | ||
|     if (!item.type) {
 | ||
|       item.type = opts.type;
 | ||
|     }
 | ||
|     if (typeof item.show == "undefined") {
 | ||
|       item.show = true;
 | ||
|     }
 | ||
|     if (!item.type) {
 | ||
|       item.type = opts.type;
 | ||
|     }
 | ||
|     if (!item.pointShape) {
 | ||
|       item.pointShape = "circle";
 | ||
|     }
 | ||
|     if (!item.legendShape) {
 | ||
|       switch (item.type) {
 | ||
|         case 'line':
 | ||
|           item.legendShape = "line";
 | ||
|           break;
 | ||
|         case 'column':
 | ||
|           item.legendShape = "rect";
 | ||
|           break;
 | ||
|         case 'area':
 | ||
|           item.legendShape = "triangle";
 | ||
|           break;
 | ||
|         default:
 | ||
|           item.legendShape = "circle";
 | ||
|       }
 | ||
|     }
 | ||
|     return item;
 | ||
|   });
 | ||
| }
 | ||
| 
 | ||
| function getDataRange(minData, maxData) {
 | ||
|   var limit = 0;
 | ||
|   var range = maxData - minData;
 | ||
|   if (range >= 10000) {
 | ||
|     limit = 1000;
 | ||
|   } else if (range >= 1000) {
 | ||
|     limit = 100;
 | ||
|   } else if (range >= 100) {
 | ||
|     limit = 10;
 | ||
|   } else if (range >= 10) {
 | ||
|     limit = 5;
 | ||
|   } else if (range >= 1) {
 | ||
|     limit = 1;
 | ||
|   } else if (range >= 0.1) {
 | ||
|     limit = 0.1;
 | ||
|   } else if (range >= 0.01) {
 | ||
|     limit = 0.01;
 | ||
|   } else if (range >= 0.001) {
 | ||
|     limit = 0.001;
 | ||
|   } else if (range >= 0.0001) {
 | ||
|     limit = 0.0001;
 | ||
|   } else if (range >= 0.00001) {
 | ||
|     limit = 0.00001;
 | ||
|   } else {
 | ||
|     limit = 0.000001;
 | ||
|   }
 | ||
|   return {
 | ||
|     minRange: findRange(minData, 'lower', limit),
 | ||
|     maxRange: findRange(maxData, 'upper', limit)
 | ||
|   };
 | ||
| }
 | ||
| 
 | ||
| function measureText(text) {
 | ||
|   var fontSize = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : config.fontSize;
 | ||
|   text = String(text);
 | ||
|   var text = text.split('');
 | ||
|   var width = 0;
 | ||
|   for (let i = 0; i < text.length; i++) {
 | ||
|     let item = text[i];
 | ||
|     if (/[a-zA-Z]/.test(item)) {
 | ||
|       width += 7;
 | ||
|     } else if (/[0-9]/.test(item)) {
 | ||
|       width += 5.5;
 | ||
|     } else if (/\./.test(item)) {
 | ||
|       width += 2.7;
 | ||
|     } else if (/-/.test(item)) {
 | ||
|       width += 3.25;
 | ||
|     } else if (/[\u4e00-\u9fa5]/.test(item)) {
 | ||
|       width += 10;
 | ||
|     } else if (/\(|\)/.test(item)) {
 | ||
|       width += 3.73;
 | ||
|     } else if (/\s/.test(item)) {
 | ||
|       width += 2.5;
 | ||
|     } else if (/%/.test(item)) {
 | ||
|       width += 8;
 | ||
|     } else {
 | ||
|       width += 10;
 | ||
|     }
 | ||
|   }
 | ||
|   return width * fontSize / 10;
 | ||
| }
 | ||
| 
 | ||
| function dataCombine(series) {
 | ||
|   return series.reduce(function(a, b) {
 | ||
|     return (a.data ? a.data : a).concat(b.data);
 | ||
|   }, []);
 | ||
| }
 | ||
| 
 | ||
| function dataCombineStack(series, len) {
 | ||
|   var sum = new Array(len);
 | ||
|   for (var j = 0; j < sum.length; j++) {
 | ||
|     sum[j] = 0;
 | ||
|   }
 | ||
|   for (var i = 0; i < series.length; i++) {
 | ||
|     for (var j = 0; j < sum.length; j++) {
 | ||
|       sum[j] += series[i].data[j];
 | ||
|     }
 | ||
|   }
 | ||
|   return series.reduce(function(a, b) {
 | ||
|     return (a.data ? a.data : a).concat(b.data).concat(sum);
 | ||
|   }, []);
 | ||
| }
 | ||
| 
 | ||
| function getTouches(touches, opts, e) {
 | ||
|   let x, y;
 | ||
|   if (touches.clientX) {
 | ||
|     if (opts.rotate) {
 | ||
|       y = opts.height - touches.clientX * opts.pixelRatio;
 | ||
|       x = (touches.pageY - e.currentTarget.offsetTop - (opts.height / opts.pixelRatio / 2) * (opts.pixelRatio - 1)) *
 | ||
|         opts.pixelRatio;
 | ||
|     } else {
 | ||
|       x = touches.clientX * opts.pixelRatio;
 | ||
|       y = (touches.pageY - e.currentTarget.offsetTop - (opts.height / opts.pixelRatio / 2) * (opts.pixelRatio - 1)) *
 | ||
|         opts.pixelRatio;
 | ||
|     }
 | ||
|   } else {
 | ||
|     if (opts.rotate) {
 | ||
|       y = opts.height - touches.x * opts.pixelRatio;
 | ||
|       x = touches.y * opts.pixelRatio;
 | ||
|     } else {
 | ||
|       x = touches.x * opts.pixelRatio;
 | ||
|       y = touches.y * opts.pixelRatio;
 | ||
|     }
 | ||
|   }
 | ||
|   return {
 | ||
|     x: x,
 | ||
|     y: y
 | ||
|   }
 | ||
| }
 | ||
| 
 | ||
| function getSeriesDataItem(series, index) {
 | ||
|   var data = [];
 | ||
|   for (let i = 0; i < series.length; i++) {
 | ||
|     let item = series[i];
 | ||
|     if (item.data[index] !== null && typeof item.data[index] !== 'undefined' && item.show) {
 | ||
|       let seriesItem = {};
 | ||
|       seriesItem.color = item.color;
 | ||
|       seriesItem.type = item.type;
 | ||
|       seriesItem.style = item.style;
 | ||
|       seriesItem.pointShape = item.pointShape;
 | ||
|       seriesItem.disableLegend = item.disableLegend;
 | ||
|       seriesItem.name = item.name;
 | ||
|       seriesItem.show = item.show;
 | ||
|       seriesItem.data = item.format ? item.format(item.data[index]) : item.data[index];
 | ||
|       data.push(seriesItem);
 | ||
|     }
 | ||
|   }
 | ||
|   return data;
 | ||
| }
 | ||
| 
 | ||
| function getMaxTextListLength(list) {
 | ||
|   var lengthList = list.map(function(item) {
 | ||
|     return measureText(item);
 | ||
|   });
 | ||
|   return Math.max.apply(null, lengthList);
 | ||
| }
 | ||
| 
 | ||
| function getRadarCoordinateSeries(length) {
 | ||
|   var eachAngle = 2 * Math.PI / length;
 | ||
|   var CoordinateSeries = [];
 | ||
|   for (var i = 0; i < length; i++) {
 | ||
|     CoordinateSeries.push(eachAngle * i);
 | ||
|   }
 | ||
| 
 | ||
|   return CoordinateSeries.map(function(item) {
 | ||
|     return -1 * item + Math.PI / 2;
 | ||
|   });
 | ||
| }
 | ||
| 
 | ||
| function getToolTipData(seriesData, calPoints, index, categories) {
 | ||
|   var option = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : {};
 | ||
| 
 | ||
|   var textList = seriesData.map(function(item) {
 | ||
| 		let titleText=[];
 | ||
| 		if(categories){
 | ||
| 			titleText=categories;
 | ||
| 		}else{
 | ||
| 			titleText=item.data;
 | ||
| 		}
 | ||
|     return {
 | ||
|       text: option.format ? option.format(item, titleText[index]) : item.name + ': ' + item.data,
 | ||
|       color: item.color
 | ||
|     };
 | ||
|   });
 | ||
|   var validCalPoints = [];
 | ||
|   var offset = {
 | ||
|     x: 0,
 | ||
|     y: 0
 | ||
|   };
 | ||
|   for (let i = 0; i < calPoints.length; i++) {
 | ||
|     let points = calPoints[i];
 | ||
|     if (typeof points[index] !== 'undefined' && points[index] !== null) {
 | ||
|       validCalPoints.push(points[index]);
 | ||
|     }
 | ||
|   }
 | ||
|   for (let i = 0; i < validCalPoints.length; i++) {
 | ||
|     let item = validCalPoints[i];
 | ||
|     offset.x = Math.round(item.x);
 | ||
|     offset.y += item.y;
 | ||
|   }
 | ||
|   offset.y /= validCalPoints.length;
 | ||
|   return {
 | ||
|     textList: textList,
 | ||
|     offset: offset
 | ||
|   };
 | ||
| }
 | ||
| 
 | ||
| function getMixToolTipData(seriesData, calPoints, index, categories) {
 | ||
|   var option = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : {};
 | ||
|   var textList = seriesData.map(function(item) {
 | ||
|     return {
 | ||
|       text: option.format ? option.format(item, categories[index]) : item.name + ': ' + item.data,
 | ||
|       color: item.color,
 | ||
|       disableLegend: item.disableLegend ? true : false
 | ||
|     };
 | ||
|   });
 | ||
|   textList = textList.filter(function(item) {
 | ||
|     if (item.disableLegend !== true) {
 | ||
|       return item;
 | ||
|     }
 | ||
|   });
 | ||
|   var validCalPoints = [];
 | ||
|   var offset = {
 | ||
|     x: 0,
 | ||
|     y: 0
 | ||
|   };
 | ||
|   for (let i = 0; i < calPoints.length; i++) {
 | ||
|     let points = calPoints[i];
 | ||
|     if (typeof points[index] !== 'undefined' && points[index] !== null) {
 | ||
|       validCalPoints.push(points[index]);
 | ||
|     }
 | ||
|   }
 | ||
|   for (let i = 0; i < validCalPoints.length; i++) {
 | ||
|     let item = validCalPoints[i];
 | ||
|     offset.x = Math.round(item.x);
 | ||
|     offset.y += item.y;
 | ||
|   }
 | ||
|   offset.y /= validCalPoints.length;
 | ||
|   return {
 | ||
|     textList: textList,
 | ||
|     offset: offset
 | ||
|   };
 | ||
| }
 | ||
| 
 | ||
| function getCandleToolTipData(series, seriesData, calPoints, index, categories, extra) {
 | ||
|   var option = arguments.length > 6 && arguments[6] !== undefined ? arguments[6] : {};
 | ||
|   let upColor = extra.color.upFill;
 | ||
|   let downColor = extra.color.downFill;
 | ||
|   //颜色顺序为开盘,收盘,最低,最高
 | ||
|   let color = [upColor, upColor, downColor, upColor];
 | ||
|   var textList = [];
 | ||
|   let text0 = {
 | ||
|     text: categories[index],
 | ||
|     color: null
 | ||
|   };
 | ||
|   textList.push(text0);
 | ||
|   seriesData.map(function(item) {
 | ||
|     if (index == 0 && item.data[1] - item.data[0] < 0) {
 | ||
|       color[1] = downColor;
 | ||
|     } else {
 | ||
|       if (item.data[0] < series[index - 1][1]) {
 | ||
|         color[0] = downColor;
 | ||
|       }
 | ||
|       if (item.data[1] < item.data[0]) {
 | ||
|         color[1] = downColor;
 | ||
|       }
 | ||
|       if (item.data[2] > series[index - 1][1]) {
 | ||
|         color[2] = upColor;
 | ||
|       }
 | ||
|       if (item.data[3] < series[index - 1][1]) {
 | ||
|         color[3] = downColor;
 | ||
|       }
 | ||
|     }
 | ||
|     let text1 = {
 | ||
|       text: '开盘:' + item.data[0],
 | ||
|       color: color[0]
 | ||
|     };
 | ||
|     let text2 = {
 | ||
|       text: '收盘:' + item.data[1],
 | ||
|       color: color[1]
 | ||
|     };
 | ||
|     let text3 = {
 | ||
|       text: '最低:' + item.data[2],
 | ||
|       color: color[2]
 | ||
|     };
 | ||
|     let text4 = {
 | ||
|       text: '最高:' + item.data[3],
 | ||
|       color: color[3]
 | ||
|     };
 | ||
|     textList.push(text1, text2, text3, text4);
 | ||
|   });
 | ||
|   var validCalPoints = [];
 | ||
|   var offset = {
 | ||
|     x: 0,
 | ||
|     y: 0
 | ||
|   };
 | ||
|   for (let i = 0; i < calPoints.length; i++) {
 | ||
|     let points = calPoints[i];
 | ||
|     if (typeof points[index] !== 'undefined' && points[index] !== null) {
 | ||
|       validCalPoints.push(points[index]);
 | ||
|     }
 | ||
|   }
 | ||
|   offset.x = Math.round(validCalPoints[0][0].x);
 | ||
|   return {
 | ||
|     textList: textList,
 | ||
|     offset: offset
 | ||
|   };
 | ||
| }
 | ||
| 
 | ||
| function filterSeries(series) {
 | ||
|   let tempSeries = [];
 | ||
|   for (let i = 0; i < series.length; i++) {
 | ||
|     if (series[i].show == true) {
 | ||
|       tempSeries.push(series[i])
 | ||
|     }
 | ||
|   }
 | ||
|   return tempSeries;
 | ||
| }
 | ||
| 
 | ||
| function findCurrentIndex(currentPoints, calPoints, opts, config) {
 | ||
|   var offset = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 0;
 | ||
|   var currentIndex = -1;
 | ||
|   var spacing = opts.chartData.eachSpacing/2;
 | ||
| 	let xAxisPoints=[];
 | ||
| 	if(calPoints.length>0){
 | ||
| 		if(opts.type=='candle'){
 | ||
| 			for(let i=0;i<calPoints[0].length;i++){
 | ||
| 				xAxisPoints.push(calPoints[0][i][0].x)
 | ||
| 			}
 | ||
| 		}else{
 | ||
| 			for(let i=0;i<calPoints[0].length;i++){
 | ||
| 				xAxisPoints.push(calPoints[0][i].x)
 | ||
| 			}
 | ||
| 		}
 | ||
| 		if((opts.type=='line' || opts.type=='area') && opts.xAxis.boundaryGap=='justify'){
 | ||
| 		  spacing = opts.chartData.eachSpacing/2;
 | ||
| 		}
 | ||
| 		if(!opts.categories){
 | ||
| 			spacing=0
 | ||
| 		}
 | ||
| 		if (isInExactChartArea(currentPoints, opts, config)) {
 | ||
| 		  xAxisPoints.forEach(function(item, index) {
 | ||
| 		    if (currentPoints.x + offset + spacing > item) {
 | ||
| 		      currentIndex = index;
 | ||
| 		    }
 | ||
| 		  });
 | ||
| 		}
 | ||
| 	}
 | ||
|   return currentIndex;
 | ||
| }
 | ||
| 
 | ||
| function findLegendIndex(currentPoints, legendData, opts) {
 | ||
|   let currentIndex = -1;
 | ||
|   if (isInExactLegendArea(currentPoints, legendData.area)) {
 | ||
|     let points = legendData.points;
 | ||
|     let index = -1;
 | ||
|     for (let i = 0, len = points.length; i < len; i++) {
 | ||
|       let item = points[i];
 | ||
|       for (let j = 0; j < item.length; j++) {
 | ||
|         index += 1;
 | ||
|         let area = item[j]['area'];
 | ||
|         if (currentPoints.x > area[0] && currentPoints.x < area[2] && currentPoints.y > area[1] && currentPoints.y < area[3]) {
 | ||
|           currentIndex = index;
 | ||
|           break;
 | ||
|         }
 | ||
|       }
 | ||
|     }
 | ||
|     return currentIndex;
 | ||
|   }
 | ||
|   return currentIndex;
 | ||
| }
 | ||
| 
 | ||
| function isInExactLegendArea(currentPoints, area) {
 | ||
|   return currentPoints.x > area.start.x && currentPoints.x < area.end.x && currentPoints.y > area.start.y &&
 | ||
|     currentPoints.y < area.end.y;
 | ||
| }
 | ||
| 
 | ||
| function isInExactChartArea(currentPoints, opts, config) {
 | ||
|   return currentPoints.x <= opts.width - opts.area[1] + 10 && currentPoints.x >= opts.area[3] -10 && currentPoints.y >= opts.area[0] && currentPoints.y <= opts.height - opts.area[2];
 | ||
| }
 | ||
| 
 | ||
| function findRadarChartCurrentIndex(currentPoints, radarData, count) {
 | ||
|   var eachAngleArea = 2 * Math.PI / count;
 | ||
|   var currentIndex = -1;
 | ||
|   if (isInExactPieChartArea(currentPoints, radarData.center, radarData.radius)) {
 | ||
|     var fixAngle = function fixAngle(angle) {
 | ||
|       if (angle < 0) {
 | ||
|         angle += 2 * Math.PI;
 | ||
|       }
 | ||
|       if (angle > 2 * Math.PI) {
 | ||
|         angle -= 2 * Math.PI;
 | ||
|       }
 | ||
|       return angle;
 | ||
|     };
 | ||
| 
 | ||
|     var angle = Math.atan2(radarData.center.y - currentPoints.y, currentPoints.x - radarData.center.x);
 | ||
|     angle = -1 * angle;
 | ||
|     if (angle < 0) {
 | ||
|       angle += 2 * Math.PI;
 | ||
|     }
 | ||
| 
 | ||
|     var angleList = radarData.angleList.map(function(item) {
 | ||
|       item = fixAngle(-1 * item);
 | ||
| 
 | ||
|       return item;
 | ||
|     });
 | ||
| 
 | ||
|     angleList.forEach(function(item, index) {
 | ||
|       var rangeStart = fixAngle(item - eachAngleArea / 2);
 | ||
|       var rangeEnd = fixAngle(item + eachAngleArea / 2);
 | ||
|       if (rangeEnd < rangeStart) {
 | ||
|         rangeEnd += 2 * Math.PI;
 | ||
|       }
 | ||
|       if (angle >= rangeStart && angle <= rangeEnd || angle + 2 * Math.PI >= rangeStart && angle + 2 * Math.PI <=
 | ||
|         rangeEnd) {
 | ||
|         currentIndex = index;
 | ||
|       }
 | ||
|     });
 | ||
|   }
 | ||
| 
 | ||
|   return currentIndex;
 | ||
| }
 | ||
| 
 | ||
| function findFunnelChartCurrentIndex(currentPoints, funnelData) {
 | ||
|   var currentIndex = -1;
 | ||
|   for (var i = 0, len = funnelData.series.length; i < len; i++) {
 | ||
|     var item = funnelData.series[i];
 | ||
|     if (currentPoints.x > item.funnelArea[0] && currentPoints.x < item.funnelArea[2] && currentPoints.y > item.funnelArea[1] && currentPoints.y < item.funnelArea[3]) {
 | ||
|       currentIndex = i;
 | ||
|       break;
 | ||
|     }
 | ||
|   }
 | ||
|   return currentIndex;
 | ||
| }
 | ||
| 
 | ||
| function findWordChartCurrentIndex(currentPoints, wordData) {
 | ||
|   var currentIndex = -1;
 | ||
|   for (var i = 0, len = wordData.length; i < len; i++) {
 | ||
|     var item = wordData[i];
 | ||
|     if (currentPoints.x > item.area[0] && currentPoints.x < item.area[2] && currentPoints.y > item.area[1] && currentPoints.y < item.area[3]) {
 | ||
|       currentIndex = i;
 | ||
|       break;
 | ||
|     }
 | ||
|   }
 | ||
|   return currentIndex;
 | ||
| }
 | ||
| 
 | ||
| function findMapChartCurrentIndex(currentPoints, opts) {
 | ||
|   var currentIndex = -1;
 | ||
|   var cData=opts.chartData.mapData;
 | ||
|   var data=opts.series;
 | ||
|   var tmp=pointToCoordinate(currentPoints.y, currentPoints.x,cData.bounds,cData.scale,cData.xoffset,cData.yoffset);
 | ||
|   var poi=[tmp.x, tmp.y];
 | ||
|   for (var i = 0, len = data.length; i < len; i++) {
 | ||
|     var item = data[i].geometry.coordinates;
 | ||
|     if(isPoiWithinPoly(poi,item)){
 | ||
|       currentIndex = i;
 | ||
|       break;
 | ||
|     }
 | ||
|   }
 | ||
|   return currentIndex;
 | ||
| }
 | ||
| 
 | ||
| function findPieChartCurrentIndex(currentPoints, pieData) {
 | ||
|   var currentIndex = -1;
 | ||
|   if (isInExactPieChartArea(currentPoints, pieData.center, pieData.radius)) {
 | ||
|     var angle = Math.atan2(pieData.center.y - currentPoints.y, currentPoints.x - pieData.center.x);
 | ||
|     angle = -angle;
 | ||
|     for (var i = 0, len = pieData.series.length; i < len; i++) {
 | ||
|       var item = pieData.series[i];
 | ||
|       if (isInAngleRange(angle, item._start_, item._start_ + item._proportion_ * 2 * Math.PI)) {
 | ||
|         currentIndex = i;
 | ||
|         break;
 | ||
|       }
 | ||
|     }
 | ||
|   }
 | ||
| 
 | ||
|   return currentIndex;
 | ||
| }
 | ||
| 
 | ||
| function isInExactPieChartArea(currentPoints, center, radius) {
 | ||
|   return Math.pow(currentPoints.x - center.x, 2) + Math.pow(currentPoints.y - center.y, 2) <= Math.pow(radius, 2);
 | ||
| }
 | ||
| 
 | ||
| function splitPoints(points) {
 | ||
|   var newPoints = [];
 | ||
|   var items = [];
 | ||
|   points.forEach(function(item, index) {
 | ||
|     if (item !== null) {
 | ||
|       items.push(item);
 | ||
|     } else {
 | ||
|       if (items.length) {
 | ||
|         newPoints.push(items);
 | ||
|       }
 | ||
|       items = [];
 | ||
|     }
 | ||
|   });
 | ||
|   if (items.length) {
 | ||
|     newPoints.push(items);
 | ||
|   }
 | ||
| 
 | ||
|   return newPoints;
 | ||
| }
 | ||
| 
 | ||
| function calLegendData(series, opts, config, chartData) {
 | ||
|   let legendData = {
 | ||
|     area: {
 | ||
|       start: {
 | ||
|         x: 0,
 | ||
|         y: 0
 | ||
|       },
 | ||
|       end: {
 | ||
|         x: 0,
 | ||
|         y: 0
 | ||
|       },
 | ||
|       width: 0,
 | ||
|       height: 0,
 | ||
|       wholeWidth: 0,
 | ||
|       wholeHeight: 0
 | ||
|     },
 | ||
|     points: [],
 | ||
|     widthArr: [],
 | ||
|     heightArr: []
 | ||
|   };
 | ||
|   if (opts.legend.show === false) {
 | ||
|     chartData.legendData = legendData;
 | ||
|     return legendData;
 | ||
|   }
 | ||
| 
 | ||
|   let padding = opts.legend.padding;
 | ||
|   let margin = opts.legend.margin;
 | ||
|   let fontSize = opts.legend.fontSize;
 | ||
|   let shapeWidth = 15 * opts.pixelRatio;
 | ||
|   let shapeRight = 5 * opts.pixelRatio;
 | ||
|   let lineHeight = Math.max(opts.legend.lineHeight * opts.pixelRatio, fontSize);
 | ||
|   if (opts.legend.position == 'top' || opts.legend.position == 'bottom') {
 | ||
|     let legendList = [];
 | ||
|     let widthCount = 0;
 | ||
|     let widthCountArr = [];
 | ||
|     let currentRow = [];
 | ||
|     for (let i = 0; i < series.length; i++) {
 | ||
|       let item = series[i];
 | ||
|       let itemWidth = shapeWidth + shapeRight + measureText(item.name || 'undefined', fontSize) + opts.legend.itemGap;
 | ||
|       if (widthCount + itemWidth > opts.width - opts.padding[1] - opts.padding[3]) {
 | ||
|         legendList.push(currentRow);
 | ||
|         widthCountArr.push(widthCount - opts.legend.itemGap);
 | ||
|         widthCount = itemWidth;
 | ||
|         currentRow = [item];
 | ||
|       } else {
 | ||
|         widthCount += itemWidth;
 | ||
|         currentRow.push(item);
 | ||
|       }
 | ||
|     }
 | ||
|     if (currentRow.length) {
 | ||
|       legendList.push(currentRow);
 | ||
|       widthCountArr.push(widthCount - opts.legend.itemGap);
 | ||
|       legendData.widthArr = widthCountArr;
 | ||
|       let legendWidth = Math.max.apply(null, widthCountArr);
 | ||
|       switch (opts.legend.float) {
 | ||
|         case 'left':
 | ||
|           legendData.area.start.x = opts.padding[3];
 | ||
|           legendData.area.end.x = opts.padding[3] + 2 * padding;
 | ||
|           break;
 | ||
|         case 'right':
 | ||
|           legendData.area.start.x = opts.width - opts.padding[1] - legendWidth - 2 * padding;
 | ||
|           legendData.area.end.x = opts.width - opts.padding[1];
 | ||
|           break;
 | ||
|         default:
 | ||
|           legendData.area.start.x = (opts.width - legendWidth) / 2 - padding;
 | ||
|           legendData.area.end.x = (opts.width + legendWidth) / 2 + padding;
 | ||
|       }
 | ||
|       legendData.area.width = legendWidth + 2 * padding;
 | ||
|       legendData.area.wholeWidth = legendWidth + 2 * padding;
 | ||
|       legendData.area.height = legendList.length * lineHeight + 2 * padding;
 | ||
|       legendData.area.wholeHeight = legendList.length * lineHeight + 2 * padding + 2 * margin;
 | ||
|       legendData.points = legendList;
 | ||
|     }
 | ||
|   } else {
 | ||
|     let len = series.length;
 | ||
|     let maxHeight = opts.height - opts.padding[0] - opts.padding[2] - 2 * margin - 2 * padding;
 | ||
|     let maxLength = Math.min(Math.floor(maxHeight / lineHeight), len);
 | ||
|     legendData.area.height = maxLength * lineHeight + padding * 2;
 | ||
|     legendData.area.wholeHeight = maxLength * lineHeight + padding * 2;
 | ||
|     switch (opts.legend.float) {
 | ||
|       case 'top':
 | ||
|         legendData.area.start.y = opts.padding[0] + margin;
 | ||
|         legendData.area.end.y = opts.padding[0] + margin + legendData.area.height;
 | ||
|         break;
 | ||
|       case 'bottom':
 | ||
|         legendData.area.start.y = opts.height - opts.padding[2] - margin - legendData.area.height;
 | ||
|         legendData.area.end.y = opts.height - opts.padding[2] - margin;
 | ||
|         break;
 | ||
|       default:
 | ||
|         legendData.area.start.y = (opts.height - legendData.area.height) / 2;
 | ||
|         legendData.area.end.y = (opts.height + legendData.area.height) / 2;
 | ||
|     }
 | ||
|     let lineNum = len % maxLength === 0 ? len / maxLength : Math.floor((len / maxLength) + 1);
 | ||
|     let currentRow = [];
 | ||
|     for (let i = 0; i < lineNum; i++) {
 | ||
|       let temp = series.slice(i * maxLength, i * maxLength + maxLength);
 | ||
|       currentRow.push(temp);
 | ||
|     }
 | ||
| 
 | ||
|     legendData.points = currentRow;
 | ||
| 
 | ||
|     if (currentRow.length) {
 | ||
|       for (let i = 0; i < currentRow.length; i++) {
 | ||
|         let item = currentRow[i];
 | ||
|         let maxWidth = 0;
 | ||
|         for (let j = 0; j < item.length; j++) {
 | ||
|           let itemWidth = shapeWidth + shapeRight + measureText(item[j].name || 'undefined', fontSize) + opts.legend.itemGap;
 | ||
|           if (itemWidth > maxWidth) {
 | ||
|             maxWidth = itemWidth;
 | ||
|           }
 | ||
|         }
 | ||
|         legendData.widthArr.push(maxWidth);
 | ||
|         legendData.heightArr.push(item.length * lineHeight + padding * 2);
 | ||
|       }
 | ||
|       let legendWidth = 0
 | ||
|       for (let i = 0; i < legendData.widthArr.length; i++) {
 | ||
|         legendWidth += legendData.widthArr[i];
 | ||
|       }
 | ||
|       legendData.area.width = legendWidth - opts.legend.itemGap + 2 * padding;
 | ||
|       legendData.area.wholeWidth = legendData.area.width + padding;
 | ||
|     }
 | ||
|   }
 | ||
| 
 | ||
|   switch (opts.legend.position) {
 | ||
|     case 'top':
 | ||
|       legendData.area.start.y = opts.padding[0] + margin;
 | ||
|       legendData.area.end.y = opts.padding[0] + margin + legendData.area.height;
 | ||
|       break;
 | ||
|     case 'bottom':
 | ||
|       legendData.area.start.y = opts.height - opts.padding[2] - legendData.area.height - margin;
 | ||
|       legendData.area.end.y = opts.height - opts.padding[2] - margin;
 | ||
|       break;
 | ||
|     case 'left':
 | ||
|       legendData.area.start.x = opts.padding[3];
 | ||
|       legendData.area.end.x = opts.padding[3] + legendData.area.width;
 | ||
|       break;
 | ||
|     case 'right':
 | ||
|       legendData.area.start.x = opts.width - opts.padding[1] - legendData.area.width;
 | ||
|       legendData.area.end.x = opts.width - opts.padding[1];
 | ||
|       break;
 | ||
|   }
 | ||
|   chartData.legendData = legendData;
 | ||
|   return legendData;
 | ||
| }
 | ||
| 
 | ||
| function calCategoriesData(categories, opts, config, eachSpacing) {
 | ||
|   var result = {
 | ||
|     angle: 0,
 | ||
|     xAxisHeight: config.xAxisHeight
 | ||
|   };
 | ||
|   var categoriesTextLenth = categories.map(function(item) {
 | ||
|     return measureText(item,opts.xAxis.fontSize||config.fontSize);
 | ||
|   });
 | ||
|   var maxTextLength = Math.max.apply(this, categoriesTextLenth);
 | ||
| 
 | ||
|   if (opts.xAxis.rotateLabel == true && maxTextLength + 2 * config.xAxisTextPadding > eachSpacing) {
 | ||
|     result.angle = 45 * Math.PI / 180;
 | ||
|     result.xAxisHeight = 2 * config.xAxisTextPadding + maxTextLength * Math.sin(result.angle);
 | ||
|   }
 | ||
|   return result;
 | ||
| }
 | ||
| 
 | ||
| function getXAxisTextList(series, opts, config) {
 | ||
|   var index = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : -1;
 | ||
|   var data = dataCombine(series);
 | ||
|   var sorted = [];
 | ||
|   // remove null from data
 | ||
|   data = data.filter(function(item) {
 | ||
|     //return item !== null;
 | ||
|     if (typeof item === 'object' && item !== null) {
 | ||
|       if (item.constructor == Array) {
 | ||
|         return item !== null;
 | ||
|       } else {
 | ||
|         return item.value !== null;
 | ||
|       }
 | ||
|     } else {
 | ||
|       return item !== null;
 | ||
|     }
 | ||
|   });
 | ||
|   data.map(function(item) {
 | ||
|     if (typeof item === 'object') {
 | ||
|       if (item.constructor == Array) {
 | ||
| 				if(opts.type=='candle'){
 | ||
| 					item.map(function(subitem) {
 | ||
| 					  sorted.push(subitem);
 | ||
| 					})
 | ||
| 				}else{
 | ||
| 					sorted.push(item[0]);
 | ||
| 				}
 | ||
|       } else {
 | ||
|         sorted.push(item.value);
 | ||
|       }
 | ||
|     } else {
 | ||
|       sorted.push(item);
 | ||
|     }
 | ||
|   })
 | ||
| 	
 | ||
|   var minData = 0;
 | ||
|   var maxData = 0;
 | ||
|   if (sorted.length > 0) {
 | ||
|     minData = Math.min.apply(this, sorted);
 | ||
|     maxData = Math.max.apply(this, sorted);
 | ||
|   }
 | ||
|   //为了兼容v1.9.0之前的项目
 | ||
|   if(index>-1){
 | ||
|     if (typeof opts.xAxis.data[index].min === 'number') {
 | ||
|       minData = Math.min(opts.xAxis.data[index].min, minData);
 | ||
|     }
 | ||
|     if (typeof opts.xAxis.data[index].max === 'number') {
 | ||
|       maxData = Math.max(opts.xAxis.data[index].max, maxData);
 | ||
|     }
 | ||
|   }else{
 | ||
|     if (typeof opts.xAxis.min === 'number') {
 | ||
|       minData = Math.min(opts.xAxis.min, minData);
 | ||
|     }
 | ||
|     if (typeof opts.xAxis.max === 'number') {
 | ||
|       maxData = Math.max(opts.xAxis.max, maxData);
 | ||
|     }
 | ||
|   }
 | ||
|   
 | ||
| 
 | ||
|   if (minData === maxData) {
 | ||
|     var rangeSpan = maxData || 10;
 | ||
|     maxData += rangeSpan;
 | ||
|   }
 | ||
| 
 | ||
|   //var dataRange = getDataRange(minData, maxData);
 | ||
|   var minRange = minData;
 | ||
|   var maxRange = maxData;
 | ||
| 
 | ||
|   var range = [];
 | ||
|   var eachRange = (maxRange - minRange) / opts.xAxis.splitNumber;
 | ||
| 
 | ||
|   for (var i = 0; i <= opts.xAxis.splitNumber; i++) {
 | ||
|     range.push(minRange + eachRange * i);
 | ||
|   }
 | ||
|   return range;
 | ||
| }
 | ||
| 
 | ||
| function calXAxisData(series, opts, config){
 | ||
|     var result = {
 | ||
|         angle: 0,
 | ||
|         xAxisHeight: config.xAxisHeight
 | ||
|     };
 | ||
| 
 | ||
|     result.ranges = getXAxisTextList(series, opts, config);
 | ||
|     result.rangesFormat = result.ranges.map(function(item){
 | ||
|         item = opts.xAxis.format? opts.xAxis.format(item):util.toFixed(item, 2);
 | ||
|         return item;
 | ||
|     });
 | ||
| 		
 | ||
|     var xAxisScaleValues = result.ranges.map(function (item) {
 | ||
|         // 如果刻度值是浮点数,则保留两位小数
 | ||
|         item = util.toFixed(item, 2);
 | ||
|         // 若有自定义格式则调用自定义的格式化函数
 | ||
|         item = opts.xAxis.format ? opts.xAxis.format(Number(item)) : item;
 | ||
|         return item;
 | ||
|     });
 | ||
| 
 | ||
|     result = Object.assign(result,getXAxisPoints(xAxisScaleValues, opts, config));
 | ||
|     // 计算X轴刻度的属性譬如每个刻度的间隔,刻度的起始点\结束点以及总长
 | ||
|     var eachSpacing = result.eachSpacing;
 | ||
| 
 | ||
|     var textLength = xAxisScaleValues.map(function (item) {
 | ||
|         return measureText(item);
 | ||
|     });
 | ||
|     
 | ||
|     // get max length of categories text
 | ||
|     var maxTextLength = Math.max.apply(this, textLength);
 | ||
| 
 | ||
|     // 如果刻度值文本内容过长,则将其逆时针旋转45°
 | ||
|     if (maxTextLength + 2 * config.xAxisTextPadding > eachSpacing) {
 | ||
|         result.angle = 45 * Math.PI / 180;
 | ||
|         result.xAxisHeight = 2 * config.xAxisTextPadding + maxTextLength * Math.sin(result.angle);
 | ||
|     }
 | ||
| 
 | ||
|     if (opts.xAxis.disabled === true) {
 | ||
|         result.xAxisHeight = 0;
 | ||
|     }
 | ||
| 
 | ||
|     return result;
 | ||
| }
 | ||
| 
 | ||
| function getRadarDataPoints(angleList, center, radius, series, opts) {
 | ||
|   var process = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : 1;
 | ||
| 
 | ||
|   var radarOption = opts.extra.radar || {};
 | ||
|   radarOption.max = radarOption.max || 0;
 | ||
|   var maxData = Math.max(radarOption.max, Math.max.apply(null, dataCombine(series)));
 | ||
| 
 | ||
|   var data = [];
 | ||
|   for (let i = 0; i < series.length; i++) {
 | ||
|     let each = series[i];
 | ||
|     let listItem = {};
 | ||
|     listItem.color = each.color;
 | ||
| 		listItem.legendShape = each.legendShape;
 | ||
| 		listItem.pointShape = each.pointShape;
 | ||
|     listItem.data = [];
 | ||
|     each.data.forEach(function(item, index) {
 | ||
|       let tmp = {};
 | ||
|       tmp.angle = angleList[index];
 | ||
| 
 | ||
|       tmp.proportion = item / maxData;
 | ||
|       tmp.position = convertCoordinateOrigin(radius * tmp.proportion * process * Math.cos(tmp.angle), radius * tmp.proportion *
 | ||
|         process * Math.sin(tmp.angle), center);
 | ||
|       listItem.data.push(tmp);
 | ||
|     });
 | ||
| 
 | ||
|     data.push(listItem);
 | ||
|   }
 | ||
| 
 | ||
|   return data;
 | ||
| }
 | ||
| 
 | ||
| function getPieDataPoints(series, radius) {
 | ||
|   var process = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 1;
 | ||
| 
 | ||
|   var count = 0;
 | ||
|   var _start_ = 0;
 | ||
|   for (let i = 0; i < series.length; i++) {
 | ||
|     let item = series[i];
 | ||
|     item.data = item.data === null ? 0 : item.data;
 | ||
|     count += item.data;
 | ||
|   }
 | ||
|   for (let i = 0; i < series.length; i++) {
 | ||
|     let item = series[i];
 | ||
|     item.data = item.data === null ? 0 : item.data;
 | ||
|     if (count === 0) {
 | ||
|       item._proportion_ = 1 / series.length * process;
 | ||
|     } else {
 | ||
|       item._proportion_ = item.data / count * process;
 | ||
|     }
 | ||
|     item._radius_ = radius;
 | ||
|   }
 | ||
|   for (let i = 0; i < series.length; i++) {
 | ||
|     let item = series[i];
 | ||
|     item._start_ = _start_;
 | ||
|     _start_ += 2 * item._proportion_ * Math.PI;
 | ||
|   }
 | ||
| 
 | ||
|   return series;
 | ||
| }
 | ||
| 
 | ||
| function getFunnelDataPoints(series, radius) {
 | ||
|   var process = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 1;
 | ||
|   series = series.sort(function(a,b){return parseInt(b.data)-parseInt(a.data);});
 | ||
|   for (let i = 0; i < series.length; i++) {
 | ||
|     series[i].radius = series[i].data/series[0].data*radius*process;
 | ||
|     series[i]._proportion_ = series[i].data/series[0].data;
 | ||
|   }
 | ||
|   return series.reverse();
 | ||
| }
 | ||
| 
 | ||
| function getRoseDataPoints(series, type, minRadius, radius) {
 | ||
|   var process = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 1;
 | ||
|   var count = 0;
 | ||
|   var _start_ = 0;
 | ||
| 
 | ||
|   var dataArr = [];
 | ||
|   for (let i = 0; i < series.length; i++) {
 | ||
|     let item = series[i];
 | ||
|     item.data = item.data === null ? 0 : item.data;
 | ||
|     count += item.data;
 | ||
|     dataArr.push(item.data);
 | ||
|   }
 | ||
|   
 | ||
|   var minData = Math.min.apply(null, dataArr);
 | ||
|   var maxData = Math.max.apply(null, dataArr);
 | ||
|   var radiusLength = radius - minRadius;
 | ||
|   
 | ||
|   for (let i = 0; i < series.length; i++) {
 | ||
|     let item = series[i];
 | ||
|     item.data = item.data === null ? 0 : item.data;
 | ||
|     if (count === 0 || type == 'area') {
 | ||
|       item._proportion_ = item.data / count * process;
 | ||
|       item._rose_proportion_ = 1 / series.length * process;
 | ||
|     } else {
 | ||
|       item._proportion_ = item.data / count * process;
 | ||
|       item._rose_proportion_ = item.data / count * process;
 | ||
|     }
 | ||
|     item._radius_ = minRadius + radiusLength * ((item.data - minData) / (maxData - minData));
 | ||
|   }
 | ||
|   for (let i = 0; i < series.length; i++) {
 | ||
|     let item = series[i];
 | ||
|     item._start_ = _start_;
 | ||
|     _start_ += 2 * item._rose_proportion_ * Math.PI;
 | ||
|   }
 | ||
| 
 | ||
|   return series;
 | ||
| }
 | ||
| 
 | ||
| function getArcbarDataPoints(series, arcbarOption) {
 | ||
|   var process = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 1;
 | ||
|   if (process == 1) {
 | ||
|     process = 0.999999;
 | ||
|   }
 | ||
|   for (let i = 0; i < series.length; i++) {
 | ||
|     let item = series[i];
 | ||
|     item.data = item.data === null ? 0 : item.data;
 | ||
|     let totalAngle;
 | ||
|     if (arcbarOption.type == 'circle') {
 | ||
|       totalAngle = 2;
 | ||
|     } else {
 | ||
| 			if (arcbarOption.endAngle < arcbarOption.startAngle) {
 | ||
| 			  totalAngle = 2 + arcbarOption.endAngle - arcbarOption.startAngle;
 | ||
| 			} else{
 | ||
| 			  totalAngle = arcbarOption.startAngle - arcbarOption.endAngle;
 | ||
| 			}
 | ||
|     }
 | ||
|     item._proportion_ = totalAngle * item.data * process + arcbarOption.startAngle;
 | ||
|     if (item._proportion_ >= 2) {
 | ||
|       item._proportion_ = item._proportion_ % 2;
 | ||
|     }
 | ||
|   }
 | ||
|   return series;
 | ||
| }
 | ||
| 
 | ||
| function getGaugeAxisPoints(categories, startAngle, endAngle) {
 | ||
|   let totalAngle = startAngle - endAngle + 1;
 | ||
|   let tempStartAngle = startAngle;
 | ||
|   for (let i = 0; i < categories.length; i++) {
 | ||
|     categories[i].value = categories[i].value === null ? 0 : categories[i].value;
 | ||
|     categories[i]._startAngle_ = tempStartAngle;
 | ||
|     categories[i]._endAngle_ = totalAngle * categories[i].value + startAngle;
 | ||
|     if (categories[i]._endAngle_ >= 2) {
 | ||
|       categories[i]._endAngle_ = categories[i]._endAngle_ % 2;
 | ||
|     }
 | ||
|     tempStartAngle = categories[i]._endAngle_;
 | ||
|   }
 | ||
|   return categories;
 | ||
| }
 | ||
| 
 | ||
| function getGaugeDataPoints(series, categories, gaugeOption) {
 | ||
|   let process = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 1;
 | ||
|   for (let i = 0; i < series.length; i++) {
 | ||
|     let item = series[i];
 | ||
|     item.data = item.data === null ? 0 : item.data;
 | ||
|     if (gaugeOption.pointer.color == 'auto') {
 | ||
|       for (let i = 0; i < categories.length; i++) {
 | ||
|         if (item.data <= categories[i].value) {
 | ||
|           item.color = categories[i].color;
 | ||
|           break;
 | ||
|         }
 | ||
|       }
 | ||
|     } else {
 | ||
|       item.color = gaugeOption.pointer.color;
 | ||
|     }
 | ||
|     let totalAngle = gaugeOption.startAngle - gaugeOption.endAngle + 1;
 | ||
|     item._endAngle_ = totalAngle * item.data + gaugeOption.startAngle;
 | ||
|     item._oldAngle_ = gaugeOption.oldAngle;
 | ||
|     if (gaugeOption.oldAngle < gaugeOption.endAngle) {
 | ||
|       item._oldAngle_ += 2;
 | ||
|     }
 | ||
|     if (item.data >= gaugeOption.oldData) {
 | ||
|       item._proportion_ = (item._endAngle_ - item._oldAngle_) * process + gaugeOption.oldAngle;
 | ||
|     } else {
 | ||
|       item._proportion_ = item._oldAngle_ - (item._oldAngle_ - item._endAngle_) * process;
 | ||
|     }
 | ||
|     if (item._proportion_ >= 2) {
 | ||
|       item._proportion_ = item._proportion_ % 2;
 | ||
|     }
 | ||
|   }
 | ||
|   return series;
 | ||
| }
 | ||
| 
 | ||
| function getPieTextMaxLength(series) {
 | ||
|   series = getPieDataPoints(series);
 | ||
|   let maxLength = 0;
 | ||
|   for (let i = 0; i < series.length; i++) {
 | ||
|     let item = series[i];
 | ||
|     let text = item.format ? item.format(+item._proportion_.toFixed(2)) : util.toFixed(item._proportion_ * 100) + '%';
 | ||
|     maxLength = Math.max(maxLength, measureText(text));
 | ||
|   }
 | ||
| 
 | ||
|   return maxLength;
 | ||
| }
 | ||
| 
 | ||
| function fixColumeData(points, eachSpacing, columnLen, index, config, opts) {
 | ||
|   return points.map(function(item) {
 | ||
|     if (item === null) {
 | ||
|       return null;
 | ||
|     }
 | ||
|     item.width = Math.ceil((eachSpacing - 2 * config.columePadding) / columnLen);
 | ||
| 
 | ||
|     if (opts.extra.column && opts.extra.column.width && +opts.extra.column.width > 0) {
 | ||
|       item.width = Math.min(item.width, +opts.extra.column.width);
 | ||
|     }
 | ||
|     if (item.width <= 0) {
 | ||
|       item.width = 1;
 | ||
|     }
 | ||
|     item.x += (index + 0.5 - columnLen / 2) * item.width;
 | ||
|     return item;
 | ||
|   });
 | ||
| }
 | ||
| 
 | ||
| function fixColumeMeterData(points, eachSpacing, columnLen, index, config, opts, border) {
 | ||
|   return points.map(function(item) {
 | ||
|     if (item === null) {
 | ||
|       return null;
 | ||
|     }
 | ||
|     item.width = Math.ceil((eachSpacing - 2 * config.columePadding) / 2);
 | ||
| 
 | ||
|     if (opts.extra.column && opts.extra.column.width && +opts.extra.column.width > 0) {
 | ||
|       item.width = Math.min(item.width, +opts.extra.column.width);
 | ||
|     }
 | ||
| 
 | ||
|     if (index > 0) {
 | ||
|       item.width -= 2 * border;
 | ||
|     }
 | ||
|     return item;
 | ||
|   });
 | ||
| }
 | ||
| 
 | ||
| function fixColumeStackData(points, eachSpacing, columnLen, index, config, opts, series) {
 | ||
| 
 | ||
|   return points.map(function(item, indexn) {
 | ||
| 
 | ||
|     if (item === null) {
 | ||
|       return null;
 | ||
|     }
 | ||
|     item.width = Math.ceil((eachSpacing - 2 * config.columePadding) / 2);
 | ||
| 
 | ||
|     if (opts.extra.column && opts.extra.column.width && +opts.extra.column.width > 0) {
 | ||
|       item.width = Math.min(item.width, +opts.extra.column.width);
 | ||
|     }
 | ||
|     return item;
 | ||
|   });
 | ||
| }
 | ||
| 
 | ||
| function getXAxisPoints(categories, opts, config) {
 | ||
|   var spacingValid = opts.width - opts.area[1] - opts.area[3];
 | ||
|   var dataCount = opts.enableScroll ? Math.min(opts.xAxis.itemCount, categories.length) : categories.length;
 | ||
|   if((opts.type=='line' || opts.type=='area') && dataCount>1 && opts.xAxis.boundaryGap=='justify'){
 | ||
|     dataCount -=1;
 | ||
|   }
 | ||
|   var eachSpacing = spacingValid / dataCount;
 | ||
| 
 | ||
|   var xAxisPoints = [];
 | ||
|   var startX = opts.area[3];
 | ||
|   var endX = opts.width - opts.area[1];
 | ||
|   categories.forEach(function(item, index) {
 | ||
|     xAxisPoints.push(startX + index * eachSpacing);
 | ||
|   });
 | ||
|   if(opts.xAxis.boundaryGap !=='justify'){
 | ||
|     if (opts.enableScroll === true) {
 | ||
|       xAxisPoints.push(startX + categories.length * eachSpacing);
 | ||
|     } else {
 | ||
|       xAxisPoints.push(endX);
 | ||
|     }
 | ||
|   }
 | ||
|   return {
 | ||
|     xAxisPoints: xAxisPoints,
 | ||
|     startX: startX,
 | ||
|     endX: endX,
 | ||
|     eachSpacing: eachSpacing
 | ||
|   };
 | ||
| }
 | ||
| 
 | ||
| function getCandleDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config) {
 | ||
|   var process = arguments.length > 7 && arguments[7] !== undefined ? arguments[7] : 1;
 | ||
|   var points = [];
 | ||
|   var validHeight = opts.height - opts.area[0] - opts.area[2];
 | ||
|   data.forEach(function(item, index) {
 | ||
|     if (item === null) {
 | ||
|       points.push(null);
 | ||
|     } else {
 | ||
|       var cPoints = [];
 | ||
|       item.forEach(function(items, indexs) {
 | ||
|         var point = {};
 | ||
|         point.x = xAxisPoints[index] + Math.round(eachSpacing / 2);
 | ||
|         var value = items.value || items;
 | ||
|         var height = validHeight * (value - minRange) / (maxRange - minRange);
 | ||
|         height *= process;
 | ||
|         point.y = opts.height - Math.round(height) - opts.area[2];
 | ||
|         cPoints.push(point);
 | ||
|       });
 | ||
|       points.push(cPoints);
 | ||
|     }
 | ||
|   });
 | ||
| 
 | ||
|   return points;
 | ||
| }
 | ||
| 
 | ||
| function getDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config) {
 | ||
|   var process = arguments.length > 7 && arguments[7] !== undefined ? arguments[7] : 1;
 | ||
|   var boundaryGap='center';
 | ||
|   if (opts.type == 'line'||opts.type == 'area'){
 | ||
|     boundaryGap=opts.xAxis.boundaryGap;
 | ||
|   }
 | ||
|   var points = [];
 | ||
|   var validHeight = opts.height - opts.area[0] - opts.area[2];
 | ||
| 	var validWidth = opts.width - opts.area[1] - opts.area[3];
 | ||
|   data.forEach(function(item, index) {
 | ||
|     if (item === null) {
 | ||
|       points.push(null);
 | ||
|     } else {
 | ||
|       var point = {};
 | ||
|       point.color = item.color;
 | ||
|       point.x = xAxisPoints[index];
 | ||
|       var value = item;
 | ||
|       if (typeof item === 'object' && item !== null) {
 | ||
| 				if (item.constructor == Array) {
 | ||
| 					let xranges,xminRange,xmaxRange;
 | ||
| 					xranges = [].concat(opts.chartData.xAxisData.ranges);
 | ||
| 					xminRange = xranges.shift();
 | ||
| 					xmaxRange = xranges.pop();
 | ||
| 				  value = item[1];
 | ||
| 					point.x = opts.area[3]+ validWidth * (item[0] - xminRange) / (xmaxRange - xminRange);
 | ||
| 				} else {
 | ||
| 				  value = item.value;
 | ||
| 				}
 | ||
|       }
 | ||
| 			if(boundaryGap=='center'){
 | ||
| 			  point.x += Math.round(eachSpacing / 2);
 | ||
| 			}
 | ||
|       var height = validHeight * (value - minRange) / (maxRange - minRange);
 | ||
|       height *= process;
 | ||
|       point.y = opts.height - Math.round(height) - opts.area[2];
 | ||
|       points.push(point);
 | ||
|     }
 | ||
|   });
 | ||
| 
 | ||
|   return points;
 | ||
| }
 | ||
| 
 | ||
| function getStackDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config, seriesIndex, stackSeries) {
 | ||
|   var process = arguments.length > 9 && arguments[9] !== undefined ? arguments[9] : 1;
 | ||
|   var points = [];
 | ||
|   var validHeight = opts.height - opts.area[0] - opts.area[2];
 | ||
| 
 | ||
|   data.forEach(function(item, index) {
 | ||
|     if (item === null) {
 | ||
|       points.push(null);
 | ||
|     } else {
 | ||
|       var point = {};
 | ||
|       point.color = item.color;
 | ||
|       point.x = xAxisPoints[index] + Math.round(eachSpacing / 2);
 | ||
| 
 | ||
|       if (seriesIndex > 0) {
 | ||
|         var value = 0;
 | ||
|         for (let i = 0; i <= seriesIndex; i++) {
 | ||
|           value += stackSeries[i].data[index];
 | ||
|         }
 | ||
|         var value0 = value - item;
 | ||
|         var height = validHeight * (value - minRange) / (maxRange - minRange);
 | ||
|         var height0 = validHeight * (value0 - minRange) / (maxRange - minRange);
 | ||
|       } else {
 | ||
|         var value = item;
 | ||
|         var height = validHeight * (value - minRange) / (maxRange - minRange);
 | ||
|         var height0 = 0;
 | ||
|       }
 | ||
|       var heightc = height0;
 | ||
|       height *= process;
 | ||
|       heightc *= process;
 | ||
|       point.y = opts.height - Math.round(height) - opts.area[2];
 | ||
|       point.y0 = opts.height - Math.round(heightc) - opts.area[2];
 | ||
|       points.push(point);
 | ||
|     }
 | ||
|   });
 | ||
| 
 | ||
|   return points;
 | ||
| }
 | ||
| 
 | ||
| function getYAxisTextList(series, opts, config, stack) {
 | ||
|   var index = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : -1;
 | ||
|   var data;
 | ||
|   if (stack == 'stack') {
 | ||
|     data = dataCombineStack(series, opts.categories.length);
 | ||
|   } else {
 | ||
|     data = dataCombine(series);
 | ||
|   }
 | ||
|   var sorted = [];
 | ||
|   // remove null from data
 | ||
|   data = data.filter(function(item) {
 | ||
|     //return item !== null;
 | ||
|     if (typeof item === 'object' && item !== null) {
 | ||
|       if (item.constructor == Array) {
 | ||
|         return item !== null;
 | ||
|       } else {
 | ||
|         return item.value !== null;
 | ||
|       }
 | ||
|     } else {
 | ||
|       return item !== null;
 | ||
|     }
 | ||
|   });
 | ||
|   data.map(function(item) {
 | ||
|     if (typeof item === 'object') {
 | ||
|       if (item.constructor == Array) {
 | ||
| 				if(opts.type=='candle'){
 | ||
| 					item.map(function(subitem) {
 | ||
| 					  sorted.push(subitem);
 | ||
| 					})
 | ||
| 				}else{
 | ||
| 					sorted.push(item[1]);
 | ||
| 				}
 | ||
|       } else {
 | ||
|         sorted.push(item.value);
 | ||
|       }
 | ||
|     } else {
 | ||
|       sorted.push(item);
 | ||
|     }
 | ||
|   })
 | ||
| 	
 | ||
|   var minData = 0;
 | ||
|   var maxData = 0;
 | ||
|   if (sorted.length > 0) {
 | ||
|     minData = Math.min.apply(this, sorted);
 | ||
|     maxData = Math.max.apply(this, sorted);
 | ||
|   }
 | ||
|   //为了兼容v1.9.0之前的项目
 | ||
|   if(index>-1){
 | ||
|     if (typeof opts.yAxis.data[index].min === 'number') {
 | ||
|       minData = Math.min(opts.yAxis.data[index].min, minData);
 | ||
|     }
 | ||
|     if (typeof opts.yAxis.data[index].max === 'number') {
 | ||
|       maxData = Math.max(opts.yAxis.data[index].max, maxData);
 | ||
|     }
 | ||
|   }else{
 | ||
|     if (typeof opts.yAxis.min === 'number') {
 | ||
|       minData = Math.min(opts.yAxis.min, minData);
 | ||
|     }
 | ||
|     if (typeof opts.yAxis.max === 'number') {
 | ||
|       maxData = Math.max(opts.yAxis.max, maxData);
 | ||
|     }
 | ||
|   }
 | ||
|   
 | ||
| 
 | ||
|   if (minData === maxData) {
 | ||
|     var rangeSpan = maxData || 10;
 | ||
|     maxData += rangeSpan;
 | ||
|   }
 | ||
| 
 | ||
|   var dataRange = getDataRange(minData, maxData);
 | ||
|   var minRange = dataRange.minRange;
 | ||
|   var maxRange = dataRange.maxRange;
 | ||
| 
 | ||
|   var range = [];
 | ||
|   var eachRange = (maxRange - minRange) / opts.yAxis.splitNumber;
 | ||
| 
 | ||
|   for (var i = 0; i <= opts.yAxis.splitNumber; i++) {
 | ||
|     range.push(minRange + eachRange * i);
 | ||
|   }
 | ||
|   return range.reverse();
 | ||
| }
 | ||
| 
 | ||
| function calYAxisData(series, opts, config) {
 | ||
|   //堆叠图重算Y轴
 | ||
|   var columnstyle = assign({}, {
 | ||
|     type: ""
 | ||
|   }, opts.extra.column);
 | ||
|   //如果是多Y轴,重新计算
 | ||
|   var YLength = opts.yAxis.data.length;
 | ||
|   var newSeries=new Array(YLength);
 | ||
|   if(YLength>0){
 | ||
|     for(let i=0;i<YLength;i++){
 | ||
|       newSeries[i]=[];
 | ||
|       for(let j=0;j<series.length;j++){
 | ||
|         if(series[j].index == i){
 | ||
|           newSeries[i].push(series[j]);
 | ||
|         }
 | ||
|       }
 | ||
|     }
 | ||
|     var rangesArr =new Array(YLength);
 | ||
|     var rangesFormatArr = new Array(YLength);
 | ||
|     var yAxisWidthArr =new Array(YLength);
 | ||
| 		
 | ||
|     for(let i=0;i<YLength;i++){
 | ||
|       let yData = opts.yAxis.data[i];
 | ||
| 			//如果总开关不显示,强制每个Y轴为不显示
 | ||
| 			if(opts.yAxis.disabled == true){
 | ||
| 				yData.disabled = true;
 | ||
| 			}
 | ||
| 			rangesArr[i]=getYAxisTextList(newSeries[i], opts, config, columnstyle.type,i);
 | ||
| 			let yAxisFontSizes = yData.fontSize || config.fontSize;
 | ||
| 			yAxisWidthArr[i] = {position:yData.position?yData.position:'left',width:0};
 | ||
| 			rangesFormatArr[i]= rangesArr[i].map(function(items) {
 | ||
| 				items = util.toFixed(items, 6);
 | ||
| 				items = yData.format ? yData.format(Number(items)) : items;
 | ||
| 				yAxisWidthArr[i].width = Math.max(yAxisWidthArr[i].width, measureText(items, yAxisFontSizes) + 5);
 | ||
| 				return items;
 | ||
| 			});
 | ||
| 			let calibration= yData.calibration? 4*opts.pixelRatio : 0 ;
 | ||
| 			yAxisWidthArr[i].width += calibration +3*opts.pixelRatio;
 | ||
|       if (yData.disabled === true) {
 | ||
|         yAxisWidthArr[i].width=0;
 | ||
|       }
 | ||
|     }
 | ||
|     
 | ||
|   }else{
 | ||
|     var rangesArr =new Array(1);
 | ||
|     var rangesFormatArr = new Array(1);
 | ||
|     var yAxisWidthArr =new Array(1);
 | ||
| 		rangesArr[0] = getYAxisTextList(series, opts, config, columnstyle.type);
 | ||
| 		yAxisWidthArr[0] = {position:'left',width:0};
 | ||
| 		var yAxisFontSize = opts.yAxis.fontSize || config.fontSize;
 | ||
| 		rangesFormatArr[0] = rangesArr[0].map(function(item) {
 | ||
| 			item = util.toFixed(item, 6);
 | ||
| 			item = opts.yAxis.format ? opts.yAxis.format(Number(item)) : item;
 | ||
| 			yAxisWidthArr[0].width = Math.max(yAxisWidthArr[0].width, measureText(item, yAxisFontSize) + 5);
 | ||
| 			return item;
 | ||
| 		});
 | ||
| 		yAxisWidthArr[0].width += 3*opts.pixelRatio;
 | ||
| 		if (opts.yAxis.disabled === true) {
 | ||
| 		  yAxisWidthArr[0] = {position:'left',width:0};
 | ||
| 		  opts.yAxis.data[0]={disabled:true};
 | ||
| 		}else{
 | ||
| 			opts.yAxis.data[0]={disabled:false,position:'left',max:opts.yAxis.max,min:opts.yAxis.min,format:opts.yAxis.format};
 | ||
| 		}
 | ||
|     
 | ||
|   }
 | ||
| 
 | ||
|   return {
 | ||
|     rangesFormat: rangesFormatArr,
 | ||
|     ranges: rangesArr,
 | ||
|     yAxisWidth: yAxisWidthArr
 | ||
|   };
 | ||
|   
 | ||
| }
 | ||
| 
 | ||
| function calTooltipYAxisData(point, series, opts, config, eachSpacing) {
 | ||
|   let ranges = [].concat(opts.chartData.yAxisData.ranges);
 | ||
|   let spacingValid = opts.height - opts.area[0] - opts.area[2];
 | ||
|   let minAxis = opts.area[0];
 | ||
|   let items=[];
 | ||
|   for(let i=0;i<ranges.length;i++){
 | ||
|     let maxVal = ranges[i].shift();
 | ||
|     let minVal = ranges[i].pop();
 | ||
|     let item = maxVal - (maxVal - minVal) * (point - minAxis) / spacingValid;
 | ||
|     item = opts.yAxis.data[i].format ? opts.yAxis.data[i].format(Number(item)) : item.toFixed(0);
 | ||
|     items.push(String(item))
 | ||
|   }
 | ||
|   return items;
 | ||
| }
 | ||
| 
 | ||
| function calMarkLineData(points, opts) {
 | ||
|   let minRange, maxRange;
 | ||
|   let spacingValid = opts.height - opts.area[0] - opts.area[2];
 | ||
|   for (let i = 0; i < points.length; i++) {
 | ||
|     points[i].yAxisIndex = points[i].yAxisIndex ? points[i].yAxisIndex:0;
 | ||
|     let range = [].concat(opts.chartData.yAxisData.ranges[points[i].yAxisIndex]);
 | ||
|     minRange = range.pop();
 | ||
|     maxRange = range.shift();
 | ||
|     let height = spacingValid * (points[i].value - minRange) / (maxRange - minRange);
 | ||
|     points[i].y = opts.height - Math.round(height) - opts.area[2];
 | ||
|   }
 | ||
|   return points;
 | ||
| }
 | ||
| 
 | ||
| function contextRotate(context, opts) {
 | ||
|   if (opts.rotateLock !== true) {
 | ||
|     context.translate(opts.height, 0);
 | ||
|     context.rotate(90 * Math.PI / 180);
 | ||
|   } else if (opts._rotate_ !== true) {
 | ||
|     context.translate(opts.height, 0);
 | ||
|     context.rotate(90 * Math.PI / 180);
 | ||
|     opts._rotate_ = true;
 | ||
|   }
 | ||
| }
 | ||
| 
 | ||
| function drawPointShape(points, color, shape, context, opts) {
 | ||
|   context.beginPath();
 | ||
| 	if(opts.dataPointShapeType == 'hollow'){
 | ||
| 		context.setStrokeStyle(color);
 | ||
| 		context.setFillStyle(opts.background);
 | ||
| 		context.setLineWidth(2 * opts.pixelRatio);
 | ||
| 	}else{
 | ||
| 		context.setStrokeStyle("#ffffff");
 | ||
| 		context.setFillStyle(color);
 | ||
| 		context.setLineWidth(1 * opts.pixelRatio);
 | ||
| 	}
 | ||
|   if (shape === 'diamond') {
 | ||
|     points.forEach(function(item, index) {
 | ||
|       if (item !== null) {
 | ||
|         context.moveTo(item.x, item.y - 4.5);
 | ||
|         context.lineTo(item.x - 4.5, item.y);
 | ||
|         context.lineTo(item.x, item.y + 4.5);
 | ||
|         context.lineTo(item.x + 4.5, item.y);
 | ||
|         context.lineTo(item.x, item.y - 4.5);
 | ||
|       }
 | ||
|     });
 | ||
|   } else if (shape === 'circle') {
 | ||
|     points.forEach(function(item, index) {
 | ||
|       if (item !== null) {
 | ||
|         context.moveTo(item.x + 2.5 * opts.pixelRatio, item.y);
 | ||
|         context.arc(item.x, item.y, 3 * opts.pixelRatio, 0, 2 * Math.PI, false);
 | ||
|       }
 | ||
|     });
 | ||
|   } else if (shape === 'rect') {
 | ||
|     points.forEach(function(item, index) {
 | ||
|       if (item !== null) {
 | ||
|         context.moveTo(item.x - 3.5, item.y - 3.5);
 | ||
|         context.rect(item.x - 3.5, item.y - 3.5, 7, 7);
 | ||
|       }
 | ||
|     });
 | ||
|   } else if (shape === 'triangle') {
 | ||
|     points.forEach(function(item, index) {
 | ||
|       if (item !== null) {
 | ||
|         context.moveTo(item.x, item.y - 4.5);
 | ||
|         context.lineTo(item.x - 4.5, item.y + 4.5);
 | ||
|         context.lineTo(item.x + 4.5, item.y + 4.5);
 | ||
|         context.lineTo(item.x, item.y - 4.5);
 | ||
|       }
 | ||
|     });
 | ||
|   }
 | ||
|   context.closePath();
 | ||
|   context.fill();
 | ||
|   context.stroke();
 | ||
| }
 | ||
| 
 | ||
| function drawRingTitle(opts, config, context, center) {
 | ||
|   var titlefontSize = opts.title.fontSize || config.titleFontSize;
 | ||
|   var subtitlefontSize = opts.subtitle.fontSize || config.subtitleFontSize;
 | ||
|   var title = opts.title.name || '';
 | ||
|   var subtitle = opts.subtitle.name || '';
 | ||
|   var titleFontColor = opts.title.color || config.titleColor;
 | ||
|   var subtitleFontColor = opts.subtitle.color || config.subtitleColor;
 | ||
|   var titleHeight = title ? titlefontSize : 0;
 | ||
|   var subtitleHeight = subtitle ? subtitlefontSize : 0;
 | ||
|   var margin = 5;
 | ||
| 
 | ||
|   if (subtitle) {
 | ||
|     var textWidth = measureText(subtitle, subtitlefontSize);
 | ||
|     var startX = center.x - textWidth / 2 + (opts.subtitle.offsetX || 0);
 | ||
|     var startY = center.y + subtitlefontSize / 2 + (opts.subtitle.offsetY || 0);
 | ||
|     if (title) {
 | ||
|       startY += (titleHeight + margin) / 2;
 | ||
|     }
 | ||
|     context.beginPath();
 | ||
|     context.setFontSize(subtitlefontSize);
 | ||
|     context.setFillStyle(subtitleFontColor);
 | ||
|     context.fillText(subtitle, startX, startY);
 | ||
|     context.closePath();
 | ||
|     context.stroke();
 | ||
|   }
 | ||
|   if (title) {
 | ||
|     var _textWidth = measureText(title, titlefontSize);
 | ||
|     var _startX = center.x - _textWidth / 2 + (opts.title.offsetX || 0);
 | ||
|     var _startY = center.y + titlefontSize / 2 + (opts.title.offsetY || 0);
 | ||
|     if (subtitle) {
 | ||
|       _startY -= (subtitleHeight + margin) / 2;
 | ||
|     }
 | ||
|     context.beginPath();
 | ||
|     context.setFontSize(titlefontSize);
 | ||
|     context.setFillStyle(titleFontColor);
 | ||
|     context.fillText(title, _startX, _startY);
 | ||
|     context.closePath();
 | ||
|     context.stroke();
 | ||
|   }
 | ||
| }
 | ||
| 
 | ||
| function drawPointText(points, series, config, context) {
 | ||
|   // 绘制数据文案
 | ||
|   var data = series.data;
 | ||
|   points.forEach(function(item, index) {
 | ||
|     if (item !== null) {
 | ||
|       //var formatVal = series.format ? series.format(data[index]) : data[index];
 | ||
|       context.beginPath();
 | ||
|       context.setFontSize(series.textSize || config.fontSize);
 | ||
|       context.setFillStyle(series.textColor || '#666666');
 | ||
|       var value = data[index]
 | ||
|       if (typeof data[index] === 'object' && data[index] !== null) {
 | ||
| 				if (data[index].constructor == Array) {
 | ||
| 					value = data[index][1];
 | ||
| 				}else{
 | ||
| 					value = data[index].value
 | ||
| 				}
 | ||
|       }
 | ||
|       var formatVal = series.format ? series.format(value) : value;
 | ||
|       context.fillText(String(formatVal), item.x - measureText(formatVal, series.textSize || config.fontSize) / 2, item.y -4);
 | ||
|       context.closePath();
 | ||
|       context.stroke();
 | ||
|     }
 | ||
|   });
 | ||
| 
 | ||
| }
 | ||
| 
 | ||
| function drawGaugeLabel(gaugeOption, radius, centerPosition, opts, config, context) {
 | ||
|   radius -= gaugeOption.width / 2 + config.gaugeLabelTextMargin;
 | ||
| 
 | ||
|   let totalAngle = gaugeOption.startAngle - gaugeOption.endAngle + 1;
 | ||
|   let splitAngle = totalAngle / gaugeOption.splitLine.splitNumber;
 | ||
|   let totalNumber = gaugeOption.endNumber - gaugeOption.startNumber;
 | ||
|   let splitNumber = totalNumber / gaugeOption.splitLine.splitNumber;
 | ||
|   let nowAngle = gaugeOption.startAngle;
 | ||
|   let nowNumber = gaugeOption.startNumber;
 | ||
|   for (let i = 0; i < gaugeOption.splitLine.splitNumber + 1; i++) {
 | ||
|     var pos = {
 | ||
|       x: radius * Math.cos(nowAngle * Math.PI),
 | ||
|       y: radius * Math.sin(nowAngle * Math.PI)
 | ||
|     };
 | ||
|     var labelText = gaugeOption.labelFormat ? gaugeOption.labelFormat(nowNumber) : nowNumber;
 | ||
|     pos.x += centerPosition.x - measureText(labelText) / 2;
 | ||
|     pos.y += centerPosition.y;
 | ||
|     var startX = pos.x;
 | ||
|     var startY = pos.y;
 | ||
|     context.beginPath();
 | ||
|     context.setFontSize(config.fontSize);
 | ||
|     context.setFillStyle(gaugeOption.labelColor || '#666666');
 | ||
|     context.fillText(labelText, startX, startY + config.fontSize / 2);
 | ||
|     context.closePath();
 | ||
|     context.stroke();
 | ||
| 
 | ||
|     nowAngle += splitAngle;
 | ||
|     if (nowAngle >= 2) {
 | ||
|       nowAngle = nowAngle % 2;
 | ||
|     }
 | ||
|     nowNumber += splitNumber;
 | ||
|   }
 | ||
| 
 | ||
| }
 | ||
| 
 | ||
| function drawRadarLabel(angleList, radius, centerPosition, opts, config, context) {
 | ||
|   var radarOption = opts.extra.radar || {};
 | ||
|   radius += config.radarLabelTextMargin;
 | ||
| 
 | ||
|   angleList.forEach(function(angle, index) {
 | ||
|     var pos = {
 | ||
|       x: radius * Math.cos(angle),
 | ||
|       y: radius * Math.sin(angle)
 | ||
|     };
 | ||
|     var posRelativeCanvas = convertCoordinateOrigin(pos.x, pos.y, centerPosition);
 | ||
|     var startX = posRelativeCanvas.x;
 | ||
|     var startY = posRelativeCanvas.y;
 | ||
|     if (util.approximatelyEqual(pos.x, 0)) {
 | ||
|       startX -= measureText(opts.categories[index] || '') / 2;
 | ||
|     } else if (pos.x < 0) {
 | ||
|       startX -= measureText(opts.categories[index] || '');
 | ||
|     }
 | ||
|     context.beginPath();
 | ||
|     context.setFontSize(config.fontSize);
 | ||
|     context.setFillStyle(radarOption.labelColor || '#666666');
 | ||
|     context.fillText(opts.categories[index] || '', startX, startY + config.fontSize / 2);
 | ||
|     context.closePath();
 | ||
|     context.stroke();
 | ||
|   });
 | ||
| 
 | ||
| }
 | ||
| 
 | ||
| function drawPieText(series, opts, config, context, radius, center) {
 | ||
|   var lineRadius = config.pieChartLinePadding;
 | ||
|   var textObjectCollection = [];
 | ||
|   var lastTextObject = null;
 | ||
| 
 | ||
|   var seriesConvert = series.map(function(item) {
 | ||
|     var text = item.format ? item.format(+item._proportion_.toFixed(2)) : util.toFixed(item._proportion_.toFixed(4) * 100) +'%';
 | ||
|     if(item._rose_proportion_) item._proportion_=item._rose_proportion_;
 | ||
|     var arc = 2 * Math.PI - (item._start_ + 2 * Math.PI * item._proportion_ / 2);
 | ||
|     var color = item.color;
 | ||
|     var radius = item._radius_;
 | ||
|     return {
 | ||
|       arc: arc,
 | ||
|       text: text,
 | ||
|       color: color,
 | ||
|       radius: radius,
 | ||
|       textColor: item.textColor,
 | ||
|       textSize: item.textSize,
 | ||
|     };
 | ||
|   });
 | ||
|   for (let i = 0; i < seriesConvert.length; i++) {
 | ||
|     let item = seriesConvert[i];
 | ||
|     // line end
 | ||
|     let orginX1 = Math.cos(item.arc) * (item.radius + lineRadius);
 | ||
|     let orginY1 = Math.sin(item.arc) * (item.radius + lineRadius);
 | ||
| 
 | ||
|     // line start
 | ||
|     let orginX2 = Math.cos(item.arc) * item.radius;
 | ||
|     let orginY2 = Math.sin(item.arc) * item.radius;
 | ||
| 
 | ||
|     // text start
 | ||
|     let orginX3 = orginX1 >= 0 ? orginX1 + config.pieChartTextPadding : orginX1 - config.pieChartTextPadding;
 | ||
|     let orginY3 = orginY1;
 | ||
|     let textWidth = measureText(item.text,item.textSize||config.fontSize);
 | ||
|     let startY = orginY3;
 | ||
| 
 | ||
|     if (lastTextObject && util.isSameXCoordinateArea(lastTextObject.start, {
 | ||
|         x: orginX3
 | ||
|       })) {
 | ||
|       if (orginX3 > 0) {
 | ||
|         startY = Math.min(orginY3, lastTextObject.start.y);
 | ||
|       } else if (orginX1 < 0) {
 | ||
|         startY = Math.max(orginY3, lastTextObject.start.y);
 | ||
|       } else {
 | ||
|         if (orginY3 > 0) {
 | ||
|           startY = Math.max(orginY3, lastTextObject.start.y);
 | ||
|         } else {
 | ||
|           startY = Math.min(orginY3, lastTextObject.start.y);
 | ||
|         }
 | ||
|       }
 | ||
|     }
 | ||
|     if (orginX3 < 0) {
 | ||
|       orginX3 -= textWidth;
 | ||
|     }
 | ||
| 
 | ||
|     let textObject = {
 | ||
|       lineStart: {
 | ||
|         x: orginX2,
 | ||
|         y: orginY2
 | ||
|       },
 | ||
|       lineEnd: {
 | ||
|         x: orginX1,
 | ||
|         y: orginY1
 | ||
|       },
 | ||
|       start: {
 | ||
|         x: orginX3,
 | ||
|         y: startY
 | ||
|       },
 | ||
|       width: textWidth,
 | ||
|       height: config.fontSize,
 | ||
|       text: item.text,
 | ||
|       color: item.color,
 | ||
|       textColor: item.textColor,
 | ||
|       textSize: item.textSize
 | ||
|     };
 | ||
|     lastTextObject = avoidCollision(textObject, lastTextObject);
 | ||
|     textObjectCollection.push(lastTextObject);
 | ||
|   }
 | ||
| 
 | ||
|   for (let i = 0; i < textObjectCollection.length; i++) {
 | ||
|     let item = textObjectCollection[i];
 | ||
|     let lineStartPoistion = convertCoordinateOrigin(item.lineStart.x, item.lineStart.y, center);
 | ||
|     let lineEndPoistion = convertCoordinateOrigin(item.lineEnd.x, item.lineEnd.y, center);
 | ||
|     let textPosition = convertCoordinateOrigin(item.start.x, item.start.y, center);
 | ||
|     context.setLineWidth(1 * opts.pixelRatio);
 | ||
|     context.setFontSize(config.fontSize);
 | ||
|     context.beginPath();
 | ||
|     context.setStrokeStyle(item.color);
 | ||
|     context.setFillStyle(item.color);
 | ||
|     context.moveTo(lineStartPoistion.x, lineStartPoistion.y);
 | ||
|     let curveStartX = item.start.x < 0 ? textPosition.x + item.width : textPosition.x;
 | ||
|     let textStartX = item.start.x < 0 ? textPosition.x - 5 : textPosition.x + 5;
 | ||
|     context.quadraticCurveTo(lineEndPoistion.x, lineEndPoistion.y, curveStartX, textPosition.y);
 | ||
|     context.moveTo(lineStartPoistion.x, lineStartPoistion.y);
 | ||
|     context.stroke();
 | ||
|     context.closePath();
 | ||
|     context.beginPath();
 | ||
|     context.moveTo(textPosition.x + item.width, textPosition.y);
 | ||
|     context.arc(curveStartX, textPosition.y, 2, 0, 2 * Math.PI);
 | ||
|     context.closePath();
 | ||
|     context.fill();
 | ||
|     context.beginPath();
 | ||
|     context.setFontSize(item.textSize || config.fontSize);
 | ||
|     context.setFillStyle(item.textColor || '#666666');
 | ||
|     context.fillText(item.text, textStartX, textPosition.y + 3);
 | ||
|     context.closePath();
 | ||
|     context.stroke();
 | ||
|     context.closePath();
 | ||
|   }
 | ||
| }
 | ||
| 
 | ||
| function drawToolTipSplitLine(offsetX, opts, config, context) {
 | ||
|   var toolTipOption = opts.extra.tooltip || {};
 | ||
|   toolTipOption.gridType = toolTipOption.gridType == undefined ? 'solid' : toolTipOption.gridType;
 | ||
|   toolTipOption.dashLength = toolTipOption.dashLength == undefined ? 4 : toolTipOption.dashLength;
 | ||
|   var startY = opts.area[0];
 | ||
|   var endY = opts.height - opts.area[2];
 | ||
| 
 | ||
|   if (toolTipOption.gridType == 'dash') {
 | ||
|     context.setLineDash([toolTipOption.dashLength, toolTipOption.dashLength]);
 | ||
|   }
 | ||
|   context.setStrokeStyle(toolTipOption.gridColor || '#cccccc');
 | ||
|   context.setLineWidth(1 * opts.pixelRatio);
 | ||
|   context.beginPath();
 | ||
|   context.moveTo(offsetX, startY);
 | ||
|   context.lineTo(offsetX, endY);
 | ||
|   context.stroke();
 | ||
|   context.setLineDash([]);
 | ||
| 
 | ||
|   if (toolTipOption.xAxisLabel) {
 | ||
|     let labelText = opts.categories[opts.tooltip.index];
 | ||
|     context.setFontSize(config.fontSize);
 | ||
|     let textWidth = measureText(labelText, config.fontSize);
 | ||
| 
 | ||
|     let textX = offsetX - 0.5 * textWidth;
 | ||
|     let textY = endY;
 | ||
|     context.beginPath();
 | ||
|     context.setFillStyle(hexToRgb(toolTipOption.labelBgColor || config.toolTipBackground, toolTipOption.labelBgOpacity || config.toolTipOpacity));
 | ||
|     context.setStrokeStyle(toolTipOption.labelBgColor || config.toolTipBackground);
 | ||
|     context.setLineWidth(1 * opts.pixelRatio);
 | ||
|     context.rect(textX - config.toolTipPadding, textY, textWidth + 2 * config.toolTipPadding, config.fontSize + 2 * config.toolTipPadding);
 | ||
|     context.closePath();
 | ||
|     context.stroke();
 | ||
|     context.fill();
 | ||
| 
 | ||
|     context.beginPath();
 | ||
|     context.setFontSize(config.fontSize);
 | ||
|     context.setFillStyle(toolTipOption.labelFontColor || config.fontColor);
 | ||
|     context.fillText(String(labelText), textX, textY + config.toolTipPadding + config.fontSize);
 | ||
|     context.closePath();
 | ||
|     context.stroke();
 | ||
|   }
 | ||
| }
 | ||
| 
 | ||
| function drawMarkLine(opts, config, context) {
 | ||
|   let markLineOption = assign({}, {
 | ||
|     type: 'solid',
 | ||
|     dashLength: 4,
 | ||
|     data: []
 | ||
|   }, opts.extra.markLine);
 | ||
|   let startX = opts.area[3];
 | ||
|   let endX = opts.width - opts.area[1];
 | ||
|   let points = calMarkLineData(markLineOption.data, opts);
 | ||
| 
 | ||
|   for (let i = 0; i < points.length; i++) {
 | ||
|     let item = assign({}, {
 | ||
|       lineColor: '#DE4A42',
 | ||
|       showLabel: false,
 | ||
|       labelFontColor: '#666666',
 | ||
|       labelBgColor: '#DFE8FF',
 | ||
|       labelBgOpacity: 0.8,
 | ||
|       yAxisIndex: 0
 | ||
|     }, points[i]);
 | ||
| 
 | ||
|     if (markLineOption.type == 'dash') {
 | ||
|       context.setLineDash([markLineOption.dashLength, markLineOption.dashLength]);
 | ||
|     }
 | ||
|     context.setStrokeStyle(item.lineColor);
 | ||
|     context.setLineWidth(1 * opts.pixelRatio);
 | ||
|     context.beginPath();
 | ||
|     context.moveTo(startX, item.y);
 | ||
|     context.lineTo(endX, item.y);
 | ||
|     context.stroke();
 | ||
|     context.setLineDash([]);
 | ||
|     if (item.showLabel) {
 | ||
|       let labelText = opts.yAxis.format ? opts.yAxis.format(Number(item.value)) : item.value;
 | ||
|       context.setFontSize(config.fontSize);
 | ||
|       let textWidth = measureText(labelText, config.fontSize);
 | ||
|       let bgStartX = opts.padding[3] + config.yAxisTitleWidth - config.toolTipPadding;
 | ||
|       let bgEndX = Math.max(opts.area[3], textWidth + config.toolTipPadding * 2);
 | ||
|       let bgWidth = bgEndX - bgStartX;
 | ||
| 
 | ||
|       let textX = bgStartX + (bgWidth - textWidth) / 2;
 | ||
|       let textY = item.y;
 | ||
|       context.setFillStyle(hexToRgb(item.labelBgColor, item.labelBgOpacity));
 | ||
|       context.setStrokeStyle(item.labelBgColor);
 | ||
|       context.setLineWidth(1 * opts.pixelRatio);
 | ||
|       context.beginPath();
 | ||
|       context.rect(bgStartX, textY - 0.5 * config.fontSize - config.toolTipPadding, bgWidth, config.fontSize + 2 * config.toolTipPadding);
 | ||
|       context.closePath();
 | ||
|       context.stroke();
 | ||
|       context.fill();
 | ||
| 
 | ||
|       context.beginPath();
 | ||
|       context.setFontSize(config.fontSize);
 | ||
|       context.setFillStyle(item.labelFontColor);
 | ||
|       context.fillText(String(labelText), textX, textY + 0.5 * config.fontSize);
 | ||
|       context.stroke();
 | ||
|     }
 | ||
|   }
 | ||
| }
 | ||
| 
 | ||
| function drawToolTipHorizentalLine(opts, config, context, eachSpacing, xAxisPoints) {
 | ||
|   var toolTipOption = assign({}, {
 | ||
|     gridType: 'solid',
 | ||
|     dashLength: 4
 | ||
|   }, opts.extra.tooltip);
 | ||
| 
 | ||
|   var startX = opts.area[3];
 | ||
|   var endX = opts.width - opts.area[1];
 | ||
| 
 | ||
|   if (toolTipOption.gridType == 'dash') {
 | ||
|     context.setLineDash([toolTipOption.dashLength, toolTipOption.dashLength]);
 | ||
|   }
 | ||
|   context.setStrokeStyle(toolTipOption.gridColor || '#cccccc');
 | ||
|   context.setLineWidth(1 * opts.pixelRatio);
 | ||
|   context.beginPath();
 | ||
|   context.moveTo(startX, opts.tooltip.offset.y);
 | ||
|   context.lineTo(endX, opts.tooltip.offset.y);
 | ||
|   context.stroke();
 | ||
|   context.setLineDash([]);
 | ||
| 
 | ||
|   if (toolTipOption.yAxisLabel) {
 | ||
|     let labelText = calTooltipYAxisData(opts.tooltip.offset.y, opts.series, opts, config, eachSpacing);
 | ||
|     let widthArr = opts.chartData.yAxisData.yAxisWidth;
 | ||
|     let tStartLeft=opts.area[3];
 | ||
|     let tStartRight=opts.width-opts.area[1];
 | ||
|     for(let i=0;i<labelText.length;i++){
 | ||
|       context.setFontSize(config.fontSize);
 | ||
|       let textWidth = measureText(labelText[i], config.fontSize);
 | ||
|       let bgStartX,bgEndX,bgWidth;
 | ||
|       if(widthArr[i].position == 'left'){
 | ||
|         bgStartX = tStartLeft - widthArr[i].width;
 | ||
|         bgEndX = Math.max(bgStartX, bgStartX + textWidth + config.toolTipPadding * 2);
 | ||
|       }else{
 | ||
|         bgStartX = tStartRight;
 | ||
|         bgEndX = Math.max(bgStartX + widthArr[i].width, bgStartX + textWidth + config.toolTipPadding * 2);
 | ||
|       }
 | ||
|       bgWidth = bgEndX - bgStartX;
 | ||
|       
 | ||
|       let textX = bgStartX + (bgWidth - textWidth) / 2;
 | ||
|       let textY = opts.tooltip.offset.y;
 | ||
|       context.beginPath();
 | ||
|       context.setFillStyle(hexToRgb(toolTipOption.labelBgColor || config.toolTipBackground, toolTipOption.labelBgOpacity || config.toolTipOpacity));
 | ||
|       context.setStrokeStyle(toolTipOption.labelBgColor || config.toolTipBackground);
 | ||
|       context.setLineWidth(1 * opts.pixelRatio);
 | ||
|       context.rect(bgStartX, textY - 0.5 * config.fontSize - config.toolTipPadding, bgWidth, config.fontSize + 2 * config.toolTipPadding);
 | ||
|       context.closePath();
 | ||
|       context.stroke();
 | ||
|       context.fill();
 | ||
|       
 | ||
|       context.beginPath();
 | ||
|       context.setFontSize(config.fontSize);
 | ||
|       context.setFillStyle(toolTipOption.labelFontColor || config.fontColor);
 | ||
|       context.fillText(labelText[i], textX, textY + 0.5 * config.fontSize);
 | ||
|       context.closePath();
 | ||
|       context.stroke();
 | ||
|       if(widthArr[i].position == 'left'){
 | ||
|         tStartLeft -=(widthArr[i].width + opts.yAxis.padding);
 | ||
|       }else{
 | ||
|         tStartRight +=widthArr[i].width+ opts.yAxis.padding;
 | ||
|       }
 | ||
|     }
 | ||
|   }
 | ||
| }
 | ||
| 
 | ||
| function drawToolTipSplitArea(offsetX, opts, config, context, eachSpacing) {
 | ||
|   var toolTipOption = assign({}, {
 | ||
|     activeBgColor: '#000000',
 | ||
|     activeBgOpacity: 0.08
 | ||
|   }, opts.extra.tooltip);
 | ||
|   var startY = opts.area[0];
 | ||
|   var endY = opts.height - opts.area[2];
 | ||
|   context.beginPath();
 | ||
|   context.setFillStyle(hexToRgb(toolTipOption.activeBgColor, toolTipOption.activeBgOpacity));
 | ||
|   context.rect(offsetX - eachSpacing / 2, startY, eachSpacing, endY - startY);
 | ||
|   context.closePath();
 | ||
|   context.fill();
 | ||
| }
 | ||
| 
 | ||
| function drawToolTip(textList, offset, opts, config, context, eachSpacing, xAxisPoints) {
 | ||
|   var toolTipOption = assign({}, {
 | ||
| 		showBox:true,
 | ||
|     bgColor: '#000000',
 | ||
|     bgOpacity: 0.7,
 | ||
|     fontColor: '#FFFFFF'
 | ||
|   }, opts.extra.tooltip);
 | ||
|   var legendWidth = 4 * opts.pixelRatio;
 | ||
|   var legendMarginRight = 5 * opts.pixelRatio;
 | ||
|   var arrowWidth = 8 * opts.pixelRatio;
 | ||
|   var isOverRightBorder = false;
 | ||
|   if (opts.type == 'line' || opts.type == 'area' || opts.type == 'candle' || opts.type == 'mix') {
 | ||
|     drawToolTipSplitLine(opts.tooltip.offset.x, opts, config, context);
 | ||
|   }
 | ||
| 
 | ||
|   offset = assign({
 | ||
|     x: 0,
 | ||
|     y: 0
 | ||
|   }, offset);
 | ||
|   offset.y -= 8 * opts.pixelRatio;
 | ||
|   var textWidth = textList.map(function(item) {
 | ||
|     return measureText(item.text, config.fontSize);
 | ||
|   });
 | ||
|   var toolTipWidth = legendWidth + legendMarginRight + 4 * config.toolTipPadding + Math.max.apply(null, textWidth);
 | ||
|   var toolTipHeight = 2 * config.toolTipPadding + textList.length * config.toolTipLineHeight;
 | ||
| 
 | ||
| 	if(toolTipOption.showBox == false){ return }
 | ||
|   // if beyond the right border
 | ||
|   if (offset.x - Math.abs(opts._scrollDistance_) + arrowWidth + toolTipWidth > opts.width) {
 | ||
|     isOverRightBorder = true;
 | ||
|   }
 | ||
|   if (toolTipHeight + offset.y > opts.height) {
 | ||
|     offset.y = opts.height - toolTipHeight;
 | ||
|   }
 | ||
|   // draw background rect
 | ||
|   context.beginPath();
 | ||
|   context.setFillStyle(hexToRgb(toolTipOption.bgColor || config.toolTipBackground, toolTipOption.bgOpacity || config.toolTipOpacity));
 | ||
|   if (isOverRightBorder) {
 | ||
|     context.moveTo(offset.x, offset.y + 10 * opts.pixelRatio);
 | ||
|     context.lineTo(offset.x - arrowWidth, offset.y + 10 * opts.pixelRatio - 5 * opts.pixelRatio);
 | ||
|     context.lineTo(offset.x - arrowWidth, offset.y);
 | ||
|     context.lineTo(offset.x - arrowWidth - Math.round(toolTipWidth), offset.y);
 | ||
|     context.lineTo(offset.x - arrowWidth - Math.round(toolTipWidth), offset.y + toolTipHeight);
 | ||
|     context.lineTo(offset.x - arrowWidth, offset.y + toolTipHeight);
 | ||
|     context.lineTo(offset.x - arrowWidth, offset.y + 10 * opts.pixelRatio + 5 * opts.pixelRatio);
 | ||
|     context.lineTo(offset.x, offset.y + 10 * opts.pixelRatio);
 | ||
|   } else {
 | ||
|     context.moveTo(offset.x, offset.y + 10 * opts.pixelRatio);
 | ||
|     context.lineTo(offset.x + arrowWidth, offset.y + 10 * opts.pixelRatio - 5 * opts.pixelRatio);
 | ||
|     context.lineTo(offset.x + arrowWidth, offset.y);
 | ||
|     context.lineTo(offset.x + arrowWidth + Math.round(toolTipWidth), offset.y);
 | ||
|     context.lineTo(offset.x + arrowWidth + Math.round(toolTipWidth), offset.y + toolTipHeight);
 | ||
|     context.lineTo(offset.x + arrowWidth, offset.y + toolTipHeight);
 | ||
|     context.lineTo(offset.x + arrowWidth, offset.y + 10 * opts.pixelRatio + 5 * opts.pixelRatio);
 | ||
|     context.lineTo(offset.x, offset.y + 10 * opts.pixelRatio);
 | ||
|   }
 | ||
| 
 | ||
|   context.closePath();
 | ||
|   context.fill();
 | ||
| 
 | ||
|   // draw legend
 | ||
|   textList.forEach(function(item, index) {
 | ||
|     if (item.color !== null) {
 | ||
|       context.beginPath();
 | ||
|       context.setFillStyle(item.color);
 | ||
|       var startX = offset.x + arrowWidth + 2 * config.toolTipPadding;
 | ||
|       var startY = offset.y + (config.toolTipLineHeight - config.fontSize) / 2 + config.toolTipLineHeight * index +
 | ||
|         config.toolTipPadding + 1;
 | ||
|       if (isOverRightBorder) {
 | ||
|         startX = offset.x - toolTipWidth - arrowWidth + 2 * config.toolTipPadding;
 | ||
|       }
 | ||
|       context.fillRect(startX, startY, legendWidth, config.fontSize);
 | ||
|       context.closePath();
 | ||
|     }
 | ||
|   });
 | ||
| 
 | ||
|   // draw text list
 | ||
| 
 | ||
|   textList.forEach(function(item, index) {
 | ||
|     var startX = offset.x + arrowWidth + 2 * config.toolTipPadding + legendWidth + legendMarginRight;
 | ||
|     if (isOverRightBorder) {
 | ||
|       startX = offset.x - toolTipWidth - arrowWidth + 2 * config.toolTipPadding + +legendWidth + legendMarginRight;
 | ||
|     }
 | ||
|     var startY = offset.y + (config.toolTipLineHeight - config.fontSize) / 2 + config.toolTipLineHeight * index +
 | ||
|       config.toolTipPadding;
 | ||
|     context.beginPath();
 | ||
|     context.setFontSize(config.fontSize);
 | ||
|     context.setFillStyle(toolTipOption.fontColor);
 | ||
|     context.fillText(item.text, startX, startY + config.fontSize);
 | ||
|     context.closePath();
 | ||
|     context.stroke();
 | ||
|   });
 | ||
| }
 | ||
| 
 | ||
| function drawYAxisTitle(title, opts, config, context) {
 | ||
|   var startX = config.xAxisHeight + (opts.height - config.xAxisHeight - measureText(title)) / 2;
 | ||
|   context.save();
 | ||
|   context.beginPath();
 | ||
|   context.setFontSize(config.fontSize);
 | ||
|   context.setFillStyle(opts.yAxis.titleFontColor || '#333333');
 | ||
|   context.translate(0, opts.height);
 | ||
|   context.rotate(-90 * Math.PI / 180);
 | ||
|   context.fillText(title, startX, opts.padding[3] + 0.5 * config.fontSize);
 | ||
|   context.closePath();
 | ||
|   context.stroke();
 | ||
|   context.restore();
 | ||
| }
 | ||
| 
 | ||
| function drawColumnDataPoints(series, opts, config, context) {
 | ||
|   let process = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 1;
 | ||
|   let xAxisData = opts.chartData.xAxisData,
 | ||
|     xAxisPoints = xAxisData.xAxisPoints,
 | ||
|     eachSpacing = xAxisData.eachSpacing;
 | ||
|   let columnOption = assign({}, {
 | ||
|     type: 'group',
 | ||
|     width: eachSpacing / 2,
 | ||
|     meter: {
 | ||
|       border: 4,
 | ||
|       fillColor: '#FFFFFF'
 | ||
|     }
 | ||
|   }, opts.extra.column);
 | ||
|   
 | ||
|   let calPoints = [];
 | ||
|   context.save();
 | ||
| 	
 | ||
| 	let leftNum=-2;
 | ||
| 	let rightNum=xAxisPoints.length+2;
 | ||
| 	
 | ||
|   if (opts._scrollDistance_ && opts._scrollDistance_ !== 0 && opts.enableScroll === true) {
 | ||
|     context.translate(opts._scrollDistance_, 0);
 | ||
| 		leftNum=Math.floor(-opts._scrollDistance_/eachSpacing)-2;
 | ||
| 		rightNum=leftNum+opts.xAxis.itemCount+4;
 | ||
|   }
 | ||
|   if (opts.tooltip && opts.tooltip.textList && opts.tooltip.textList.length && process === 1) {
 | ||
|     drawToolTipSplitArea(opts.tooltip.offset.x, opts, config, context, eachSpacing);
 | ||
|   }
 | ||
| 	
 | ||
|   series.forEach(function(eachSeries, seriesIndex) {
 | ||
|     let ranges,minRange,maxRange;
 | ||
|     ranges = [].concat(opts.chartData.yAxisData.ranges[eachSeries.index]);
 | ||
|     minRange = ranges.pop();
 | ||
|     maxRange = ranges.shift();
 | ||
|     
 | ||
|     var data = eachSeries.data;
 | ||
|     switch (columnOption.type) {
 | ||
|       case 'group':
 | ||
|         var points = getDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config, process);
 | ||
|         var tooltipPoints = getStackDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config, seriesIndex, series, process);
 | ||
|         calPoints.push(tooltipPoints);
 | ||
|         points = fixColumeData(points, eachSpacing, series.length, seriesIndex, config, opts);
 | ||
| 				for(let i=0;i<points.length;i++){
 | ||
| 					let item=points[i];
 | ||
|           if (item !== null && i>leftNum && i<rightNum) {
 | ||
|             context.beginPath();
 | ||
|             context.setStrokeStyle(item.color || eachSeries.color);
 | ||
|             context.setLineWidth(1)
 | ||
|             context.setFillStyle(item.color || eachSeries.color);
 | ||
|             var startX = item.x - item.width / 2;
 | ||
|             var height = opts.height - item.y - opts.area[2];
 | ||
|             context.moveTo(startX, item.y);
 | ||
|             context.lineTo(startX+item.width-2,item.y);
 | ||
|             context.lineTo(startX+item.width-2,opts.height - opts.area[2]);
 | ||
|             context.lineTo(startX,opts.height - opts.area[2]);
 | ||
|             context.lineTo(startX,item.y);
 | ||
|             context.closePath();
 | ||
|             context.stroke();
 | ||
|             context.fill();
 | ||
|           }
 | ||
|         };
 | ||
|         break;
 | ||
|       case 'stack':
 | ||
|         // 绘制堆叠数据图
 | ||
|         var points = getStackDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config, seriesIndex, series, process);
 | ||
|         calPoints.push(points);
 | ||
|         points = fixColumeStackData(points, eachSpacing, series.length, seriesIndex, config, opts, series);
 | ||
| 
 | ||
|         for(let i=0;i<points.length;i++){
 | ||
|         	let item=points[i];
 | ||
|           if (item !== null && i>leftNum && i<rightNum) {
 | ||
|             context.beginPath();
 | ||
|             context.setFillStyle(item.color || eachSeries.color);
 | ||
|             var startX = item.x - item.width / 2 + 1;
 | ||
|             var height = opts.height - item.y - opts.area[2];
 | ||
|             var height0 = opts.height - item.y0 - opts.area[2];
 | ||
|             if (seriesIndex > 0) {
 | ||
|               height -= height0;
 | ||
|             }
 | ||
|             context.moveTo(startX, item.y);
 | ||
|             context.fillRect(startX, item.y, item.width - 2, height);
 | ||
|             context.closePath();
 | ||
|             context.fill();
 | ||
|           }
 | ||
|         };
 | ||
|         break;
 | ||
|       case 'meter':
 | ||
|         // 绘制温度计数据图
 | ||
|         var points = getDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config, process);
 | ||
|         calPoints.push(points);
 | ||
|         points = fixColumeMeterData(points, eachSpacing, series.length, seriesIndex, config, opts, columnOption.meter.border);
 | ||
|         if (seriesIndex == 0) {
 | ||
|           for(let i=0;i<points.length;i++){
 | ||
|           	let item=points[i];
 | ||
|             if (item !== null && i>leftNum && i<rightNum) {
 | ||
|               //画背景颜色
 | ||
|               context.beginPath();
 | ||
|               context.setFillStyle(columnOption.meter.fillColor);
 | ||
|               var startX = item.x - item.width / 2;
 | ||
|               var height = opts.height - item.y - opts.area[2];
 | ||
|               context.moveTo(startX, item.y);
 | ||
|               context.fillRect(startX, item.y, item.width, height);
 | ||
|               context.closePath();
 | ||
|               context.fill();
 | ||
|               //画边框线
 | ||
|               if (columnOption.meter.border > 0) {
 | ||
|                 context.beginPath();
 | ||
|                 context.setStrokeStyle(eachSeries.color);
 | ||
|                 context.setLineWidth(columnOption.meter.border * opts.pixelRatio);
 | ||
|                 context.moveTo(startX + columnOption.meter.border * 0.5, item.y + height);
 | ||
|                 context.lineTo(startX + columnOption.meter.border * 0.5, item.y + columnOption.meter.border * 0.5);
 | ||
|                 context.lineTo(startX + item.width - columnOption.meter.border * 0.5, item.y + columnOption.meter.border * 0.5);
 | ||
|                 context.lineTo(startX + item.width - columnOption.meter.border * 0.5, item.y + height);
 | ||
|                 context.stroke();
 | ||
|               }
 | ||
|             }
 | ||
|           };
 | ||
|         } else {
 | ||
|           for(let i=0;i<points.length;i++){
 | ||
|           	let item=points[i];
 | ||
|             if (item !== null && i>leftNum && i<rightNum) {
 | ||
|               context.beginPath();
 | ||
|               context.setFillStyle(item.color || eachSeries.color);
 | ||
|               var startX = item.x - item.width / 2;
 | ||
|               var height = opts.height - item.y - opts.area[2];
 | ||
|               context.moveTo(startX, item.y);
 | ||
|               context.fillRect(startX, item.y, item.width, height);
 | ||
|               context.closePath();
 | ||
|               context.fill();
 | ||
|             }
 | ||
|           };
 | ||
|         }
 | ||
|         break;
 | ||
|     }
 | ||
|   });
 | ||
| 
 | ||
|   if (opts.dataLabel !== false && process === 1) {
 | ||
|     series.forEach(function(eachSeries, seriesIndex) {
 | ||
|       let ranges,minRange,maxRange;
 | ||
|         ranges = [].concat(opts.chartData.yAxisData.ranges[eachSeries.index]);
 | ||
|         minRange = ranges.pop();
 | ||
|         maxRange = ranges.shift();
 | ||
|       var data = eachSeries.data;
 | ||
|       switch (columnOption.type) {
 | ||
|         case 'group':
 | ||
|           var points = getDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config, process);
 | ||
|           points = fixColumeData(points, eachSpacing, series.length, seriesIndex, config, opts);
 | ||
|           drawPointText(points, eachSeries, config, context);
 | ||
|           break;
 | ||
|         case 'stack':
 | ||
|           var points = getStackDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config, seriesIndex, series, process);
 | ||
|           drawPointText(points, eachSeries, config, context);
 | ||
|           break;
 | ||
|         case 'meter':
 | ||
|           var points = getDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config, process);
 | ||
|           drawPointText(points, eachSeries, config, context);
 | ||
|           break;
 | ||
|       }
 | ||
|     });
 | ||
|   }
 | ||
| 
 | ||
|   context.restore();
 | ||
| 
 | ||
|   return {
 | ||
|     xAxisPoints: xAxisPoints,
 | ||
|     calPoints: calPoints,
 | ||
|     eachSpacing: eachSpacing
 | ||
|   };
 | ||
| }
 | ||
| 
 | ||
| function drawCandleDataPoints(series, seriesMA, opts, config, context) {
 | ||
|   var process = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : 1;
 | ||
|   var candleOption = assign({}, {
 | ||
|     color: {},
 | ||
|     average: {}
 | ||
|   }, opts.extra.candle);
 | ||
|   candleOption.color = assign({}, {
 | ||
|     upLine: '#f04864',
 | ||
|     upFill: '#f04864',
 | ||
|     downLine: '#2fc25b',
 | ||
|     downFill: '#2fc25b'
 | ||
|   }, candleOption.color);
 | ||
|   candleOption.average = assign({}, {
 | ||
|     show: false,
 | ||
|     name: [],
 | ||
|     day: [],
 | ||
|     color: config.colors
 | ||
|   }, candleOption.average);
 | ||
|   opts.extra.candle = candleOption;
 | ||
| 
 | ||
|   let xAxisData = opts.chartData.xAxisData,
 | ||
|     xAxisPoints = xAxisData.xAxisPoints,
 | ||
|     eachSpacing = xAxisData.eachSpacing;
 | ||
| 
 | ||
|   let calPoints = [];
 | ||
| 
 | ||
|   context.save();
 | ||
| 	
 | ||
| 	let leftNum=-2;
 | ||
| 	let rightNum=xAxisPoints.length+2;
 | ||
| 	let leftSpace=0;
 | ||
| 	let rightSpace=opts.width+eachSpacing;
 | ||
| 	
 | ||
|   if (opts._scrollDistance_ && opts._scrollDistance_ !== 0 && opts.enableScroll === true) {
 | ||
|     context.translate(opts._scrollDistance_, 0);
 | ||
| 		leftNum=Math.floor(-opts._scrollDistance_/eachSpacing)-2;
 | ||
| 		rightNum=leftNum+opts.xAxis.itemCount+4;
 | ||
| 		leftSpace=-opts._scrollDistance_-eachSpacing+opts.area[3];
 | ||
| 		rightSpace=leftSpace+(opts.xAxis.itemCount+4)*eachSpacing;
 | ||
|   }
 | ||
| 
 | ||
|   //画均线
 | ||
|   if (candleOption.average.show) {
 | ||
|     seriesMA.forEach(function(eachSeries, seriesIndex) {
 | ||
|       let ranges,minRange,maxRange;
 | ||
|       ranges = [].concat(opts.chartData.yAxisData.ranges[eachSeries.index]);
 | ||
|       minRange = ranges.pop();
 | ||
|       maxRange = ranges.shift();
 | ||
| 
 | ||
|       var data = eachSeries.data;
 | ||
|       var points = getDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config, process);
 | ||
|       var splitPointList = splitPoints(points);
 | ||
| 			
 | ||
| 			for(let i=0;i<splitPointList.length;i++){
 | ||
| 				let points=splitPointList[i];
 | ||
| 				context.beginPath();
 | ||
| 				context.setStrokeStyle(eachSeries.color);
 | ||
| 				context.setLineWidth(1);
 | ||
| 				if (points.length === 1) {
 | ||
| 					context.moveTo(points[0].x, points[0].y);
 | ||
| 					context.arc(points[0].x, points[0].y, 1, 0, 2 * Math.PI);
 | ||
| 				} else {
 | ||
| 					context.moveTo(points[0].x, points[0].y);
 | ||
| 					let startPoint=0;
 | ||
| 					for(let j=0;j<points.length;j++){
 | ||
| 						let item=points[j];
 | ||
| 						if(startPoint==0 && item.x > leftSpace){
 | ||
| 							context.moveTo(item.x, item.y);
 | ||
| 							startPoint=1;
 | ||
| 						}
 | ||
| 						if (j > 0 && item.x > leftSpace && item.x < rightSpace) {
 | ||
| 							var ctrlPoint = createCurveControlPoints(points, j - 1);
 | ||
| 							context.bezierCurveTo(ctrlPoint.ctrA.x, ctrlPoint.ctrA.y, ctrlPoint.ctrB.x, ctrlPoint.ctrB.y,item.x, item.y);
 | ||
| 						}
 | ||
| 					}
 | ||
| 					context.moveTo(points[0].x, points[0].y);
 | ||
| 				}
 | ||
| 				context.closePath();
 | ||
| 				context.stroke();
 | ||
|       }
 | ||
|     });
 | ||
|   }
 | ||
|   //画K线
 | ||
|   series.forEach(function(eachSeries, seriesIndex) {
 | ||
|     let ranges,minRange,maxRange;
 | ||
|     ranges = [].concat(opts.chartData.yAxisData.ranges[eachSeries.index]);
 | ||
|     minRange = ranges.pop();
 | ||
|     maxRange = ranges.shift();
 | ||
|     var data = eachSeries.data;
 | ||
|     var points = getCandleDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config, process);
 | ||
|     calPoints.push(points);
 | ||
|     var splitPointList = splitPoints(points);
 | ||
| 
 | ||
| 		for(let i=0;i<splitPointList[0].length;i++){
 | ||
| 			if(i>leftNum && i<rightNum){
 | ||
| 				let item=splitPointList[0][i];
 | ||
| 				context.beginPath();
 | ||
| 				//如果上涨
 | ||
| 				if (data[i][1] - data[i][0] > 0) {
 | ||
| 					context.setStrokeStyle(candleOption.color.upLine);
 | ||
| 					context.setFillStyle(candleOption.color.upFill);
 | ||
| 					context.setLineWidth(1 * opts.pixelRatio);
 | ||
| 					context.moveTo(item[3].x, item[3].y); //顶点
 | ||
| 					context.lineTo(item[1].x, item[1].y); //收盘中间点
 | ||
| 					context.lineTo(item[1].x - eachSpacing / 4, item[1].y); //收盘左侧点
 | ||
| 					context.lineTo(item[0].x - eachSpacing / 4, item[0].y); //开盘左侧点
 | ||
| 					context.lineTo(item[0].x, item[0].y); //开盘中间点
 | ||
| 					context.lineTo(item[2].x, item[2].y); //底点
 | ||
| 					context.lineTo(item[0].x, item[0].y); //开盘中间点
 | ||
| 					context.lineTo(item[0].x + eachSpacing / 4, item[0].y); //开盘右侧点
 | ||
| 					context.lineTo(item[1].x + eachSpacing / 4, item[1].y); //收盘右侧点
 | ||
| 					context.lineTo(item[1].x, item[1].y); //收盘中间点
 | ||
| 					context.moveTo(item[3].x, item[3].y); //顶点
 | ||
| 				} else {
 | ||
| 					context.setStrokeStyle(candleOption.color.downLine);
 | ||
| 					context.setFillStyle(candleOption.color.downFill);
 | ||
| 					context.setLineWidth(1 * opts.pixelRatio);
 | ||
| 					context.moveTo(item[3].x, item[3].y); //顶点
 | ||
| 					context.lineTo(item[0].x, item[0].y); //开盘中间点
 | ||
| 					context.lineTo(item[0].x - eachSpacing / 4, item[0].y); //开盘左侧点
 | ||
| 					context.lineTo(item[1].x - eachSpacing / 4, item[1].y); //收盘左侧点
 | ||
| 					context.lineTo(item[1].x, item[1].y); //收盘中间点
 | ||
| 					context.lineTo(item[2].x, item[2].y); //底点
 | ||
| 					context.lineTo(item[1].x, item[1].y); //收盘中间点
 | ||
| 					context.lineTo(item[1].x + eachSpacing / 4, item[1].y); //收盘右侧点
 | ||
| 					context.lineTo(item[0].x + eachSpacing / 4, item[0].y); //开盘右侧点
 | ||
| 					context.lineTo(item[0].x, item[0].y); //开盘中间点
 | ||
| 					context.moveTo(item[3].x, item[3].y); //顶点
 | ||
| 				}
 | ||
| 				context.closePath();
 | ||
| 				context.fill();
 | ||
| 				context.stroke();
 | ||
| 			}
 | ||
|     }
 | ||
|   });
 | ||
| 
 | ||
|   context.restore();
 | ||
| 
 | ||
|   return {
 | ||
|     xAxisPoints: xAxisPoints,
 | ||
|     calPoints: calPoints,
 | ||
|     eachSpacing: eachSpacing
 | ||
|   };
 | ||
| }
 | ||
| 
 | ||
| function drawAreaDataPoints(series, opts, config, context) {
 | ||
|   var process = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 1;
 | ||
|   var areaOption = assign({},{
 | ||
|     type: 'straight',
 | ||
|     opacity: 0.2,
 | ||
|     addLine: false,
 | ||
|     width: 2,
 | ||
| 		gradient:false
 | ||
|   },opts.extra.area);
 | ||
| 
 | ||
|   let xAxisData = opts.chartData.xAxisData,
 | ||
|     xAxisPoints = xAxisData.xAxisPoints,
 | ||
|     eachSpacing = xAxisData.eachSpacing;
 | ||
| 
 | ||
|   let endY = opts.height - opts.area[2];
 | ||
|   let calPoints = [];
 | ||
| 
 | ||
|   context.save();
 | ||
| 	let leftSpace=0;
 | ||
| 	let rightSpace=opts.width+eachSpacing;
 | ||
|   if (opts._scrollDistance_ && opts._scrollDistance_ !== 0 && opts.enableScroll === true) {
 | ||
|     context.translate(opts._scrollDistance_, 0);
 | ||
| 		leftSpace=-opts._scrollDistance_-eachSpacing+opts.area[3];
 | ||
| 		rightSpace=leftSpace+(opts.xAxis.itemCount+4)*eachSpacing;
 | ||
|   }
 | ||
| 
 | ||
|   series.forEach(function(eachSeries, seriesIndex) {
 | ||
|     let ranges,minRange,maxRange;
 | ||
|     ranges = [].concat(opts.chartData.yAxisData.ranges[eachSeries.index]);
 | ||
|     minRange = ranges.pop();
 | ||
|     maxRange = ranges.shift();
 | ||
|     let data = eachSeries.data;
 | ||
|     let points = getDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config, process);
 | ||
|     calPoints.push(points);
 | ||
| 
 | ||
|     let splitPointList = splitPoints(points);
 | ||
|     for (let i = 0; i < splitPointList.length; i++) {
 | ||
|       let points = splitPointList[i];
 | ||
|       // 绘制区域数
 | ||
|       context.beginPath();
 | ||
|       context.setStrokeStyle(hexToRgb(eachSeries.color, areaOption.opacity));
 | ||
| 			if(areaOption.gradient){
 | ||
| 				let gradient = context.createLinearGradient(0, opts.area[0], 0, opts.height-opts.area[2]);
 | ||
| 				gradient.addColorStop('0', hexToRgb(eachSeries.color, areaOption.opacity));
 | ||
| 				gradient.addColorStop('1.0',hexToRgb("#FFFFFF", 0.1));
 | ||
| 				context.setFillStyle(gradient);
 | ||
| 			}else{
 | ||
| 				context.setFillStyle(hexToRgb(eachSeries.color, areaOption.opacity));
 | ||
| 			}
 | ||
|       context.setLineWidth(areaOption.width * opts.pixelRatio);
 | ||
|       if (points.length > 1) {
 | ||
|         let firstPoint = points[0];
 | ||
|         let lastPoint = points[points.length - 1];
 | ||
|         context.moveTo(firstPoint.x, firstPoint.y);
 | ||
| 				let startPoint=0;
 | ||
|         if (areaOption.type === 'curve') {
 | ||
| 					for(let j=0;j<points.length;j++){
 | ||
| 						let item=points[j];
 | ||
| 						if(startPoint==0 && item.x > leftSpace){
 | ||
| 							context.moveTo(item.x, item.y);
 | ||
| 							startPoint=1;
 | ||
| 						}
 | ||
|             if (j > 0 && item.x > leftSpace && item.x < rightSpace) {
 | ||
|               let ctrlPoint = createCurveControlPoints(points, j - 1);
 | ||
|               context.bezierCurveTo(ctrlPoint.ctrA.x, ctrlPoint.ctrA.y, ctrlPoint.ctrB.x, ctrlPoint.ctrB.y,item.x, item.y);
 | ||
|             }
 | ||
|           };
 | ||
|         } else {
 | ||
| 					for(let j=0;j<points.length;j++){
 | ||
| 						let item=points[j];
 | ||
| 						if(startPoint==0 && item.x > leftSpace){
 | ||
| 							context.moveTo(item.x, item.y);
 | ||
| 							startPoint=1;
 | ||
| 						}
 | ||
| 					  if (j > 0 && item.x > leftSpace && item.x < rightSpace) {
 | ||
|               context.lineTo(item.x, item.y);
 | ||
|             }
 | ||
|           };
 | ||
|         }
 | ||
| 
 | ||
|         context.lineTo(lastPoint.x, endY);
 | ||
|         context.lineTo(firstPoint.x, endY);
 | ||
|         context.lineTo(firstPoint.x, firstPoint.y);
 | ||
|       } else {
 | ||
|         let item = points[0];
 | ||
|         context.moveTo(item.x - eachSpacing / 2, item.y);
 | ||
|         context.lineTo(item.x + eachSpacing / 2, item.y);
 | ||
|         context.lineTo(item.x + eachSpacing / 2, endY);
 | ||
|         context.lineTo(item.x - eachSpacing / 2, endY);
 | ||
|         context.moveTo(item.x - eachSpacing / 2, item.y);
 | ||
|       }
 | ||
|       context.closePath();
 | ||
|       context.fill();
 | ||
| 
 | ||
|       //画连线
 | ||
|       if (areaOption.addLine) {
 | ||
| 				if (eachSeries.lineType == 'dash') {
 | ||
| 					let dashLength = eachSeries.dashLength?eachSeries.dashLength:8;
 | ||
| 					dashLength *= opts.pixelRatio;
 | ||
| 				  context.setLineDash([dashLength, dashLength]);
 | ||
| 				}
 | ||
|         context.beginPath();
 | ||
|         context.setStrokeStyle(eachSeries.color);
 | ||
|         context.setLineWidth(areaOption.width * opts.pixelRatio);
 | ||
|         if (points.length === 1) {
 | ||
|           context.moveTo(points[0].x, points[0].y);
 | ||
|           context.arc(points[0].x, points[0].y, 1, 0, 2 * Math.PI);
 | ||
|         } else {
 | ||
|           context.moveTo(points[0].x, points[0].y);
 | ||
| 					let startPoint=0;
 | ||
|           if (areaOption.type === 'curve') {
 | ||
|             for(let j=0;j<points.length;j++){
 | ||
|             	let item=points[j];
 | ||
|             	if(startPoint==0 && item.x > leftSpace){
 | ||
|             		context.moveTo(item.x, item.y);
 | ||
|             		startPoint=1;
 | ||
|             	}
 | ||
|               if (j > 0 && item.x > leftSpace && item.x < rightSpace) {
 | ||
|                 let ctrlPoint = createCurveControlPoints(points, j - 1);
 | ||
|                 context.bezierCurveTo(ctrlPoint.ctrA.x, ctrlPoint.ctrA.y, ctrlPoint.ctrB.x, ctrlPoint.ctrB.y,item.x,item.y);
 | ||
|               }
 | ||
|             };
 | ||
|           } else {
 | ||
|             for(let j=0;j<points.length;j++){
 | ||
|             	let item=points[j];
 | ||
|             	if(startPoint==0 && item.x > leftSpace){
 | ||
|             		context.moveTo(item.x, item.y);
 | ||
|             		startPoint=1;
 | ||
|             	}
 | ||
|               if (j > 0 && item.x > leftSpace && item.x < rightSpace) {
 | ||
|                 context.lineTo(item.x, item.y);
 | ||
|               }
 | ||
|             };
 | ||
|           }
 | ||
|           context.moveTo(points[0].x, points[0].y);
 | ||
|         }
 | ||
|         context.stroke();
 | ||
| 				context.setLineDash([]);
 | ||
|       }
 | ||
|     }
 | ||
| 
 | ||
|     //画点
 | ||
|     if (opts.dataPointShape !== false) {
 | ||
|       drawPointShape(points, eachSeries.color, eachSeries.pointShape, context, opts);
 | ||
|     }
 | ||
| 
 | ||
|   });
 | ||
| 
 | ||
|   if (opts.dataLabel !== false && process === 1) {
 | ||
|     series.forEach(function(eachSeries, seriesIndex) {
 | ||
|       let ranges,minRange,maxRange;
 | ||
|       ranges = [].concat(opts.chartData.yAxisData.ranges[eachSeries.index]);
 | ||
|       minRange = ranges.pop();
 | ||
|       maxRange = ranges.shift();
 | ||
|       var data = eachSeries.data;
 | ||
|       var points = getDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config, process);
 | ||
|       drawPointText(points, eachSeries, config, context);
 | ||
|     });
 | ||
|   }
 | ||
| 
 | ||
|   context.restore();
 | ||
| 
 | ||
|   return {
 | ||
|     xAxisPoints: xAxisPoints,
 | ||
|     calPoints: calPoints,
 | ||
|     eachSpacing: eachSpacing
 | ||
|   };
 | ||
| }
 | ||
| 
 | ||
| function drawLineDataPoints(series, opts, config, context) {
 | ||
|   var process = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 1;
 | ||
|   var lineOption = assign({},{
 | ||
| 		type: 'straight',
 | ||
| 		width: 2
 | ||
| 	},opts.extra.line);
 | ||
| 	lineOption.width *=opts.pixelRatio;
 | ||
| 	
 | ||
|   let xAxisData = opts.chartData.xAxisData,
 | ||
|     xAxisPoints = xAxisData.xAxisPoints,
 | ||
|     eachSpacing = xAxisData.eachSpacing;
 | ||
|   var calPoints = [];
 | ||
| 
 | ||
|   context.save();
 | ||
| 	let leftSpace=0;
 | ||
| 	let rightSpace=opts.width+eachSpacing;
 | ||
|   if (opts._scrollDistance_ && opts._scrollDistance_ !== 0 && opts.enableScroll === true) {
 | ||
|     context.translate(opts._scrollDistance_, 0);
 | ||
| 		leftSpace=-opts._scrollDistance_-eachSpacing+opts.area[3];
 | ||
| 		rightSpace=leftSpace+(opts.xAxis.itemCount+4)*eachSpacing;
 | ||
|   }
 | ||
| 
 | ||
|   series.forEach(function(eachSeries, seriesIndex) {
 | ||
|     let ranges,minRange,maxRange;
 | ||
|     ranges = [].concat(opts.chartData.yAxisData.ranges[eachSeries.index]);
 | ||
|     minRange = ranges.pop();
 | ||
|     maxRange = ranges.shift();
 | ||
|     var data = eachSeries.data;
 | ||
|     var points = getDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config, process);
 | ||
|     calPoints.push(points);
 | ||
|     var splitPointList = splitPoints(points);
 | ||
| 		
 | ||
| 		if (eachSeries.lineType == 'dash') {
 | ||
| 			let dashLength = eachSeries.dashLength?eachSeries.dashLength:8;
 | ||
| 			dashLength *= opts.pixelRatio;
 | ||
| 		  context.setLineDash([dashLength, dashLength]);
 | ||
| 		}
 | ||
| 		context.beginPath();
 | ||
| 		context.setStrokeStyle(eachSeries.color);
 | ||
| 		context.setLineWidth(lineOption.width);
 | ||
| 		
 | ||
|     splitPointList.forEach(function(points, index) {
 | ||
| 			
 | ||
|       if (points.length === 1) {
 | ||
|         context.moveTo(points[0].x, points[0].y);
 | ||
|         context.arc(points[0].x, points[0].y, 1, 0, 2 * Math.PI);
 | ||
|       } else {
 | ||
|         context.moveTo(points[0].x, points[0].y);
 | ||
| 				let startPoint=0;
 | ||
|         if (lineOption.type === 'curve') {
 | ||
|           for(let j=0;j<points.length;j++){
 | ||
|           	let item=points[j];
 | ||
|           	if(startPoint==0 && item.x > leftSpace){
 | ||
|           		context.moveTo(item.x, item.y);
 | ||
|           		startPoint=1;
 | ||
|           	}
 | ||
|             if (j > 0 && item.x > leftSpace && item.x < rightSpace) {
 | ||
|               var ctrlPoint = createCurveControlPoints(points, j - 1);
 | ||
|               context.bezierCurveTo(ctrlPoint.ctrA.x, ctrlPoint.ctrA.y, ctrlPoint.ctrB.x, ctrlPoint.ctrB.y,item.x, item.y);
 | ||
|             }
 | ||
|           };
 | ||
|         } else {
 | ||
|           for(let j=0;j<points.length;j++){
 | ||
|           	let item=points[j];
 | ||
|           	if(startPoint==0 && item.x > leftSpace){
 | ||
|           		context.moveTo(item.x, item.y);
 | ||
|           		startPoint=1;
 | ||
|           	}
 | ||
|             if (j > 0 && item.x > leftSpace && item.x < rightSpace) {
 | ||
|               context.lineTo(item.x, item.y);
 | ||
|             }
 | ||
|           };
 | ||
|         }
 | ||
|         context.moveTo(points[0].x, points[0].y);
 | ||
|       }
 | ||
|       
 | ||
|     });
 | ||
| 		
 | ||
| 		context.stroke();
 | ||
| 		context.setLineDash([]);
 | ||
| 		
 | ||
|     if (opts.dataPointShape !== false) {
 | ||
|       drawPointShape(points, eachSeries.color, eachSeries.pointShape, context, opts);
 | ||
|     }
 | ||
|   });
 | ||
| 
 | ||
|   if (opts.dataLabel !== false && process === 1) {
 | ||
|     series.forEach(function(eachSeries, seriesIndex) {
 | ||
|       let ranges,minRange,maxRange;
 | ||
|       ranges = [].concat(opts.chartData.yAxisData.ranges[eachSeries.index]);
 | ||
|       minRange = ranges.pop();
 | ||
|       maxRange = ranges.shift();
 | ||
|       var data = eachSeries.data;
 | ||
|       var points = getDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config, process);
 | ||
|       drawPointText(points, eachSeries, config, context);
 | ||
|     });
 | ||
|   }
 | ||
| 
 | ||
|   context.restore();
 | ||
| 
 | ||
|   return {
 | ||
|     xAxisPoints: xAxisPoints,
 | ||
|     calPoints: calPoints,
 | ||
|     eachSpacing: eachSpacing
 | ||
|   };
 | ||
| }
 | ||
| 
 | ||
| function drawMixDataPoints(series, opts, config, context) {
 | ||
|   let process = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 1;
 | ||
|   
 | ||
|   let xAxisData = opts.chartData.xAxisData,
 | ||
|     xAxisPoints = xAxisData.xAxisPoints,
 | ||
|     eachSpacing = xAxisData.eachSpacing;
 | ||
| 
 | ||
|   let endY = opts.height - opts.area[2];
 | ||
|   let calPoints = [];
 | ||
| 
 | ||
|   var columnIndex = 0;
 | ||
|   var columnLength = 0;
 | ||
|   series.forEach(function(eachSeries, seriesIndex) {
 | ||
|     if (eachSeries.type == 'column') {
 | ||
|       columnLength += 1;
 | ||
|     }
 | ||
|   });
 | ||
|   context.save();
 | ||
| 	let leftNum=-2;
 | ||
| 	let rightNum=xAxisPoints.length+2;
 | ||
| 	let leftSpace=0;
 | ||
| 	let rightSpace=opts.width+eachSpacing;
 | ||
|   if (opts._scrollDistance_ && opts._scrollDistance_ !== 0 && opts.enableScroll === true) {
 | ||
|     context.translate(opts._scrollDistance_, 0);
 | ||
| 		leftNum=Math.floor(-opts._scrollDistance_/eachSpacing)-2;
 | ||
| 		rightNum=leftNum+opts.xAxis.itemCount+4;
 | ||
| 		leftSpace=-opts._scrollDistance_-eachSpacing+opts.area[3];
 | ||
| 		rightSpace=leftSpace+(opts.xAxis.itemCount+4)*eachSpacing;
 | ||
|   }
 | ||
| 
 | ||
|   series.forEach(function(eachSeries, seriesIndex) {
 | ||
|     let ranges,minRange,maxRange;
 | ||
|     
 | ||
| 		ranges = [].concat(opts.chartData.yAxisData.ranges[eachSeries.index]);
 | ||
| 		minRange = ranges.pop();
 | ||
| 		maxRange = ranges.shift();
 | ||
| 
 | ||
|     var data = eachSeries.data;
 | ||
|     var points = getDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config, process);
 | ||
|     calPoints.push(points);
 | ||
| 
 | ||
|     // 绘制柱状数据图
 | ||
|     if (eachSeries.type == 'column') {
 | ||
|       points = fixColumeData(points, eachSpacing, columnLength, columnIndex, config, opts);
 | ||
|       for(let i=0;i<points.length;i++){
 | ||
|       	let item=points[i];
 | ||
|         if (item !== null && i>leftNum && i<rightNum) {
 | ||
|           context.beginPath();
 | ||
|           context.setStrokeStyle(item.color || eachSeries.color);
 | ||
|           context.setLineWidth(1)
 | ||
|           context.setFillStyle(item.color || eachSeries.color);
 | ||
|           var startX = item.x - item.width / 2;
 | ||
|           var height = opts.height - item.y - opts.area[2];
 | ||
|           context.moveTo(startX, item.y);
 | ||
|           context.moveTo(startX, item.y);
 | ||
|           context.lineTo(startX+item.width-2,item.y);
 | ||
|           context.lineTo(startX+item.width-2,opts.height - opts.area[2]);
 | ||
|           context.lineTo(startX,opts.height - opts.area[2]);
 | ||
|           context.lineTo(startX,item.y);
 | ||
|           context.closePath();
 | ||
|           context.stroke();
 | ||
|           context.fill();
 | ||
|           context.closePath();
 | ||
|           context.fill();
 | ||
|         }
 | ||
|       }
 | ||
|       columnIndex += 1;
 | ||
|     }
 | ||
| 
 | ||
|     //绘制区域图数据
 | ||
| 
 | ||
|     if (eachSeries.type == 'area') {
 | ||
|       let splitPointList = splitPoints(points);
 | ||
|       for (let i = 0; i < splitPointList.length; i++) {
 | ||
|         let points = splitPointList[i];
 | ||
|         // 绘制区域数据
 | ||
|         context.beginPath();
 | ||
|         context.setStrokeStyle(eachSeries.color);
 | ||
|         context.setFillStyle(hexToRgb(eachSeries.color, 0.2));
 | ||
|         context.setLineWidth(2 * opts.pixelRatio);
 | ||
|         if (points.length > 1) {
 | ||
|           var firstPoint = points[0];
 | ||
|           let lastPoint = points[points.length - 1];
 | ||
|           context.moveTo(firstPoint.x, firstPoint.y);
 | ||
| 					let startPoint=0;
 | ||
|           if (eachSeries.style === 'curve') {
 | ||
|             for(let j=0;j<points.length;j++){
 | ||
|             	let item=points[j];
 | ||
|             	if(startPoint==0 && item.x > leftSpace){
 | ||
|             		context.moveTo(item.x, item.y);
 | ||
|             		startPoint=1;
 | ||
|             	}
 | ||
|               if (j > 0 && item.x > leftSpace && item.x < rightSpace) {
 | ||
|                 var ctrlPoint = createCurveControlPoints(points, j - 1);
 | ||
|                 context.bezierCurveTo(ctrlPoint.ctrA.x, ctrlPoint.ctrA.y, ctrlPoint.ctrB.x, ctrlPoint.ctrB.y, item.x, item.y);
 | ||
|               }
 | ||
|             };
 | ||
|           } else {
 | ||
|             for(let j=0;j<points.length;j++){
 | ||
|             	let item=points[j];
 | ||
|             	if(startPoint==0 && item.x > leftSpace){
 | ||
|             		context.moveTo(item.x, item.y);
 | ||
|             		startPoint=1;
 | ||
|             	}
 | ||
|               if (j > 0 && item.x > leftSpace && item.x < rightSpace) {
 | ||
|                 context.lineTo(item.x, item.y);
 | ||
|               }
 | ||
|             };
 | ||
|           }
 | ||
|           context.lineTo(lastPoint.x, endY);
 | ||
|           context.lineTo(firstPoint.x, endY);
 | ||
|           context.lineTo(firstPoint.x, firstPoint.y);
 | ||
|         } else {
 | ||
|           let item = points[0];
 | ||
|           context.moveTo(item.x - eachSpacing / 2, item.y);
 | ||
|           context.lineTo(item.x + eachSpacing / 2, item.y);
 | ||
|           context.lineTo(item.x + eachSpacing / 2, endY);
 | ||
|           context.lineTo(item.x - eachSpacing / 2, endY);
 | ||
|           context.moveTo(item.x - eachSpacing / 2, item.y);
 | ||
|         }
 | ||
|         context.closePath();
 | ||
|         context.fill();
 | ||
|       }
 | ||
|     }
 | ||
| 
 | ||
|     // 绘制折线数据图
 | ||
|     if (eachSeries.type == 'line') {
 | ||
|       var splitPointList = splitPoints(points);
 | ||
|       splitPointList.forEach(function(points, index) {
 | ||
| 				if (eachSeries.lineType == 'dash') {
 | ||
| 					let dashLength = eachSeries.dashLength?eachSeries.dashLength:8;
 | ||
| 					dashLength *= opts.pixelRatio;
 | ||
| 				  context.setLineDash([dashLength, dashLength]);
 | ||
| 				}
 | ||
|         context.beginPath();
 | ||
|         context.setStrokeStyle(eachSeries.color);
 | ||
|         context.setLineWidth(2 * opts.pixelRatio);
 | ||
|         if (points.length === 1) {
 | ||
|           context.moveTo(points[0].x, points[0].y);
 | ||
|           context.arc(points[0].x, points[0].y, 1, 0, 2 * Math.PI);
 | ||
|         } else {
 | ||
|           context.moveTo(points[0].x, points[0].y);
 | ||
| 					let startPoint=0;
 | ||
|           if (eachSeries.style == 'curve') {
 | ||
|             for(let j=0;j<points.length;j++){
 | ||
|             	let item=points[j];
 | ||
|             	if(startPoint==0 && item.x > leftSpace){
 | ||
|             		context.moveTo(item.x, item.y);
 | ||
|             		startPoint=1;
 | ||
|             	}
 | ||
|               if (j > 0 && item.x > leftSpace && item.x < rightSpace) {
 | ||
|                 var ctrlPoint = createCurveControlPoints(points, j - 1);
 | ||
|                 context.bezierCurveTo(ctrlPoint.ctrA.x, ctrlPoint.ctrA.y, ctrlPoint.ctrB.x, ctrlPoint.ctrB.y,item.x,item.y);
 | ||
|               }
 | ||
|             }
 | ||
|           } else {
 | ||
|             for(let j=0;j<points.length;j++){
 | ||
|             	let item=points[j];
 | ||
|             	if(startPoint==0 && item.x > leftSpace){
 | ||
|             		context.moveTo(item.x, item.y);
 | ||
|             		startPoint=1;
 | ||
|             	}
 | ||
|               if (j > 0 && item.x > leftSpace && item.x < rightSpace) {
 | ||
|                 context.lineTo(item.x, item.y);
 | ||
|               }
 | ||
|             }
 | ||
|           }
 | ||
|           context.moveTo(points[0].x, points[0].y);
 | ||
|         }
 | ||
|         context.stroke();
 | ||
| 				context.setLineDash([]);
 | ||
|       });
 | ||
|     }
 | ||
| 
 | ||
|     // 绘制点数据图
 | ||
|     if (eachSeries.type == 'point') {
 | ||
| 			eachSeries.addPoint = true;
 | ||
|     }
 | ||
| 
 | ||
|     if (eachSeries.addPoint == true && eachSeries.type !== 'column' ) {
 | ||
|       drawPointShape(points, eachSeries.color, eachSeries.pointShape, context, opts);
 | ||
|     }
 | ||
|   });
 | ||
|   if (opts.dataLabel !== false && process === 1) {
 | ||
|     var columnIndex = 0;
 | ||
|     series.forEach(function(eachSeries, seriesIndex) {
 | ||
|       let ranges,minRange,maxRange;
 | ||
|       
 | ||
| 			ranges = [].concat(opts.chartData.yAxisData.ranges[eachSeries.index]);
 | ||
| 			minRange = ranges.pop();
 | ||
| 			maxRange = ranges.shift();
 | ||
| 				
 | ||
|       var data = eachSeries.data;
 | ||
|       var points = getDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config, process);
 | ||
|       if (eachSeries.type !== 'column') {
 | ||
|         drawPointText(points, eachSeries, config, context);
 | ||
|       } else {
 | ||
|         points = fixColumeData(points, eachSpacing, columnLength, columnIndex, config, opts);
 | ||
|         drawPointText(points, eachSeries, config, context);
 | ||
|         columnIndex += 1;
 | ||
|       }
 | ||
| 
 | ||
|     });
 | ||
|   }
 | ||
| 
 | ||
|   context.restore();
 | ||
| 
 | ||
|   return {
 | ||
|     xAxisPoints: xAxisPoints,
 | ||
|     calPoints: calPoints,
 | ||
|     eachSpacing: eachSpacing,
 | ||
|   }
 | ||
| }
 | ||
| 
 | ||
| function drawToolTipBridge(opts, config, context, process, eachSpacing, xAxisPoints) {
 | ||
|   var toolTipOption = opts.extra.tooltip || {};
 | ||
|   if (toolTipOption.horizentalLine && opts.tooltip && process === 1 && (opts.type == 'line' || opts.type == 'area' || opts.type == 'column' || opts.type == 'candle' || opts.type == 'mix')) {
 | ||
|     drawToolTipHorizentalLine(opts, config, context, eachSpacing, xAxisPoints)
 | ||
|   }
 | ||
|   context.save();
 | ||
|   if (opts._scrollDistance_ && opts._scrollDistance_ !== 0 && opts.enableScroll === true) {
 | ||
|     context.translate(opts._scrollDistance_, 0);
 | ||
|   }
 | ||
|   if (opts.tooltip && opts.tooltip.textList && opts.tooltip.textList.length && process === 1) {
 | ||
|     drawToolTip(opts.tooltip.textList, opts.tooltip.offset, opts, config, context, eachSpacing, xAxisPoints);
 | ||
|   }
 | ||
|   context.restore();
 | ||
| 
 | ||
| }
 | ||
| 
 | ||
| function drawXAxis(categories, opts, config, context) {
 | ||
| 
 | ||
|   let xAxisData = opts.chartData.xAxisData,
 | ||
|     xAxisPoints = xAxisData.xAxisPoints,
 | ||
|     startX = xAxisData.startX,
 | ||
|     endX = xAxisData.endX,
 | ||
|     eachSpacing = xAxisData.eachSpacing;
 | ||
|   var boundaryGap='center';
 | ||
|   if (opts.type == 'line'||opts.type == 'area'){
 | ||
|     boundaryGap=opts.xAxis.boundaryGap;
 | ||
|   }
 | ||
|   var startY = opts.height - opts.area[2];
 | ||
|   var endY = opts.area[0];
 | ||
| 
 | ||
|   //绘制滚动条
 | ||
|   if (opts.enableScroll && opts.xAxis.scrollShow) {
 | ||
|     var scrollY = opts.height - opts.area[2] + config.xAxisHeight;
 | ||
|     var scrollScreenWidth = endX - startX;
 | ||
|     var scrollTotalWidth = eachSpacing * (xAxisPoints.length - 1);
 | ||
|     var scrollWidth = scrollScreenWidth * scrollScreenWidth / scrollTotalWidth;
 | ||
|     var scrollLeft = 0;
 | ||
|     if (opts._scrollDistance_) {
 | ||
|       scrollLeft = -opts._scrollDistance_ * (scrollScreenWidth) / scrollTotalWidth;
 | ||
|     }
 | ||
|     context.beginPath();
 | ||
|     context.setLineCap('round');
 | ||
|     context.setLineWidth(6 * opts.pixelRatio);
 | ||
|     context.setStrokeStyle(opts.xAxis.scrollBackgroundColor || "#EFEBEF");
 | ||
|     context.moveTo(startX, scrollY);
 | ||
|     context.lineTo(endX, scrollY);
 | ||
|     context.stroke();
 | ||
|     context.closePath();
 | ||
|     context.beginPath();
 | ||
|     context.setLineCap('round');
 | ||
|     context.setLineWidth(6 * opts.pixelRatio);
 | ||
|     context.setStrokeStyle(opts.xAxis.scrollColor || "#A6A6A6");
 | ||
|     context.moveTo(startX + scrollLeft, scrollY);
 | ||
|     context.lineTo(startX + scrollLeft + scrollWidth, scrollY);
 | ||
|     context.stroke();
 | ||
|     context.closePath();
 | ||
|     context.setLineCap('butt');
 | ||
|   }
 | ||
| 
 | ||
|   context.save();
 | ||
| 
 | ||
|   if (opts._scrollDistance_ && opts._scrollDistance_ !== 0) {
 | ||
|     context.translate(opts._scrollDistance_, 0);
 | ||
|   }
 | ||
| 	
 | ||
| 	//绘制X轴刻度线
 | ||
| 	if (opts.xAxis.calibration === true) {
 | ||
| 		context.setStrokeStyle(opts.xAxis.gridColor || "#cccccc");
 | ||
| 		context.setLineCap('butt');
 | ||
| 		context.setLineWidth(1 * opts.pixelRatio);
 | ||
| 	  xAxisPoints.forEach(function(item, index) {
 | ||
| 	    if (index > 0) {
 | ||
| 	      context.beginPath();
 | ||
| 	      context.moveTo(item - eachSpacing / 2, startY);
 | ||
| 	      context.lineTo(item - eachSpacing / 2, startY + 3 * opts.pixelRatio);
 | ||
| 	      context.closePath();
 | ||
| 	      context.stroke();
 | ||
| 	    }
 | ||
| 	  });
 | ||
| 	}
 | ||
| 	//绘制X轴网格
 | ||
|   if (opts.xAxis.disableGrid !== true) {
 | ||
|     context.setStrokeStyle(opts.xAxis.gridColor || "#cccccc");
 | ||
|     context.setLineCap('butt');
 | ||
|     context.setLineWidth(1 * opts.pixelRatio);
 | ||
|     if (opts.xAxis.gridType == 'dash') {
 | ||
|       context.setLineDash([opts.xAxis.dashLength, opts.xAxis.dashLength]);
 | ||
|     }
 | ||
| 		opts.xAxis.gridEval = opts.xAxis.gridEval || 1;
 | ||
| 		xAxisPoints.forEach(function(item, index) {
 | ||
| 			if (index % opts.xAxis.gridEval == 0) {
 | ||
| 				context.beginPath();
 | ||
| 				context.moveTo(item, startY);
 | ||
| 				context.lineTo(item, endY);
 | ||
| 				context.stroke();
 | ||
| 			}
 | ||
| 		});
 | ||
|     context.setLineDash([]);
 | ||
|   }
 | ||
|   
 | ||
| 
 | ||
|   //绘制X轴文案
 | ||
|   if (opts.xAxis.disabled !== true) {
 | ||
|     // 对X轴列表做抽稀处理
 | ||
|     //默认全部显示X轴标签
 | ||
|     let maxXAxisListLength = categories.length;
 | ||
|     //如果设置了X轴单屏数量
 | ||
|     if (opts.xAxis.labelCount) {
 | ||
|       //如果设置X轴密度
 | ||
|       if (opts.xAxis.itemCount) {
 | ||
|         maxXAxisListLength = Math.ceil(categories.length / opts.xAxis.itemCount * opts.xAxis.labelCount);
 | ||
|       } else {
 | ||
|         maxXAxisListLength = opts.xAxis.labelCount;
 | ||
|       }
 | ||
|       maxXAxisListLength -= 1;
 | ||
|     }
 | ||
| 
 | ||
|     let ratio = Math.ceil(categories.length / maxXAxisListLength);
 | ||
| 
 | ||
|     let newCategories = [];
 | ||
|     let cgLength = categories.length;
 | ||
|     for (let i = 0; i < cgLength; i++) {
 | ||
|       if (i % ratio !== 0) {
 | ||
|         newCategories.push("");
 | ||
|       } else {
 | ||
|         newCategories.push(categories[i]);
 | ||
|       }
 | ||
|     }
 | ||
|     newCategories[cgLength - 1] = categories[cgLength - 1];
 | ||
| 
 | ||
|     var xAxisFontSize = opts.xAxis.fontSize || config.fontSize;
 | ||
|     if (config._xAxisTextAngle_ === 0) {
 | ||
|       newCategories.forEach(function(item, index) {
 | ||
|         var offset = - measureText(String(item), xAxisFontSize) / 2;
 | ||
|         if(boundaryGap == 'center'){
 | ||
|           offset+=eachSpacing / 2;
 | ||
|         }
 | ||
|         var scrollHeight=0;
 | ||
|         if(opts.xAxis.scrollShow){
 | ||
|           scrollHeight=6*opts.pixelRatio;
 | ||
|         }
 | ||
|         context.beginPath();
 | ||
|         context.setFontSize(xAxisFontSize);
 | ||
|         context.setFillStyle(opts.xAxis.fontColor || '#666666');
 | ||
|         context.fillText(String(item), xAxisPoints[index] + offset, startY + xAxisFontSize + (config.xAxisHeight - scrollHeight - xAxisFontSize) / 2);
 | ||
|         context.closePath();
 | ||
|         context.stroke();
 | ||
|       });
 | ||
| 
 | ||
|     } else {
 | ||
|       newCategories.forEach(function(item, index) {
 | ||
|         context.save();
 | ||
|         context.beginPath();
 | ||
|         context.setFontSize(xAxisFontSize);
 | ||
|         context.setFillStyle(opts.xAxis.fontColor || '#666666');
 | ||
|         var textWidth = measureText(String(item),xAxisFontSize);
 | ||
|         var offset = - textWidth;
 | ||
|         if(boundaryGap == 'center'){
 | ||
|           offset+=eachSpacing / 2;
 | ||
|         }
 | ||
|         var _calRotateTranslate = calRotateTranslate(xAxisPoints[index] + eachSpacing / 2, startY + xAxisFontSize / 2 + 5, opts.height),
 | ||
|           transX = _calRotateTranslate.transX,
 | ||
|           transY = _calRotateTranslate.transY;
 | ||
| 
 | ||
|         context.rotate(-1 * config._xAxisTextAngle_);
 | ||
|         context.translate(transX, transY);
 | ||
|         context.fillText(String(item), xAxisPoints[index] + offset, startY + xAxisFontSize + 5);
 | ||
|         context.closePath();
 | ||
|         context.stroke();
 | ||
|         context.restore();
 | ||
|       });
 | ||
|     }
 | ||
|   }
 | ||
|   context.restore();
 | ||
| 	
 | ||
| 	//绘制X轴轴线
 | ||
|   if(opts.xAxis.axisLine){
 | ||
|     context.beginPath();
 | ||
|     context.setStrokeStyle(opts.xAxis.axisLineColor);
 | ||
|     context.setLineWidth(1 * opts.pixelRatio);
 | ||
|     context.moveTo(startX,opts.height-opts.area[2]);
 | ||
|     context.lineTo(endX,opts.height-opts.area[2]);
 | ||
|     context.stroke();
 | ||
|   }
 | ||
| }
 | ||
| 
 | ||
| function drawYAxisGrid(categories, opts, config, context) {
 | ||
|   if (opts.yAxis.disableGrid === true) {
 | ||
|     return;
 | ||
|   }
 | ||
|   let spacingValid = opts.height - opts.area[0] - opts.area[2];
 | ||
|   let eachSpacing = spacingValid / opts.yAxis.splitNumber;
 | ||
|   let startX = opts.area[3];
 | ||
|   let xAxisPoints = opts.chartData.xAxisData.xAxisPoints,
 | ||
|     xAxiseachSpacing = opts.chartData.xAxisData.eachSpacing;
 | ||
|   let TotalWidth = xAxiseachSpacing * (xAxisPoints.length - 1);
 | ||
|   let endX = startX + TotalWidth;
 | ||
| 
 | ||
|   let points = [];
 | ||
|   for (let i = 0; i < opts.yAxis.splitNumber + 1; i++) {
 | ||
|     points.push(opts.height - opts.area[2] - eachSpacing * i);
 | ||
|   }
 | ||
| 
 | ||
|   context.save();
 | ||
|   if (opts._scrollDistance_ && opts._scrollDistance_ !== 0) {
 | ||
|     context.translate(opts._scrollDistance_, 0);
 | ||
|   }
 | ||
| 
 | ||
|   if (opts.yAxis.gridType == 'dash') {
 | ||
|     context.setLineDash([opts.yAxis.dashLength, opts.yAxis.dashLength]);
 | ||
|   }
 | ||
|   context.setStrokeStyle(opts.yAxis.gridColor);
 | ||
|   context.setLineWidth(1 * opts.pixelRatio);
 | ||
|   points.forEach(function(item, index) {
 | ||
|     context.beginPath();
 | ||
|     context.moveTo(startX, item);
 | ||
|     context.lineTo(endX, item);
 | ||
|     context.stroke();
 | ||
|   });
 | ||
|   context.setLineDash([]);
 | ||
| 
 | ||
|   context.restore();
 | ||
| }
 | ||
| 
 | ||
| function drawYAxis(series, opts, config, context) {
 | ||
|   if (opts.yAxis.disabled === true) {
 | ||
|     return;
 | ||
|   }
 | ||
|   var spacingValid = opts.height - opts.area[0] - opts.area[2];
 | ||
|   var eachSpacing = spacingValid / opts.yAxis.splitNumber;
 | ||
|   var startX = opts.area[3];
 | ||
|   var endX = opts.width - opts.area[1];
 | ||
|   var endY = opts.height - opts.area[2];
 | ||
|   var fillEndY = endY + config.xAxisHeight;
 | ||
|   if (opts.xAxis.scrollShow) {
 | ||
|     fillEndY -= 3 * opts.pixelRatio;
 | ||
|   }
 | ||
| 	if (opts.xAxis.rotateLabel){
 | ||
| 		fillEndY = opts.height - opts.area[2]+3;
 | ||
| 	}
 | ||
|   // set YAxis background
 | ||
|   context.beginPath();
 | ||
|   context.setFillStyle(opts.background || '#ffffff');
 | ||
|   if (opts._scrollDistance_ < 0) {
 | ||
|     context.fillRect(0, 0, startX, fillEndY);
 | ||
|   }
 | ||
|   if(opts.enableScroll == true){
 | ||
|     context.fillRect(endX, 0, opts.width, fillEndY);
 | ||
|   }
 | ||
|   context.closePath();
 | ||
|   context.stroke();
 | ||
| 
 | ||
|   var points = [];
 | ||
|   for (let i = 0; i <= opts.yAxis.splitNumber; i++) {
 | ||
|     points.push(opts.area[0] + eachSpacing * i);
 | ||
|   }
 | ||
| 
 | ||
|   let tStartLeft=opts.area[3];
 | ||
|   let tStartRight=opts.width-opts.area[1];
 | ||
| 
 | ||
|   for (let i = 0; i < opts.yAxis.data.length; i++) {
 | ||
|     let yData = opts.yAxis.data[i];
 | ||
|     if(yData.disabled !== true){
 | ||
|       let rangesFormat = opts.chartData.yAxisData.rangesFormat[i];
 | ||
|       let yAxisFontSize = yData.fontSize || config.fontSize;
 | ||
|       let yAxisWidth = opts.chartData.yAxisData.yAxisWidth[i];
 | ||
|       //画Y轴刻度及文案
 | ||
|       rangesFormat.forEach(function(item, index) {
 | ||
|         var pos = points[index] ? points[index] : endY;
 | ||
|         context.beginPath();
 | ||
|         context.setFontSize(yAxisFontSize);
 | ||
|         context.setLineWidth(1*opts.pixelRatio);
 | ||
|         context.setStrokeStyle(yData.axisLineColor||'#cccccc');
 | ||
|         context.setFillStyle(yData.fontColor|| '#666666');
 | ||
|         if(yAxisWidth.position=='left'){
 | ||
|           context.fillText(String(item), tStartLeft - yAxisWidth.width , pos + yAxisFontSize / 2);
 | ||
|           //画刻度线
 | ||
|           if(yData.calibration==true){
 | ||
|             context.moveTo(tStartLeft,pos);
 | ||
|             context.lineTo(tStartLeft - 3*opts.pixelRatio,pos);
 | ||
|           }
 | ||
|         }else{
 | ||
|           context.fillText(String(item), tStartRight + 4*opts.pixelRatio, pos + yAxisFontSize / 2);
 | ||
|           //画刻度线
 | ||
|           if(yData.calibration==true){
 | ||
|             context.moveTo(tStartRight,pos);
 | ||
|             context.lineTo(tStartRight + 3*opts.pixelRatio,pos);
 | ||
|           }
 | ||
|         }
 | ||
|         context.closePath();
 | ||
|         context.stroke();
 | ||
|       });
 | ||
|       //画Y轴轴线
 | ||
|       if (yData.axisLine!==false) {
 | ||
|         context.beginPath();
 | ||
|         context.setStrokeStyle(yData.axisLineColor||'#cccccc');
 | ||
|         context.setLineWidth(1 * opts.pixelRatio);
 | ||
|         if(yAxisWidth.position=='left'){
 | ||
|           context.moveTo(tStartLeft,opts.height-opts.area[2]);
 | ||
|           context.lineTo(tStartLeft,opts.area[0]);
 | ||
|         }else{
 | ||
|           context.moveTo(tStartRight,opts.height-opts.area[2]);
 | ||
|           context.lineTo(tStartRight,opts.area[0]);
 | ||
|         }
 | ||
|         context.stroke();
 | ||
|       }
 | ||
| 			
 | ||
|       //画Y轴标题
 | ||
|       if (opts.yAxis.showTitle) {
 | ||
| 				
 | ||
|         let titleFontSize = yData.titleFontSize || config.fontSize;
 | ||
|         let title = yData.title;
 | ||
|         context.beginPath();
 | ||
|         context.setFontSize(titleFontSize);
 | ||
|         context.setFillStyle(yData.titleFontColor || '#666666');
 | ||
|         if(yAxisWidth.position=='left'){
 | ||
|           context.fillText(title, tStartLeft - measureText(title,titleFontSize)/2, opts.area[0]-10*opts.pixelRatio);
 | ||
|         }else{
 | ||
|           context.fillText(title,tStartRight - measureText(title,titleFontSize)/2, opts.area[0]-10*opts.pixelRatio);
 | ||
|         }
 | ||
|         context.closePath();
 | ||
|         context.stroke();
 | ||
|       }
 | ||
|       if(yAxisWidth.position=='left'){
 | ||
|         tStartLeft -=(yAxisWidth.width + opts.yAxis.padding);
 | ||
|       }else{
 | ||
|         tStartRight +=yAxisWidth.width+ opts.yAxis.padding;
 | ||
|       }
 | ||
|     }
 | ||
|   }
 | ||
| }
 | ||
| 
 | ||
| function drawLegend(series, opts, config, context, chartData) {
 | ||
|   if (opts.legend.show === false) {
 | ||
|     return;
 | ||
|   }
 | ||
|   let legendData = chartData.legendData;
 | ||
|   let legendList = legendData.points;
 | ||
|   let legendArea = legendData.area;
 | ||
|   let padding = opts.legend.padding;
 | ||
|   let fontSize = opts.legend.fontSize;
 | ||
|   let shapeWidth = 15 * opts.pixelRatio;
 | ||
|   let shapeRight = 5 * opts.pixelRatio;
 | ||
|   let itemGap = opts.legend.itemGap;
 | ||
|   let lineHeight = Math.max(opts.legend.lineHeight * opts.pixelRatio, fontSize);
 | ||
| 
 | ||
|   //画背景及边框
 | ||
|   context.beginPath();
 | ||
|   context.setLineWidth(opts.legend.borderWidth);
 | ||
|   context.setStrokeStyle(opts.legend.borderColor);
 | ||
|   context.setFillStyle(opts.legend.backgroundColor);
 | ||
|   context.moveTo(legendArea.start.x, legendArea.start.y);
 | ||
|   context.rect(legendArea.start.x, legendArea.start.y, legendArea.width, legendArea.height);
 | ||
|   context.closePath();
 | ||
|   context.fill();
 | ||
|   context.stroke();
 | ||
| 
 | ||
|   legendList.forEach(function(itemList, listIndex) {
 | ||
|     let width = 0;
 | ||
|     let height = 0;
 | ||
|     width = legendData.widthArr[listIndex];
 | ||
|     height = legendData.heightArr[listIndex];
 | ||
|     let startX = 0;
 | ||
|     let startY = 0;
 | ||
|     if (opts.legend.position == 'top' || opts.legend.position == 'bottom') {
 | ||
|       startX = legendArea.start.x + (legendArea.width - width) / 2;
 | ||
|       startY = legendArea.start.y + padding + listIndex * lineHeight;
 | ||
|     } else {
 | ||
|       if (listIndex == 0) {
 | ||
|         width = 0;
 | ||
|       } else {
 | ||
|         width = legendData.widthArr[listIndex - 1];
 | ||
|       }
 | ||
|       startX = legendArea.start.x + padding + width;
 | ||
|       startY = legendArea.start.y + padding + (legendArea.height - height) / 2;
 | ||
|     }
 | ||
| 
 | ||
|     context.setFontSize(config.fontSize);
 | ||
|     for (let i = 0; i < itemList.length; i++) {
 | ||
|       let item = itemList[i];
 | ||
|       item.area = [0, 0, 0, 0];
 | ||
|       item.area[0] = startX;
 | ||
|       item.area[1] = startY;
 | ||
|       item.area[3] = startY + lineHeight;
 | ||
|       context.beginPath();
 | ||
|       context.setLineWidth(1 * opts.pixelRatio);
 | ||
|       context.setStrokeStyle(item.show ? item.color : opts.legend.hiddenColor);
 | ||
|       context.setFillStyle(item.show ? item.color : opts.legend.hiddenColor);
 | ||
|       switch (item.legendShape) {
 | ||
|         case 'line':
 | ||
|           context.moveTo(startX, startY + 0.5 * lineHeight - 2 * opts.pixelRatio);
 | ||
|           context.fillRect(startX, startY + 0.5 * lineHeight - 2 * opts.pixelRatio, 15 * opts.pixelRatio, 4 * opts.pixelRatio);
 | ||
|           break;
 | ||
|         case 'triangle':
 | ||
|           context.moveTo(startX + 7.5 * opts.pixelRatio, startY + 0.5 * lineHeight - 5 * opts.pixelRatio);
 | ||
|           context.lineTo(startX + 2.5 * opts.pixelRatio, startY + 0.5 * lineHeight + 5 * opts.pixelRatio);
 | ||
|           context.lineTo(startX + 12.5 * opts.pixelRatio, startY + 0.5 * lineHeight + 5 * opts.pixelRatio);
 | ||
|           context.lineTo(startX + 7.5 * opts.pixelRatio, startY + 0.5 * lineHeight - 5 * opts.pixelRatio);
 | ||
|           break;
 | ||
|         case 'diamond':
 | ||
|           context.moveTo(startX + 7.5 * opts.pixelRatio, startY + 0.5 * lineHeight - 5 * opts.pixelRatio);
 | ||
|           context.lineTo(startX + 2.5 * opts.pixelRatio, startY + 0.5 * lineHeight);
 | ||
|           context.lineTo(startX + 7.5 * opts.pixelRatio, startY + 0.5 * lineHeight + 5 * opts.pixelRatio);
 | ||
|           context.lineTo(startX + 12.5 * opts.pixelRatio, startY + 0.5 * lineHeight);
 | ||
|           context.lineTo(startX + 7.5 * opts.pixelRatio, startY + 0.5 * lineHeight - 5 * opts.pixelRatio);
 | ||
|           break;
 | ||
|         case 'circle':
 | ||
|           context.moveTo(startX + 7.5 * opts.pixelRatio, startY + 0.5 * lineHeight);
 | ||
|           context.arc(startX + 7.5 * opts.pixelRatio, startY + 0.5 * lineHeight, 5 * opts.pixelRatio, 0, 2 * Math.PI);
 | ||
|           break;
 | ||
|         case 'rect':
 | ||
|           context.moveTo(startX, startY + 0.5 * lineHeight - 5 * opts.pixelRatio);
 | ||
|           context.fillRect(startX, startY + 0.5 * lineHeight - 5 * opts.pixelRatio, 15 * opts.pixelRatio, 10 * opts.pixelRatio);
 | ||
|           break;
 | ||
|         default:
 | ||
|           context.moveTo(startX, startY + 0.5 * lineHeight - 5 * opts.pixelRatio);
 | ||
|           context.fillRect(startX, startY + 0.5 * lineHeight - 5 * opts.pixelRatio, 15 * opts.pixelRatio, 10 * opts.pixelRatio);
 | ||
|       }
 | ||
|       context.closePath();
 | ||
|       context.fill();
 | ||
|       context.stroke();
 | ||
| 
 | ||
|       startX += shapeWidth + shapeRight;
 | ||
|       let fontTrans = 0.5 * lineHeight + 0.5 * fontSize - 2;
 | ||
|       context.beginPath();
 | ||
|       context.setFontSize(fontSize);
 | ||
|       context.setFillStyle(item.show ? opts.legend.fontColor : opts.legend.hiddenColor);
 | ||
|       context.fillText(item.name, startX, startY + fontTrans);
 | ||
|       context.closePath();
 | ||
|       context.stroke();
 | ||
|       if (opts.legend.position == 'top' || opts.legend.position == 'bottom') {
 | ||
|         startX += measureText(item.name, fontSize) + itemGap;
 | ||
|         item.area[2] = startX;
 | ||
|       } else {
 | ||
|         item.area[2] = startX + measureText(item.name, fontSize) + itemGap;;
 | ||
|         startX -= shapeWidth + shapeRight;
 | ||
|         startY += lineHeight;
 | ||
|       }
 | ||
|     }
 | ||
|   });
 | ||
| }
 | ||
| 
 | ||
| function drawPieDataPoints(series, opts, config, context) {
 | ||
|   var process = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 1;
 | ||
|   var pieOption = assign({}, {
 | ||
|     activeOpacity: 0.5,
 | ||
|     activeRadius: 10 * opts.pixelRatio,
 | ||
|     offsetAngle: 0,
 | ||
|     labelWidth: 15 * opts.pixelRatio,
 | ||
|     ringWidth: 0,
 | ||
|     border:false,
 | ||
|     borderWidth:2,
 | ||
|     borderColor:'#FFFFFF'
 | ||
|   }, opts.extra.pie);
 | ||
|   var centerPosition = {
 | ||
|     x: opts.area[3] + (opts.width - opts.area[1] - opts.area[3]) / 2,
 | ||
|     y: opts.area[0] + (opts.height - opts.area[0] - opts.area[2]) / 2
 | ||
|   };
 | ||
|   if (config.pieChartLinePadding == 0) {
 | ||
|     config.pieChartLinePadding = pieOption.activeRadius;
 | ||
|   }
 | ||
| 
 | ||
|   var radius = Math.min((opts.width - opts.area[1] - opts.area[3]) / 2 - config.pieChartLinePadding - config.pieChartTextPadding - config._pieTextMaxLength_, (opts.height - opts.area[0] - opts.area[2]) / 2 - config.pieChartLinePadding - config.pieChartTextPadding);
 | ||
| 
 | ||
|   series = getPieDataPoints(series, radius, process);
 | ||
| 
 | ||
|   var activeRadius = pieOption.activeRadius;
 | ||
| 
 | ||
|   series = series.map(function(eachSeries) {
 | ||
|     eachSeries._start_ += (pieOption.offsetAngle) * Math.PI / 180;
 | ||
|     return eachSeries;
 | ||
|   });
 | ||
|   series.forEach(function(eachSeries, seriesIndex) {
 | ||
|     if (opts.tooltip) {
 | ||
|       if (opts.tooltip.index == seriesIndex) {
 | ||
|         context.beginPath();
 | ||
|         context.setFillStyle(hexToRgb(eachSeries.color, opts.extra.pie.activeOpacity || 0.5));
 | ||
|         context.moveTo(centerPosition.x, centerPosition.y);
 | ||
|         context.arc(centerPosition.x, centerPosition.y, eachSeries._radius_ + activeRadius, eachSeries._start_,
 | ||
|           eachSeries._start_ + 2 *
 | ||
|           eachSeries._proportion_ * Math.PI);
 | ||
|         context.closePath();
 | ||
|         context.fill();
 | ||
|       }
 | ||
|     }
 | ||
|     context.beginPath();
 | ||
|     context.setLineWidth(pieOption.borderWidth * opts.pixelRatio);
 | ||
|     context.lineJoin = "round";
 | ||
|     context.setStrokeStyle(pieOption.borderColor);
 | ||
|     context.setFillStyle(eachSeries.color);
 | ||
|     context.moveTo(centerPosition.x, centerPosition.y);
 | ||
|     context.arc(centerPosition.x, centerPosition.y, eachSeries._radius_, eachSeries._start_, eachSeries._start_ + 2 * eachSeries._proportion_ * Math.PI);
 | ||
|     context.closePath();
 | ||
|     context.fill();
 | ||
|     if (pieOption.border == true) {
 | ||
|       context.stroke();
 | ||
|     }
 | ||
|   });
 | ||
| 
 | ||
|   if (opts.type === 'ring') {
 | ||
|     var innerPieWidth = radius * 0.6;
 | ||
|     if (typeof opts.extra.pie.ringWidth === 'number' && opts.extra.pie.ringWidth > 0) {
 | ||
|       innerPieWidth = Math.max(0, radius - opts.extra.pie.ringWidth);
 | ||
|     }
 | ||
|     context.beginPath();
 | ||
|     context.setFillStyle(opts.background || '#ffffff');
 | ||
|     context.moveTo(centerPosition.x, centerPosition.y);
 | ||
|     context.arc(centerPosition.x, centerPosition.y, innerPieWidth, 0, 2 * Math.PI);
 | ||
|     context.closePath();
 | ||
|     context.fill();
 | ||
|   }
 | ||
| 
 | ||
|   if (opts.dataLabel !== false && process === 1) {
 | ||
|     var valid = false;
 | ||
|     for (var i = 0, len = series.length; i < len; i++) {
 | ||
|       if (series[i].data > 0) {
 | ||
|         valid = true;
 | ||
|         break;
 | ||
|       }
 | ||
|     }
 | ||
| 
 | ||
|     if (valid) {
 | ||
|       drawPieText(series, opts, config, context, radius, centerPosition);
 | ||
|     }
 | ||
|   }
 | ||
| 
 | ||
|   if (process === 1 && opts.type === 'ring') {
 | ||
|     drawRingTitle(opts, config, context, centerPosition);
 | ||
|   }
 | ||
| 
 | ||
|   return {
 | ||
|     center: centerPosition,
 | ||
|     radius: radius,
 | ||
|     series: series
 | ||
|   };
 | ||
| }
 | ||
| 
 | ||
| function drawRoseDataPoints(series, opts, config, context) {
 | ||
|   var process = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 1;
 | ||
|   var roseOption = assign({}, {
 | ||
|     type: 'area',
 | ||
|     activeOpacity: 0.5,
 | ||
|     activeRadius: 10 * opts.pixelRatio,
 | ||
|     offsetAngle: 0,
 | ||
|     labelWidth: 15 * opts.pixelRatio,
 | ||
|     border:false,
 | ||
|     borderWidth:2,
 | ||
|     borderColor:'#FFFFFF'
 | ||
|   }, opts.extra.rose);
 | ||
|   if (config.pieChartLinePadding == 0) {
 | ||
|     config.pieChartLinePadding = roseOption.activeRadius;
 | ||
|   }
 | ||
|   var centerPosition = {
 | ||
|     x: opts.area[3] + (opts.width - opts.area[1] - opts.area[3]) / 2,
 | ||
|     y: opts.area[0] + (opts.height - opts.area[0] - opts.area[2]) / 2
 | ||
|   };
 | ||
|    var radius = Math.min((opts.width - opts.area[1] - opts.area[3]) / 2 - config.pieChartLinePadding - config.pieChartTextPadding - config._pieTextMaxLength_, (opts.height - opts.area[0] - opts.area[2]) / 2 - config.pieChartLinePadding - config.pieChartTextPadding);
 | ||
|   var minRadius = roseOption.minRadius || radius * 0.5;
 | ||
| 
 | ||
|   series = getRoseDataPoints(series, roseOption.type, minRadius, radius, process);
 | ||
| 
 | ||
|   var activeRadius = roseOption.activeRadius;
 | ||
| 
 | ||
|   series = series.map(function(eachSeries) {
 | ||
|     eachSeries._start_ += (roseOption.offsetAngle || 0) * Math.PI / 180;
 | ||
|     return eachSeries;
 | ||
|   });
 | ||
| 
 | ||
|   series.forEach(function(eachSeries, seriesIndex) {
 | ||
|     if (opts.tooltip) {
 | ||
|       if (opts.tooltip.index == seriesIndex) {
 | ||
|         context.beginPath();
 | ||
|         context.setFillStyle(hexToRgb(eachSeries.color, roseOption.activeOpacity || 0.5));
 | ||
|         context.moveTo(centerPosition.x, centerPosition.y);
 | ||
|         context.arc(centerPosition.x, centerPosition.y, activeRadius + eachSeries._radius_, eachSeries._start_,
 | ||
|           eachSeries._start_ + 2 * eachSeries._rose_proportion_ * Math.PI);
 | ||
|         context.closePath();
 | ||
|         context.fill();
 | ||
|       }
 | ||
|     }
 | ||
|     context.beginPath();
 | ||
|     context.setLineWidth(roseOption.borderWidth * opts.pixelRatio);
 | ||
|     context.lineJoin = "round";
 | ||
|     context.setStrokeStyle(roseOption.borderColor);
 | ||
|     context.setFillStyle(eachSeries.color);
 | ||
|     context.moveTo(centerPosition.x, centerPosition.y);
 | ||
|     context.arc(centerPosition.x, centerPosition.y, eachSeries._radius_, eachSeries._start_, eachSeries._start_ + 2 *
 | ||
|       eachSeries._rose_proportion_ * Math.PI);
 | ||
|     context.closePath();
 | ||
|     context.fill();
 | ||
|     if (roseOption.border == true) {
 | ||
|       context.stroke();
 | ||
|     }
 | ||
|   });
 | ||
| 
 | ||
|   if (opts.dataLabel !== false && process === 1) {
 | ||
|     var valid = false;
 | ||
|     for (var i = 0, len = series.length; i < len; i++) {
 | ||
|       if (series[i].data > 0) {
 | ||
|         valid = true;
 | ||
|         break;
 | ||
|       }
 | ||
|     }
 | ||
| 
 | ||
|     if (valid) {
 | ||
|       drawPieText(series, opts, config, context, radius, centerPosition);
 | ||
|     }
 | ||
|   }
 | ||
| 
 | ||
|   return {
 | ||
|     center: centerPosition,
 | ||
|     radius: radius,
 | ||
|     series: series
 | ||
|   };
 | ||
| }
 | ||
| 
 | ||
| function drawArcbarDataPoints(series, opts, config, context) {
 | ||
|   var process = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 1;
 | ||
|   var arcbarOption = assign({}, {
 | ||
|     startAngle: 0.75,
 | ||
|     endAngle: 0.25,
 | ||
|     type: 'default',
 | ||
|     width: 12 * opts.pixelRatio,
 | ||
| 		gap:2 * opts.pixelRatio
 | ||
|   }, opts.extra.arcbar);
 | ||
| 
 | ||
|   series = getArcbarDataPoints(series, arcbarOption, process);
 | ||
| 	
 | ||
|   var centerPosition;
 | ||
| 	if(arcbarOption.center){
 | ||
| 		centerPosition=arcbarOption.center;
 | ||
| 	}else{
 | ||
| 		centerPosition= {
 | ||
| 		  x: opts.width / 2,
 | ||
| 		  y: opts.height / 2
 | ||
| 		};
 | ||
| 	}
 | ||
| 	
 | ||
|   var radius;
 | ||
| 	if(arcbarOption.radius){
 | ||
| 		radius=arcbarOption.radius;
 | ||
| 	}else{
 | ||
| 		radius = Math.min(centerPosition.x, centerPosition.y);
 | ||
| 		radius -= 5 * opts.pixelRatio;
 | ||
| 		radius -= arcbarOption.width / 2;
 | ||
| 	}
 | ||
| 	
 | ||
|   for (let i = 0; i < series.length; i++) {
 | ||
|     let eachSeries = series[i];
 | ||
| 		//背景颜色
 | ||
| 		context.setLineWidth(arcbarOption.width);
 | ||
| 		context.setStrokeStyle(arcbarOption.backgroundColor || '#E9E9E9');
 | ||
| 		context.setLineCap('round');
 | ||
| 		context.beginPath();
 | ||
| 		if (arcbarOption.type == 'default') {
 | ||
| 		  context.arc(centerPosition.x, centerPosition.y, radius-(arcbarOption.width+arcbarOption.gap)*i, arcbarOption.startAngle * Math.PI, arcbarOption.endAngle * Math.PI, false);
 | ||
| 		} else {
 | ||
| 		  context.arc(centerPosition.x, centerPosition.y, radius-(arcbarOption.width+arcbarOption.gap)*i, 0, 2 * Math.PI, false);
 | ||
| 		}
 | ||
| 		context.stroke();
 | ||
| 		//进度条
 | ||
|     context.setLineWidth(arcbarOption.width);
 | ||
|     context.setStrokeStyle(eachSeries.color);
 | ||
|     context.setLineCap('round');
 | ||
|     context.beginPath();
 | ||
|     context.arc(centerPosition.x, centerPosition.y, radius-(arcbarOption.width+arcbarOption.gap)*i, arcbarOption.startAngle * Math.PI, eachSeries._proportion_ * Math.PI, false);
 | ||
|     context.stroke();
 | ||
|   }
 | ||
| 
 | ||
|   drawRingTitle(opts, config, context, centerPosition);
 | ||
| 
 | ||
|   return {
 | ||
|     center: centerPosition,
 | ||
|     radius: radius,
 | ||
|     series: series
 | ||
|   };
 | ||
| }
 | ||
| 
 | ||
| function drawGaugeDataPoints(categories, series, opts, config, context) {
 | ||
|   var process = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : 1;
 | ||
|   var gaugeOption = assign({}, {
 | ||
| 		type:'default',
 | ||
|     startAngle: 0.75,
 | ||
|     endAngle: 0.25,
 | ||
|     width: 15,
 | ||
|     splitLine: {
 | ||
|       fixRadius: 0,
 | ||
|       splitNumber: 10,
 | ||
|       width: 15,
 | ||
|       color: '#FFFFFF',
 | ||
|       childNumber: 5,
 | ||
|       childWidth: 5
 | ||
|     },
 | ||
|     pointer: {
 | ||
|       width: 15,
 | ||
|       color: 'auto'
 | ||
|     }
 | ||
|   }, opts.extra.gauge);
 | ||
| 
 | ||
|   if (gaugeOption.oldAngle == undefined) {
 | ||
|     gaugeOption.oldAngle = gaugeOption.startAngle;
 | ||
|   }
 | ||
|   if (gaugeOption.oldData == undefined) {
 | ||
|     gaugeOption.oldData = 0;
 | ||
|   }
 | ||
|   categories = getGaugeAxisPoints(categories, gaugeOption.startAngle, gaugeOption.endAngle);
 | ||
| 
 | ||
|   var centerPosition = {
 | ||
|     x: opts.width / 2,
 | ||
|     y: opts.height / 2
 | ||
|   };
 | ||
|   var radius = Math.min(centerPosition.x, centerPosition.y);
 | ||
|   radius -= 5 * opts.pixelRatio;
 | ||
|   radius -= gaugeOption.width / 2;
 | ||
|   var innerRadius = radius - gaugeOption.width;
 | ||
| 	var totalAngle=0;
 | ||
| 	
 | ||
| 	//判断仪表盘的样式:default百度样式,progress新样式
 | ||
| 	if(gaugeOption.type == 'progress'){
 | ||
| 		
 | ||
| 		//## 第一步画中心圆形背景和进度条背景
 | ||
| 		//中心圆形背景
 | ||
| 		var pieRadius = radius - gaugeOption.width*3;
 | ||
| 		context.beginPath();
 | ||
| 		let gradient = context.createLinearGradient(centerPosition.x, centerPosition.y-pieRadius, centerPosition.x , centerPosition.y+pieRadius);
 | ||
| 		//配置渐变填充(起点:中心点向上减半径;结束点中心点向下加半径)
 | ||
| 		gradient.addColorStop('0', hexToRgb(series[0].color, 0.3));
 | ||
| 		gradient.addColorStop('1.0',hexToRgb("#FFFFFF", 0.1));
 | ||
| 		context.setFillStyle(gradient);
 | ||
| 		context.arc(centerPosition.x, centerPosition.y, pieRadius, 0, 2*Math.PI, false);
 | ||
| 		context.fill();
 | ||
| 		//画进度条背景
 | ||
| 		context.setLineWidth(gaugeOption.width);
 | ||
| 		context.setStrokeStyle(hexToRgb(series[0].color, 0.3));
 | ||
| 		context.setLineCap('round');
 | ||
| 		context.beginPath();
 | ||
| 		context.arc(centerPosition.x, centerPosition.y, innerRadius , gaugeOption.startAngle * Math.PI, gaugeOption.endAngle *Math.PI, false);
 | ||
| 		context.stroke();
 | ||
| 		
 | ||
| 		//## 第二步画刻度线
 | ||
| 		totalAngle = gaugeOption.startAngle - gaugeOption.endAngle + 1;
 | ||
| 		let splitAngle = totalAngle / gaugeOption.splitLine.splitNumber;
 | ||
| 		let childAngle = totalAngle / gaugeOption.splitLine.splitNumber / gaugeOption.splitLine.childNumber;
 | ||
| 		let startX = -radius - gaugeOption.width * 0.5 - gaugeOption.splitLine.fixRadius;
 | ||
| 		let endX = -radius - gaugeOption.width - gaugeOption.splitLine.fixRadius + gaugeOption.splitLine.width;
 | ||
| 		context.save();
 | ||
| 		context.translate(centerPosition.x, centerPosition.y);
 | ||
| 		context.rotate((gaugeOption.startAngle - 1) * Math.PI);
 | ||
| 		let len = gaugeOption.splitLine.splitNumber * gaugeOption.splitLine.childNumber + 1;
 | ||
| 		let proc = series[0].data * process;
 | ||
| 		for (let i = 0; i < len; i++) {
 | ||
| 		  context.beginPath();
 | ||
| 			//刻度线随进度变色
 | ||
| 			if(proc>(i/len)){
 | ||
| 				context.setStrokeStyle(hexToRgb(series[0].color, 1));
 | ||
| 			}else{
 | ||
| 				context.setStrokeStyle(hexToRgb(series[0].color, 0.3));
 | ||
| 			}
 | ||
| 		  context.setLineWidth(3 * opts.pixelRatio);
 | ||
| 		  context.moveTo(startX, 0);
 | ||
| 		  context.lineTo(endX, 0);
 | ||
| 		  context.stroke();
 | ||
| 		  context.rotate(childAngle * Math.PI);
 | ||
| 		}
 | ||
| 		context.restore();
 | ||
| 		
 | ||
| 		//## 第三步画进度条
 | ||
| 		series = getArcbarDataPoints(series, gaugeOption, process);
 | ||
| 		context.setLineWidth(gaugeOption.width);
 | ||
| 		context.setStrokeStyle(series[0].color);
 | ||
| 		context.setLineCap('round');
 | ||
| 		context.beginPath();
 | ||
| 		context.arc(centerPosition.x, centerPosition.y, innerRadius , gaugeOption.startAngle * Math.PI, series[0]._proportion_ *Math.PI, false);
 | ||
| 		context.stroke();
 | ||
| 		
 | ||
| 		//## 第四步画指针
 | ||
| 		let pointerRadius = radius - gaugeOption.width*2.5;
 | ||
| 		context.save();
 | ||
| 		context.translate(centerPosition.x, centerPosition.y);
 | ||
| 		context.rotate((series[0]._proportion_ - 1) * Math.PI);
 | ||
| 		context.beginPath();
 | ||
| 		context.setLineWidth(gaugeOption.width/3);
 | ||
| 		let gradient3 = context.createLinearGradient(0, -pointerRadius*0.6, 0 , pointerRadius*0.6);
 | ||
| 		gradient3.addColorStop('0', hexToRgb('#FFFFFF', 0));
 | ||
| 		gradient3.addColorStop('0.5', hexToRgb(series[0].color, 1));
 | ||
| 		gradient3.addColorStop('1.0', hexToRgb('#FFFFFF', 0));
 | ||
| 		context.setStrokeStyle(gradient3);
 | ||
| 		context.arc(0, 0, pointerRadius , 0.85* Math.PI, 1.15 * Math.PI, false);
 | ||
| 		context.stroke();
 | ||
| 		context.beginPath();
 | ||
| 		context.setLineWidth(1);
 | ||
| 		context.setStrokeStyle(series[0].color);
 | ||
| 		context.setFillStyle(series[0].color);
 | ||
| 		context.moveTo(-pointerRadius-gaugeOption.width/3/2,-4);
 | ||
| 		context.lineTo(-pointerRadius-gaugeOption.width/3/2-4,0);
 | ||
| 		context.lineTo(-pointerRadius-gaugeOption.width/3/2,4);
 | ||
| 		context.lineTo(-pointerRadius-gaugeOption.width/3/2,-4);
 | ||
| 		context.stroke();
 | ||
| 		context.fill();
 | ||
| 		context.restore();
 | ||
| 		
 | ||
| 	//default百度样式
 | ||
| 	}else{
 | ||
| 		//画背景
 | ||
| 		context.setLineWidth(gaugeOption.width);
 | ||
| 		context.setLineCap('butt');
 | ||
| 		for (let i = 0; i < categories.length; i++) {
 | ||
| 		  let eachCategories = categories[i];
 | ||
| 		  context.beginPath();
 | ||
| 		  context.setStrokeStyle(eachCategories.color);
 | ||
| 		  context.arc(centerPosition.x, centerPosition.y, radius, eachCategories._startAngle_ * Math.PI, eachCategories._endAngle_ *Math.PI, false);
 | ||
| 		  context.stroke();
 | ||
| 		}
 | ||
| 		context.save();
 | ||
| 		
 | ||
| 		//画刻度线
 | ||
| 		totalAngle = gaugeOption.startAngle - gaugeOption.endAngle + 1;
 | ||
| 		let splitAngle = totalAngle / gaugeOption.splitLine.splitNumber;
 | ||
| 		let childAngle = totalAngle / gaugeOption.splitLine.splitNumber / gaugeOption.splitLine.childNumber;
 | ||
| 		let startX = -radius - gaugeOption.width * 0.5 - gaugeOption.splitLine.fixRadius;
 | ||
| 		let endX = -radius - gaugeOption.width * 0.5 - gaugeOption.splitLine.fixRadius + gaugeOption.splitLine.width;
 | ||
| 		let childendX = -radius - gaugeOption.width * 0.5 - gaugeOption.splitLine.fixRadius + gaugeOption.splitLine.childWidth;
 | ||
| 		
 | ||
| 		context.translate(centerPosition.x, centerPosition.y);
 | ||
| 		context.rotate((gaugeOption.startAngle - 1) * Math.PI);
 | ||
| 		
 | ||
| 		for (let i = 0; i < gaugeOption.splitLine.splitNumber + 1; i++) {
 | ||
| 		  context.beginPath();
 | ||
| 		  context.setStrokeStyle(gaugeOption.splitLine.color);
 | ||
| 		  context.setLineWidth(2 * opts.pixelRatio);
 | ||
| 		  context.moveTo(startX, 0);
 | ||
| 		  context.lineTo(endX, 0);
 | ||
| 		  context.stroke();
 | ||
| 		  context.rotate(splitAngle * Math.PI);
 | ||
| 		}
 | ||
| 		context.restore();
 | ||
| 		
 | ||
| 		context.save();
 | ||
| 		context.translate(centerPosition.x, centerPosition.y);
 | ||
| 		context.rotate((gaugeOption.startAngle - 1) * Math.PI);
 | ||
| 		
 | ||
| 		for (let i = 0; i < gaugeOption.splitLine.splitNumber * gaugeOption.splitLine.childNumber + 1; i++) {
 | ||
| 		  context.beginPath();
 | ||
| 		  context.setStrokeStyle(gaugeOption.splitLine.color);
 | ||
| 		  context.setLineWidth(1 * opts.pixelRatio);
 | ||
| 		  context.moveTo(startX, 0);
 | ||
| 		  context.lineTo(childendX, 0);
 | ||
| 		  context.stroke();
 | ||
| 		  context.rotate(childAngle * Math.PI);
 | ||
| 		}
 | ||
| 		context.restore();
 | ||
| 		
 | ||
| 		//画指针
 | ||
| 		series = getGaugeDataPoints(series, categories, gaugeOption, process);
 | ||
| 		
 | ||
| 		for (let i = 0; i < series.length; i++) {
 | ||
| 		  let eachSeries = series[i];
 | ||
| 		  context.save();
 | ||
| 		  context.translate(centerPosition.x, centerPosition.y);
 | ||
| 		  context.rotate((eachSeries._proportion_ - 1) * Math.PI);
 | ||
| 		  context.beginPath();
 | ||
| 		  context.setFillStyle(eachSeries.color);
 | ||
| 		  context.moveTo(gaugeOption.pointer.width, 0);
 | ||
| 		  context.lineTo(0, -gaugeOption.pointer.width / 2);
 | ||
| 		  context.lineTo(-innerRadius, 0);
 | ||
| 		  context.lineTo(0, gaugeOption.pointer.width / 2);
 | ||
| 		  context.lineTo(gaugeOption.pointer.width, 0);
 | ||
| 		  context.closePath();
 | ||
| 		  context.fill();
 | ||
| 		  context.beginPath();
 | ||
| 		  context.setFillStyle('#FFFFFF');
 | ||
| 		  context.arc(0, 0, gaugeOption.pointer.width / 6, 0, 2 * Math.PI, false);
 | ||
| 		  context.fill();
 | ||
| 		  context.restore();
 | ||
| 		}
 | ||
| 		
 | ||
| 		if (opts.dataLabel !== false) {
 | ||
| 		  drawGaugeLabel(gaugeOption, radius, centerPosition, opts, config, context);
 | ||
| 		}
 | ||
| 	}
 | ||
| 	
 | ||
| 	//画仪表盘标题,副标题
 | ||
|   drawRingTitle(opts, config, context, centerPosition);
 | ||
| 
 | ||
|   if (process === 1 && opts.type === 'gauge') {
 | ||
|     opts.extra.gauge.oldAngle = series[0]._proportion_;
 | ||
|     opts.extra.gauge.oldData = series[0].data;
 | ||
|   }
 | ||
|   return {
 | ||
|     center: centerPosition,
 | ||
|     radius: radius,
 | ||
|     innerRadius: innerRadius,
 | ||
|     categories: categories,
 | ||
|     totalAngle: totalAngle
 | ||
|   };
 | ||
| }
 | ||
| 
 | ||
| function drawRadarDataPoints(series, opts, config, context) {
 | ||
|   var process = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 1;
 | ||
|   var radarOption = assign({},{
 | ||
|     gridColor: '#cccccc',
 | ||
|     labelColor: '#666666',
 | ||
|     opacity: 0.2,
 | ||
| 		gridCount:3
 | ||
|   },opts.extra.radar);
 | ||
|   
 | ||
|   var coordinateAngle = getRadarCoordinateSeries(opts.categories.length);
 | ||
|   
 | ||
|   var centerPosition = {
 | ||
|     x: opts.area[3] + (opts.width - opts.area[1] - opts.area[3]) / 2,
 | ||
|     y: opts.area[0] + (opts.height - opts.area[0] - opts.area[2]) / 2
 | ||
|   };
 | ||
| 
 | ||
|   var radius = Math.min(centerPosition.x - (getMaxTextListLength(opts.categories) + config.radarLabelTextMargin),
 | ||
|     centerPosition.y - config.radarLabelTextMargin);
 | ||
|   //TODO逻辑不对
 | ||
|   radius -= opts.padding[1];
 | ||
| 
 | ||
|   // draw grid
 | ||
|   context.beginPath();
 | ||
|   context.setLineWidth(1 * opts.pixelRatio);
 | ||
|   context.setStrokeStyle(radarOption.gridColor);
 | ||
|   coordinateAngle.forEach(function(angle) {
 | ||
|     var pos = convertCoordinateOrigin(radius * Math.cos(angle), radius * Math.sin(angle), centerPosition);
 | ||
|     context.moveTo(centerPosition.x, centerPosition.y);
 | ||
|     context.lineTo(pos.x, pos.y);
 | ||
|   });
 | ||
|   context.stroke();
 | ||
|   context.closePath();
 | ||
|   // draw split line grid
 | ||
| 
 | ||
|   var _loop = function _loop(i) {
 | ||
|     var startPos = {};
 | ||
|     context.beginPath();
 | ||
|     context.setLineWidth(1 * opts.pixelRatio);
 | ||
|     context.setStrokeStyle(radarOption.gridColor);
 | ||
|     coordinateAngle.forEach(function(angle, index) {
 | ||
|       var pos = convertCoordinateOrigin(radius / radarOption.gridCount * i * Math.cos(angle), radius / radarOption.gridCount * i * Math.sin(angle), centerPosition);
 | ||
|       if (index === 0) {
 | ||
|         startPos = pos;
 | ||
|         context.moveTo(pos.x, pos.y);
 | ||
|       } else {
 | ||
|         context.lineTo(pos.x, pos.y);
 | ||
|       }
 | ||
|     });
 | ||
|     context.lineTo(startPos.x, startPos.y);
 | ||
|     context.stroke();
 | ||
|     context.closePath();
 | ||
|   };
 | ||
| 
 | ||
|   for (var i = 1; i <= radarOption.gridCount; i++) {
 | ||
|     _loop(i);
 | ||
|   }
 | ||
| 
 | ||
|   var radarDataPoints = getRadarDataPoints(coordinateAngle, centerPosition, radius, series, opts, process);
 | ||
| 
 | ||
|   radarDataPoints.forEach(function(eachSeries, seriesIndex) {
 | ||
|     // 绘制区域数据
 | ||
|     context.beginPath();
 | ||
|     context.setFillStyle(hexToRgb(eachSeries.color, radarOption.opacity));
 | ||
|     eachSeries.data.forEach(function(item, index) {
 | ||
|       if (index === 0) {
 | ||
|         context.moveTo(item.position.x, item.position.y);
 | ||
|       } else {
 | ||
|         context.lineTo(item.position.x, item.position.y);
 | ||
|       }
 | ||
|     });
 | ||
|     context.closePath();
 | ||
|     context.fill();
 | ||
| 
 | ||
|     if (opts.dataPointShape !== false) {
 | ||
|       var points = eachSeries.data.map(function(item) {
 | ||
|         return item.position;
 | ||
|       });
 | ||
|       drawPointShape(points, eachSeries.color, eachSeries.pointShape, context, opts);
 | ||
|     }
 | ||
|   });
 | ||
|   // draw label text
 | ||
|   drawRadarLabel(coordinateAngle, radius, centerPosition, opts, config, context);
 | ||
| 
 | ||
|   return {
 | ||
|     center: centerPosition,
 | ||
|     radius: radius,
 | ||
|     angleList: coordinateAngle
 | ||
|   };
 | ||
| }
 | ||
| 
 | ||
| function normalInt(min, max, iter) {
 | ||
|     iter = iter==0?1:iter;
 | ||
|     var arr = [];
 | ||
|     for (var i = 0; i < iter; i++) {
 | ||
|         arr[i] = Math.random();
 | ||
|     };
 | ||
|     return  Math.floor(arr.reduce(function(i,j){return i+j})/iter*(max-min))+min;  
 | ||
| };
 | ||
| 
 | ||
| function collisionNew(area,points,width,height){
 | ||
|     var isIn=false;
 | ||
|     for(let i=0;i<points.length;i++){
 | ||
|       if(points[i].area){
 | ||
|         if(area[3]<points[i].area[1]||area[0]>points[i].area[2]||area[1]>points[i].area[3]||area[2]<points[i].area[0]){
 | ||
|           if(area[0]<0 || area[1]<0 || area[2]>width || area[3]>height){
 | ||
|             isIn=true;
 | ||
|             break;
 | ||
|           }else{
 | ||
|             isIn=false;
 | ||
|           }
 | ||
|         }else{
 | ||
|           isIn=true;
 | ||
|           break;
 | ||
|         }
 | ||
|       }
 | ||
|     }
 | ||
|     return isIn;
 | ||
| };
 | ||
| 
 | ||
| function getBoundingBox(data) {
 | ||
|   var bounds = {}, coords;
 | ||
|   bounds.xMin = 180;
 | ||
|   bounds.xMax = 0;
 | ||
|   bounds.yMin = 90;
 | ||
|   bounds.yMax = 0
 | ||
|   for (var i = 0; i < data.length; i++) {
 | ||
|       var coorda = data[i].geometry.coordinates
 | ||
|       for (var k = 0; k < coorda.length; k++) {
 | ||
|           coords = coorda[k];
 | ||
|           if (coords.length == 1) {
 | ||
|               coords = coords[0]
 | ||
|           }
 | ||
|           for (var j = 0; j < coords.length; j++) {
 | ||
|               var longitude = coords[j][0];
 | ||
|               var latitude = coords[j][1];
 | ||
|               var point = {
 | ||
|                   x: longitude, 
 | ||
|                   y: latitude 
 | ||
|               }
 | ||
|               bounds.xMin = bounds.xMin < point.x ? bounds.xMin : point.x;
 | ||
|               bounds.xMax = bounds.xMax > point.x ? bounds.xMax : point.x;
 | ||
|               bounds.yMin = bounds.yMin < point.y ? bounds.yMin : point.y;
 | ||
|               bounds.yMax = bounds.yMax > point.y ? bounds.yMax : point.y;
 | ||
|           }
 | ||
|       }
 | ||
|   }
 | ||
|   return bounds;
 | ||
| }
 | ||
| 
 | ||
| function coordinateToPoint(latitude, longitude,bounds,scale,xoffset,yoffset) {
 | ||
|   return {
 | ||
|       x: (longitude - bounds.xMin) * scale+xoffset,
 | ||
|       y: (bounds.yMax - latitude) * scale+yoffset
 | ||
|   };
 | ||
| }
 | ||
| 
 | ||
| function pointToCoordinate(pointY, pointX,bounds,scale,xoffset,yoffset) {
 | ||
|   return {
 | ||
|       x: (pointX-xoffset)/scale+bounds.xMin,
 | ||
|       y: bounds.yMax - (pointY-yoffset)/scale
 | ||
|   };
 | ||
| }
 | ||
| 
 | ||
| function isRayIntersectsSegment(poi,s_poi,e_poi){
 | ||
|       if (s_poi[1]==e_poi[1]){return false;} 
 | ||
|       if (s_poi[1]>poi[1] && e_poi[1]>poi[1]){return false;}
 | ||
|       if (s_poi[1]<poi[1] && e_poi[1]<poi[1]){return false;}
 | ||
|       if (s_poi[1]==poi[1] && e_poi[1]>poi[1]){return false;}
 | ||
|       if (e_poi[1]==poi[1] && s_poi[1]>poi[1]){return false;}
 | ||
|       if (s_poi[0]<poi[0] && e_poi[1]<poi[1]){return false;}
 | ||
|       let xseg=e_poi[0]-(e_poi[0]-s_poi[0])*(e_poi[1]-poi[1])/(e_poi[1]-s_poi[1]); 
 | ||
|       if (xseg<poi[0]){
 | ||
|         return false;
 | ||
|       }else{
 | ||
|         return true;
 | ||
|       }
 | ||
| } 
 | ||
| 
 | ||
| function isPoiWithinPoly(poi,poly){
 | ||
|   let sinsc=0;
 | ||
|   for (let i=0;i<poly.length;i++){
 | ||
|     let epoly=poly[i][0];
 | ||
|     if (poly.length == 1) {
 | ||
|       epoly = poly[i][0]
 | ||
|     }
 | ||
|     for(let j=0;j<epoly.length-1;j++){
 | ||
|       let s_poi=epoly[j];
 | ||
|       let e_poi=epoly[j+1];
 | ||
|       if (isRayIntersectsSegment(poi,s_poi,e_poi)){
 | ||
|         sinsc+=1;
 | ||
|       }
 | ||
|     }
 | ||
|   }
 | ||
|   
 | ||
|   if(sinsc%2==1){
 | ||
|     return true;
 | ||
|   }else{
 | ||
|     return false;
 | ||
|   }
 | ||
| }
 | ||
| 
 | ||
| 
 | ||
| function drawMapDataPoints(series, opts, config, context) {
 | ||
|   var mapOption=assign({},{
 | ||
|     border:true,
 | ||
|     borderWidth:1,
 | ||
|     borderColor:'#666666',
 | ||
|     fillOpacity:0.6,
 | ||
|     activeBorderColor:'#f04864',
 | ||
|     activeFillColor:'#facc14',
 | ||
|     activeFillOpacity:1
 | ||
|   },opts.extra.map);
 | ||
|   var coords, point;
 | ||
|   var data = series;
 | ||
|   var bounds= getBoundingBox(data);
 | ||
|   var xScale = opts.width / Math.abs(bounds.xMax - bounds.xMin);
 | ||
|   var yScale = opts.height / Math.abs(bounds.yMax - bounds.yMin);
 | ||
|   var scale = xScale < yScale ? xScale : yScale;
 | ||
|   var xoffset=opts.width/2-Math.abs(bounds.xMax - bounds.xMin)/2*scale;
 | ||
|   var yoffset=opts.height/2-Math.abs(bounds.yMax - bounds.yMin)/2*scale;
 | ||
|   context.beginPath();
 | ||
|   context.clearRect(0, 0, opts.width, opts.height);
 | ||
|   context.setFillStyle(opts.background||'#FFFFFF');
 | ||
|   context.rect(0,0,opts.width,opts.height);
 | ||
|   context.fill();
 | ||
|   for (var i = 0; i < data.length; i++) {
 | ||
|     context.beginPath();
 | ||
|     context.setLineWidth(mapOption.borderWidth * opts.pixelRatio);
 | ||
|     context.setStrokeStyle(mapOption.borderColor);
 | ||
|     context.setFillStyle(hexToRgb(series[i].color, mapOption.fillOpacity));
 | ||
|     if (opts.tooltip) {
 | ||
|       if (opts.tooltip.index == i ) {
 | ||
|         context.setStrokeStyle(mapOption.activeBorderColor);
 | ||
|         context.setFillStyle(hexToRgb(mapOption.activeFillColor, mapOption.activeFillOpacity));
 | ||
|       }
 | ||
|     }
 | ||
|     var coorda = data[i].geometry.coordinates
 | ||
|     for (var k = 0; k < coorda.length; k++) {
 | ||
|       coords = coorda[k];
 | ||
|       if (coords.length == 1) {
 | ||
|         coords = coords[0]
 | ||
|       }
 | ||
|       for (var j = 0; j < coords.length; j++) {
 | ||
|         point = coordinateToPoint(coords[j][1], coords[j][0],bounds,scale,xoffset,yoffset)
 | ||
|         if (j === 0) {
 | ||
|           context.beginPath();
 | ||
|           context.moveTo(point.x, point.y);
 | ||
|         } else {
 | ||
|           context.lineTo(point.x, point.y);
 | ||
|         }
 | ||
|       }
 | ||
|       context.fill();
 | ||
|       if(mapOption.border == true){
 | ||
|         context.stroke();
 | ||
|       }
 | ||
|     }
 | ||
|     if(opts.dataLabel == true){
 | ||
|       var centerPoint = data[i].properties.centroid;
 | ||
|       if(centerPoint){
 | ||
|         point = coordinateToPoint(centerPoint[1], centerPoint[0],bounds,scale,xoffset,yoffset);
 | ||
|         let fontSize=data[i].textSize||config.fontSize;
 | ||
|         let text=data[i].properties.name;
 | ||
|         context.beginPath();
 | ||
|         context.setFontSize(fontSize)
 | ||
|         context.setFillStyle(data[i].textColor||'#666666')
 | ||
|         context.fillText(text, point.x-measureText(text,fontSize)/2, point.y+fontSize/2);
 | ||
|         context.closePath();
 | ||
|         context.stroke();
 | ||
|       }
 | ||
|     }
 | ||
|   }
 | ||
|   opts.chartData.mapData={
 | ||
|     bounds:bounds,
 | ||
|     scale:scale,
 | ||
|     xoffset:xoffset,
 | ||
|     yoffset:yoffset
 | ||
|   }
 | ||
|   drawToolTipBridge(opts, config, context,1);
 | ||
|   context.draw();
 | ||
| }
 | ||
| 
 | ||
| function getWordCloudPoint(opts,type){
 | ||
|   let points = opts.series.sort(function(a,b){return parseInt(b.textSize)-parseInt(a.textSize);});
 | ||
|   switch (type) {
 | ||
|     case 'normal':
 | ||
|       for (let i = 0; i < points.length; i++) {
 | ||
|         let text = points[i].name;
 | ||
|         let tHeight = points[i].textSize;
 | ||
|         let tWidth = measureText(text,tHeight);
 | ||
|         let x,y;
 | ||
|         let area;
 | ||
|         let breaknum=0;
 | ||
|         while(true) {
 | ||
|             breaknum++;
 | ||
|             x = normalInt(-opts.width/2, opts.width/2,5) - tWidth/2;
 | ||
|             y = normalInt(-opts.height/2, opts.height/2,5) + tHeight/2;
 | ||
|             area=[x-5+opts.width/2,y-5-tHeight+opts.height/2,x+tWidth+5+opts.width/2,y+5+opts.height/2];
 | ||
|             let isCollision = collisionNew(area,points,opts.width,opts.height);
 | ||
|             if (!isCollision) break;
 | ||
|             if (breaknum==1000){
 | ||
|               area=[-100,-100,-100,-100];
 | ||
|               break;
 | ||
|             }
 | ||
|         };
 | ||
|         points[i].area=area;
 | ||
|       }
 | ||
|     break;
 | ||
|     case 'vertical':
 | ||
|       function Spin(){
 | ||
|         //获取均匀随机值,是否旋转,旋转的概率为(1-0.5)
 | ||
|         if (Math.random()>0.7) {
 | ||
|             return true;
 | ||
|         }else {return false};
 | ||
|       };
 | ||
|       for (let i = 0; i < points.length; i++) { 
 | ||
|         let text = points[i].name;
 | ||
|         let tHeight = points[i].textSize;
 | ||
|         let tWidth = measureText(text,tHeight);
 | ||
|         let isSpin = Spin(); 
 | ||
|         let x,y,area,areav;
 | ||
|         let breaknum=0;
 | ||
|         while(true) {
 | ||
|           breaknum++;
 | ||
|           let isCollision;
 | ||
|           if (isSpin) {
 | ||
|               x = normalInt(-opts.width/2, opts.width/2,5) - tWidth/2;
 | ||
|               y = normalInt(-opts.height/2, opts.height/2,5)+tHeight/2;
 | ||
|               area=[y-5-tWidth+opts.width/2,(-x-5+opts.height/2),y+5+opts.width/2,(-x+tHeight+5+opts.height/2)];
 | ||
|               areav=[opts.width-(opts.width/2-opts.height/2)-(-x+tHeight+5+opts.height/2)-5,(opts.height/2-opts.width/2)+(y-5-tWidth+opts.width/2)-5,opts.width-(opts.width/2-opts.height/2)-(-x+tHeight+5+opts.height/2)+tHeight,(opts.height/2-opts.width/2)+(y-5-tWidth+opts.width/2)+tWidth+5];
 | ||
|               isCollision = collisionNew(areav,points,opts.height,opts.width);
 | ||
|           }else{
 | ||
|             x = normalInt(-opts.width/2, opts.width/2,5) - tWidth/2;
 | ||
|             y = normalInt(-opts.height/2, opts.height/2,5)+tHeight/2;
 | ||
|             area=[x-5+opts.width/2,y-5-tHeight+opts.height/2,x+tWidth+5+opts.width/2,y+5+opts.height/2];
 | ||
|             isCollision = collisionNew(area,points,opts.width,opts.height);
 | ||
|           } 
 | ||
|           if (!isCollision) break;
 | ||
|           if (breaknum==1000){
 | ||
|             area=[-1000,-1000,-1000,-1000];
 | ||
|             break;
 | ||
|           }
 | ||
|         };
 | ||
|         if (isSpin) {
 | ||
|           points[i].area=areav;
 | ||
|           points[i].areav=area;
 | ||
|         }else{
 | ||
|           points[i].area=area;
 | ||
|         }
 | ||
|         points[i].rotate=isSpin;
 | ||
|       };
 | ||
|     break;
 | ||
|   }
 | ||
|   return points;
 | ||
| }
 | ||
| 
 | ||
| 
 | ||
| function drawWordCloudDataPoints(series, opts, config, context) {
 | ||
|   let process = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 1;
 | ||
|   let wordOption = assign({},{
 | ||
|     type: 'normal',
 | ||
|     autoColors: true
 | ||
|   },opts.extra.word);
 | ||
|   
 | ||
|   context.beginPath();
 | ||
|   context.setFillStyle(opts.background||'#FFFFFF');
 | ||
|   context.rect(0,0,opts.width,opts.height);
 | ||
|   context.fill();
 | ||
|   context.save();
 | ||
|   let points = opts.chartData.wordCloudData;
 | ||
|   context.translate(opts.width/2,opts.height/2);
 | ||
|   
 | ||
|   for(let i=0;i<points.length;i++){
 | ||
|       context.save();
 | ||
|       if(points[i].rotate){
 | ||
|         context.rotate(90 * Math.PI / 180);
 | ||
|       }
 | ||
|       let text = points[i].name;
 | ||
|       let tHeight = points[i].textSize;
 | ||
|       let tWidth = measureText(text,tHeight);
 | ||
|       context.beginPath();
 | ||
|       context.setStrokeStyle(points[i].color);
 | ||
|       context.setFillStyle(points[i].color);
 | ||
|       context.setFontSize(tHeight);
 | ||
|       if(points[i].rotate){
 | ||
|         if(points[i].areav[0]>0){
 | ||
|           if (opts.tooltip) {
 | ||
|             if (opts.tooltip.index == i) {
 | ||
|               context.strokeText(text,(points[i].areav[0]+5-opts.width/2)*process-tWidth*(1-process)/2,(points[i].areav[1]+5+tHeight-opts.height/2)*process);
 | ||
|               }else{
 | ||
|                 context.fillText(text,(points[i].areav[0]+5-opts.width/2)*process-tWidth*(1-process)/2,(points[i].areav[1]+5+tHeight-opts.height/2)*process);
 | ||
|               }
 | ||
|           }else{
 | ||
|             context.fillText(text,(points[i].areav[0]+5-opts.width/2)*process-tWidth*(1-process)/2,(points[i].areav[1]+5+tHeight-opts.height/2)*process);
 | ||
|           } 
 | ||
|         }
 | ||
|       }else{
 | ||
|         if(points[i].area[0]>0){
 | ||
|           if (opts.tooltip) {
 | ||
|             if (opts.tooltip.index == i) {
 | ||
|               context.strokeText(text,(points[i].area[0]+5-opts.width/2)*process-tWidth*(1-process)/2,(points[i].area[1]+5+tHeight-opts.height/2)*process);
 | ||
|             }else{
 | ||
|               context.fillText(text,(points[i].area[0]+5-opts.width/2)*process-tWidth*(1-process)/2,(points[i].area[1]+5+tHeight-opts.height/2)*process);
 | ||
|             }
 | ||
|           }else{
 | ||
|             context.fillText(text,(points[i].area[0]+5-opts.width/2)*process-tWidth*(1-process)/2,(points[i].area[1]+5+tHeight-opts.height/2)*process);
 | ||
|           }
 | ||
|             
 | ||
|         }
 | ||
|       }
 | ||
|       
 | ||
|       context.stroke();
 | ||
|       context.restore();
 | ||
|   }
 | ||
|   context.restore();
 | ||
| }
 | ||
| 
 | ||
| function drawFunnelDataPoints(series, opts, config, context) {
 | ||
|   let process = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 1;
 | ||
|   let funnelOption = assign({},{
 | ||
|     activeWidth:10,
 | ||
|     activeOpacity:0.3,
 | ||
|     border:false,
 | ||
|     borderWidth:2,
 | ||
|     borderColor:'#FFFFFF',
 | ||
|     fillOpacity:1,
 | ||
|     labelAlign:'right'
 | ||
|   },opts.extra.funnel);
 | ||
|   let eachSpacing = (opts.height - opts.area[0] - opts.area[2])/series.length;
 | ||
|   let centerPosition = {
 | ||
|     x: opts.area[3] + (opts.width - opts.area[1] - opts.area[3]) / 2,
 | ||
|     y: opts.height-opts.area[2]
 | ||
|   };
 | ||
|   let activeWidth = funnelOption.activeWidth;
 | ||
|   let radius = Math.min((opts.width - opts.area[1] - opts.area[3]) / 2 - activeWidth, (opts.height - opts.area[0] - opts.area[2]) / 2 - activeWidth);
 | ||
|   series = getFunnelDataPoints(series, radius, process);
 | ||
|   context.save();
 | ||
|   context.translate(centerPosition.x,centerPosition.y);
 | ||
|   for(let i=0;i<series.length;i++){
 | ||
|     if(i==0){
 | ||
|       if (opts.tooltip) {
 | ||
|         if (opts.tooltip.index == i) {
 | ||
|           context.beginPath();
 | ||
|           context.setFillStyle(hexToRgb(series[i].color, funnelOption.activeOpacity));
 | ||
|           context.moveTo(-activeWidth, 0);
 | ||
|           context.lineTo(-series[i].radius-activeWidth, -eachSpacing);
 | ||
|           context.lineTo(series[i].radius+activeWidth, -eachSpacing);
 | ||
|           context.lineTo(activeWidth, 0);
 | ||
|           context.lineTo(-activeWidth, 0);
 | ||
|           context.closePath();
 | ||
|           context.fill();
 | ||
|         }
 | ||
|       }
 | ||
|       series[i].funnelArea=[centerPosition.x-series[i].radius,centerPosition.y-eachSpacing,centerPosition.x+series[i].radius,centerPosition.y];
 | ||
|       context.beginPath();
 | ||
|       context.setLineWidth(funnelOption.borderWidth * opts.pixelRatio);
 | ||
|       context.setStrokeStyle(funnelOption.borderColor);
 | ||
|       context.setFillStyle(hexToRgb(series[i].color, funnelOption.fillOpacity));
 | ||
|       context.moveTo(0, 0);
 | ||
|       context.lineTo(-series[i].radius, -eachSpacing);
 | ||
|       context.lineTo(series[i].radius, -eachSpacing);
 | ||
|       context.lineTo(0, 0);
 | ||
|       context.closePath();
 | ||
|       context.fill();
 | ||
|       if(funnelOption.border == true){
 | ||
|         context.stroke();
 | ||
|       }
 | ||
|     }else{
 | ||
|       if (opts.tooltip) {
 | ||
|         if (opts.tooltip.index == i) {
 | ||
|           context.beginPath();
 | ||
|           context.setFillStyle(hexToRgb(series[i].color, funnelOption.activeOpacity));
 | ||
|           context.moveTo(0, 0);
 | ||
|           context.lineTo(-series[i-1].radius-activeWidth, 0);
 | ||
|           context.lineTo(-series[i].radius-activeWidth, -eachSpacing);
 | ||
|           context.lineTo(series[i].radius+activeWidth, -eachSpacing);
 | ||
|           context.lineTo(series[i-1].radius+activeWidth, 0);
 | ||
|           context.lineTo(0, 0);
 | ||
|           context.closePath();
 | ||
|           context.fill();
 | ||
|         }
 | ||
|       }
 | ||
|       series[i].funnelArea=[centerPosition.x-series[i].radius,centerPosition.y-eachSpacing*(i+1),centerPosition.x+series[i].radius,centerPosition.y-eachSpacing*i];
 | ||
|       context.beginPath();
 | ||
|       context.setLineWidth(funnelOption.borderWidth * opts.pixelRatio);
 | ||
|       context.setStrokeStyle(funnelOption.borderColor);
 | ||
|       context.setFillStyle(hexToRgb(series[i].color, funnelOption.fillOpacity));
 | ||
|       context.moveTo(0, 0);
 | ||
|       context.lineTo(-series[i-1].radius, 0);
 | ||
|       context.lineTo(-series[i].radius, -eachSpacing);
 | ||
|       context.lineTo(series[i].radius, -eachSpacing);
 | ||
|       context.lineTo(series[i-1].radius, 0);
 | ||
|       context.lineTo(0, 0);
 | ||
|       context.closePath();
 | ||
|       context.fill();
 | ||
|       if(funnelOption.border == true){
 | ||
|         context.stroke();
 | ||
|       }
 | ||
|     }
 | ||
|     context.translate(0,-eachSpacing)
 | ||
|   }
 | ||
|   context.restore();
 | ||
|   
 | ||
|   if (opts.dataLabel !== false && process === 1) {
 | ||
|     drawFunnelText(series, opts, context, eachSpacing, funnelOption.labelAlign, activeWidth, centerPosition);
 | ||
|   }
 | ||
|   
 | ||
|   return {
 | ||
|     center: centerPosition,
 | ||
|     radius: radius,
 | ||
|     series: series
 | ||
|   };
 | ||
| }
 | ||
| 
 | ||
| function drawFunnelText(series, opts, context, eachSpacing, labelAlign,activeWidth, centerPosition){
 | ||
|   for(let i=0;i<series.length;i++){
 | ||
|     let item = series[i];
 | ||
|     let startX,endX,startY,fontSize;
 | ||
|     let text = item.format ? item.format(+item._proportion_.toFixed(2)) : util.toFixed(item._proportion_ * 100) +'%';
 | ||
|     if(labelAlign == 'right'){
 | ||
|       if(i==0){
 | ||
|         startX=(item.funnelArea[2]+centerPosition.x)/2;
 | ||
|       }else{
 | ||
|         startX=(item.funnelArea[2]+series[i-1].funnelArea[2])/2;
 | ||
|       }
 | ||
|       endX=startX+activeWidth*2;
 | ||
|       startY=item.funnelArea[1]+eachSpacing/2;
 | ||
|       fontSize = item.textSize || opts.fontSize;
 | ||
|       context.setLineWidth(1 * opts.pixelRatio);
 | ||
|       context.setStrokeStyle(item.color);
 | ||
|       context.setFillStyle(item.color);
 | ||
|       context.beginPath();
 | ||
|       context.moveTo(startX,startY );
 | ||
|       context.lineTo(endX,startY);
 | ||
|       context.stroke();
 | ||
|       context.closePath();
 | ||
|       context.beginPath();
 | ||
|       context.moveTo(endX, startY);
 | ||
|       context.arc(endX, startY, 2, 0, 2 * Math.PI);
 | ||
|       context.closePath();
 | ||
|       context.fill();
 | ||
|       context.beginPath();
 | ||
|       context.setFontSize(fontSize);
 | ||
|       context.setFillStyle(item.textColor || '#666666');
 | ||
|       context.fillText(text, endX+5, startY + fontSize/2 -2);
 | ||
|       context.closePath();
 | ||
|       context.stroke();
 | ||
|       context.closePath();
 | ||
|     }else{
 | ||
|       if(i==0){
 | ||
|         startX=(item.funnelArea[0]+centerPosition.x)/2;
 | ||
|       }else{
 | ||
|         startX=(item.funnelArea[0]+series[i-1].funnelArea[0])/2;
 | ||
|       }
 | ||
|       endX=startX-activeWidth*2;
 | ||
|       startY=item.funnelArea[1]+eachSpacing/2;
 | ||
|       fontSize = item.textSize || opts.fontSize;
 | ||
|       context.setLineWidth(1 * opts.pixelRatio);
 | ||
|       context.setStrokeStyle(item.color);
 | ||
|       context.setFillStyle(item.color);
 | ||
|       context.beginPath();
 | ||
|       context.moveTo(startX,startY );
 | ||
|       context.lineTo(endX,startY);
 | ||
|       context.stroke();
 | ||
|       context.closePath();
 | ||
|       context.beginPath();
 | ||
|       context.moveTo(endX, startY);
 | ||
|       context.arc(endX, startY, 2, 0, 2 * Math.PI);
 | ||
|       context.closePath();
 | ||
|       context.fill();
 | ||
|       context.beginPath();
 | ||
|       context.setFontSize(fontSize);
 | ||
|       context.setFillStyle(item.textColor || '#666666');
 | ||
|       context.fillText(text, endX-5-measureText(text), startY + fontSize/2 -2);
 | ||
|       context.closePath();
 | ||
|       context.stroke();
 | ||
|       context.closePath();
 | ||
|     }
 | ||
|     
 | ||
|   }
 | ||
| }
 | ||
| 
 | ||
| 
 | ||
| function drawCanvas(opts, context) {
 | ||
|   context.draw();
 | ||
| }
 | ||
| 
 | ||
| var Timing = {
 | ||
|   easeIn: function easeIn(pos) {
 | ||
|     return Math.pow(pos, 3);
 | ||
|   },
 | ||
|   easeOut: function easeOut(pos) {
 | ||
|     return Math.pow(pos - 1, 3) + 1;
 | ||
|   },
 | ||
|   easeInOut: function easeInOut(pos) {
 | ||
|     if ((pos /= 0.5) < 1) {
 | ||
|       return 0.5 * Math.pow(pos, 3);
 | ||
|     } else {
 | ||
|       return 0.5 * (Math.pow(pos - 2, 3) + 2);
 | ||
|     }
 | ||
|   },
 | ||
|   linear: function linear(pos) {
 | ||
|     return pos;
 | ||
|   }
 | ||
| };
 | ||
| 
 | ||
| function Animation(opts) {
 | ||
|   this.isStop = false;
 | ||
|   opts.duration = typeof opts.duration === 'undefined' ? 1000 : opts.duration;
 | ||
|   opts.timing = opts.timing || 'linear';
 | ||
|   var delay = 17;
 | ||
| 
 | ||
|   function createAnimationFrame() {
 | ||
|     if (typeof setTimeout !== 'undefined') {
 | ||
|       return function(step, delay) {
 | ||
|         setTimeout(function() {
 | ||
|           var timeStamp = +new Date();
 | ||
|           step(timeStamp);
 | ||
|         }, delay);
 | ||
|       };
 | ||
|     } else if (typeof requestAnimationFrame !== 'undefined') {
 | ||
|       return requestAnimationFrame;
 | ||
|     } else {
 | ||
|       return function(step) {
 | ||
|         step(null);
 | ||
|       };
 | ||
|     }
 | ||
|   };
 | ||
|   var animationFrame = createAnimationFrame();
 | ||
|   var startTimeStamp = null;
 | ||
|   var _step = function step(timestamp) {
 | ||
|     if (timestamp === null || this.isStop === true) {
 | ||
|       opts.onProcess && opts.onProcess(1);
 | ||
|       opts.onAnimationFinish && opts.onAnimationFinish();
 | ||
|       return;
 | ||
|     }
 | ||
|     if (startTimeStamp === null) {
 | ||
|       startTimeStamp = timestamp;
 | ||
|     }
 | ||
|     if (timestamp - startTimeStamp < opts.duration) {
 | ||
|       var process = (timestamp - startTimeStamp) / opts.duration;
 | ||
|       var timingFunction = Timing[opts.timing];
 | ||
|       process = timingFunction(process);
 | ||
| 
 | ||
|       opts.onProcess && opts.onProcess(process);
 | ||
|       animationFrame(_step, delay);
 | ||
|     } else {
 | ||
|       opts.onProcess && opts.onProcess(1);
 | ||
|       opts.onAnimationFinish && opts.onAnimationFinish();
 | ||
|     }
 | ||
|   };
 | ||
|   _step = _step.bind(this);
 | ||
|   animationFrame(_step, delay);
 | ||
| }
 | ||
| 
 | ||
| // stop animation immediately
 | ||
| // and tigger onAnimationFinish
 | ||
| Animation.prototype.stop = function() {
 | ||
|   this.isStop = true;
 | ||
| };
 | ||
| 
 | ||
| function drawCharts(type, opts, config, context) {
 | ||
|   var _this = this;
 | ||
|   var series = opts.series;
 | ||
|   var categories = opts.categories;
 | ||
|   series = fillSeries(series, opts, config);
 | ||
|   var duration = opts.animation ? opts.duration : 0;
 | ||
|   _this.animationInstance && _this.animationInstance.stop();
 | ||
|   var seriesMA = null;
 | ||
|   if (type == 'candle') {
 | ||
|     let average = assign({}, opts.extra.candle.average);
 | ||
|     if (average.show) {
 | ||
|       seriesMA = calCandleMA(average.day, average.name, average.color, series[0].data);
 | ||
|       seriesMA = fillSeries(seriesMA, opts, config);
 | ||
|       opts.seriesMA = seriesMA;
 | ||
|     } else if (opts.seriesMA) {
 | ||
|       seriesMA = opts.seriesMA = fillSeries(opts.seriesMA, opts, config);
 | ||
|     } else {
 | ||
|       seriesMA = series;
 | ||
|     }
 | ||
|   } else {
 | ||
|     seriesMA = series;
 | ||
|   }
 | ||
| 
 | ||
|   /* 过滤掉show=false的series */
 | ||
|   opts._series_ = series = filterSeries(series);
 | ||
| 
 | ||
|   //重新计算图表区域
 | ||
| 
 | ||
|   opts.area = new Array(4);
 | ||
|   //复位绘图区域
 | ||
|   for (let j = 0; j < 4; j++) {
 | ||
|     opts.area[j] = opts.padding[j];
 | ||
|   }
 | ||
| 
 | ||
|   //通过计算三大区域:图例、X轴、Y轴的大小,确定绘图区域
 | ||
|   var _calLegendData = calLegendData(seriesMA, opts, config, opts.chartData),
 | ||
|     legendHeight = _calLegendData.area.wholeHeight,
 | ||
|     legendWidth = _calLegendData.area.wholeWidth;
 | ||
|     
 | ||
|   switch (opts.legend.position) {
 | ||
|     case 'top':
 | ||
|       opts.area[0] += legendHeight;
 | ||
|       break;
 | ||
|     case 'bottom':
 | ||
|       opts.area[2] += legendHeight;
 | ||
|       break;
 | ||
|     case 'left':
 | ||
|       opts.area[3] += legendWidth;
 | ||
|       break;
 | ||
|     case 'right':
 | ||
|       opts.area[1] += legendWidth;
 | ||
|       break;
 | ||
|   }
 | ||
| 
 | ||
|   let _calYAxisData = {},yAxisWidth = 0;
 | ||
|   if (opts.type === 'line' || opts.type === 'column' || opts.type === 'area' || opts.type === 'mix' || opts.type === 'candle') {
 | ||
|     _calYAxisData = calYAxisData(series, opts, config);
 | ||
|     yAxisWidth = _calYAxisData.yAxisWidth;
 | ||
|     //如果显示Y轴标题
 | ||
|     if(opts.yAxis.showTitle){
 | ||
|       let maxTitleHeight=0;
 | ||
|       for(let i=0;i<opts.yAxis.data.length;i++){
 | ||
|         maxTitleHeight = Math.max(maxTitleHeight,opts.yAxis.data[i].titleFontSize?opts.yAxis.data[i].titleFontSize:config.fontSize)
 | ||
|       }
 | ||
|       opts.area[0] += (maxTitleHeight+6)*opts.pixelRatio;
 | ||
|     }
 | ||
|     let rightIndex=0,leftIndex=0;
 | ||
|     //计算主绘图区域左右位置
 | ||
|     for(let i=0;i<yAxisWidth.length;i++){
 | ||
|       if(yAxisWidth[i].position=='left'){
 | ||
|         if(leftIndex>0){
 | ||
|           opts.area[3] += yAxisWidth[i].width + opts.yAxis.padding;
 | ||
|         }else{
 | ||
|           opts.area[3] += yAxisWidth[i].width;
 | ||
|         }
 | ||
|         leftIndex +=1;
 | ||
|       }else{
 | ||
|         if(rightIndex>0){
 | ||
|           opts.area[1] += yAxisWidth[i].width + opts.yAxis.padding;
 | ||
|         }else{
 | ||
|           opts.area[1] += yAxisWidth[i].width;
 | ||
|         }
 | ||
|         rightIndex +=1;
 | ||
|       }
 | ||
|     }
 | ||
|   }else{
 | ||
|     config.yAxisWidth = yAxisWidth;
 | ||
|   }
 | ||
|   opts.chartData.yAxisData = _calYAxisData;
 | ||
| 
 | ||
|   if (opts.categories && opts.categories.length) {
 | ||
|     opts.chartData.xAxisData = getXAxisPoints(opts.categories, opts, config);
 | ||
|     let _calCategoriesData = calCategoriesData(opts.categories, opts, config, opts.chartData.xAxisData.eachSpacing),
 | ||
|       xAxisHeight = _calCategoriesData.xAxisHeight,
 | ||
|       angle = _calCategoriesData.angle;
 | ||
|     config.xAxisHeight = xAxisHeight;
 | ||
|     config._xAxisTextAngle_ = angle;
 | ||
|     opts.area[2] += xAxisHeight;
 | ||
|     opts.chartData.categoriesData = _calCategoriesData;
 | ||
|   }else{
 | ||
| 		if (opts.type === 'line' || opts.type === 'area' || opts.type === 'points') {
 | ||
| 			opts.chartData.xAxisData = calXAxisData(series, opts, config);
 | ||
| 			categories=opts.chartData.xAxisData.rangesFormat;
 | ||
| 			let _calCategoriesData = calCategoriesData(categories, opts, config, opts.chartData.xAxisData.eachSpacing),
 | ||
| 			  xAxisHeight = _calCategoriesData.xAxisHeight,
 | ||
| 			  angle = _calCategoriesData.angle;
 | ||
| 			config.xAxisHeight = xAxisHeight;
 | ||
| 			config._xAxisTextAngle_ = angle;
 | ||
| 			opts.area[2] += xAxisHeight;
 | ||
| 			opts.chartData.categoriesData = _calCategoriesData;
 | ||
| 		}else{
 | ||
| 			opts.chartData.xAxisData={
 | ||
| 				xAxisPoints: []
 | ||
| 			};
 | ||
| 		}
 | ||
| 	}
 | ||
|   //计算右对齐偏移距离
 | ||
|   if (opts.enableScroll && opts.xAxis.scrollAlign == 'right' && opts._scrollDistance_ === undefined) {
 | ||
|     let offsetLeft = 0,
 | ||
|       xAxisPoints = opts.chartData.xAxisData.xAxisPoints,
 | ||
|       startX = opts.chartData.xAxisData.startX,
 | ||
|       endX = opts.chartData.xAxisData.endX,
 | ||
|       eachSpacing = opts.chartData.xAxisData.eachSpacing;
 | ||
|     let totalWidth = eachSpacing * (xAxisPoints.length - 1);
 | ||
|     let screenWidth = endX - startX;
 | ||
|     offsetLeft = screenWidth - totalWidth;
 | ||
|     _this.scrollOption = {
 | ||
|       currentOffset: offsetLeft,
 | ||
|       startTouchX: offsetLeft,
 | ||
|       distance: 0,
 | ||
|       lastMoveTime: 0
 | ||
|     };
 | ||
|     opts._scrollDistance_ = offsetLeft;
 | ||
|   }
 | ||
| 
 | ||
|   if (type === 'pie' || type === 'ring' || type === 'rose') {
 | ||
|     config._pieTextMaxLength_ = opts.dataLabel === false ? 0 : getPieTextMaxLength(seriesMA);
 | ||
|   }
 | ||
| 
 | ||
|   switch (type) {
 | ||
|     case 'word':
 | ||
|       let wordOption = assign({},{
 | ||
|         type: 'normal',
 | ||
|         autoColors: true
 | ||
|       },opts.extra.word);
 | ||
|       if(opts.updateData==true || opts.updateData==undefined){
 | ||
|         opts.chartData.wordCloudData=getWordCloudPoint(opts,wordOption.type);
 | ||
|       }
 | ||
|       this.animationInstance = new Animation({
 | ||
|         timing: 'easeInOut',
 | ||
|         duration: duration,
 | ||
|         onProcess: function(process) {
 | ||
|           context.clearRect(0, 0, opts.width, opts.height);
 | ||
|           if (opts.rotate) {
 | ||
|             contextRotate(context, opts);
 | ||
|           }
 | ||
|           drawWordCloudDataPoints(series, opts, config, context,process);
 | ||
|           drawCanvas(opts, context);
 | ||
|         },
 | ||
|         onAnimationFinish: function onAnimationFinish() {
 | ||
|           _this.event.trigger('renderComplete');
 | ||
|         }
 | ||
|       });
 | ||
|     break;
 | ||
|     case 'map':
 | ||
|       context.clearRect(0, 0, opts.width, opts.height);
 | ||
|       drawMapDataPoints(series, opts, config, context);
 | ||
|     break;
 | ||
|     case 'funnel':
 | ||
|       this.animationInstance = new Animation({
 | ||
|         timing: 'easeInOut',
 | ||
|         duration: duration,
 | ||
|         onProcess: function(process) {
 | ||
|           context.clearRect(0, 0, opts.width, opts.height);
 | ||
|           if (opts.rotate) {
 | ||
|             contextRotate(context, opts);
 | ||
|           }
 | ||
|           opts.chartData.funnelData = drawFunnelDataPoints(series, opts, config, context, process);
 | ||
|           drawLegend(opts.series, opts, config, context, opts.chartData);
 | ||
|           drawToolTipBridge(opts, config, context, process);
 | ||
|           drawCanvas(opts, context);
 | ||
|         },
 | ||
|         onAnimationFinish: function onAnimationFinish() {
 | ||
|           _this.event.trigger('renderComplete');
 | ||
|         }
 | ||
|       });
 | ||
|     break;
 | ||
|     case 'line':
 | ||
|       this.animationInstance = new Animation({
 | ||
|         timing: 'easeIn',
 | ||
|         duration: duration,
 | ||
|         onProcess: function onProcess(process) {
 | ||
|           context.clearRect(0, 0, opts.width, opts.height);
 | ||
|           if (opts.rotate) {
 | ||
|             contextRotate(context, opts);
 | ||
|           }
 | ||
|           drawYAxisGrid(categories, opts, config, context);
 | ||
|           drawXAxis(categories, opts, config, context);
 | ||
|           var _drawLineDataPoints = drawLineDataPoints(series, opts, config, context, process),
 | ||
|             xAxisPoints = _drawLineDataPoints.xAxisPoints,
 | ||
|             calPoints = _drawLineDataPoints.calPoints,
 | ||
|             eachSpacing = _drawLineDataPoints.eachSpacing;
 | ||
|           opts.chartData.xAxisPoints = xAxisPoints;
 | ||
|           opts.chartData.calPoints = calPoints;
 | ||
|           opts.chartData.eachSpacing = eachSpacing;
 | ||
|           drawYAxis(series, opts, config, context);
 | ||
|           if (opts.enableMarkLine !== false && process === 1) {
 | ||
|             drawMarkLine(opts, config, context);
 | ||
|           }
 | ||
|           drawLegend(opts.series, opts, config, context, opts.chartData);
 | ||
|           drawToolTipBridge(opts, config, context, process, eachSpacing, xAxisPoints);
 | ||
|           drawCanvas(opts, context);
 | ||
| 
 | ||
|         },
 | ||
|         onAnimationFinish: function onAnimationFinish() {
 | ||
|           _this.event.trigger('renderComplete');
 | ||
|         }
 | ||
|       });
 | ||
|       break;
 | ||
|     case 'mix':
 | ||
|       this.animationInstance = new Animation({
 | ||
|         timing: 'easeIn',
 | ||
|         duration: duration,
 | ||
|         onProcess: function onProcess(process) {
 | ||
|           context.clearRect(0, 0, opts.width, opts.height);
 | ||
|           if (opts.rotate) {
 | ||
|             contextRotate(context, opts);
 | ||
|           }
 | ||
|           drawYAxisGrid(categories, opts, config, context);
 | ||
|           drawXAxis(categories, opts, config, context);
 | ||
|           var _drawMixDataPoints = drawMixDataPoints(series, opts, config, context, process),
 | ||
|             xAxisPoints = _drawMixDataPoints.xAxisPoints,
 | ||
|             calPoints = _drawMixDataPoints.calPoints,
 | ||
|             eachSpacing = _drawMixDataPoints.eachSpacing;
 | ||
|           opts.chartData.xAxisPoints = xAxisPoints;
 | ||
|           opts.chartData.calPoints = calPoints;
 | ||
|           opts.chartData.eachSpacing = eachSpacing;
 | ||
|           drawYAxis(series, opts, config, context);
 | ||
|           if (opts.enableMarkLine !== false && process === 1) {
 | ||
|             drawMarkLine(opts, config, context);
 | ||
|           }
 | ||
|           drawLegend(opts.series, opts, config, context, opts.chartData);
 | ||
|           drawToolTipBridge(opts, config, context, process, eachSpacing, xAxisPoints);
 | ||
|           drawCanvas(opts, context);
 | ||
|         },
 | ||
|         onAnimationFinish: function onAnimationFinish() {
 | ||
|           _this.event.trigger('renderComplete');
 | ||
|         }
 | ||
|       });
 | ||
|       break;
 | ||
|     case 'column':
 | ||
|       this.animationInstance = new Animation({
 | ||
|         timing: 'easeIn',
 | ||
|         duration: duration,
 | ||
|         onProcess: function onProcess(process) {
 | ||
|           context.clearRect(0, 0, opts.width, opts.height);
 | ||
|           if (opts.rotate) {
 | ||
|             contextRotate(context, opts);
 | ||
|           }
 | ||
|           drawYAxisGrid(categories, opts, config, context);
 | ||
|           drawXAxis(categories, opts, config, context);
 | ||
|           var _drawColumnDataPoints = drawColumnDataPoints(series, opts, config, context, process),
 | ||
|             xAxisPoints = _drawColumnDataPoints.xAxisPoints,
 | ||
|             calPoints = _drawColumnDataPoints.calPoints,
 | ||
|             eachSpacing = _drawColumnDataPoints.eachSpacing;
 | ||
|           opts.chartData.xAxisPoints = xAxisPoints;
 | ||
|           opts.chartData.calPoints = calPoints;
 | ||
|           opts.chartData.eachSpacing = eachSpacing;
 | ||
|           drawYAxis(series, opts, config, context);
 | ||
|           if (opts.enableMarkLine !== false && process === 1) {
 | ||
|             drawMarkLine(opts, config, context);
 | ||
|           }
 | ||
|           drawLegend(opts.series, opts, config, context, opts.chartData);
 | ||
|           drawToolTipBridge(opts, config, context, process, eachSpacing, xAxisPoints);
 | ||
|           drawCanvas(opts, context);
 | ||
|         },
 | ||
|         onAnimationFinish: function onAnimationFinish() {
 | ||
|           _this.event.trigger('renderComplete');
 | ||
|         }
 | ||
|       });
 | ||
|       break;
 | ||
|     case 'area':
 | ||
|       this.animationInstance = new Animation({
 | ||
|         timing: 'easeIn',
 | ||
|         duration: duration,
 | ||
|         onProcess: function onProcess(process) {
 | ||
|           context.clearRect(0, 0, opts.width, opts.height);
 | ||
|           if (opts.rotate) {
 | ||
|             contextRotate(context, opts);
 | ||
|           }
 | ||
|           drawYAxisGrid(categories, opts, config, context);
 | ||
|           drawXAxis(categories, opts, config, context);
 | ||
|           var _drawAreaDataPoints = drawAreaDataPoints(series, opts, config, context, process),
 | ||
|             xAxisPoints = _drawAreaDataPoints.xAxisPoints,
 | ||
|             calPoints = _drawAreaDataPoints.calPoints,
 | ||
|             eachSpacing = _drawAreaDataPoints.eachSpacing;
 | ||
|           opts.chartData.xAxisPoints = xAxisPoints;
 | ||
|           opts.chartData.calPoints = calPoints;
 | ||
|           opts.chartData.eachSpacing = eachSpacing;
 | ||
|           drawYAxis(series, opts, config, context);
 | ||
|           if (opts.enableMarkLine !== false && process === 1) {
 | ||
|             drawMarkLine(opts, config, context);
 | ||
|           }
 | ||
|           drawLegend(opts.series, opts, config, context, opts.chartData);
 | ||
|           drawToolTipBridge(opts, config, context, process, eachSpacing, xAxisPoints);
 | ||
|           drawCanvas(opts, context);
 | ||
|         },
 | ||
|         onAnimationFinish: function onAnimationFinish() {
 | ||
|           _this.event.trigger('renderComplete');
 | ||
|         }
 | ||
|       });
 | ||
|       break;
 | ||
|     case 'ring':
 | ||
|     case 'pie':
 | ||
|       this.animationInstance = new Animation({
 | ||
|         timing: 'easeInOut',
 | ||
|         duration: duration,
 | ||
|         onProcess: function onProcess(process) {
 | ||
|           context.clearRect(0, 0, opts.width, opts.height);
 | ||
|           if (opts.rotate) {
 | ||
|             contextRotate(context, opts);
 | ||
|           }
 | ||
|           opts.chartData.pieData = drawPieDataPoints(series, opts, config, context, process);
 | ||
|           drawLegend(opts.series, opts, config, context, opts.chartData);
 | ||
|           drawToolTipBridge(opts, config, context, process);
 | ||
|           drawCanvas(opts, context);
 | ||
|         },
 | ||
|         onAnimationFinish: function onAnimationFinish() {
 | ||
|           _this.event.trigger('renderComplete');
 | ||
|         }
 | ||
|       });
 | ||
|       break;
 | ||
|     case 'rose':
 | ||
|       this.animationInstance = new Animation({
 | ||
|         timing: 'easeInOut',
 | ||
|         duration: duration,
 | ||
|         onProcess: function onProcess(process) {
 | ||
|           context.clearRect(0, 0, opts.width, opts.height);
 | ||
|           if (opts.rotate) {
 | ||
|             contextRotate(context, opts);
 | ||
|           }
 | ||
|           opts.chartData.pieData = drawRoseDataPoints(series, opts, config, context, process);
 | ||
|           drawLegend(opts.series, opts, config, context, opts.chartData);
 | ||
|           drawToolTipBridge(opts, config, context, process);
 | ||
|           drawCanvas(opts, context);
 | ||
|         },
 | ||
|         onAnimationFinish: function onAnimationFinish() {
 | ||
|           _this.event.trigger('renderComplete');
 | ||
|         }
 | ||
|       });
 | ||
|       break;
 | ||
|     case 'radar':
 | ||
|       this.animationInstance = new Animation({
 | ||
|         timing: 'easeInOut',
 | ||
|         duration: duration,
 | ||
|         onProcess: function onProcess(process) {
 | ||
|           context.clearRect(0, 0, opts.width, opts.height);
 | ||
|           if (opts.rotate) {
 | ||
|             contextRotate(context, opts);
 | ||
|           }
 | ||
|           opts.chartData.radarData = drawRadarDataPoints(series, opts, config, context, process);
 | ||
|           drawLegend(opts.series, opts, config, context, opts.chartData);
 | ||
|           drawToolTipBridge(opts, config, context, process);
 | ||
|           drawCanvas(opts, context);
 | ||
|         },
 | ||
|         onAnimationFinish: function onAnimationFinish() {
 | ||
|           _this.event.trigger('renderComplete');
 | ||
|         }
 | ||
|       });
 | ||
|       break;
 | ||
|     case 'arcbar':
 | ||
|       this.animationInstance = new Animation({
 | ||
|         timing: 'easeInOut',
 | ||
|         duration: duration,
 | ||
|         onProcess: function onProcess(process) {
 | ||
|           context.clearRect(0, 0, opts.width, opts.height);
 | ||
|           if (opts.rotate) {
 | ||
|             contextRotate(context, opts);
 | ||
|           }
 | ||
|           opts.chartData.arcbarData = drawArcbarDataPoints(series, opts, config, context, process);
 | ||
|           drawCanvas(opts, context);
 | ||
|         },
 | ||
|         onAnimationFinish: function onAnimationFinish() {
 | ||
|           _this.event.trigger('renderComplete');
 | ||
|         }
 | ||
|       });
 | ||
|       break;
 | ||
|     case 'gauge':
 | ||
|       this.animationInstance = new Animation({
 | ||
|         timing: 'easeInOut',
 | ||
|         duration: duration,
 | ||
|         onProcess: function onProcess(process) {
 | ||
|           context.clearRect(0, 0, opts.width, opts.height);
 | ||
|           if (opts.rotate) {
 | ||
|             contextRotate(context, opts);
 | ||
|           }
 | ||
|           opts.chartData.gaugeData = drawGaugeDataPoints(categories, series, opts, config, context, process);
 | ||
|           drawCanvas(opts, context);
 | ||
|         },
 | ||
|         onAnimationFinish: function onAnimationFinish() {
 | ||
|           _this.event.trigger('renderComplete');
 | ||
|         }
 | ||
|       });
 | ||
|       break;
 | ||
|     case 'candle':
 | ||
|       this.animationInstance = new Animation({
 | ||
|         timing: 'easeIn',
 | ||
|         duration: duration,
 | ||
|         onProcess: function onProcess(process) {
 | ||
|           context.clearRect(0, 0, opts.width, opts.height);
 | ||
|           if (opts.rotate) {
 | ||
|             contextRotate(context, opts);
 | ||
|           }
 | ||
|           drawYAxisGrid(categories, opts, config, context);
 | ||
|           drawXAxis(categories, opts, config, context);
 | ||
|           var _drawCandleDataPoints = drawCandleDataPoints(series, seriesMA, opts, config, context, process),
 | ||
|             xAxisPoints = _drawCandleDataPoints.xAxisPoints,
 | ||
|             calPoints = _drawCandleDataPoints.calPoints,
 | ||
|             eachSpacing = _drawCandleDataPoints.eachSpacing;
 | ||
|           opts.chartData.xAxisPoints = xAxisPoints;
 | ||
|           opts.chartData.calPoints = calPoints;
 | ||
|           opts.chartData.eachSpacing = eachSpacing;
 | ||
|           drawYAxis(series, opts, config, context);
 | ||
|           if (opts.enableMarkLine !== false && process === 1) {
 | ||
|             drawMarkLine(opts, config, context);
 | ||
|           }
 | ||
|           if (seriesMA) {
 | ||
|             drawLegend(seriesMA, opts, config, context, opts.chartData);
 | ||
|           } else {
 | ||
|             drawLegend(opts.series, opts, config, context, opts.chartData);
 | ||
|           }
 | ||
|           drawToolTipBridge(opts, config, context, process, eachSpacing, xAxisPoints);
 | ||
|           drawCanvas(opts, context);
 | ||
|         },
 | ||
|         onAnimationFinish: function onAnimationFinish() {
 | ||
|           _this.event.trigger('renderComplete');
 | ||
|         }
 | ||
|       });
 | ||
|       break;
 | ||
|   }
 | ||
| }
 | ||
| 
 | ||
| // simple event implement
 | ||
| 
 | ||
| function Event() {
 | ||
|   this.events = {};
 | ||
| }
 | ||
| 
 | ||
| Event.prototype.addEventListener = function(type, listener) {
 | ||
|   this.events[type] = this.events[type] || [];
 | ||
|   this.events[type].push(listener);
 | ||
| };
 | ||
| 
 | ||
| Event.prototype.trigger = function() {
 | ||
|   for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
 | ||
|     args[_key] = arguments[_key];
 | ||
|   }
 | ||
| 
 | ||
|   var type = args[0];
 | ||
|   var params = args.slice(1);
 | ||
|   if (!!this.events[type]) {
 | ||
|     this.events[type].forEach(function(listener) {
 | ||
|       try {
 | ||
|         listener.apply(null, params);
 | ||
|       } catch (e) {
 | ||
|         console.error(e);
 | ||
|       }
 | ||
|     });
 | ||
|   }
 | ||
| };
 | ||
| 
 | ||
| var Charts = function Charts(opts) {
 | ||
|   opts.pixelRatio = opts.pixelRatio ? opts.pixelRatio : 1;
 | ||
|   opts.fontSize = opts.fontSize ? opts.fontSize * opts.pixelRatio : 13 * opts.pixelRatio;
 | ||
|   opts.title = assign({}, opts.title);
 | ||
|   opts.subtitle = assign({}, opts.subtitle);
 | ||
|   opts.duration = opts.duration ? opts.duration : 1000;
 | ||
|   opts.yAxis = assign({}, {
 | ||
|     data:[],
 | ||
|     showTitle:false,
 | ||
|     disabled:false,
 | ||
|     disableGrid:false,
 | ||
|     splitNumber:5,
 | ||
|     gridType: 'solid',
 | ||
|     dashLength: 4 * opts.pixelRatio,
 | ||
|     gridColor:'#cccccc',
 | ||
|     padding:10,
 | ||
|     fontColor:'#666666'
 | ||
|   }, opts.yAxis);
 | ||
|   opts.yAxis.dashLength *= opts.pixelRatio;
 | ||
|   opts.yAxis.padding *= opts.pixelRatio;
 | ||
|   opts.xAxis = assign({}, {
 | ||
|     rotateLabel: false,
 | ||
|     type: 'calibration',
 | ||
|     gridType: 'solid',
 | ||
|     dashLength: 4,
 | ||
|     scrollAlign: 'left',
 | ||
|     boundaryGap:'center',
 | ||
|     axisLine:true,
 | ||
|     axisLineColor:'#cccccc'
 | ||
|   }, opts.xAxis);
 | ||
|   opts.xAxis.dashLength *= opts.pixelRatio;
 | ||
|   opts.legend = assign({}, {
 | ||
|     show: true,
 | ||
|     position: 'bottom',
 | ||
|     float: 'center',
 | ||
|     backgroundColor: 'rgba(0,0,0,0)',
 | ||
|     borderColor: 'rgba(0,0,0,0)',
 | ||
|     borderWidth: 0,
 | ||
|     padding: 5,
 | ||
|     margin: 5,
 | ||
|     itemGap: 10,
 | ||
|     fontSize: opts.fontSize,
 | ||
|     lineHeight: opts.fontSize,
 | ||
|     fontColor: '#333333',
 | ||
|     format: {},
 | ||
|     hiddenColor: '#CECECE'
 | ||
|   }, opts.legend);
 | ||
|   opts.legend.borderWidth = opts.legend.borderWidth * opts.pixelRatio;
 | ||
|   opts.legend.itemGap = opts.legend.itemGap * opts.pixelRatio;
 | ||
|   opts.legend.padding = opts.legend.padding * opts.pixelRatio;
 | ||
|   opts.legend.margin = opts.legend.margin * opts.pixelRatio;
 | ||
|   opts.extra = assign({}, opts.extra);
 | ||
|   opts.rotate = opts.rotate ? true : false;
 | ||
|   opts.animation = opts.animation ? true : false;
 | ||
| 	opts.rotate = opts.rotate ? true : false;
 | ||
| 
 | ||
|   let config$$1 = JSON.parse(JSON.stringify(config));
 | ||
|   config$$1.colors = opts.colors ? opts.colors : config$$1.colors;
 | ||
|   config$$1.yAxisTitleWidth = opts.yAxis.disabled !== true && opts.yAxis.title ? config$$1.yAxisTitleWidth : 0;
 | ||
|   if (opts.type == 'pie' || opts.type == 'ring') {
 | ||
|     config$$1.pieChartLinePadding = opts.dataLabel === false ? 0 : opts.extra.pie.labelWidth * opts.pixelRatio || config$$1.pieChartLinePadding * opts.pixelRatio;
 | ||
|   }
 | ||
|   if (opts.type == 'rose') {
 | ||
|     config$$1.pieChartLinePadding = opts.dataLabel === false ? 0 : opts.extra.rose.labelWidth * opts.pixelRatio || config$$1.pieChartLinePadding * opts.pixelRatio;
 | ||
|   }
 | ||
|   config$$1.pieChartTextPadding = opts.dataLabel === false ? 0 : config$$1.pieChartTextPadding * opts.pixelRatio;
 | ||
|   config$$1.yAxisSplit = opts.yAxis.splitNumber ? opts.yAxis.splitNumber : config.yAxisSplit;
 | ||
| 
 | ||
|   //屏幕旋转
 | ||
|   config$$1.rotate = opts.rotate;
 | ||
|   if (opts.rotate) {
 | ||
|     let tempWidth = opts.width;
 | ||
|     let tempHeight = opts.height;
 | ||
|     opts.width = tempHeight;
 | ||
|     opts.height = tempWidth;
 | ||
|   }
 | ||
| 
 | ||
|   //适配高分屏
 | ||
|   opts.padding = opts.padding ? opts.padding : config$$1.padding;
 | ||
|   for (let i = 0; i < 4; i++) {
 | ||
|     opts.padding[i] *= opts.pixelRatio;
 | ||
|   }
 | ||
|   config$$1.yAxisWidth = config.yAxisWidth * opts.pixelRatio;
 | ||
|   config$$1.xAxisHeight = config.xAxisHeight * opts.pixelRatio;
 | ||
|   if (opts.enableScroll && opts.xAxis.scrollShow) {
 | ||
|     config$$1.xAxisHeight += 6 * opts.pixelRatio;
 | ||
|   }
 | ||
|   config$$1.xAxisLineHeight = config.xAxisLineHeight * opts.pixelRatio;
 | ||
|   config$$1.fontSize = opts.fontSize;
 | ||
|   config$$1.titleFontSize = config.titleFontSize * opts.pixelRatio;
 | ||
|   config$$1.subtitleFontSize = config.subtitleFontSize * opts.pixelRatio;
 | ||
|   config$$1.toolTipPadding = config.toolTipPadding * opts.pixelRatio;
 | ||
|   config$$1.toolTipLineHeight = config.toolTipLineHeight * opts.pixelRatio;
 | ||
|   config$$1.columePadding = config.columePadding * opts.pixelRatio;
 | ||
|   opts.$this = opts.$this ? opts.$this : this;
 | ||
|   
 | ||
|   this.context = uni.createCanvasContext(opts.canvasId, opts.$this);
 | ||
|   /* 兼容原生H5
 | ||
|   this.context = document.getElementById(opts.canvasId).getContext("2d");
 | ||
|   this.context.setStrokeStyle = function(e){ return this.strokeStyle=e; }
 | ||
|   this.context.setLineWidth = function(e){ return this.lineWidth=e; }
 | ||
|   this.context.setLineCap = function(e){ return this.lineCap=e; }
 | ||
|   this.context.setFontSize = function(e){ return this.font=e+"px sans-serif"; }
 | ||
|   this.context.setFillStyle = function(e){ return this.fillStyle=e; }
 | ||
|   this.context.draw = function(){ }
 | ||
|   */
 | ||
| 
 | ||
|   opts.chartData = {};
 | ||
|   this.event = new Event();
 | ||
|   this.scrollOption = {
 | ||
|     currentOffset: 0,
 | ||
|     startTouchX: 0,
 | ||
|     distance: 0,
 | ||
|     lastMoveTime: 0
 | ||
|   };
 | ||
| 
 | ||
|   this.opts = opts;
 | ||
|   this.config = config$$1;
 | ||
| 
 | ||
|   drawCharts.call(this, opts.type, opts, config$$1, this.context);
 | ||
| };
 | ||
| 
 | ||
| Charts.prototype.updateData = function() {
 | ||
|   let data = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
 | ||
|   this.opts = assign({}, this.opts, data);
 | ||
|   this.opts.updateData = true;
 | ||
|   let scrollPosition = data.scrollPosition || 'current';
 | ||
|   switch (scrollPosition) {
 | ||
|     case 'current':
 | ||
|       this.opts._scrollDistance_ = this.scrollOption.currentOffset;
 | ||
|       break;
 | ||
|     case 'left':
 | ||
|       this.opts._scrollDistance_ = 0;
 | ||
|       this.scrollOption = {
 | ||
|         currentOffset: 0,
 | ||
|         startTouchX: 0,
 | ||
|         distance: 0,
 | ||
|         lastMoveTime: 0
 | ||
|       };
 | ||
|       break;
 | ||
|     case 'right':
 | ||
|       let _calYAxisData = calYAxisData(this.opts.series, this.opts, this.config),
 | ||
|         yAxisWidth = _calYAxisData.yAxisWidth;
 | ||
|       this.config.yAxisWidth = yAxisWidth;
 | ||
|       let offsetLeft = 0;
 | ||
|       let _getXAxisPoints0 = getXAxisPoints(this.opts.categories, this.opts, this.config),
 | ||
|         xAxisPoints = _getXAxisPoints0.xAxisPoints,
 | ||
|         startX = _getXAxisPoints0.startX,
 | ||
|         endX = _getXAxisPoints0.endX,
 | ||
|         eachSpacing = _getXAxisPoints0.eachSpacing;
 | ||
|       let totalWidth = eachSpacing * (xAxisPoints.length - 1);
 | ||
|       let screenWidth = endX - startX;
 | ||
|       offsetLeft = screenWidth - totalWidth;
 | ||
|       this.scrollOption = {
 | ||
|         currentOffset: offsetLeft,
 | ||
|         startTouchX: offsetLeft,
 | ||
|         distance: 0,
 | ||
|         lastMoveTime: 0
 | ||
|       };
 | ||
|       this.opts._scrollDistance_ = offsetLeft;
 | ||
|       break;
 | ||
|   }
 | ||
|   drawCharts.call(this, this.opts.type, this.opts, this.config, this.context);
 | ||
| };
 | ||
| 
 | ||
| Charts.prototype.zoom = function() {
 | ||
|   var val = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.opts.xAxis.itemCount;
 | ||
|   if (this.opts.enableScroll !== true) {
 | ||
|     console.log('请启用滚动条后使用!')
 | ||
|     return;
 | ||
|   }
 | ||
|   //当前屏幕中间点
 | ||
|   let centerPoint = Math.round(Math.abs(this.scrollOption.currentOffset) / this.opts.chartData.eachSpacing) + Math.round(
 | ||
|     this.opts.xAxis.itemCount / 2);
 | ||
|   this.opts.animation = false;
 | ||
|   this.opts.xAxis.itemCount = val.itemCount;
 | ||
|   //重新计算x轴偏移距离
 | ||
|   let _calYAxisData = calYAxisData(this.opts.series, this.opts, this.config),
 | ||
|     yAxisWidth = _calYAxisData.yAxisWidth;
 | ||
|   this.config.yAxisWidth = yAxisWidth;
 | ||
|   let offsetLeft = 0;
 | ||
|   let _getXAxisPoints0 = getXAxisPoints(this.opts.categories, this.opts, this.config),
 | ||
|     xAxisPoints = _getXAxisPoints0.xAxisPoints,
 | ||
|     startX = _getXAxisPoints0.startX,
 | ||
|     endX = _getXAxisPoints0.endX,
 | ||
|     eachSpacing = _getXAxisPoints0.eachSpacing;
 | ||
|   let centerLeft = eachSpacing * centerPoint;
 | ||
|   let screenWidth = endX - startX;
 | ||
|   let MaxLeft = screenWidth - eachSpacing * (xAxisPoints.length - 1);
 | ||
|   offsetLeft = screenWidth / 2 - centerLeft;
 | ||
|   if (offsetLeft > 0) {
 | ||
|     offsetLeft = 0;
 | ||
|   }
 | ||
|   if (offsetLeft < MaxLeft) {
 | ||
|     offsetLeft = MaxLeft;
 | ||
|   }
 | ||
|   this.scrollOption = {
 | ||
|     currentOffset: offsetLeft,
 | ||
|     startTouchX: offsetLeft,
 | ||
|     distance: 0,
 | ||
|     lastMoveTime: 0
 | ||
|   };
 | ||
|   this.opts._scrollDistance_ = offsetLeft;
 | ||
|   drawCharts.call(this, this.opts.type, this.opts, this.config, this.context);
 | ||
| };
 | ||
| 
 | ||
| Charts.prototype.stopAnimation = function() {
 | ||
|   this.animationInstance && this.animationInstance.stop();
 | ||
| };
 | ||
| 
 | ||
| Charts.prototype.addEventListener = function(type, listener) {
 | ||
|   this.event.addEventListener(type, listener);
 | ||
| };
 | ||
| 
 | ||
| Charts.prototype.getCurrentDataIndex = function(e) {
 | ||
|   var touches = null;
 | ||
|   if (e.changedTouches) {
 | ||
|     touches = e.changedTouches[0];
 | ||
|   } else {
 | ||
|     touches = e.mp.changedTouches[0];
 | ||
|   }
 | ||
|   if (touches) {
 | ||
|     let _touches$ = getTouches(touches, this.opts, e);
 | ||
|     if (this.opts.type === 'pie' || this.opts.type === 'ring' || this.opts.type === 'rose') {
 | ||
|       return findPieChartCurrentIndex({
 | ||
|         x: _touches$.x,
 | ||
|         y: _touches$.y
 | ||
|       }, this.opts.chartData.pieData);
 | ||
|     } else if (this.opts.type === 'radar') {
 | ||
|       return findRadarChartCurrentIndex({
 | ||
|         x: _touches$.x,
 | ||
|         y: _touches$.y
 | ||
|       }, this.opts.chartData.radarData, this.opts.categories.length);
 | ||
|     } else if (this.opts.type === 'funnel') {
 | ||
|       return findFunnelChartCurrentIndex({
 | ||
|         x: _touches$.x,
 | ||
|         y: _touches$.y
 | ||
|       }, this.opts.chartData.funnelData);
 | ||
|     } else if (this.opts.type === 'map') {
 | ||
|       return findMapChartCurrentIndex({
 | ||
|         x: _touches$.x,
 | ||
|         y: _touches$.y
 | ||
|       }, this.opts);
 | ||
|     }else if (this.opts.type === 'word') {
 | ||
|       return findWordChartCurrentIndex({
 | ||
|         x: _touches$.x,
 | ||
|         y: _touches$.y
 | ||
|       }, this.opts.chartData.wordCloudData);
 | ||
|     } else {
 | ||
|       return findCurrentIndex({
 | ||
|         x: _touches$.x,
 | ||
|         y: _touches$.y
 | ||
|       }, this.opts.chartData.calPoints, this.opts, this.config, Math.abs(this.scrollOption.currentOffset));
 | ||
|     }
 | ||
|   }
 | ||
|   return -1;
 | ||
| };
 | ||
| 
 | ||
| Charts.prototype.getLegendDataIndex = function(e) {
 | ||
|   var touches = null;
 | ||
|   if (e.changedTouches) {
 | ||
|     touches = e.changedTouches[0];
 | ||
|   } else {
 | ||
|     touches = e.mp.changedTouches[0];
 | ||
|   }
 | ||
|   if (touches) {
 | ||
|     let _touches$ = getTouches(touches, this.opts, e);
 | ||
|     return findLegendIndex({
 | ||
|       x: _touches$.x,
 | ||
|       y: _touches$.y
 | ||
|     }, this.opts.chartData.legendData);
 | ||
|   }
 | ||
|   return -1;
 | ||
| };
 | ||
| 
 | ||
| Charts.prototype.touchLegend = function(e) {
 | ||
|   var option = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
 | ||
|   var touches = null;
 | ||
|   if (e.changedTouches) {
 | ||
|     touches = e.changedTouches[0];
 | ||
|   } else {
 | ||
|     touches = e.mp.changedTouches[0];
 | ||
|   }
 | ||
|   if (touches) {
 | ||
|     var _touches$ = getTouches(touches, this.opts, e);
 | ||
|     var index = this.getLegendDataIndex(e);
 | ||
|     if (index >= 0) {
 | ||
|       this.opts.series[index].show = !this.opts.series[index].show;
 | ||
|       this.opts.animation = option.animation ? true : false;
 | ||
| 			this.opts._scrollDistance_= this.scrollOption.currentOffset;
 | ||
|       drawCharts.call(this, this.opts.type, this.opts, this.config, this.context);
 | ||
|     }
 | ||
|   }
 | ||
| 
 | ||
| };
 | ||
| 
 | ||
| Charts.prototype.showToolTip = function(e) {
 | ||
|   var option = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
 | ||
|   var touches = null;
 | ||
|   if (e.changedTouches) {
 | ||
|     touches = e.changedTouches[0];
 | ||
|   } else {
 | ||
|     touches = e.mp.changedTouches[0];
 | ||
|   }
 | ||
|   if (!touches) {
 | ||
|     console.log("touchError");
 | ||
|   }
 | ||
|   var _touches$ = getTouches(touches, this.opts, e);
 | ||
|   var currentOffset = this.scrollOption.currentOffset;
 | ||
|   var opts = assign({}, this.opts, {
 | ||
|     _scrollDistance_: currentOffset,
 | ||
|     animation: false
 | ||
|   });
 | ||
|   if (this.opts.type === 'line' || this.opts.type === 'area' || this.opts.type === 'column') {
 | ||
|     var index = option.index==undefined? this.getCurrentDataIndex(e):option.index ;
 | ||
|     if (index > -1) {
 | ||
|       var seriesData = getSeriesDataItem(this.opts.series, index);
 | ||
|       if (seriesData.length !== 0) {
 | ||
|         var _getToolTipData = getToolTipData(seriesData, this.opts.chartData.calPoints, index, this.opts.categories,option),
 | ||
|           textList = _getToolTipData.textList,
 | ||
|           offset = _getToolTipData.offset;
 | ||
|         offset.y = _touches$.y;
 | ||
|         opts.tooltip = {
 | ||
|           textList: option.textList?option.textList:textList,
 | ||
|           offset: offset,
 | ||
|           option: option,
 | ||
|           index: index
 | ||
|         };
 | ||
|       }
 | ||
|     }
 | ||
|     drawCharts.call(this, opts.type, opts, this.config, this.context);
 | ||
|   }
 | ||
|   if (this.opts.type === 'mix') {
 | ||
|     var index = option.index==undefined? this.getCurrentDataIndex(e):option.index ;
 | ||
|     if (index > -1) {
 | ||
|       var currentOffset = this.scrollOption.currentOffset;
 | ||
|       var opts = assign({}, this.opts, {
 | ||
|         _scrollDistance_: currentOffset,
 | ||
|         animation: false
 | ||
|       });
 | ||
|       var seriesData = getSeriesDataItem(this.opts.series, index);
 | ||
|       if (seriesData.length !== 0) {
 | ||
|         var _getMixToolTipData = getMixToolTipData(seriesData, this.opts.chartData.calPoints, index, this.opts.categories,option),
 | ||
|           textList = _getMixToolTipData.textList,
 | ||
|           offset = _getMixToolTipData.offset;
 | ||
|         offset.y = _touches$.y;
 | ||
|         opts.tooltip = {
 | ||
|           textList: option.textList?option.textList:textList,
 | ||
|           offset: offset,
 | ||
|           option: option,
 | ||
|           index: index
 | ||
|         };
 | ||
|       }
 | ||
|     }
 | ||
|     drawCharts.call(this, opts.type, opts, this.config, this.context);
 | ||
|   }
 | ||
|   if (this.opts.type === 'candle') {
 | ||
|     var index = option.index==undefined? this.getCurrentDataIndex(e):option.index ;
 | ||
|     if (index > -1) {
 | ||
|       var currentOffset = this.scrollOption.currentOffset;
 | ||
|       var opts = assign({}, this.opts, {
 | ||
|         _scrollDistance_: currentOffset,
 | ||
|         animation: false
 | ||
|       });
 | ||
|       var seriesData = getSeriesDataItem(this.opts.series, index);
 | ||
|       if (seriesData.length !== 0) {
 | ||
|         var _getToolTipData = getCandleToolTipData(this.opts.series[0].data, seriesData, this.opts.chartData.calPoints,
 | ||
|             index, this.opts.categories, this.opts.extra.candle, option),
 | ||
|           textList = _getToolTipData.textList,
 | ||
|           offset = _getToolTipData.offset;
 | ||
|         offset.y = _touches$.y;
 | ||
|         opts.tooltip = {
 | ||
|           textList: option.textList?option.textList:textList,
 | ||
|           offset: offset,
 | ||
|           option: option,
 | ||
|           index: index
 | ||
|         };
 | ||
|       }
 | ||
|     }
 | ||
|     drawCharts.call(this, opts.type, opts, this.config, this.context);
 | ||
|   }
 | ||
|   if (this.opts.type === 'pie' || this.opts.type === 'ring' || this.opts.type === 'rose'||this.opts.type === 'funnel' ) {
 | ||
|     var index = option.index==undefined? this.getCurrentDataIndex(e):option.index ;
 | ||
|     if (index > -1) {
 | ||
|       var currentOffset = this.scrollOption.currentOffset;
 | ||
|       var opts = assign({}, this.opts, {
 | ||
|         _scrollDistance_: currentOffset,
 | ||
|         animation: false
 | ||
|       });
 | ||
|       var seriesData = this.opts._series_[index];
 | ||
|       var textList = [{
 | ||
|         text: option.format ? option.format(seriesData) : seriesData.name + ': ' + seriesData.data,
 | ||
|         color: seriesData.color
 | ||
|       }];
 | ||
|       var offset = {
 | ||
|         x: _touches$.x,
 | ||
|         y: _touches$.y
 | ||
|       };
 | ||
|       opts.tooltip = {
 | ||
|         textList: option.textList?option.textList:textList,
 | ||
|         offset: offset,
 | ||
|         option: option,
 | ||
|         index: index
 | ||
|       };
 | ||
|     }
 | ||
|     drawCharts.call(this, opts.type, opts, this.config, this.context);
 | ||
|   }
 | ||
|   if (this.opts.type === 'map'||this.opts.type === 'word') {
 | ||
|     var index = option.index==undefined? this.getCurrentDataIndex(e):option.index ;
 | ||
|     if (index > -1) {
 | ||
|       var currentOffset = this.scrollOption.currentOffset;
 | ||
|       var opts = assign({}, this.opts, {
 | ||
|         _scrollDistance_: currentOffset,
 | ||
|         animation: false
 | ||
|       });
 | ||
|       var seriesData = this.opts._series_[index];
 | ||
|       var textList = [{
 | ||
|         text: option.format ? option.format(seriesData) : seriesData.properties.name ,
 | ||
|         color: seriesData.color
 | ||
|       }];
 | ||
|       var offset = {
 | ||
|         x: _touches$.x,
 | ||
|         y: _touches$.y
 | ||
|       };
 | ||
|       opts.tooltip = {
 | ||
|         textList: option.textList?option.textList:textList,
 | ||
|         offset: offset,
 | ||
|         option: option,
 | ||
|         index: index
 | ||
|       };
 | ||
|     }
 | ||
|     opts.updateData = false;
 | ||
|     drawCharts.call(this, opts.type, opts, this.config, this.context);
 | ||
|   }
 | ||
|   if (this.opts.type === 'radar') {
 | ||
|     var index = option.index==undefined? this.getCurrentDataIndex(e):option.index ;
 | ||
|     if (index > -1) {
 | ||
|       var currentOffset = this.scrollOption.currentOffset;
 | ||
|       var opts = assign({}, this.opts, {
 | ||
|         _scrollDistance_: currentOffset,
 | ||
|         animation: false
 | ||
|       });
 | ||
|       var seriesData = getSeriesDataItem(this.opts.series, index);
 | ||
|       if (seriesData.length !== 0) {
 | ||
|         var textList = seriesData.map(function(item) {
 | ||
|           return {
 | ||
|             text: option.format ? option.format(item) : item.name + ': ' + item.data,
 | ||
|             color: item.color
 | ||
|           };
 | ||
|         });
 | ||
|         var offset = {
 | ||
|           x: _touches$.x,
 | ||
|           y: _touches$.y
 | ||
|         };
 | ||
|         opts.tooltip = {
 | ||
|           textList: option.textList?option.textList:textList,
 | ||
|           offset: offset,
 | ||
|           option: option,
 | ||
|           index: index
 | ||
|         };
 | ||
|       }
 | ||
|     }
 | ||
|     drawCharts.call(this, opts.type, opts, this.config, this.context);
 | ||
|   }
 | ||
| };
 | ||
| 
 | ||
| Charts.prototype.translate = function(distance) {
 | ||
|   this.scrollOption = {
 | ||
|     currentOffset: distance,
 | ||
|     startTouchX: distance,
 | ||
|     distance: 0,
 | ||
|     lastMoveTime: 0
 | ||
|   };
 | ||
|   let opts = assign({}, this.opts, {
 | ||
|     _scrollDistance_: distance,
 | ||
|     animation: false
 | ||
|   });
 | ||
|   drawCharts.call(this, this.opts.type, opts, this.config, this.context);
 | ||
| };
 | ||
| 
 | ||
| Charts.prototype.scrollStart = function(e) {
 | ||
|   var touches = null;
 | ||
|   if (e.changedTouches) {
 | ||
|     touches = e.changedTouches[0];
 | ||
|   } else {
 | ||
|     touches = e.mp.changedTouches[0];
 | ||
|   }
 | ||
|   var _touches$ = getTouches(touches, this.opts, e);
 | ||
|   if (touches && this.opts.enableScroll === true) {
 | ||
|     this.scrollOption.startTouchX = _touches$.x;
 | ||
|   }
 | ||
| };
 | ||
| 
 | ||
| Charts.prototype.scroll = function(e) {
 | ||
|   if (this.scrollOption.lastMoveTime === 0) {
 | ||
|     this.scrollOption.lastMoveTime = Date.now();
 | ||
|   }
 | ||
|   let Limit = this.opts.extra.touchMoveLimit || 20;
 | ||
|   let currMoveTime = Date.now();
 | ||
|   let duration = currMoveTime - this.scrollOption.lastMoveTime;
 | ||
|   if (duration < Math.floor(1000 / Limit)) return;
 | ||
|   this.scrollOption.lastMoveTime = currMoveTime;
 | ||
|   var touches = null;
 | ||
|   if (e.changedTouches) {
 | ||
|     touches = e.changedTouches[0];
 | ||
|   } else {
 | ||
|     touches = e.mp.changedTouches[0];
 | ||
|   }
 | ||
|   if (touches && this.opts.enableScroll === true) {
 | ||
|     var _touches$ = getTouches(touches, this.opts, e);
 | ||
|     var _distance;
 | ||
|     _distance = _touches$.x - this.scrollOption.startTouchX;
 | ||
|     var currentOffset = this.scrollOption.currentOffset;
 | ||
|     var validDistance = calValidDistance(this,currentOffset + _distance, this.opts.chartData, this.config, this.opts);
 | ||
|     this.scrollOption.distance = _distance = validDistance - currentOffset;
 | ||
|     var opts = assign({}, this.opts, {
 | ||
|       _scrollDistance_: currentOffset + _distance,
 | ||
|       animation: false
 | ||
|     });
 | ||
|     drawCharts.call(this, opts.type, opts, this.config, this.context);
 | ||
|     return currentOffset + _distance;
 | ||
|   }
 | ||
| };
 | ||
| 
 | ||
| Charts.prototype.scrollEnd = function(e) {
 | ||
|   if (this.opts.enableScroll === true) {
 | ||
|     var _scrollOption = this.scrollOption,
 | ||
|       currentOffset = _scrollOption.currentOffset,
 | ||
|       distance = _scrollOption.distance;
 | ||
|     this.scrollOption.currentOffset = currentOffset + distance;
 | ||
|     this.scrollOption.distance = 0;
 | ||
|   }
 | ||
| };
 | ||
| if (typeof module === "object" && typeof module.exports === "object") {
 | ||
|   module.exports = Charts;
 | ||
|   //export default Charts;//建议使用nodejs的module导出方式,如报错请使用export方式导出
 | ||
| }
 |