mirror of
https://github.com/XCharts-Team/XCharts.git
synced 2026-05-30 13:28:47 +00:00
优化Candlestick对时间轴的支持
This commit is contained in:
@@ -80,6 +80,7 @@ slug: /changelog
|
|||||||
|
|
||||||
## master
|
## master
|
||||||
|
|
||||||
|
* (2025.10.30) 优化`Candlestick`对时间轴的支持
|
||||||
* (2025.10.30) 增加`Scatter`的`ignore`支持设置忽略数据
|
* (2025.10.30) 增加`Scatter`的`ignore`支持设置忽略数据
|
||||||
* (2025.10.24) 优化`Sankey`的线条绘制排序
|
* (2025.10.24) 优化`Sankey`的线条绘制排序
|
||||||
* (2025.10.22) 增加`Pie`的`pieType`支持实心饼图和线框柄图 (#349)
|
* (2025.10.22) 增加`Pie`的`pieType`支持实心饼图和线框柄图 (#349)
|
||||||
|
|||||||
@@ -485,6 +485,7 @@ namespace XCharts.Runtime
|
|||||||
context.maxValue = 0;
|
context.maxValue = 0;
|
||||||
context.destMinValue = 0;
|
context.destMinValue = 0;
|
||||||
context.destMaxValue = 0;
|
context.destMaxValue = 0;
|
||||||
|
context.labelValueList.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Axis Clone()
|
public Axis Clone()
|
||||||
|
|||||||
@@ -364,7 +364,7 @@ namespace XCharts
|
|||||||
{
|
{
|
||||||
var lastCount = axis.context.labelValueList.Count;
|
var lastCount = axis.context.labelValueList.Count;
|
||||||
axis.context.tickValue = DateTimeUtil.UpdateTimeAxisDateTimeList(axis.context.labelValueList,
|
axis.context.tickValue = DateTimeUtil.UpdateTimeAxisDateTimeList(axis.context.labelValueList,
|
||||||
axis.context.minValue, axis.context.maxValue, axis.splitNumber);
|
axis.context.minValue, axis.context.maxValue, axis.splitNumber, axis.ceilRate);
|
||||||
|
|
||||||
if (axis.context.labelValueList.Count != lastCount)
|
if (axis.context.labelValueList.Count != lastCount)
|
||||||
axis.SetAllDirty();
|
axis.SetAllDirty();
|
||||||
|
|||||||
@@ -204,7 +204,7 @@ namespace XCharts.Runtime
|
|||||||
protected override void OnValidate()
|
protected override void OnValidate()
|
||||||
{
|
{
|
||||||
base.OnValidate();
|
base.OnValidate();
|
||||||
foreach (var handler in m_SerieHandlers) handler.ForceUpdateSerieContext();
|
ResetChartStatus();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -157,13 +157,13 @@ namespace XCharts.Runtime
|
|||||||
(itemStyle.borderWidth == 0 ? theme.serie.candlestickBorderWidth :
|
(itemStyle.borderWidth == 0 ? theme.serie.candlestickBorderWidth :
|
||||||
itemStyle.borderWidth);
|
itemStyle.borderWidth);
|
||||||
if (serieData.IsDataChanged()) dataChanging = true;
|
if (serieData.IsDataChanged()) dataChanging = true;
|
||||||
float pX = grid.context.x + i * categoryWidth;
|
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 zeroY = grid.context.y + yAxis.context.offset;
|
||||||
if (!xAxis.boundaryGap) pX -= categoryWidth / 2;
|
if (!xAxis.boundaryGap) pX -= categoryWidth / 2;
|
||||||
float pY = zeroY;
|
float pY = zeroY;
|
||||||
var barHig = 0f;
|
var barHig = 0f;
|
||||||
double valueTotal = yMaxValue - yMinValue;
|
double valueTotal = yMaxValue - yMinValue;
|
||||||
var minCut = (yMinValue > 0 ? yMinValue : 0);
|
var minCut = yMinValue > 0 ? yMinValue : 0;
|
||||||
if (valueTotal != 0)
|
if (valueTotal != 0)
|
||||||
{
|
{
|
||||||
barHig = (float)((close - open) / valueTotal * grid.context.height);
|
barHig = (float)((close - open) / valueTotal * grid.context.height);
|
||||||
|
|||||||
@@ -645,11 +645,12 @@ namespace XCharts.Runtime
|
|||||||
/// the maxinum value.
|
/// the maxinum value.
|
||||||
/// ||最大值。
|
/// ||最大值。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public double GetMaxData(bool inverse = false)
|
public double GetMaxData(bool inverse = false, int startDimensionIndex = 0)
|
||||||
{
|
{
|
||||||
if (m_Data.Count == 0) return 0;
|
if (m_Data.Count == 0) return 0;
|
||||||
var temp = double.MinValue;
|
var temp = double.MinValue;
|
||||||
for (int i = 0; i < m_Data.Count; i++)
|
if (startDimensionIndex < 0) startDimensionIndex = 0;
|
||||||
|
for (int i = startDimensionIndex; i < m_Data.Count; i++)
|
||||||
{
|
{
|
||||||
var value = GetData(i, inverse);
|
var value = GetData(i, inverse);
|
||||||
if (value > temp) temp = value;
|
if (value > temp) temp = value;
|
||||||
@@ -661,11 +662,12 @@ namespace XCharts.Runtime
|
|||||||
/// the mininum value.
|
/// the mininum value.
|
||||||
/// ||最小值。
|
/// ||最小值。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public double GetMinData(bool inverse = false)
|
public double GetMinData(bool inverse = false, int startDimensionIndex = 0)
|
||||||
{
|
{
|
||||||
if (m_Data.Count == 0) return 0;
|
if (m_Data.Count == 0) return 0;
|
||||||
var temp = double.MaxValue;
|
var temp = double.MaxValue;
|
||||||
for (int i = 0; i < m_Data.Count; i++)
|
if (startDimensionIndex < 0) startDimensionIndex = 0;
|
||||||
|
for (int i = startDimensionIndex; i < m_Data.Count; i++)
|
||||||
{
|
{
|
||||||
var value = GetData(i, inverse);
|
var value = GetData(i, inverse);
|
||||||
if (value < temp) temp = value;
|
if (value < temp) temp = value;
|
||||||
|
|||||||
@@ -384,7 +384,7 @@ namespace XCharts.Runtime
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
var showData = serie.GetDataList(filterByDataZoom ? chart.GetXDataZoomOfSerie(serie) : null);
|
var showData = serie.GetDataList(filterByDataZoom ? chart.GetXDataZoomOfSerie(serie) : null);
|
||||||
if (serie is Candlestick || serie is SimplifiedCandlestick)
|
if (dimension > 0 && (serie is Candlestick || serie is SimplifiedCandlestick))
|
||||||
{
|
{
|
||||||
foreach (var data in showData)
|
foreach (var data in showData)
|
||||||
{
|
{
|
||||||
@@ -441,9 +441,9 @@ namespace XCharts.Runtime
|
|||||||
if (!_serieTotalValueForMinMax.ContainsKey(j))
|
if (!_serieTotalValueForMinMax.ContainsKey(j))
|
||||||
_serieTotalValueForMinMax[j] = 0;
|
_serieTotalValueForMinMax[j] = 0;
|
||||||
double currData = 0;
|
double currData = 0;
|
||||||
if (serie is Candlestick)
|
if (serie is Candlestick || serie is SimplifiedCandlestick)
|
||||||
{
|
{
|
||||||
currData = showData[j].GetMaxData(false);
|
currData = showData[j].GetMaxData(false, dimension);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -83,15 +83,16 @@ namespace XCharts.Runtime
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static DateTime GetDateTime(double timestamp, bool local = true)
|
public static DateTime GetDateTime(double timestamp, bool local = false)
|
||||||
{
|
{
|
||||||
return local ? k_LocalDateTime1970.AddSeconds(timestamp) : k_DateTime1970.AddSeconds(timestamp);
|
var dateTime = local ? k_LocalDateTime1970.AddSeconds(timestamp) : k_DateTime1970.AddSeconds(timestamp);
|
||||||
|
return dateTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string GetDefaultDateTimeString(double timestamp, double range = 0)
|
public static string GetDefaultDateTimeString(double timestamp, double range = 0, bool local = false)
|
||||||
{
|
{
|
||||||
var dateString = String.Empty;
|
var dateString = String.Empty;
|
||||||
var dateTime = GetDateTime(timestamp);
|
var dateTime = GetDateTime(timestamp, local);
|
||||||
if (range <= 0 || range >= DateTimeUtil.ONE_DAY)
|
if (range <= 0 || range >= DateTimeUtil.ONE_DAY)
|
||||||
{
|
{
|
||||||
dateString = dateTime.ToString("yyyy-MM-dd");
|
dateString = dateTime.ToString("yyyy-MM-dd");
|
||||||
@@ -144,7 +145,7 @@ namespace XCharts.Runtime
|
|||||||
/// <param name="minTimestamp"></param>
|
/// <param name="minTimestamp"></param>
|
||||||
/// <param name="maxTimestamp"></param>
|
/// <param name="maxTimestamp"></param>
|
||||||
/// <param name="splitNumber"></param>
|
/// <param name="splitNumber"></param>
|
||||||
internal static float UpdateTimeAxisDateTimeList(List<double> list, double minTimestamp, double maxTimestamp, int splitNumber)
|
internal static float UpdateTimeAxisDateTimeList(List<double> list, double minTimestamp, double maxTimestamp, int splitNumber, double ceilRate)
|
||||||
{
|
{
|
||||||
var range = maxTimestamp - minTimestamp;
|
var range = maxTimestamp - minTimestamp;
|
||||||
if (range <= 0)
|
if (range <= 0)
|
||||||
@@ -152,61 +153,15 @@ namespace XCharts.Runtime
|
|||||||
list.Clear();
|
list.Clear();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
var dtMin = DateTimeUtil.GetDateTime(minTimestamp);
|
var dtMin = GetDateTime(minTimestamp);
|
||||||
var dtMax = DateTimeUtil.GetDateTime(maxTimestamp);
|
var dtMax = GetDateTime(maxTimestamp);
|
||||||
int tick = 0;
|
int tick;
|
||||||
if (range >= ONE_YEAR * MIN_TIME_SPLIT_NUMBER)
|
if (ceilRate != 0)
|
||||||
{
|
{
|
||||||
var num = splitNumber <= 0 ? GetSplitNumber(range, ONE_YEAR) : (int)Math.Max(range / (splitNumber * ONE_YEAR), 1);
|
var tickSecond = (int)ceilRate;
|
||||||
var dtStart = GetDateTime(GetFirstMaxValue(list, minTimestamp));
|
tick = GetTickSecond(range, 0, tickSecond);
|
||||||
dtStart = new DateTime(dtStart.Year, dtStart.Month, 1);
|
var let = minTimestamp % tickSecond;
|
||||||
while (dtStart > dtMin)
|
var defaultTimestamp = let == 0 ? minTimestamp : minTimestamp - let + tickSecond;
|
||||||
{
|
|
||||||
dtStart = dtStart.AddYears(-num);
|
|
||||||
}
|
|
||||||
if (dtStart < dtMin)
|
|
||||||
{
|
|
||||||
dtStart = dtStart.AddYears(num);
|
|
||||||
}
|
|
||||||
tick = num * 365 * 24 * 3600;
|
|
||||||
list.Clear();
|
|
||||||
while (dtStart.Ticks < dtMax.Ticks)
|
|
||||||
{
|
|
||||||
list.Add(DateTimeUtil.GetTimestamp(dtStart));
|
|
||||||
dtStart = dtStart.AddYears(num);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (range >= ONE_MONTH * MIN_TIME_SPLIT_NUMBER)
|
|
||||||
{
|
|
||||||
var num = splitNumber <= 0 ? GetSplitNumber(range, ONE_MONTH) : (int)Math.Max(range / (splitNumber * ONE_MONTH), 1);
|
|
||||||
var dtStart = GetDateTime(GetFirstMaxValue(list, minTimestamp));
|
|
||||||
dtStart = new DateTime(dtStart.Year, dtStart.Month, 1);
|
|
||||||
while (dtStart > dtMin)
|
|
||||||
{
|
|
||||||
dtStart = dtStart.AddMonths(-num);
|
|
||||||
}
|
|
||||||
if (dtStart < dtMin)
|
|
||||||
{
|
|
||||||
dtStart = dtStart.AddMonths(num);
|
|
||||||
}
|
|
||||||
tick = num * 30 * 24 * 3600;
|
|
||||||
list.Clear();
|
|
||||||
while (dtStart.Ticks < dtMax.Ticks)
|
|
||||||
{
|
|
||||||
list.Add(DateTimeUtil.GetTimestamp(dtStart));
|
|
||||||
dtStart = dtStart.AddMonths(num);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
int tickSecond;
|
|
||||||
if (range >= ONE_DAY * MIN_TIME_SPLIT_NUMBER) tickSecond = ONE_DAY;
|
|
||||||
else if (range >= ONE_HOUR * MIN_TIME_SPLIT_NUMBER) tickSecond = ONE_HOUR;
|
|
||||||
else if (range >= ONE_MINUTE * MIN_TIME_SPLIT_NUMBER) tickSecond = ONE_MINUTE;
|
|
||||||
else tickSecond = ONE_SECOND;
|
|
||||||
tick = GetTickSecond(range, splitNumber, tickSecond);
|
|
||||||
var let = minTimestamp % tick;
|
|
||||||
var defaultTimestamp = let == 0 ? minTimestamp : minTimestamp - let + tick;
|
|
||||||
var startTimestamp = (int)GetFirstMaxValue(list, minTimestamp, defaultTimestamp);
|
var startTimestamp = (int)GetFirstMaxValue(list, minTimestamp, defaultTimestamp);
|
||||||
while (startTimestamp > minTimestamp)
|
while (startTimestamp > minTimestamp)
|
||||||
{
|
{
|
||||||
@@ -219,6 +174,85 @@ namespace XCharts.Runtime
|
|||||||
list.Clear();
|
list.Clear();
|
||||||
AddTickTimestamp(list, startTimestamp, maxTimestamp, tick);
|
AddTickTimestamp(list, startTimestamp, maxTimestamp, tick);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (range >= ONE_YEAR * MIN_TIME_SPLIT_NUMBER)
|
||||||
|
{
|
||||||
|
var num = splitNumber <= 0 ? GetSplitNumber(range, ONE_YEAR) : (int)Math.Max(range / (splitNumber * ONE_YEAR), 1);
|
||||||
|
var dtStart = GetDateTime(GetFirstMaxValue(list, minTimestamp));
|
||||||
|
dtStart = new DateTime(dtStart.Year, dtStart.Month, 1);
|
||||||
|
while (dtStart > dtMin)
|
||||||
|
{
|
||||||
|
dtStart = dtStart.AddYears(-num);
|
||||||
|
}
|
||||||
|
if (dtStart < dtMin)
|
||||||
|
{
|
||||||
|
dtStart = dtStart.AddYears(num);
|
||||||
|
}
|
||||||
|
tick = num * 365 * 24 * 3600;
|
||||||
|
list.Clear();
|
||||||
|
while (dtStart.Ticks < dtMax.Ticks)
|
||||||
|
{
|
||||||
|
list.Add(DateTimeUtil.GetTimestamp(dtStart));
|
||||||
|
dtStart = dtStart.AddYears(num);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (range >= ONE_MONTH * MIN_TIME_SPLIT_NUMBER)
|
||||||
|
{
|
||||||
|
var num = splitNumber <= 0 ? GetSplitNumber(range, ONE_MONTH) : (int)Math.Max(range / (splitNumber * ONE_MONTH), 1);
|
||||||
|
var dtStart = GetDateTime(GetFirstMaxValue(list, minTimestamp));
|
||||||
|
dtStart = new DateTime(dtStart.Year, dtStart.Month, 1);
|
||||||
|
while (dtStart > dtMin)
|
||||||
|
{
|
||||||
|
dtStart = dtStart.AddMonths(-num);
|
||||||
|
}
|
||||||
|
if (dtStart < dtMin)
|
||||||
|
{
|
||||||
|
dtStart = dtStart.AddMonths(num);
|
||||||
|
}
|
||||||
|
tick = num * 30 * 24 * 3600;
|
||||||
|
list.Clear();
|
||||||
|
while (dtStart.Ticks < dtMax.Ticks)
|
||||||
|
{
|
||||||
|
list.Add(DateTimeUtil.GetTimestamp(dtStart));
|
||||||
|
dtStart = dtStart.AddMonths(num);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int tickSecond;
|
||||||
|
if (range >= ONE_DAY * MIN_TIME_SPLIT_NUMBER)
|
||||||
|
{
|
||||||
|
tickSecond = ONE_DAY;
|
||||||
|
}
|
||||||
|
else if (range >= ONE_HOUR * MIN_TIME_SPLIT_NUMBER)
|
||||||
|
{
|
||||||
|
tickSecond = ONE_HOUR;
|
||||||
|
}
|
||||||
|
else if (range >= ONE_MINUTE * MIN_TIME_SPLIT_NUMBER)
|
||||||
|
{
|
||||||
|
tickSecond = ONE_MINUTE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tickSecond = ONE_SECOND;
|
||||||
|
}
|
||||||
|
tick = GetTickSecond(range, splitNumber, tickSecond);
|
||||||
|
var let = minTimestamp % tickSecond;
|
||||||
|
var defaultTimestamp = let == 0 ? minTimestamp : minTimestamp - let + tickSecond;
|
||||||
|
var startTimestamp = (int)GetFirstMaxValue(list, minTimestamp, defaultTimestamp);
|
||||||
|
while (startTimestamp > minTimestamp)
|
||||||
|
{
|
||||||
|
startTimestamp -= tick;
|
||||||
|
}
|
||||||
|
if (startTimestamp < minTimestamp)
|
||||||
|
{
|
||||||
|
startTimestamp += tick;
|
||||||
|
}
|
||||||
|
list.Clear();
|
||||||
|
AddTickTimestamp(list, startTimestamp, maxTimestamp, tick);
|
||||||
|
}
|
||||||
|
}
|
||||||
return tick;
|
return tick;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user