/// <summary> /// 替换字符串中的通配符,支持的通配符有{.}、{a}、{b}、{c}、{d}、{e}、{f}、{g}。 /// </summary> /// <param name="content">要替换的字符串</param> /// <param name="dataIndex">选中的数据项serieData索引</param> /// <param name="numericFormatter">默认的数字格式化</param> /// <param name="serie">选中的serie</param> /// <param name="series">所有serie</param> /// <param name="theme">用来获取指定index的颜色</param> /// <param name="category">选中的类目,一般用在折线图和柱状图</param> /// <param name="dataZoom">dataZoom</param> /// <returns></returns> public static bool ReplaceContent(ref string content, int dataIndex, string numericFormatter, Serie serie, BaseChart chart, DataZoom dataZoom = null) { var foundDot = false; var mc = s_Regex.Matches(content); foreach (var m in mc) { var old = m.ToString(); var args = s_RegexSub.Matches(m.ToString()); var argsCount = args.Count; if (argsCount <= 0) { continue; } int targetIndex = 0; char p = GetSerieIndex(args[0].ToString(), ref targetIndex); if (targetIndex >= 0) { serie = chart.GetSerie(targetIndex); if (serie == null) { continue; } } else if (serie != null) { targetIndex = serie.index; } else { serie = chart.GetSerie(0); targetIndex = 0; } if (serie == null) { continue; } if (p == '.') { var bIndex = targetIndex; if (argsCount >= 2) { var args1Str = args[1].ToString(); if (s_RegexN.IsMatch(args1Str)) { bIndex = int.Parse(args1Str); } } content = content.Replace(old, ChartCached.ColorToDotStr(chart.theme.GetColor(bIndex))); foundDot = true; } else if (p == 'a' || p == 'A') { if (argsCount == 1) { content = content.Replace(old, serie.serieName); } } else if (p == 'b' || p == 'B' || p == 'e' || p == 'E') { var bIndex = dataIndex; if (argsCount >= 2) { var args1Str = args[1].ToString(); if (s_RegexN.IsMatch(args1Str)) { bIndex = int.Parse(args1Str); } } var needCategory = (p != 'e' && p != 'E') && (serie is Line || serie is Bar); if (needCategory) { var category = chart.GetTooltipCategory(dataIndex, serie, dataZoom); content = content.Replace(old, category); } else { var serieData = serie.GetSerieData(bIndex, dataZoom); content = content.Replace(old, serieData.name); } } else if (p == 'g' || p == 'G') { content = content.Replace(old, ChartCached.NumberToStr(serie.dataCount, "")); } else if (p == 'c' || p == 'C' || p == 'd' || p == 'D' || p == 'f' || p == 'f') { var isPercent = p == 'd' || p == 'D'; var isTotal = p == 'f' || p == 'f'; var bIndex = dataIndex; var dimensionIndex = -1; if (argsCount >= 2) { var args1Str = args[1].ToString(); if (s_RegexFn.IsMatch(args1Str)) { numericFormatter = args1Str; } else if (s_RegexN_N.IsMatch(args1Str)) { var temp = args1Str.Split('-'); bIndex = int.Parse(temp[0]); dimensionIndex = int.Parse(temp[1]); } else if (s_RegexN.IsMatch(args1Str)) { dimensionIndex = int.Parse(args1Str); } else { Debug.LogError("unmatch:" + args1Str); continue; } } if (argsCount >= 3) { numericFormatter = args[2].ToString(); } if (dimensionIndex == -1) { dimensionIndex = 1; } if (numericFormatter == string.Empty) { numericFormatter = SerieHelper.GetNumericFormatter(serie, serie.GetSerieData(bIndex), ""); } var value = serie.GetData(bIndex, dimensionIndex, dataZoom); if (isPercent) { var total = serie.GetDataTotal(dimensionIndex, serie.GetSerieData(bIndex)); var percent = total == 0 ? 0 : value / serie.yTotal * 100; content = content.Replace(old, ChartCached.FloatToStr(percent, numericFormatter)); } else if (isTotal) { var total = serie.GetDataTotal(dimensionIndex, serie.GetSerieData(bIndex)); content = content.Replace(old, ChartCached.FloatToStr(total, numericFormatter)); } else { content = content.Replace(old, ChartCached.FloatToStr(value, numericFormatter)); } } } content = s_RegexNewLine.Replace(content, PH_NN); return(foundDot); }
private float GetAxisPosition(GridCoord grid, Axis axis, DataZoom dataZoom, int dataCount, double value) { return(AxisHelper.GetAxisPosition(grid, axis, value, dataCount, dataZoom)); }
private Vector3 GetSinglePos(Axis xAxis, Axis yAxis, GridCoord grid, Serie serie, DataZoom dataZoom, MarkLineData data, int serieDataCount) { switch (data.type) { case MarkLineType.Min: var serieData = SerieHelper.GetMinSerieData(serie, data.dimension, dataZoom); data.runtimeValue = serieData.GetData(data.dimension); var pX = GetAxisPosition(grid, xAxis, dataZoom, serieDataCount, serieData.index); var pY = GetAxisPosition(grid, yAxis, dataZoom, serieDataCount, data.runtimeValue); return(new Vector3(pX, pY)); case MarkLineType.Max: serieData = SerieHelper.GetMaxSerieData(serie, data.dimension, dataZoom); data.runtimeValue = serieData.GetData(data.dimension); pX = GetAxisPosition(grid, xAxis, dataZoom, serieDataCount, serieData.index); pY = GetAxisPosition(grid, yAxis, dataZoom, serieDataCount, data.runtimeValue); return(new Vector3(pX, pY)); case MarkLineType.None: if (data.zeroPosition) { data.runtimeValue = 0; return(grid.context.position); } else { pX = data.xPosition != 0 ? grid.context.x + data.xPosition : GetAxisPosition(grid, xAxis, dataZoom, serieDataCount, data.xValue); pY = data.yPosition != 0 ? grid.context.y + data.yPosition : GetAxisPosition(grid, yAxis, dataZoom, serieDataCount, data.yValue); data.runtimeValue = data.yValue; return(new Vector3(pX, pY)); } default: return(grid.context.position); } }
/// <summary> /// 获得一个类目数据在坐标系中代表的宽度 /// </summary> /// <param name="coordinateWidth"></param> /// <param name="dataZoom"></param> /// <returns></returns> public static float GetDataWidth(Axis axis, float coordinateWidth, int dataCount, DataZoom dataZoom) { if (dataCount < 1) { dataCount = 1; } if (axis.IsValue()) { return(dataCount > 1 ? coordinateWidth / (dataCount - 1) : coordinateWidth); } var categoryCount = axis.GetDataCount(dataZoom); int segment = (axis.boundaryGap ? categoryCount : categoryCount - 1); segment = segment <= 0 ? dataCount : segment; if (segment <= 0) { segment = 1; } return(coordinateWidth / segment); }
/// <summary> /// 获得类目数据个数 /// </summary> /// <param name="dataZoom"></param> /// <returns></returns> internal int GetDataCount(DataZoom dataZoom) { return(IsCategory() ? GetDataList(dataZoom).Count : 0); }
/// <summary> /// 获得分割段宽度 /// </summary> /// <param name="coordinateWidth"></param> /// <param name="dataZoom"></param> /// <returns></returns> public static float GetScaleWidth(Axis axis, float coordinateWidth, int index, DataZoom dataZoom = null) { if (index < 0) { return(0); } int num = GetScaleNumber(axis, coordinateWidth, dataZoom); int splitNum = GetSplitNumber(axis, coordinateWidth, dataZoom); if (num <= 0) { num = 1; } if (axis.IsTime() || axis.IsValue()) { var value = axis.GetLabelValue(index); var lastValue = axis.GetLabelValue(index - 1); return(axis.context.minMaxRange == 0 ? 0 : (float)(coordinateWidth * (value - lastValue) / axis.context.minMaxRange)); } else { var data = axis.GetDataList(dataZoom); if (axis.IsCategory() && data.Count > 0) { var count = axis.boundaryGap ? data.Count : data.Count - 1; int tick = count / splitNum; if (count <= 0) { return(0); } var each = coordinateWidth / count; if (axis.insertDataToHead) { var max = axis.boundaryGap ? splitNum : splitNum - 1; if (index == 1) { if (axis.axisTick.alignWithLabel) { return(each * tick); } else { return(coordinateWidth - each * tick * max); } } else { if (count < splitNum) { return(each); } else { return(each * (count / splitNum)); } } } else { var max = axis.boundaryGap ? num - 1 : num; if (index >= max) { if (axis.axisTick.alignWithLabel) { return(each * tick); } else { return(coordinateWidth - each * tick * (index - 1)); } } else { if (count < splitNum) { return(each); } else { return(each * (count / splitNum)); } } } } else { if (splitNum <= 0) { return(0); } else { return(coordinateWidth / splitNum); } } } }
public static float GetAxisPosition(GridCoord grid, Axis axis, double value, int dataCount = 0, DataZoom dataZoom = null) { var gridHeight = axis is YAxis ? grid.context.height : grid.context.width; var gridXY = axis is YAxis ? grid.context.y : grid.context.x; if (axis.IsCategory()) { if (dataCount == 0) { dataCount = axis.data.Count; } var categoryIndex = (int)value; var scaleWid = AxisHelper.GetDataWidth(axis, gridHeight, dataCount, dataZoom); float startY = gridXY + (axis.boundaryGap ? scaleWid / 2 : 0); return(startY + scaleWid * categoryIndex); } else { var yDataHig = (axis.context.minMaxRange == 0) ? 0f : (float)((value - axis.context.minValue) / axis.context.minMaxRange * gridHeight); return(gridXY + yDataHig); } }
/// <summary> /// 获得分割段数 /// </summary> /// <param name="dataZoom"></param> /// <returns></returns> public static int GetSplitNumber(Axis axis, float coordinateWid, DataZoom dataZoom) { if (axis.type == Axis.AxisType.Value) { return(axis.context.labelValueList.Count - 1); } else if (axis.type == Axis.AxisType.Time) { return(axis.context.labelValueList.Count); } else if (axis.type == Axis.AxisType.Log) { return(axis.splitNumber > 0 ? axis.splitNumber : 4); } else if (axis.type == Axis.AxisType.Category) { int dataCount = axis.GetDataList(dataZoom).Count; if (!axis.boundaryGap) { dataCount -= 1; } if (dataCount <= 0) { dataCount = 1; } if (axis.splitNumber <= 0) { if (dataCount <= 10) { return(dataCount); } else { for (int i = 4; i < 6; i++) { if (dataCount % i == 0) { return(i); } } return(5); } } else { if (axis.splitNumber <= 0 || axis.splitNumber > dataCount) { return(dataCount); } if (dataCount >= axis.splitNumber * 2) { return(axis.splitNumber); } else { return(dataCount); } } } return(0); }
/// <summary> /// 获得标签显示的名称 /// </summary> /// <param name="index"></param> /// <param name="minValue"></param> /// <param name="maxValue"></param> /// <param name="dataZoom"></param> /// <returns></returns> public static string GetLabelName(Axis axis, float coordinateWidth, int index, double minValue, double maxValue, DataZoom dataZoom, bool forcePercent) { int split = GetSplitNumber(axis, coordinateWidth, dataZoom); if (axis.type == Axis.AxisType.Value) { if (minValue == 0 && maxValue == 0) { maxValue = axis.max != 0 ? axis.max : 1; } double value = 0; if (forcePercent) { maxValue = 100; } value = axis.GetLabelValue(index); if (axis.inverse) { value = -value; minValue = -minValue; maxValue = -maxValue; } if (forcePercent) { return(string.Format("{0}%", (int)value)); } else { return(axis.axisLabel.GetFormatterContent(index, value, minValue, maxValue)); } } else if (axis.type == Axis.AxisType.Log) { double value = axis.logBaseE ? System.Math.Exp(axis.GetLogMinIndex() + index) : System.Math.Pow(axis.logBase, axis.GetLogMinIndex() + index); if (axis.inverse) { value = -value; minValue = -minValue; maxValue = -maxValue; } return(axis.axisLabel.GetFormatterContent(index, value, minValue, maxValue, true)); } else if (axis.type == Axis.AxisType.Time) { if (minValue == 0 && maxValue == 0) { return(string.Empty); } if (index > axis.context.labelValueList.Count - 1) { return(string.Empty); } var value = axis.GetLabelValue(index); return(axis.axisLabel.GetFormatterDateTime(index, value, minValue, maxValue)); } var showData = axis.GetDataList(dataZoom); int dataCount = showData.Count; if (dataCount <= 0) { return(""); } int rate = axis.boundaryGap ? (dataCount / split) : (dataCount - 1) / split; if (rate == 0) { rate = 1; } if (axis.insertDataToHead) { if (index > 0) { var residue = (dataCount - 1) - split * rate; var newIndex = residue + (index - 1) * rate; if (newIndex < 0) { newIndex = 0; } return(axis.axisLabel.GetFormatterContent(newIndex, showData[newIndex])); } else { if (axis.boundaryGap && coordinateWidth / dataCount > 5) { return(string.Empty); } else { return(axis.axisLabel.GetFormatterContent(0, showData[0])); } } } else { int newIndex = index * rate; if (newIndex < dataCount) { return(axis.axisLabel.GetFormatterContent(newIndex, showData[newIndex])); } else { if (axis.boundaryGap && coordinateWidth / dataCount > 5) { return(string.Empty); } else { return(axis.axisLabel.GetFormatterContent(dataCount - 1, showData[dataCount - 1])); } } } }
private static void UpdateFilterData_Category(Serie serie, DataZoom dataZoom) { var data = serie.data; var range = Mathf.RoundToInt(data.Count * (dataZoom.end - dataZoom.start) / 100); if (range <= 0) { range = 1; } int start = 0, end = 0; if (dataZoom.context.invert) { end = Mathf.CeilToInt(data.Count * dataZoom.end / 100); start = end - range; if (start < 0) { start = 0; } } else { start = Mathf.FloorToInt(data.Count * dataZoom.start / 100); end = start + range; if (end > data.Count) { end = data.Count; } } if (start != serie.m_FilterStart || end != serie.m_FilterEnd || dataZoom.minShowNum != serie.m_FilterMinShow || serie.m_NeedUpdateFilterData) { serie.m_FilterStart = start; serie.m_FilterEnd = end; serie.m_FilterMinShow = dataZoom.minShowNum; serie.m_NeedUpdateFilterData = false; if (data.Count > 0) { if (range < dataZoom.minShowNum) { if (dataZoom.minShowNum > data.Count) { range = data.Count; } else { range = dataZoom.minShowNum; } } if (range > data.Count - start - 1) { start = data.Count - range - 1; } if (start >= 0) { serie.context.dataZoomStartIndex = start; serie.m_FilterData = data.GetRange(start, range); } else { serie.context.dataZoomStartIndex = 0; serie.m_FilterData = data; } } else { serie.context.dataZoomStartIndex = 0; serie.m_FilterData = data; } } else if (end == 0) { serie.context.dataZoomStartIndex = 0; serie.m_FilterData = emptyFilter; } }
/// <summary> /// 获得指定维数的最大最小值 /// </summary> /// <param name="dimension"></param> /// <param name="dataZoom"></param> /// <returns></returns> public static void UpdateMinMaxData(Serie serie, int dimension, int ceilRate = 0, DataZoom dataZoom = null) { double min = 0, max = 0; GetMinMaxData(serie, dimension, out min, out max, dataZoom); if (ceilRate < 0) { serie.context.dataMin = min; serie.context.dataMax = max; } else { serie.context.dataMin = ChartHelper.GetMinDivisibleValue(min, ceilRate); serie.context.dataMax = ChartHelper.GetMaxDivisibleValue(max, ceilRate); } }
/// <summary> /// Gets the maximum and minimum values of all data in the serie. /// |获得系列所有数据的最大最小值。 /// </summary> /// <param name="serie"></param> /// <param name="min"></param> /// <param name="max"></param> /// <param name="dataZoom"></param> public static void GetMinMaxData(Serie serie, out double min, out double max, DataZoom dataZoom = null, int dimension = 0) { max = double.MinValue; min = double.MaxValue; var dataList = serie.GetDataList(dataZoom); for (int i = 0; i < dataList.Count; i++) { var serieData = dataList[i]; if (serieData.show) { var count = 0; if (dimension > 0) { count = dimension; } else { count = serie.showDataDimension > serieData.data.Count ? serieData.data.Count : serie.showDataDimension; } for (int j = 0; j < count; j++) { var value = serieData.data[j]; if (!serie.IsIgnoreValue(value)) { if (value > max) { max = value; } if (value < min) { min = value; } } } } } }