增加CandlestickChartK线图 #124

This commit is contained in:
monitor1394
2021-03-10 13:03:36 +08:00
parent 0eeacdebe7
commit 555e6d47ca
28 changed files with 708 additions and 22 deletions

View File

@@ -175,6 +175,9 @@ namespace XCharts
case SerieType.Heatmap:
DrawHeatmapSerie(vh, colorIndex, serie);
break;
case SerieType.Candlestick:
DrawCandlestickSerie(vh, colorIndex, serie);
break;
}
}
@@ -846,7 +849,7 @@ namespace XCharts
if (dataZoom != null && dataZoom.enable)
{
if (axis is XAxis) dataZoom.SetXAxisIndexValueInfo(axisIndex, tempMinValue, tempMaxValue);
else dataZoom.SetXAxisIndexValueInfo(axisIndex, tempMinValue, tempMaxValue);
else dataZoom.SetYAxisIndexValueInfo(axisIndex, tempMinValue, tempMaxValue);
}
if (updateChart)
{

View File

@@ -587,7 +587,7 @@ namespace XCharts
for (int i = 0; i < m_Series.Count; i++)
{
var serie = m_Series.list[i];
if (serie.type == SerieType.Bar)
if (serie.type == SerieType.Bar || serie.type == SerieType.Candlestick)
{
if (serie.barGap != 0)
{
@@ -625,7 +625,8 @@ namespace XCharts
for (int i = 0; i < m_Series.Count; i++)
{
var serie = m_Series.list[i];
if (serie.type == SerieType.Bar && serie.show)
if (!serie.show) continue;
if (serie.type == SerieType.Bar || serie.type == SerieType.Candlestick)
{
if (!string.IsNullOrEmpty(serie.stack))
{
@@ -656,7 +657,8 @@ namespace XCharts
for (int i = 0; i < m_Series.Count; i++)
{
var serie = m_Series.list[i];
if (serie.type == SerieType.Bar && serie.show && now.stack.Equals(serie.stack))
if ((serie.type == SerieType.Bar && serie.type == SerieType.Candlestick)
&& serie.show && now.stack.Equals(serie.stack))
{
if (serie.barWidth > barWidth) barWidth = serie.barWidth;
}

View File

@@ -0,0 +1,150 @@
/************************************************/
/* */
/* Copyright (c) 2018 - 2021 monitor1394 */
/* https://github.com/monitor1394 */
/* */
/************************************************/
using UnityEngine;
using UnityEngine.UI;
using XUGL;
namespace XCharts
{
public partial class CoordinateChart
{
protected void DrawCandlestickSerie(VertexHelper vh, int colorIndex, Serie serie)
{
if (!IsActive(serie.index)) return;
if (serie.animation.HasFadeOut()) return;
var showData = serie.GetDataList(dataZoom);
var yAxis = m_YAxes[serie.yAxisIndex];
var xAxis = m_XAxes[serie.xAxisIndex];
var grid = GetSerieGridOrDefault(serie);
float categoryWidth = AxisHelper.GetDataWidth(xAxis, grid.runtimeWidth, showData.Count, dataZoom);
float barGap = GetBarGap();
float totalBarWidth = GetBarTotalWidth(categoryWidth, barGap);
float barWidth = serie.GetBarWidth(categoryWidth);
float offset = (categoryWidth - totalBarWidth) / 2;
float barGapWidth = barWidth + barWidth * barGap;
float space = serie.barGap == -1 ? offset : offset + GetBarIndex(serie) * barGapWidth;
int maxCount = serie.maxShow > 0
? (serie.maxShow > showData.Count ? showData.Count : serie.maxShow)
: showData.Count;
bool dataChanging = false;
float dataChangeDuration = serie.animation.GetUpdateAnimationDuration();
float yMinValue = yAxis.GetCurrMinValue(dataChangeDuration);
float yMaxValue = yAxis.GetCurrMaxValue(dataChangeDuration);
var isAllBarEnd = true;
var isYAxis = false;
for (int i = serie.minShow; i < maxCount; i++)
{
var serieData = showData[i];
if (serie.IsIgnoreValue(serieData.GetData(1)))
{
serie.dataPoints.Add(Vector3.zero);
continue;
}
var highlight = (tooltip.show && tooltip.IsSelected(i))
|| serie.data[i].highlighted
|| serie.highlighted;
var itemStyle = SerieHelper.GetItemStyle(serie, serieData, highlight);
var open = serieData.GetCurrData(0, dataChangeDuration, yAxis.inverse, yMinValue, yMaxValue);
var close = serieData.GetCurrData(1, dataChangeDuration, yAxis.inverse, yMinValue, yMaxValue);
var lowest = serieData.GetCurrData(2, dataChangeDuration, yAxis.inverse, yMinValue, yMaxValue);
var heighest = serieData.GetCurrData(3, dataChangeDuration, yAxis.inverse, yMinValue, yMaxValue);
var isRise = close > open;
var borderWidth = open == 0 ? 0f
: (itemStyle.runtimeBorderWidth == 0 ? m_Theme.serie.candlestickBorderWidth
: itemStyle.runtimeBorderWidth);
if (serieData.IsDataChanged()) dataChanging = true;
float pX = grid.runtimeX + i * categoryWidth;
float zeroY = grid.runtimeY + yAxis.runtimeZeroYOffset;
if (!xAxis.boundaryGap) pX -= categoryWidth / 2;
float pY = zeroY;
var barHig = 0f;
var valueTotal = yMaxValue - yMinValue;
var minCut = (yMinValue > 0 ? yMinValue : 0);
if (valueTotal != 0)
{
barHig = (close - open) / valueTotal * grid.runtimeHeight;
pY += (open - minCut) / valueTotal * grid.runtimeHeight;
}
serieData.runtimeStackHig = barHig;
var isBarEnd = false;
float currHig = CheckAnimation(serie, i, barHig, out isBarEnd);
if (!isBarEnd) isAllBarEnd = false;
Vector3 plb, plt, prt, prb, top;
plb = new Vector3(pX + space + borderWidth, pY + borderWidth);
plt = new Vector3(pX + space + borderWidth, pY + currHig - borderWidth);
prt = new Vector3(pX + space + barWidth - borderWidth, pY + currHig - borderWidth);
prb = new Vector3(pX + space + barWidth - borderWidth, pY + borderWidth);
top = new Vector3(pX + space + barWidth / 2, pY + currHig - borderWidth);
if (serie.clip)
{
plb = ClampInGrid(grid, plb);
plt = ClampInGrid(grid, plt);
prt = ClampInGrid(grid, prt);
prb = ClampInGrid(grid, prb);
top = ClampInGrid(grid, top);
}
serie.dataPoints.Add(top);
var areaColor = isRise
? itemStyle.GetColor(m_Theme.serie.candlestickColor)
: itemStyle.GetColor0(m_Theme.serie.candlestickColor0);
var borderColor = isRise
? itemStyle.GetBorderColor(m_Theme.serie.candlestickBorderColor)
: itemStyle.GetBorderColor0(m_Theme.serie.candlestickBorderColor0);
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 + (lowest - minCut) / valueTotal * grid.runtimeHeight);
var heighPos = new Vector3(center.x, zeroY + (heighest - minCut) / valueTotal * grid.runtimeHeight);
var openCenterPos = new Vector3(center.x, prb.y);
var closeCenterPos = new Vector3(center.x, prt.y);
if (barWidth > 2f * borderWidth)
{
if (itemWidth > 0 && itemHeight > 0)
{
if (ItemStyleHelper.IsNeedCorner(itemStyle))
{
UGL.DrawRoundRectangle(vh, center, itemWidth, itemHeight, areaColor, areaColor, 0,
itemStyle.cornerRadius, isYAxis, 0.5f);
}
else
{
CheckClipAndDrawPolygon(vh, ref prb, ref plb, ref plt, ref prt, areaColor, areaColor,
serie.clip, grid);
}
UGL.DrawBorder(vh, center, itemWidth, itemHeight, 2 * borderWidth, borderColor, 0,
itemStyle.cornerRadius, isYAxis, 0.5f);
}
}
else
{
UGL.DrawLine(vh, openCenterPos, closeCenterPos, Mathf.Max(borderWidth, barWidth / 2), borderColor);
}
if (isRise)
{
UGL.DrawLine(vh, openCenterPos, lowPos, borderWidth, borderColor);
UGL.DrawLine(vh, closeCenterPos, heighPos, borderWidth, borderColor);
}
else
{
UGL.DrawLine(vh, closeCenterPos, lowPos, borderWidth, borderColor);
UGL.DrawLine(vh, openCenterPos, heighPos, borderWidth, borderColor);
}
}
if (isAllBarEnd)
{
serie.animation.AllBarEnd();
}
if (dataChanging)
{
RefreshPainter(serie);
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c404a9bbfdf51409e808fb354c438ca2
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -454,9 +454,19 @@ namespace XCharts
var showData = serie.GetDataList(dataZoom);
foreach (var data in showData)
{
var currData = data.GetData(yValue ? 1 : 0, inverse);
if (currData > max) max = currData;
if (currData < min) min = currData;
if (serie.type == SerieType.Candlestick)
{
var dataMin = data.min;
var dataMax = data.max;
if (dataMax > max) max = dataMax;
if (dataMin < min) min = dataMin;
}
else
{
var currData = data.GetData(yValue ? 1 : 0, inverse);
if (currData > max) max = currData;
if (currData < min) min = currData;
}
}
}
}
@@ -488,7 +498,15 @@ namespace XCharts
{
if (!_serieTotalValueForMinMax.ContainsKey(j))
_serieTotalValueForMinMax[j] = 0;
var currData = (yValue ? showData[j].GetData(1) : showData[j].GetData(0));
var currData = 0f;
if (serie.type == SerieType.Candlestick)
{
currData = showData[j].max;
}
else
{
currData = yValue ? showData[j].GetData(1) : showData[j].GetData(0);
}
if (inverse) currData = -currData;
_serieTotalValueForMinMax[j] = _serieTotalValueForMinMax[j] + currData;
}

View File

@@ -210,9 +210,25 @@ namespace XCharts
{
var valueTxt = isIngore ? tooltip.ignoreDataDefaultContent :
ChartCached.FloatToStr(yValue, numericFormatter);
sb.Append("<color=#").Append(theme.GetColorStr(serie.index)).Append(">● </color>")
.Append(key).Append(!string.IsNullOrEmpty(key) ? " : " : "")
.Append(valueTxt);
sb.Append("<color=#").Append(theme.GetColorStr(serie.index)).Append(">● </color>");
if (serie.type == SerieType.Candlestick)
{
sb.Append(key).Append(FormatterHelper.PH_NN);
var data = serieData.data;
var open = ChartCached.FloatToStr(data[0], numericFormatter);
var close = ChartCached.FloatToStr(data[1], numericFormatter);
var lowest = ChartCached.FloatToStr(data[2], numericFormatter);
var heighest = ChartCached.FloatToStr(data[3], numericFormatter);
sb.Append(" open: ").Append(open).Append(FormatterHelper.PH_NN);
sb.Append(" close: ").Append(close).Append(FormatterHelper.PH_NN);
sb.Append(" lowest: ").Append(lowest).Append(FormatterHelper.PH_NN);
sb.Append(" heighest: ").Append(heighest).Append(FormatterHelper.PH_NN);
}
else
{
sb.Append(key).Append(!string.IsNullOrEmpty(key) ? " : " : "");
sb.Append(valueTxt);
}
}
}
@@ -224,6 +240,7 @@ namespace XCharts
{
case SerieType.Line:
case SerieType.Bar:
case SerieType.Candlestick:
InitCoordinateTooltip(ref sb, tooltip, serie, index, theme, isCartesian, dataZoom);
break;
case SerieType.Scatter: