优化DataZoomMarquee框选功能

This commit is contained in:
monitor1394
2026-05-28 09:14:53 +08:00
parent b040f27b2c
commit 2688d93f17
5 changed files with 121 additions and 34 deletions

View File

@@ -869,21 +869,36 @@ namespace XCharts.Runtime
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)
// Use (N-1) intervals so that data point i maps to exactly i/(N-1)*100% of the
// DataZoom width — matching how the shadow draws data via scaleWid = width/(N-1).
// CeilToInt for start ensures we never include a point that lies before the filler.
// FloorToInt for end ensures we never include a point that lies after the filler.
int n = data.Count - 1;
int startIndex, endIndex;
if (n > 0)
{
end = Mathf.RoundToInt(data.Count * dataZoom.end / 100);
start = end - range;
if (start < 0) start = 0;
if (dataZoom.context.invert)
{
startIndex = Mathf.CeilToInt((float)n * (100 - dataZoom.end) / 100);
endIndex = Mathf.FloorToInt((float)n * (100 - dataZoom.start) / 100);
}
else
{
startIndex = Mathf.CeilToInt((float)n * dataZoom.start / 100);
endIndex = Mathf.FloorToInt((float)n * dataZoom.end / 100);
}
}
else
{
start = Mathf.RoundToInt(data.Count * dataZoom.start / 100);
end = start + range;
if (end > data.Count) end = data.Count;
startIndex = 0;
endIndex = 0;
}
var range = endIndex - startIndex + 1;
if (range <= 0) range = 1;
int start = startIndex;
if (start < 0) start = 0;
int end = start + range;
if (end > data.Count) end = data.Count;
var minZoomRatio = (int)(data.Count * dataZoom.minZoomRatio);
if (start != serie.m_FilterStart || end != serie.m_FilterEnd ||
minZoomRatio != serie.m_FilterMinShow || serie.m_NeedUpdateFilterData)

View File

@@ -379,7 +379,12 @@ namespace XCharts.Runtime
// determine whether DataZoom filtering applies for this serie
var dz = chart.GetXDataZoomOfSerie(serie);
bool useDataZoomFilter = dz != null && dz.enable && dz.filterAxisRange;
// Only apply DataZoom filter for non-X dimensions (dimension > 0, e.g. Y axis
// scaling to visible data). For dimension=0 (X axis whose range is controlled
// by DataZoom), using filtered X data would create a circular dependency:
// rawMin/rawMax would be set from filtered data, making the filter boundary
// relative to an already-filtered range instead of the full data range.
bool useDataZoomFilter = dimension > 0 && dz != null && dz.enable && dz.filterAxisRange;
// try per-serie cache when not filtering by dataZoom and not in animation mode
if (!useDataZoomFilter && !needAnimation)
@@ -476,7 +481,8 @@ namespace XCharts.Runtime
(!isPolar && serie.yAxisIndex != axisIndex) ||
!serie.show) continue;
var stackDz = chart.GetXDataZoomOfSerie(serie);
if (stackDz != null && (!stackDz.filterAxisRange || !stackDz.enable)) stackDz = null;
// Same rule as non-stack: don't use filtered data for dimension=0 (X axis).
if (stackDz != null && (dimension == 0 || !stackDz.filterAxisRange || !stackDz.enable)) stackDz = null;
var showData = serie.GetDataList(stackDz);
if (SeriesHelper.IsPercentStack<Bar>(series, serie.stack))
{