From ac41dd1d0721f177bc561e07a2257d862f82a252 Mon Sep 17 00:00:00 2001 From: monitor1394 Date: Wed, 5 Nov 2025 08:55:02 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96`Candlestick`=E5=AF=B9?= =?UTF-8?q?=E6=97=B6=E9=97=B4=E8=BD=B4=E7=9A=84=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Runtime/Component/Tooltip/TooltipHandler.cs | 22 +++- .../Serie/Candlestick/CandlestickHandler.cs | 108 +++++++++++++++--- Runtime/Serie/Line/LineHandler.GridCoord.cs | 2 +- 3 files changed, 108 insertions(+), 24 deletions(-) diff --git a/Runtime/Component/Tooltip/TooltipHandler.cs b/Runtime/Component/Tooltip/TooltipHandler.cs index 94cf8e61..16de25e4 100644 --- a/Runtime/Component/Tooltip/TooltipHandler.cs +++ b/Runtime/Component/Tooltip/TooltipHandler.cs @@ -473,13 +473,25 @@ namespace XCharts.Runtime { var serieData = data[i]; currValue = serieData.GetData(dimension); - if (i == 0 && i + 1 < dataCount) + if (i == 0) { - nextValue = data[i + 1].GetData(dimension); - if (axisValue <= currValue + (nextValue - currValue) / 2) + if (i + 1 < dataCount) { - serie.context.pointerAxisDataIndexs.Add(serieData.index); - break; + nextValue = data[i + 1].GetData(dimension); + if (axisValue <= currValue + (nextValue - currValue) / 2) + { + serie.context.pointerAxisDataIndexs.Add(serieData.index); + break; + } + } + else + { + var diff = axis.context.tickValue * 0.5f; + if (axisValue >= currValue - diff && axisValue <= currValue + diff) + { + serie.context.pointerAxisDataIndexs.Add(serieData.index); + break; + } } } else if (i == dataCount - 1) diff --git a/Runtime/Serie/Candlestick/CandlestickHandler.cs b/Runtime/Serie/Candlestick/CandlestickHandler.cs index b17cc585..05c20498 100644 --- a/Runtime/Serie/Candlestick/CandlestickHandler.cs +++ b/Runtime/Serie/Candlestick/CandlestickHandler.cs @@ -8,6 +8,7 @@ namespace XCharts.Runtime [UnityEngine.Scripting.Preserve] internal sealed class CandlestickHandler : SerieHandler { + private GridCoord m_SerieGrid; public override void DrawSerie(VertexHelper vh) { DrawCandlestickSerie(vh, serie); @@ -106,20 +107,84 @@ namespace XCharts.Runtime } } + public override void UpdateSerieContext() + { + if (m_SerieGrid == null) + return; + + var needCheck = (chart.isPointerInChart && m_SerieGrid.IsPointerEnter() && !serie.placeHolder) || m_LegendEnter; + var needInteract = false; + if (!needCheck) + { + if (m_LastCheckContextFlag != needCheck) + { + m_LastCheckContextFlag = needCheck; + serie.context.pointerItemDataIndex = -1; + serie.context.pointerEnter = false; + Color32 color1, toColor1; + foreach (var serieData in serie.data) + { + serieData.context.highlight = false; + var state = SerieHelper.GetSerieState(serie, serieData, true); + SerieHelper.GetItemColor(out color1, out toColor1, serie, serieData, chart.theme, state); + serieData.interact.SetColor(ref needInteract, color1, toColor1); + } + chart.RefreshPainter(serie); + } + return; + } + m_LastCheckContextFlag = needCheck; + Color32 color, toColor; + if (m_LegendEnter) + { + serie.context.pointerEnter = true; + foreach (var serieData in serie.data) + { + SerieHelper.GetItemColor(out color, out toColor, serie, serieData, chart.theme); + serieData.interact.SetColor(ref needInteract, color, toColor); + } + } + else + { + serie.context.pointerItemDataIndex = -1; + serie.context.pointerEnter = false; + foreach (var serieData in serie.data) + { + if (serie.context.pointerAxisDataIndexs.Contains(serieData.index) || + serieData.context.rect.Contains(chart.pointerPos)) + { + serie.context.pointerItemDataIndex = serieData.index; + serie.context.pointerEnter = true; + serieData.context.highlight = true; + } + else + { + serieData.context.highlight = false; + } + var state = SerieHelper.GetSerieState(serie, serieData, true); + SerieHelper.GetItemColor(out color, out toColor, serie, serieData, chart.theme, state); + serieData.interact.SetColor(ref needInteract, color, toColor); + } + } + if (needInteract) + { + chart.RefreshPainter(serie); + } + } + private void DrawCandlestickSerie(VertexHelper vh, Candlestick serie) { if (!serie.show) return; if (serie.animation.HasFadeOut()) return; XAxis xAxis; YAxis yAxis; - GridCoord grid; if (!chart.TryGetChartComponent(out xAxis, serie.xAxisIndex)) return; if (!chart.TryGetChartComponent(out yAxis, serie.yAxisIndex)) return; - if (!chart.TryGetChartComponent(out grid, xAxis.gridIndex)) return; + if (!chart.TryGetChartComponent(out m_SerieGrid, xAxis.gridIndex)) return; var theme = chart.theme; var dataZoom = chart.GetDataZoomOfAxis(xAxis); var showData = serie.GetDataList(dataZoom); - float categoryWidth = AxisHelper.GetDataWidth(xAxis, grid.context.width, showData.Count, dataZoom); + float categoryWidth = AxisHelper.GetDataWidth(xAxis, m_SerieGrid.context.width, showData.Count, dataZoom); float barWidth = serie.GetBarWidth(categoryWidth); float gap = (categoryWidth - barWidth) / 2; int maxCount = serie.maxShow > 0 ? @@ -133,9 +198,9 @@ namespace XCharts.Runtime double yMinValue = yAxis.context.minValue; double yMaxValue = yAxis.context.maxValue; var isYAxis = false; - serie.containerIndex = grid.index; - serie.containterInstanceId = grid.instanceId; - var intensive = grid.context.width / (maxCount - serie.minShow) < 0.6f; + serie.containerIndex = m_SerieGrid.index; + serie.containterInstanceId = m_SerieGrid.instanceId; + var intensive = m_SerieGrid.context.width / (maxCount - serie.minShow) < 0.6f; for (int i = serie.minShow; i < maxCount; i++) { var serieData = showData[i]; @@ -157,8 +222,8 @@ namespace XCharts.Runtime (itemStyle.borderWidth == 0 ? theme.serie.candlestickBorderWidth : itemStyle.borderWidth); if (serieData.IsDataChanged()) dataChanging = true; - float pX = xAxis.IsCategory() ? grid.context.x + i * categoryWidth : AxisHelper.GetAxisValuePosition(grid, xAxis, categoryWidth, serieData.GetData(0)); - float zeroY = grid.context.y + yAxis.context.offset; + float pX = xAxis.IsCategory() ? m_SerieGrid.context.x + i * categoryWidth : AxisHelper.GetAxisValuePosition(m_SerieGrid, xAxis, categoryWidth, serieData.GetData(0)); + float zeroY = m_SerieGrid.context.y + yAxis.context.offset; if (!xAxis.boundaryGap) pX -= categoryWidth / 2; float pY = zeroY; var barHig = 0f; @@ -166,8 +231,8 @@ namespace XCharts.Runtime var minCut = yMinValue > 0 ? yMinValue : 0; if (valueTotal != 0) { - barHig = (float)((close - open) / valueTotal * grid.context.height); - pY += (float)((open - minCut) / valueTotal * grid.context.height); + barHig = (float)((close - open) / valueTotal * m_SerieGrid.context.height); + pY += (float)((open - minCut) / valueTotal * m_SerieGrid.context.height); } serieData.context.stackHeight = barHig; float currHig = AnimationStyleHelper.CheckDataAnimation(chart, serie, i, barHig); @@ -192,11 +257,11 @@ namespace XCharts.Runtime } if (serie.clip) { - plb = chart.ClampInGrid(grid, plb); - plt = chart.ClampInGrid(grid, plt); - prt = chart.ClampInGrid(grid, prt); - prb = chart.ClampInGrid(grid, prb); - top = chart.ClampInGrid(grid, top); + plb = chart.ClampInGrid(m_SerieGrid, plb); + plt = chart.ClampInGrid(m_SerieGrid, plt); + prt = chart.ClampInGrid(m_SerieGrid, prt); + prb = chart.ClampInGrid(m_SerieGrid, prb); + top = chart.ClampInGrid(m_SerieGrid, top); } serie.context.dataPoints.Add(top); serie.context.dataIndexs.Add(serieData.index); @@ -209,10 +274,17 @@ namespace XCharts.Runtime var itemWidth = Mathf.Abs(prt.x - plb.x); var itemHeight = Mathf.Abs(plt.y - prb.y); var center = new Vector3((plb.x + prt.x) / 2, (plt.y + prb.y) / 2); - var lowPos = new Vector3(center.x, zeroY + (float)((lowest - minCut) / valueTotal * grid.context.height)); - var heighPos = new Vector3(center.x, zeroY + (float)((heighest - minCut) / valueTotal * grid.context.height)); + var lowPos = new Vector3(center.x, zeroY + (float)((lowest - minCut) / valueTotal * m_SerieGrid.context.height)); + var heighPos = new Vector3(center.x, zeroY + (float)((heighest - minCut) / valueTotal * m_SerieGrid.context.height)); var openCenterPos = new Vector3(center.x, prb.y); var closeCenterPos = new Vector3(center.x, prt.y); + + var rectMinX = Mathf.Min(plb.x, prb.x, plt.x, prt.x); + var rectMaxX = Mathf.Max(plb.x, prb.x, plt.x, prt.x); + var rectMinY = Mathf.Min(plb.y, prb.y, plt.y, prt.y, lowPos.y, heighPos.y); + var rectMaxY = Mathf.Max(plb.y, prb.y, plt.y, prt.y, lowPos.y, heighPos.y); + serieData.context.rect = new Rect(rectMinX, rectMinY, rectMaxX - rectMinX, rectMaxY - rectMinY); + UGL.DrawRectangle(vh, serieData.context.rect, Color.yellow); if (intensive) { UGL.DrawLine(vh, lowPos, heighPos, borderWidth, borderColor); @@ -231,7 +303,7 @@ namespace XCharts.Runtime else { chart.DrawClipPolygon(vh, ref prb, ref plb, ref plt, ref prt, areaColor, areaColor, - serie.clip, grid); + serie.clip, m_SerieGrid); } UGL.DrawBorder(vh, center, itemWidth, itemHeight, 2 * borderWidth, borderColor, 0, itemStyle.cornerRadius, isYAxis, 0.5f); diff --git a/Runtime/Serie/Line/LineHandler.GridCoord.cs b/Runtime/Serie/Line/LineHandler.GridCoord.cs index c390ff7c..bc129b6b 100644 --- a/Runtime/Serie/Line/LineHandler.GridCoord.cs +++ b/Runtime/Serie/Line/LineHandler.GridCoord.cs @@ -100,7 +100,7 @@ namespace XCharts.Runtime var serieData = serie.data[i]; var dist = Vector3.Distance(chart.pointerPos, serieData.context.position); var size = SerieHelper.GetSysmbolSize(serie, serieData, themeSymbolSize); - var highlight = dist <= size; + var highlight = dist <= size * 2.5f; serieData.context.highlight = highlight; var state = SerieHelper.GetSerieState(serie, serieData, true); size = SerieHelper.GetSysmbolSize(serie, serieData, themeSymbolSize, state);