增加BarrealtimeSort支持实时排序

This commit is contained in:
monitor1394
2025-03-01 22:30:51 +08:00
parent 063b5529d7
commit ffed67d8ee
16 changed files with 143 additions and 61 deletions

View File

@@ -79,6 +79,8 @@ slug: /changelog
## master ## master
* (2025.03.01) 优化`Comment`的组件刷新
* (2025.02.23) 增加`Axis``Label``formatter`支持`{index}``{index-1}``{-index}``{-index-1}`通配符
* (2025.02.23) 增加`Bar``realtimeSort`支持实时排序 * (2025.02.23) 增加`Bar``realtimeSort`支持实时排序
* (2025.02.19) 增加`Tooltip``itemFormatter``\n`换行的支持 * (2025.02.19) 增加`Tooltip``itemFormatter``\n`换行的支持
* (2025.02.18) 优化`Tooltip`的对齐方式 * (2025.02.18) 优化`Tooltip`的对齐方式

View File

@@ -253,7 +253,7 @@ namespace XCharts
var serie = chart.GetSerie(0); var serie = chart.GetSerie(0);
if (isCategory && serie != null && serie.useSortData) if (isCategory && serie != null && serie.useSortData)
{ {
var showData = serie.GetDataList(dataZoom); var showData = serie.GetDataList(dataZoom, true);
var isChanged = CheckSortedDataChanged(axis, showData); var isChanged = CheckSortedDataChanged(axis, showData);
if (isChanged) if (isChanged)
{ {
@@ -262,15 +262,11 @@ namespace XCharts
if (context.labelObjectList[i] != null) if (context.labelObjectList[i] != null)
{ {
var index = i < showData.Count ? showData[i].index : i; var index = i < showData.Count ? showData[i].index : i;
var text = AxisHelper.GetLabelName(axis, coordinateWidth, index, destMinValue, destMaxValue, dataZoom, forcePercent); var text = AxisHelper.GetLabelName(axis, coordinateWidth, index, destMinValue, destMaxValue, dataZoom, forcePercent, i);
context.labelObjectList[i].SetText(text); context.labelObjectList[i].SetText(text);
} }
} }
axis.context.sortedDataIndices.Clear(); SaveSortedDataIndex(axis, showData);
for (int i = 0; i < showData.Count; i++)
{
axis.context.sortedDataIndices.Add(showData[i].index);
}
} }
} }
else else
@@ -296,6 +292,15 @@ namespace XCharts
return false; return false;
} }
private void SaveSortedDataIndex(Axis axis, List<SerieData> dataList)
{
axis.context.sortedDataIndices.Clear();
for (int i = 0; i < dataList.Count; i++)
{
axis.context.sortedDataIndices.Add(dataList[i].index);
}
}
internal void UpdateAxisTickValueList(Axis axis) internal void UpdateAxisTickValueList(Axis axis)
{ {
if (axis.IsTime()) if (axis.IsTime())
@@ -473,13 +478,21 @@ namespace XCharts
if (axis.IsCategory() && axis.boundaryGap) if (axis.IsCategory() && axis.boundaryGap)
splitNumber -= 1; splitNumber -= 1;
axis.context.aligment = defaultAlignment; axis.context.aligment = defaultAlignment;
var sortSerie = chart.GetRealtimeSortSerie();
if (sortSerie != null)
{
SerieHelper.UpdateSerieRuntimeFilterData(sortSerie);
}
var showData = sortSerie != null ? sortSerie.GetDataList(dataZoom, true) : null;
for (int i = 0; i < splitNumber; i++) for (int i = 0; i < splitNumber; i++)
{ {
var labelWidth = AxisHelper.GetScaleWidth(axis, axisLength, i + 1, dataZoom); var labelWidth = AxisHelper.GetScaleWidth(axis, axisLength, i + 1, dataZoom);
var labelName = AxisHelper.GetLabelName(axis, axisLength, i, var sortIndex = sortSerie != null ? (i < showData.Count ? showData[i].index : i) : i;
var labelName = AxisHelper.GetLabelName(axis, axisLength, sortIndex,
axis.context.destMinValue, axis.context.destMinValue,
axis.context.destMaxValue, axis.context.destMaxValue,
dataZoom, isPercentStack); dataZoom, isPercentStack, i);
var label = ChartHelper.AddAxisLabelObject(splitNumber, i, var label = ChartHelper.AddAxisLabelObject(splitNumber, i,
ChartCached.GetAxisLabelName(i), ChartCached.GetAxisLabelName(i),
@@ -585,13 +598,20 @@ namespace XCharts
if (axis.IsCategory() && axis.boundaryGap) if (axis.IsCategory() && axis.boundaryGap)
splitNumber -= 1; splitNumber -= 1;
axis.context.aligment = defaultAlignment; axis.context.aligment = defaultAlignment;
var sortSerie = chart.GetRealtimeSortSerie();
if (sortSerie != null)
{
SerieHelper.UpdateSerieRuntimeFilterData(sortSerie);
}
var showData = sortSerie != null ? sortSerie.GetDataList(dataZoom, true) : null;
for (int i = 0; i < splitNumber; i++) for (int i = 0; i < splitNumber; i++)
{ {
var labelWidth = AxisHelper.GetScaleWidth(axis, axisLength, i + 1, dataZoom); var labelWidth = AxisHelper.GetScaleWidth(axis, axisLength, i + 1, dataZoom);
var labelName = AxisHelper.GetLabelName(axis, axisLength, i, var sortIndex = sortSerie != null ? (i < showData.Count ? showData[i].index : i) : i;
var labelName = AxisHelper.GetLabelName(axis, axisLength, sortIndex,
axis.context.destMinValue, axis.context.destMinValue,
axis.context.destMaxValue, axis.context.destMaxValue,
dataZoom, isPercentStack); dataZoom, isPercentStack, i);
var label = ChartHelper.AddAxisLabelObject(splitNumber, i, var label = ChartHelper.AddAxisLabelObject(splitNumber, i,
ChartCached.GetAxisLabelName(i), ChartCached.GetAxisLabelName(i),

View File

@@ -116,9 +116,10 @@ namespace XCharts.Runtime
/// <param name="dataZoom"></param> /// <param name="dataZoom"></param>
/// <returns></returns> /// <returns></returns>
public static string GetLabelName(Axis axis, float coordinateWidth, int index, double minValue, double maxValue, public static string GetLabelName(Axis axis, float coordinateWidth, int index, double minValue, double maxValue,
DataZoom dataZoom, bool forcePercent) DataZoom dataZoom, bool forcePercent, int sortIndex = -1)
{ {
int split = GetSplitNumber(axis, coordinateWidth, dataZoom); int split = GetSplitNumber(axis, coordinateWidth, dataZoom);
if(sortIndex == -1) sortIndex = index;
if (axis.type == Axis.AxisType.Value) if (axis.type == Axis.AxisType.Value)
{ {
if (minValue == 0 && maxValue == 0) if (minValue == 0 && maxValue == 0)
@@ -137,7 +138,7 @@ namespace XCharts.Runtime
if (forcePercent) if (forcePercent)
return string.Format("{0}%", (int)value); return string.Format("{0}%", (int)value);
else else
return axis.axisLabel.GetFormatterContent(index, value, minValue, maxValue); return axis.axisLabel.GetFormatterContent(sortIndex, axis.context.labelValueList.Count, value, minValue, maxValue);
} }
else if (axis.type == Axis.AxisType.Log) else if (axis.type == Axis.AxisType.Log)
{ {
@@ -150,7 +151,7 @@ namespace XCharts.Runtime
minValue = -minValue; minValue = -minValue;
maxValue = -maxValue; maxValue = -maxValue;
} }
return axis.axisLabel.GetFormatterContent(index, value, minValue, maxValue, true); return axis.axisLabel.GetFormatterContent(sortIndex, 0, value, minValue, maxValue, true);
} }
else if (axis.type == Axis.AxisType.Time) else if (axis.type == Axis.AxisType.Time)
{ {
@@ -160,7 +161,7 @@ namespace XCharts.Runtime
return string.Empty; return string.Empty;
var value = axis.GetLabelValue(index); var value = axis.GetLabelValue(index);
return axis.axisLabel.GetFormatterDateTime(index, value, minValue, maxValue); return axis.axisLabel.GetFormatterDateTime(sortIndex, axis.context.labelValueList.Count, value, minValue, maxValue);
} }
var showData = axis.GetDataList(dataZoom); var showData = axis.GetDataList(dataZoom);
int dataCount = showData.Count; int dataCount = showData.Count;
@@ -172,18 +173,18 @@ namespace XCharts.Runtime
{ {
if (index > 0) if (index > 0)
{ {
var residue = (dataCount - 1) - split * rate; var residue = dataCount - 1 - split * rate;
var newIndex = residue + (index - 1) * rate; var newIndex = residue + (index - 1) * rate;
if (newIndex < 0) if (newIndex < 0)
newIndex = 0; newIndex = 0;
return axis.axisLabel.GetFormatterContent(newIndex, showData[newIndex]); return axis.axisLabel.GetFormatterContent(sortIndex, dataCount, showData[newIndex]);
} }
else else
{ {
if (axis.boundaryGap && coordinateWidth / dataCount > 5) if (axis.boundaryGap && coordinateWidth / dataCount > 5)
return string.Empty; return string.Empty;
else else
return axis.axisLabel.GetFormatterContent(0, showData[0]); return axis.axisLabel.GetFormatterContent(sortIndex, dataCount, showData[0]);
} }
} }
else else
@@ -191,7 +192,7 @@ namespace XCharts.Runtime
int newIndex = index * rate; int newIndex = index * rate;
if (newIndex < dataCount) if (newIndex < dataCount)
{ {
return axis.axisLabel.GetFormatterContent(newIndex, showData[newIndex]); return axis.axisLabel.GetFormatterContent(sortIndex, dataCount, showData[newIndex]);
} }
else else
{ {
@@ -199,7 +200,7 @@ namespace XCharts.Runtime
if (axis.boundaryGap && ((diff > 0 && diff / rate < 0.4f) || dataCount >= axis.data.Count)) if (axis.boundaryGap && ((diff > 0 && diff / rate < 0.4f) || dataCount >= axis.data.Count))
return string.Empty; return string.Empty;
else else
return axis.axisLabel.GetFormatterContent(dataCount - 1, showData[dataCount - 1]); return axis.axisLabel.GetFormatterContent(sortIndex, dataCount, showData[dataCount - 1]);
} }
} }
} }

View File

@@ -145,7 +145,7 @@ namespace XCharts.Runtime
m_TextLimit.SetRelatedText(txt, labelWidth); m_TextLimit.SetRelatedText(txt, labelWidth);
} }
public override string GetFormatterContent(int labelIndex, string category) public override string GetFormatterContent(int labelIndex, int totalIndex, string category)
{ {
if (string.IsNullOrEmpty(category)) if (string.IsNullOrEmpty(category))
return GetFormatterFunctionContent(labelIndex, category, category); return GetFormatterFunctionContent(labelIndex, category, category);
@@ -157,18 +157,18 @@ namespace XCharts.Runtime
else else
{ {
var content = m_Formatter; var content = m_Formatter;
FormatterHelper.ReplaceAxisLabelContent(ref content, category); FormatterHelper.ReplaceAxisLabelContent(ref content, category, labelIndex, totalIndex);
return GetFormatterFunctionContent(labelIndex, category, m_TextLimit.GetLimitContent(content)); return GetFormatterFunctionContent(labelIndex, category, m_TextLimit.GetLimitContent(content));
} }
} }
public override string GetFormatterContent(int labelIndex, double value, double minValue, double maxValue, bool isLog = false) public override string GetFormatterContent(int labelIndex, int totalIndex, double value, double minValue, double maxValue, bool isLog = false)
{ {
if (showAsPositiveNumber && value < 0) if (showAsPositiveNumber && value < 0)
{ {
value = Math.Abs(value); value = Math.Abs(value);
} }
return base.GetFormatterContent(labelIndex, value, minValue, maxValue, isLog); return base.GetFormatterContent(labelIndex, totalIndex, value, minValue, maxValue, isLog);
} }
public bool IsNeedShowLabel(int index, int total) public bool IsNeedShowLabel(int index, int total)

View File

@@ -37,6 +37,7 @@ namespace XCharts.Runtime
label.SetActive(comment.show && item.show, true); label.SetActive(comment.show && item.show, true);
label.SetPosition(labelPos); label.SetPosition(labelPos);
label.text.SetLocalPosition(labelStyle.offset); label.text.SetLocalPosition(labelStyle.offset);
item.labelObject = label;
} }
}; };
comment.refreshComponent(); comment.refreshComponent();

View File

@@ -17,6 +17,8 @@ namespace XCharts.Runtime
[SerializeField] private LabelStyle m_LabelStyle = new LabelStyle() { show = false }; [SerializeField] private LabelStyle m_LabelStyle = new LabelStyle() { show = false };
[SerializeField][Since("v3.5.0")] private Location m_Location = new Location() { align = Location.Align.TopLeft, top = 0.125f }; [SerializeField][Since("v3.5.0")] private Location m_Location = new Location() { align = Location.Align.TopLeft, top = 0.125f };
public ChartLabel labelObject { get; set; }
/// <summary> /// <summary>
/// Set this to false to prevent this comment item from showing. /// Set this to false to prevent this comment item from showing.
@@ -27,7 +29,18 @@ namespace XCharts.Runtime
/// content of comment. /// content of comment.
/// ||注解的文本内容。支持模板参数可以参考Tooltip的itemFormatter。 /// ||注解的文本内容。支持模板参数可以参考Tooltip的itemFormatter。
/// </summary> /// </summary>
public string content { get { return m_Content; } set { if (PropertyUtil.SetClass(ref m_Content, value)) SetComponentDirty(); } } public string content
{
get { return m_Content; }
set
{
if (PropertyUtil.SetClass(ref m_Content, value))
{
if (labelObject != null) labelObject.SetText(value);
else SetComponentDirty();
}
}
}
/// <summary> /// <summary>
/// the mark rect of comment. /// the mark rect of comment.
/// ||注解区域。 /// ||注解区域。

View File

@@ -131,7 +131,8 @@ namespace XCharts.Runtime
/// `{g}` : indicates the total number of data. <br /> /// `{g}` : indicates the total number of data. <br />
/// `{h}` : hexadecimal color value. <br /> /// `{h}` : hexadecimal color value. <br />
/// `{y}` : category value of y axis. <br /> /// `{y}` : category value of y axis. <br />
/// `{value}` : The value of the axis or legend. <br /> /// `{value}` : the value of the axis or legend. <br />
/// `{index}` : the index of the axis. <br />
/// The following placeholder apply to `UITable` components: <br /> /// The following placeholder apply to `UITable` components: <br />
/// `{name}` : indicates the row name of the table. <br /> /// `{name}` : indicates the row name of the table. <br />
/// `{index}` : indicates the row number of the table. <br /> /// `{index}` : indicates the row number of the table. <br />
@@ -161,6 +162,7 @@ namespace XCharts.Runtime
/// `{h}`:十六进制颜色值。<br/> /// `{h}`:十六进制颜色值。<br/>
/// `{y}`Y轴的类目名。<br/> /// `{y}`Y轴的类目名。<br/>
/// `{value}`:坐标轴或图例的值。<br/> /// `{value}`:坐标轴或图例的值。<br/>
/// `{index}`:坐标轴编号。<br/>
/// 以下通配符适用UITable组件<br/> /// 以下通配符适用UITable组件<br/>
/// `{name}` 表格的行名。<br/> /// `{name}` 表格的行名。<br/>
/// `{index}`:表格的行号。<br/> /// `{index}`:表格的行号。<br/>
@@ -398,7 +400,7 @@ namespace XCharts.Runtime
m_TextStyle.Copy(label.m_TextStyle); m_TextStyle.Copy(label.m_TextStyle);
} }
public virtual string GetFormatterContent(int labelIndex, string category) public virtual string GetFormatterContent(int labelIndex, int totalIndex, string category)
{ {
if (string.IsNullOrEmpty(category)) if (string.IsNullOrEmpty(category))
return GetFormatterFunctionContent(labelIndex, category, category); return GetFormatterFunctionContent(labelIndex, category, category);
@@ -410,12 +412,12 @@ namespace XCharts.Runtime
else else
{ {
var content = m_Formatter; var content = m_Formatter;
FormatterHelper.ReplaceAxisLabelContent(ref content, category); FormatterHelper.ReplaceAxisLabelContent(ref content, category, labelIndex, totalIndex);
return GetFormatterFunctionContent(labelIndex, category, category); return GetFormatterFunctionContent(labelIndex, category, category);
} }
} }
public virtual string GetFormatterContent(int labelIndex, double value, double minValue, double maxValue, bool isLog = false) public virtual string GetFormatterContent(int labelIndex, int totalIndex, double value, double minValue, double maxValue, bool isLog = false)
{ {
var newNumericFormatter = numericFormatter; var newNumericFormatter = numericFormatter;
if (value == 0 && !DateTimeUtil.IsDateOrTimeRegex(newNumericFormatter)) if (value == 0 && !DateTimeUtil.IsDateOrTimeRegex(newNumericFormatter))
@@ -452,14 +454,14 @@ namespace XCharts.Runtime
else else
{ {
var content = m_Formatter; var content = m_Formatter;
FormatterHelper.ReplaceAxisLabelContent(ref content, newNumericFormatter, value); FormatterHelper.ReplaceAxisLabelContent(ref content, newNumericFormatter, value, labelIndex, totalIndex);
return GetFormatterFunctionContent(labelIndex, value, content); return GetFormatterFunctionContent(labelIndex, value, content);
} }
} }
private static bool isDateFormatter = false; private static bool isDateFormatter = false;
private static string newFormatter = null; private static string newFormatter = null;
public string GetFormatterDateTime(int labelIndex, double value, double minValue, double maxValue) public string GetFormatterDateTime(int labelIndex, int totalIndex, double value, double minValue, double maxValue)
{ {
var timestamp = (int)value; var timestamp = (int)value;
var dateTime = DateTimeUtil.GetDateTime(timestamp); var dateTime = DateTimeUtil.GetDateTime(timestamp);
@@ -492,7 +494,7 @@ namespace XCharts.Runtime
if (!string.IsNullOrEmpty(m_Formatter)) if (!string.IsNullOrEmpty(m_Formatter))
{ {
var content = m_Formatter; var content = m_Formatter;
FormatterHelper.ReplaceAxisLabelContent(ref content, dateString); FormatterHelper.ReplaceAxisLabelContent(ref content, dateString, labelIndex, totalIndex);
return GetFormatterFunctionContent(labelIndex, value, content); return GetFormatterFunctionContent(labelIndex, value, content);
} }
else else

View File

@@ -464,16 +464,16 @@ namespace XCharts.Runtime
indicatorList.Clear(); indicatorList.Clear();
} }
public string GetFormatterIndicatorContent(int indicatorIndex) public string GetFormatterIndicatorContent(int indicatorIndex, int totalIndex)
{ {
var indicator = GetIndicator(indicatorIndex); var indicator = GetIndicator(indicatorIndex);
if (indicator == null) if (indicator == null)
return string.Empty; return string.Empty;
else else
return GetFormatterIndicatorContent(indicator.name); return GetFormatterIndicatorContent(indicator.name, indicatorIndex, totalIndex);
} }
public string GetFormatterIndicatorContent(string indicatorName) public string GetFormatterIndicatorContent(string indicatorName, int index, int totalIndex)
{ {
if (string.IsNullOrEmpty(indicatorName)) if (string.IsNullOrEmpty(indicatorName))
return indicatorName; return indicatorName;
@@ -485,7 +485,7 @@ namespace XCharts.Runtime
else else
{ {
var content = m_AxisName.labelStyle.formatter; var content = m_AxisName.labelStyle.formatter;
FormatterHelper.ReplaceAxisLabelContent(ref content, indicatorName); FormatterHelper.ReplaceAxisLabelContent(ref content, indicatorName, index, totalIndex);
return content; return content;
} }
} }

View File

@@ -50,9 +50,9 @@ namespace XCharts.Runtime
var indicator = radar.indicatorList[i]; var indicator = radar.indicatorList[i];
var pos = radar.GetIndicatorPosition(i); var pos = radar.GetIndicatorPosition(i);
var objName = INDICATOR_TEXT + "_" + i; var objName = INDICATOR_TEXT + "_" + i;
var content = radar.GetFormatterIndicatorContent(i, radar.indicatorList.Count);
var label = ChartHelper.AddChartLabel(objName, radarObject.transform, radar.axisName.labelStyle, var label = ChartHelper.AddChartLabel(objName, radarObject.transform, radar.axisName.labelStyle,
chart.theme.common, radar.GetFormatterIndicatorContent(i), Color.clear, TextAnchor.MiddleCenter); chart.theme.common, content, Color.clear, TextAnchor.MiddleCenter);
label.SetActive(radar.axisName.show && radar.indicator && radar.axisName.labelStyle.show, true); label.SetActive(radar.axisName.show && radar.indicator && radar.axisName.labelStyle.show, true);
AxisHelper.AdjustCircleLabelPos(label, pos, radar.context.center, txtHig, radar.axisName.labelStyle.offset); AxisHelper.AdjustCircleLabelPos(label, pos, radar.context.center, txtHig, radar.axisName.labelStyle.offset);
} }

View File

@@ -264,15 +264,15 @@ namespace XCharts.Runtime
var index = (int)axis.context.pointerValue; var index = (int)axis.context.pointerValue;
var dataZoom = chart.GetDataZoomOfAxis(axis); var dataZoom = chart.GetDataZoomOfAxis(axis);
var category = axis.GetData(index, dataZoom); var category = axis.GetData(index, dataZoom);
label.SetText(axis.indicatorLabel.GetFormatterContent(index, category)); label.SetText(axis.indicatorLabel.GetFormatterContent(index, 0, category));
} }
else if (axis.IsTime()) else if (axis.IsTime())
{ {
label.SetText(axis.indicatorLabel.GetFormatterDateTime(0, axis.context.pointerValue, axis.context.minValue, axis.context.maxValue)); label.SetText(axis.indicatorLabel.GetFormatterDateTime(0, 0, axis.context.pointerValue, axis.context.minValue, axis.context.maxValue));
} }
else else
{ {
label.SetText(axis.indicatorLabel.GetFormatterContent(0, axis.context.pointerValue, axis.context.minValue, axis.context.maxValue, axis.IsLog())); label.SetText(axis.indicatorLabel.GetFormatterContent(0, 0, axis.context.pointerValue, axis.context.minValue, axis.context.maxValue, axis.IsLog()));
} }
var textColor = axis.axisLabel.textStyle.GetColor(chart.theme.axis.textColor); var textColor = axis.axisLabel.textStyle.GetColor(chart.theme.axis.textColor);
if (ChartHelper.IsClearColor(axis.indicatorLabel.background.color)) if (ChartHelper.IsClearColor(axis.indicatorLabel.background.color))
@@ -356,6 +356,7 @@ namespace XCharts.Runtime
if (isTriggerAxis) if (isTriggerAxis)
{ {
var index = serie.context.dataZoomStartIndex + (int)yAxis.context.pointerValue; var index = serie.context.dataZoomStartIndex + (int)yAxis.context.pointerValue;
if(serie.useSortData) index = yAxis.context.sortedDataIndices[index];
serie.context.pointerEnter = true; serie.context.pointerEnter = true;
serie.context.pointerAxisDataIndexs.Add(index); serie.context.pointerAxisDataIndexs.Add(index);
serie.context.pointerItemDataIndex = index; serie.context.pointerItemDataIndex = index;
@@ -375,6 +376,7 @@ namespace XCharts.Runtime
if (isTriggerAxis) if (isTriggerAxis)
{ {
var index = serie.context.dataZoomStartIndex + (int)xAxis.context.pointerValue; var index = serie.context.dataZoomStartIndex + (int)xAxis.context.pointerValue;
if(serie.useSortData) index = xAxis.context.sortedDataIndices[index];
if (chart.isTriggerOnClick) if (chart.isTriggerOnClick)
{ {
if (serie.insertDataToHead) if (serie.insertDataToHead)
@@ -452,7 +454,7 @@ namespace XCharts.Runtime
var dataCount = serie.dataCount; var dataCount = serie.dataCount;
var themeSymbolSize = chart.theme.serie.scatterSymbolSize; var themeSymbolSize = chart.theme.serie.scatterSymbolSize;
var data = serie.data; var data = serie.data;
if (!isTimeAxis) if (!isTimeAxis)// || serie.useSortData)
{ {
serie.context.sortedData.Clear(); serie.context.sortedData.Clear();
for (int i = 0; i < dataCount; i++) for (int i = 0; i < dataCount; i++)
@@ -641,7 +643,6 @@ namespace XCharts.Runtime
private bool GetAxisCategory(int gridIndex, ref int dataIndex, ref string category, ref int timestamp, ref double axisRange) private bool GetAxisCategory(int gridIndex, ref int dataIndex, ref string category, ref int timestamp, ref double axisRange)
{ {
var needSort = chart.HasRealtimeSortSerie();
foreach (var component in chart.components) foreach (var component in chart.components)
{ {
if (component is Axis) if (component is Axis)
@@ -654,12 +655,7 @@ namespace XCharts.Runtime
dataIndex = double.IsNaN(axis.context.pointerValue) dataIndex = double.IsNaN(axis.context.pointerValue)
? axis.context.dataZoomStartIndex ? axis.context.dataZoomStartIndex
: (int)axis.context.axisTooltipValue; : (int)axis.context.axisTooltipValue;
int axisIndex = dataIndex; category = axis.GetData(dataIndex);
if (needSort && axisIndex < axis.context.sortedDataIndices.Count)
{
axisIndex = axis.context.sortedDataIndices[axisIndex];
}
category = axis.GetData(axisIndex);
return true; return true;
} }
else if (axis.IsTime()) else if (axis.IsTime())

View File

@@ -18,6 +18,7 @@ namespace XCharts.Runtime
private static Regex s_RegexSubForAxisLabel = new Regex(@"(value)|([c-g|x|p|r]\d*)", RegexOptions.IgnoreCase); private static Regex s_RegexSubForAxisLabel = new Regex(@"(value)|([c-g|x|p|r]\d*)", RegexOptions.IgnoreCase);
private static Regex s_RegexForSerieLabel = new Regex(@"{[a-h|\.|y]\d*(:[c-g|x|p|r]\d*)?}", RegexOptions.IgnoreCase); private static Regex s_RegexForSerieLabel = new Regex(@"{[a-h|\.|y]\d*(:[c-g|x|p|r]\d*)?}", RegexOptions.IgnoreCase);
private static Regex s_RegexSubForSerieLabel = new Regex(@"(\.)|([a-h|y]\d*)|([c-g|x|p|r]\d*)", RegexOptions.IgnoreCase); private static Regex s_RegexSubForSerieLabel = new Regex(@"(\.)|([a-h|y]\d*)|([c-g|x|p|r]\d*)", RegexOptions.IgnoreCase);
private static Regex s_RegexForAxisIndex = new Regex(@"\{(-?)index([+-]\d+)?\}", RegexOptions.IgnoreCase);
public static bool NeedFormat(string content) public static bool NeedFormat(string content)
{ {
@@ -334,7 +335,7 @@ namespace XCharts.Runtime
return s_RegexNewLine.Replace(content.Trim(), PH_NN); return s_RegexNewLine.Replace(content.Trim(), PH_NN);
} }
public static void ReplaceAxisLabelContent(ref string content, string numericFormatter, double value) public static void ReplaceAxisLabelContent(ref string content, string numericFormatter, double value, int index, int totalIndex)
{ {
var mc = s_RegexForAxisLabel.Matches(content); var mc = s_RegexForAxisLabel.Matches(content);
foreach (var m in mc) foreach (var m in mc)
@@ -349,10 +350,11 @@ namespace XCharts.Runtime
} }
content = content.Replace(old, ChartCached.FloatToStr(value, numericFormatter)); content = content.Replace(old, ChartCached.FloatToStr(value, numericFormatter));
} }
ReplaceIndexContent(ref content, index, totalIndex);
content = TrimAndReplaceLine(content); content = TrimAndReplaceLine(content);
} }
public static void ReplaceAxisLabelContent(ref string content, string value) public static void ReplaceAxisLabelContent(ref string content, string value, int index, int totalIndex)
{ {
var mc = s_RegexForAxisLabel.Matches(content); var mc = s_RegexForAxisLabel.Matches(content);
foreach (var m in mc) foreach (var m in mc)
@@ -363,8 +365,26 @@ namespace XCharts.Runtime
if (argsCount <= 0) continue; if (argsCount <= 0) continue;
content = content.Replace(old, value); content = content.Replace(old, value);
} }
ReplaceIndexContent(ref content, index, totalIndex);
content = TrimAndReplaceLine(content); content = TrimAndReplaceLine(content);
} }
public static void ReplaceIndexContent(ref string content, int currIndex, int totalIndex)
{
if (totalIndex <= 0) return;
content = s_RegexForAxisIndex.Replace(content, (match) =>
{
bool isNegative = match.Groups[1].Value == "-";
int offset = 0;
int parsedOffset = 0;
if (match.Groups[2].Success &&
int.TryParse(match.Groups[2].Value, out parsedOffset))
{
offset = parsedOffset;
}
int baseValue = isNegative ? totalIndex - currIndex : currIndex + 1;
return (baseValue + offset).ToString();
});
}
} }
} }

View File

@@ -111,6 +111,16 @@ namespace XCharts.Runtime
return false; return false;
} }
public Serie GetRealtimeSortSerie()
{
foreach (var serie in m_Series)
{
if (serie.useSortData)
return serie;
}
return null;
}
public T GetSerie<T>() where T : Serie public T GetSerie<T>() where T : Serie
{ {
foreach (var serie in m_Series) foreach (var serie in m_Series)

View File

@@ -167,7 +167,7 @@ namespace XCharts.Runtime
} }
var dataZoom = chart.GetDataZoomOfAxis(axis); var dataZoom = chart.GetDataZoomOfAxis(axis);
var showData = serie.GetDataList(dataZoom); var showData = serie.GetDataList(dataZoom, true);
if (showData.Count <= 0) if (showData.Count <= 0)
return; return;

View File

@@ -1750,7 +1750,7 @@ namespace XCharts.Runtime
/// </summary> /// </summary>
/// <param name="dataZoom"></param> /// <param name="dataZoom"></param>
/// <returns></returns> /// <returns></returns>
public List<SerieData> GetDataList(DataZoom dataZoom = null) public List<SerieData> GetDataList(DataZoom dataZoom = null, bool sorted = false)
{ {
if (dataZoom != null && dataZoom.enable && if (dataZoom != null && dataZoom.enable &&
(dataZoom.IsContainsXAxis(xAxisIndex) || dataZoom.IsContainsYAxis(yAxisIndex))) (dataZoom.IsContainsXAxis(xAxisIndex) || dataZoom.IsContainsYAxis(yAxisIndex)))
@@ -1760,7 +1760,7 @@ namespace XCharts.Runtime
} }
else else
{ {
return useSortData && context.sortedData.Count > 0 ? context.sortedData : m_Data; return useSortData && sorted && context.sortedData.Count > 0 ? context.sortedData : m_Data;
} }
} }

View File

@@ -59,6 +59,7 @@ namespace XCharts.Runtime
public ChartLabel labelObject { get; set; } public ChartLabel labelObject { get; set; }
public ChartLabel titleObject { get; set; } public ChartLabel titleObject { get; set; }
public int sortIndex { get; set; }
private bool m_Show = true; private bool m_Show = true;
/// <summary> /// <summary>

View File

@@ -955,6 +955,10 @@ namespace XCharts.Runtime
public static void UpdateSerieRuntimeFilterData(Serie serie, bool filterInvisible = true) public static void UpdateSerieRuntimeFilterData(Serie serie, bool filterInvisible = true)
{ {
var realtimeData = true;
var dataChangeDuration = serie.animation.GetChangeDuration();
var dataAddDuration = serie.animation.GetAdditionDuration();
var unscaledTime = serie.animation.unscaledTime;
serie.context.sortedData.Clear(); serie.context.sortedData.Clear();
foreach (var serieData in serie.data) foreach (var serieData in serie.data)
{ {
@@ -966,8 +970,12 @@ namespace XCharts.Runtime
case SerieDataSortType.Ascending: case SerieDataSortType.Ascending:
serie.context.sortedData.Sort(delegate (SerieData data1, SerieData data2) serie.context.sortedData.Sort(delegate (SerieData data1, SerieData data2)
{ {
var value1 = data1.GetData(1); var value1 = realtimeData ?
var value2 = data2.GetData(1); data1.GetCurrData(1, dataAddDuration, dataChangeDuration, false, 0, 0, unscaledTime) :
data1.GetData(1);
var value2 = realtimeData ?
data2.GetCurrData(1, dataAddDuration, dataChangeDuration, false, 0, 0, unscaledTime) :
data2.GetData(1);
if (value1 == value2) return 0; if (value1 == value2) return 0;
else if (value1 > value2) return 1; else if (value1 > value2) return 1;
else return -1; else return -1;
@@ -976,8 +984,12 @@ namespace XCharts.Runtime
case SerieDataSortType.Descending: case SerieDataSortType.Descending:
serie.context.sortedData.Sort(delegate (SerieData data1, SerieData data2) serie.context.sortedData.Sort(delegate (SerieData data1, SerieData data2)
{ {
var value1 = data1.GetData(1); var value1 = realtimeData ?
var value2 = data2.GetData(1); data1.GetCurrData(1, dataAddDuration, dataChangeDuration, false, 0, 0, unscaledTime) :
data1.GetData(1);
var value2 = realtimeData ?
data2.GetCurrData(1, dataAddDuration, dataChangeDuration, false, 0, 0, unscaledTime) :
data2.GetData(1);
if (value1 == value2) return 0; if (value1 == value2) return 0;
else if (value1 > value2) return -1; else if (value1 > value2) return -1;
else return 1; else return 1;
@@ -986,6 +998,10 @@ namespace XCharts.Runtime
case SerieDataSortType.None: case SerieDataSortType.None:
break; break;
} }
for (int i = 0; i < serie.context.sortedData.Count; i++)
{
serie.context.sortedData[i].sortIndex = i;
}
} }
public static T CloneSerie<T>(Serie serie) where T : Serie public static T CloneSerie<T>(Serie serie) where T : Serie