private void DrawXCategory(VertexHelper vh) { var stackSeries = m_Series.GetStackSeries(); int seriesCount = stackSeries.Count; float scaleWid = m_XAxis.GetDataWidth(coordinateWid, m_DataZoom); int serieCount = 0; List <Vector3> points = new List <Vector3>(); List <Vector3> smoothPoints = new List <Vector3>(); List <Color> colorList = new List <Color>(); int dataCount = 0; for (int j = 0; j < seriesCount; j++) { var seriesCurrHig = new Dictionary <int, float>(); var serieList = stackSeries[j]; for (int n = 0; n < serieList.Count; n++) { Serie serie = serieList[n]; if (!IsActive(serie.name)) { continue; } List <Vector3> lastPoints = new List <Vector3>(); List <Vector3> lastSmoothPoints = new List <Vector3>(); List <float> serieData = serie.GetData(m_DataZoom); Color color = m_ThemeInfo.GetColor(serieCount); Vector3 lp = Vector3.zero; Vector3 np = Vector3.zero; float startX = zeroX + (m_XAxis.boundaryGap ? scaleWid / 2 : 0); int maxCount = maxShowDataNumber > 0 ? (maxShowDataNumber > serieData.Count ? serieData.Count : maxShowDataNumber) : serieData.Count; dataCount = (maxCount - minShowDataNumber); if (m_Line.area && points.Count > 0) { if (!m_Line.smooth && points.Count > 0) { for (int m = points.Count - dataCount; m < points.Count; m++) { lastPoints.Add(points[m]); } } else if (m_Line.smooth && smoothPoints.Count > 0) { for (int m = 0; m < smoothPoints.Count; m++) { lastSmoothPoints.Add(smoothPoints[m]); } smoothPoints.Clear(); } } int smoothPointCount = 1; for (int i = minShowDataNumber; i < maxCount; i++) { if (!seriesCurrHig.ContainsKey(i)) { seriesCurrHig[i] = 0; } float value = serieData[i]; float pX = startX + i * scaleWid; float pY = seriesCurrHig[i] + zeroY + m_Coordinate.tickness; float dataHig = value / (maxValue - minValue) * coordinateHig; np = new Vector3(pX, pY + dataHig); if (i > 0) { if (m_Line.step) { Vector2 middle1, middle2; switch (m_Line.stepTpe) { case Line.StepType.Start: middle1 = new Vector2(lp.x, np.y + m_Line.tickness); middle2 = new Vector2(lp.x - m_Line.tickness, np.y); ChartHelper.DrawLine(vh, lp, middle1, m_Line.tickness, color); ChartHelper.DrawLine(vh, middle2, np, m_Line.tickness, color); if (m_Line.area) { Color areaColor = new Color(color.r, color.g, color.b, color.a * 0.75f); ChartHelper.DrawPolygon(vh, new Vector2(middle1.x, zeroY), middle1, np, new Vector2(np.x, zeroY), areaColor); } break; case Line.StepType.Middle: middle1 = new Vector2((lp.x + np.x) / 2 + m_Line.tickness, lp.y); middle2 = new Vector2((lp.x + np.x) / 2 - m_Line.tickness, np.y); ChartHelper.DrawLine(vh, lp, middle1, m_Line.tickness, color); ChartHelper.DrawLine(vh, new Vector2(middle1.x - m_Line.tickness, middle1.y), new Vector2(middle2.x + m_Line.tickness, middle2.y), m_Line.tickness, color); ChartHelper.DrawLine(vh, middle2, np, m_Line.tickness, color); if (m_Line.area) { Color areaColor = new Color(color.r, color.g, color.b, color.a * 0.75f); ChartHelper.DrawPolygon(vh, new Vector2(lp.x, zeroY), lp, middle1, new Vector2(middle1.x, zeroY), areaColor); ChartHelper.DrawPolygon(vh, new Vector2(middle2.x + 2 * m_Line.tickness, zeroY), new Vector2(middle2.x + 2 * m_Line.tickness, middle2.y), np, new Vector2(np.x, zeroY), areaColor); } break; case Line.StepType.End: middle1 = new Vector2(np.x + m_Line.tickness, lp.y); middle2 = new Vector2(np.x, lp.y); ChartHelper.DrawLine(vh, lp, middle1, m_Line.tickness, color); ChartHelper.DrawLine(vh, middle2, np, m_Line.tickness, color); if (m_Line.area) { Color areaColor = new Color(color.r, color.g, color.b, color.a * 0.75f); ChartHelper.DrawPolygon(vh, new Vector2(lp.x, zeroY), lp, new Vector2(middle1.x - m_Line.tickness, middle1.y), new Vector2(middle1.x - m_Line.tickness, zeroY), areaColor); } break; } } else if (m_Line.smooth) { var list = ChartHelper.GetBezierList(lp, np, m_Line.smoothStyle); Vector3 start, to; start = list[0]; for (int k = 1; k < list.Length; k++) { smoothPoints.Add(list[k]); to = list[k]; ChartHelper.DrawLine(vh, start, to, m_Line.tickness, color); if (m_Line.area) { Vector3 alp = new Vector3(start.x, start.y - m_Line.tickness); Vector3 anp = new Vector3(to.x, to.y - m_Line.tickness); Vector3 tnp = serieCount > 0 ? (smoothPointCount > lastSmoothPoints.Count - 1 ? new Vector3(lastSmoothPoints[lastSmoothPoints.Count - 1].x, lastSmoothPoints[lastSmoothPoints.Count - 1].y + m_Line.tickness) : new Vector3(lastSmoothPoints[smoothPointCount].x, lastSmoothPoints[smoothPointCount].y + m_Line.tickness)) : new Vector3(to.x, zeroY + m_Coordinate.tickness); Vector3 tlp = serieCount > 0 ? (smoothPointCount > lastSmoothPoints.Count - 1 ? new Vector3(lastSmoothPoints[lastSmoothPoints.Count - 2].x, lastSmoothPoints[lastSmoothPoints.Count - 2].y + m_Line.tickness) : new Vector3(lastSmoothPoints[smoothPointCount - 1].x, lastSmoothPoints[smoothPointCount - 1].y + m_Line.tickness)) : new Vector3(start.x, zeroY + m_Coordinate.tickness); Color areaColor = new Color(color.r, color.g, color.b, color.a * 0.75f); ChartHelper.DrawPolygon(vh, alp, anp, tnp, tlp, areaColor); } smoothPointCount++; start = to; } } else { ChartHelper.DrawLine(vh, lp, np, m_Line.tickness, color); if (m_Line.area) { Vector3 alp = new Vector3(lp.x, lp.y - m_Line.tickness); Vector3 anp = new Vector3(np.x, np.y - m_Line.tickness); Color areaColor = new Color(color.r, color.g, color.b, color.a * 0.75f); var cross = ChartHelper.GetIntersection(lp, np, new Vector3(zeroX, zeroY), new Vector3(zeroX + coordinateWid, zeroY)); if (cross == Vector3.zero) { Vector3 tnp = serieCount > 0 ? new Vector3(lastPoints[i].x, lastPoints[i].y + m_Line.tickness) : new Vector3(np.x, zeroY + m_Coordinate.tickness); Vector3 tlp = serieCount > 0 ? new Vector3(lastPoints[i - 1].x, lastPoints[i - 1].y + m_Line.tickness) : new Vector3(lp.x, zeroY + m_Coordinate.tickness); ChartHelper.DrawPolygon(vh, alp, anp, tnp, tlp, areaColor); } else { Vector3 cross1 = new Vector3(cross.x, cross.y + (alp.y > zeroY ? m_Coordinate.tickness : -m_Coordinate.tickness)); Vector3 cross2 = new Vector3(cross.x, cross.y + (anp.y > zeroY ? m_Coordinate.tickness : -m_Coordinate.tickness)); Vector3 xp1 = new Vector3(alp.x, zeroY + (alp.y > zeroY ? m_Coordinate.tickness : -m_Coordinate.tickness)); Vector3 xp2 = new Vector3(anp.x, zeroY + (anp.y > zeroY ? m_Coordinate.tickness : -m_Coordinate.tickness)); ChartHelper.DrawTriangle(vh, alp, cross1, xp1, areaColor); ChartHelper.DrawTriangle(vh, anp, cross2, xp2, areaColor); } } } } if (m_Line.point) { points.Add(np); colorList.Add(color); } seriesCurrHig[i] += dataHig; lp = np; } if (serie.show) { serieCount++; } } // draw point if (m_Line.point) { for (int i = 0; i < points.Count; i++) { Vector3 p = points[i]; float pointWid = m_Line.pointWidth; if (m_Tooltip.show && i % dataCount == m_Tooltip.dataIndex - 1) { pointWid = pointWid * 1.8f; } if (m_Theme == Theme.Dark) { ChartHelper.DrawCricle(vh, p, pointWid, colorList[i], (int)m_Line.pointWidth * 5); } else { ChartHelper.DrawCricle(vh, p, pointWid, Color.white); ChartHelper.DrawDoughnut(vh, p, pointWid - m_Line.tickness, pointWid, 0, 360, colorList[i]); } } } } //draw tooltip line if (m_Tooltip.show && m_Tooltip.dataIndex > 0) { float splitWidth = m_XAxis.GetSplitWidth(coordinateWid, m_DataZoom); float px = zeroX + (m_Tooltip.dataIndex - 1) * splitWidth + (m_XAxis.boundaryGap ? splitWidth / 2 : 0); Vector2 sp = new Vector2(px, coordinateY); Vector2 ep = new Vector2(px, coordinateY + coordinateHig); ChartHelper.DrawLine(vh, sp, ep, m_Coordinate.tickness, m_ThemeInfo.tooltipLineColor); if (m_Tooltip.crossLabel) { sp = new Vector2(zeroX, m_Tooltip.pointerPos.y); ep = new Vector2(zeroX + coordinateWid, m_Tooltip.pointerPos.y); DrawSplitLine(vh, true, Axis.SplitLineType.Dashed, sp, ep, m_ThemeInfo.tooltipLineColor); } } }
/// <summary> /// 替换字符串中的通配符,支持的通配符有{.}、{a}、{b}、{c}、{d}。 /// </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, Series series, ChartTheme theme, string category = null, 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 = series.GetSerie(targetIndex); if (serie == null) { continue; } } else if (serie != null) { targetIndex = serie.index; } else { serie = series.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(theme.GetColor(bIndex))); foundDot = true; } else if (p == 'a' || p == 'A') { if (argsCount == 1) { content = content.Replace(old, serie.name); } } else if (p == 'b' || p == 'B') { var bIndex = dataIndex; if (argsCount >= 2) { var args1Str = args[1].ToString(); if (s_RegexN.IsMatch(args1Str)) { bIndex = int.Parse(args1Str); } } var needCategory = serie.type == SerieType.Line || serie.type == SerieType.Bar; if (needCategory) { content = content.Replace(old, category); } else { var serieData = serie.GetSerieData(bIndex, dataZoom); content = content.Replace(old, serieData.name); } } else if (p == 'c' || p == 'C' || p == 'd' || p == 'D') { var isPercent = p == 'd' || p == 'D'; 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); var percent = total == 0 ? 0 : value / serie.yTotal * 100; content = content.Replace(old, ChartCached.FloatToStr(percent, numericFormatter)); } else { content = content.Replace(old, ChartCached.FloatToStr(value, numericFormatter)); } } } content = s_RegexNewLine.Replace(content, PH_NN); return(foundDot); }
protected override void DrawChart(VertexHelper vh) { base.DrawChart(vh); if (m_YAxis.type == Axis.AxisType.Category) { var stackSeries = m_Series.GetStackSeries(); int seriesCount = stackSeries.Count; float scaleWid = m_YAxis.GetDataWidth(coordinateHig, m_DataZoom); float barWid = m_Bar.barWidth > 1 ? m_Bar.barWidth : scaleWid * m_Bar.barWidth; float offset = m_Bar.inSameBar ? (scaleWid - barWid - m_Bar.space * (seriesCount - 1)) / 2 : (scaleWid - barWid * seriesCount - m_Bar.space * (seriesCount - 1)) / 2; int serieCount = 0; for (int j = 0; j < seriesCount; j++) { var seriesCurrHig = new Dictionary <int, float>(); var serieList = stackSeries[j]; for (int n = 0; n < serieList.Count; n++) { Serie serie = serieList[n]; if (!m_Legend.IsActive(serie.name)) { continue; } Color color = m_ThemeInfo.GetColor(serieCount); int maxCount = maxShowDataNumber > 0 ? (maxShowDataNumber > serie.data.Count ? serie.data.Count : maxShowDataNumber) : serie.data.Count; for (int i = minShowDataNumber; i < maxCount; i++) { if (!seriesCurrHig.ContainsKey(i)) { seriesCurrHig[i] = 0; } float value = serie.data[i]; float pX = seriesCurrHig[i] + zeroX + m_Coordinate.tickness; float pY = coordinateY + i * scaleWid; if (!m_YAxis.boundaryGap) { pY -= scaleWid / 2; } float barHig = value / (maxValue - minValue) * coordinateWid; float space = m_Bar.inSameBar ? offset : offset + j * (barWid + m_Bar.space); seriesCurrHig[i] += barHig; Vector3 p1 = new Vector3(pX, pY + space + barWid); Vector3 p2 = new Vector3(pX + barHig, pY + space + barWid); Vector3 p3 = new Vector3(pX + barHig, pY + space); Vector3 p4 = new Vector3(pX, pY + space); if (serie.show) { ChartHelper.DrawPolygon(vh, p1, p2, p3, p4, color); } } if (serie.show) { serieCount++; } } } if (m_Tooltip.show && m_Tooltip.dataIndex > 0) { if (m_Tooltip.crossLabel) { Vector3 sp = new Vector2(m_Tooltip.pointerPos.x, zeroY); Vector3 ep = new Vector2(m_Tooltip.pointerPos.x, zeroY + coordinateHig); DrawSplitLine(vh, false, Axis.SplitLineType.Dashed, sp, ep, m_ThemeInfo.tooltipLineColor); float splitWidth = m_YAxis.GetSplitWidth(coordinateHig, m_DataZoom); float pY = zeroY + (m_Tooltip.dataIndex - 1) * splitWidth + (m_YAxis.boundaryGap ? splitWidth / 2 : 0); sp = new Vector2(coordinateX, pY); ep = new Vector2(coordinateX + coordinateWid, pY); DrawSplitLine(vh, true, Axis.SplitLineType.Dashed, sp, ep, m_ThemeInfo.tooltipLineColor); } else { float tooltipSplitWid = scaleWid < 1 ? 1 : scaleWid; float pX = coordinateX + coordinateWid; float pY = coordinateY + scaleWid * (m_Tooltip.dataIndex - 1) - (m_YAxis.boundaryGap ? 0 : scaleWid / 2); Vector3 p1 = new Vector3(coordinateX, pY); Vector3 p2 = new Vector3(coordinateX, pY + tooltipSplitWid); Vector3 p3 = new Vector3(pX, pY + tooltipSplitWid); Vector3 p4 = new Vector3(pX, pY); ChartHelper.DrawPolygon(vh, p1, p2, p3, p4, m_ThemeInfo.tooltipFlagAreaColor); } } } else { var stackSeries = m_Series.GetStackSeries(); int seriesCount = stackSeries.Count; float scaleWid = m_XAxis.GetDataWidth(coordinateWid, m_DataZoom); float barWid = m_Bar.barWidth > 1 ? m_Bar.barWidth : scaleWid * m_Bar.barWidth; float offset = m_Bar.inSameBar ? (scaleWid - barWid - m_Bar.space * (seriesCount - 1)) / 2 : (scaleWid - barWid * seriesCount - m_Bar.space * (seriesCount - 1)) / 2; int serieCount = 0; for (int j = 0; j < seriesCount; j++) { var seriesCurrHig = new Dictionary <int, float>(); var serieList = stackSeries[j]; for (int n = 0; n < serieList.Count; n++) { Serie serie = serieList[n]; if (!m_Legend.IsActive(serie.name)) { continue; } Color color = m_ThemeInfo.GetColor(serieCount); List <float> showData = serie.GetData(m_DataZoom); int maxCount = maxShowDataNumber > 0 ? (maxShowDataNumber > showData.Count ? showData.Count : maxShowDataNumber) : showData.Count; for (int i = minShowDataNumber; i < maxCount; i++) { if (!seriesCurrHig.ContainsKey(i)) { seriesCurrHig[i] = 0; } float value = showData[i]; float pX = zeroX + i * scaleWid; if (!m_XAxis.boundaryGap) { pX -= scaleWid / 2; } float pY = seriesCurrHig[i] + zeroY + m_Coordinate.tickness; float barHig = value / (maxValue - minValue) * coordinateHig; seriesCurrHig[i] += barHig; float space = m_Bar.inSameBar ? offset : offset + j * (barWid + m_Bar.space); Vector3 p1 = new Vector3(pX + space, pY); Vector3 p2 = new Vector3(pX + space, pY + barHig); Vector3 p3 = new Vector3(pX + space + barWid, pY + barHig); Vector3 p4 = new Vector3(pX + space + barWid, pY); if (serie.show) { ChartHelper.DrawPolygon(vh, p1, p2, p3, p4, color); } } if (serie.show) { serieCount++; } } } if (m_Tooltip.show && m_Tooltip.dataIndex > 0) { if (m_Tooltip.crossLabel) { Vector3 sp = new Vector2(zeroX, m_Tooltip.pointerPos.y); Vector3 ep = new Vector2(zeroX + coordinateWid, m_Tooltip.pointerPos.y); DrawSplitLine(vh, true, Axis.SplitLineType.Dashed, sp, ep, m_ThemeInfo.tooltipLineColor); float splitWidth = m_XAxis.GetSplitWidth(coordinateWid, m_DataZoom); float px = zeroX + (m_Tooltip.dataIndex - 1) * splitWidth + (m_XAxis.boundaryGap ? splitWidth / 2 : 0); sp = new Vector2(px, coordinateY); ep = new Vector2(px, coordinateY + coordinateHig); DrawSplitLine(vh, false, Axis.SplitLineType.Dashed, sp, ep, m_ThemeInfo.tooltipLineColor); } else { float tooltipSplitWid = scaleWid < 1 ? 1 : scaleWid; float pX = coordinateX + scaleWid * (m_Tooltip.dataIndex - 1) - (m_XAxis.boundaryGap ? 0 : scaleWid / 2); float pY = coordinateY + coordinateHig; Vector3 p1 = new Vector3(pX, coordinateY); Vector3 p2 = new Vector3(pX, pY); Vector3 p3 = new Vector3(pX + tooltipSplitWid, pY); Vector3 p4 = new Vector3(pX + tooltipSplitWid, coordinateY); ChartHelper.DrawPolygon(vh, p1, p2, p3, p4, m_ThemeInfo.tooltipFlagAreaColor); } } } }