mirror of
https://github.com/XCharts-Team/XCharts.git
synced 2026-05-17 14:00:12 +00:00
[feature][polar] support heatmap in polar
This commit is contained in:
@@ -58,6 +58,7 @@
|
||||
|
||||
## master
|
||||
|
||||
* (2022.09.20) 增加`PolarChart`对`Heatmap`热力图的支持
|
||||
* (2022.09.19) 增加`PolarChart`对多柱图和堆叠柱图的支持
|
||||
* (2022.09.16) 增加`PolarChart`对`Bar`柱图的支持
|
||||
* (2022.09.14) 增加`PolarCoord`可通过`radius`设置环形极坐标的支持
|
||||
|
||||
@@ -19,13 +19,20 @@ namespace XCharts.Editor
|
||||
PropertyField("m_YAxisIndex");
|
||||
}
|
||||
PropertyField("m_BarType");
|
||||
PropertyField("m_BarPercentStack");
|
||||
PropertyField("m_BarWidth");
|
||||
PropertyField("m_BarGap");
|
||||
if (serie.barType == BarType.Zebra)
|
||||
if (serie.IsUseCoord<PolarCoord>())
|
||||
{
|
||||
PropertyField("m_BarZebraWidth");
|
||||
PropertyField("m_BarZebraGap");
|
||||
PropertyField("m_RoundCap");
|
||||
}
|
||||
else
|
||||
{
|
||||
PropertyField("m_BarPercentStack");
|
||||
if (serie.barType == BarType.Zebra)
|
||||
{
|
||||
PropertyField("m_BarZebraWidth");
|
||||
PropertyField("m_BarZebraGap");
|
||||
}
|
||||
}
|
||||
PropertyField("m_Clip");
|
||||
PropertyFiledMore(() =>
|
||||
|
||||
@@ -7,6 +7,15 @@ namespace XCharts.Editor
|
||||
{
|
||||
public override void OnCustomInspectorGUI()
|
||||
{
|
||||
if (serie.IsUseCoord<PolarCoord>())
|
||||
{
|
||||
PropertyField("m_PolarIndex");
|
||||
}
|
||||
else
|
||||
{
|
||||
PropertyField("m_XAxisIndex");
|
||||
PropertyField("m_YAxisIndex");
|
||||
}
|
||||
PropertyField("m_HeatmapType");
|
||||
PropertyField("m_Ignore");
|
||||
PropertyField("m_IgnoreValue");
|
||||
|
||||
@@ -225,6 +225,10 @@ namespace XCharts.Runtime
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
iconType = Legend.Type.Rect;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -175,7 +175,7 @@ namespace XCharts.Runtime
|
||||
for (int n = 0; n < m_StackSerieData.Count - 1; n++)
|
||||
start += m_StackSerieData[n][i].context.stackHeight;
|
||||
}
|
||||
end = startAngle + m_AngleAxis.GetValueLength(angleValue, 360);
|
||||
end = start + m_AngleAxis.GetValueLength(angleValue, 360);
|
||||
serieData.context.stackHeight = end - start;
|
||||
inside = m_SeriePolar.context.insideRadius + categoryWidth * (float) radiusValue + gap;
|
||||
outside = inside + barWidth;
|
||||
|
||||
@@ -24,6 +24,7 @@ namespace XCharts.Runtime
|
||||
[SerieHandler(typeof(HeatmapHandler), true)]
|
||||
[DefaultAnimation(AnimationType.LeftToRight)]
|
||||
[RequireChartComponent(typeof(VisualMap))]
|
||||
[CoordOptions(typeof(GridCoord), typeof(PolarCoord))]
|
||||
[SerieExtraComponent(typeof(LabelStyle), typeof(EmphasisStyle), typeof(BlurStyle), typeof(SelectStyle))]
|
||||
[SerieDataExtraComponent(typeof(ItemStyle), typeof(LabelStyle), typeof(EmphasisStyle), typeof(BlurStyle), typeof(SelectStyle))]
|
||||
[SerieDataExtraField()]
|
||||
|
||||
202
Runtime/Serie/Heatmap/HeatmapHandler.PolarCoord.cs
Normal file
202
Runtime/Serie/Heatmap/HeatmapHandler.PolarCoord.cs
Normal file
@@ -0,0 +1,202 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using XUGL;
|
||||
|
||||
namespace XCharts.Runtime
|
||||
{
|
||||
/// <summary>
|
||||
/// For polar coord
|
||||
/// </summary>
|
||||
internal sealed partial class HeatmapHandler
|
||||
{
|
||||
private PolarCoord m_SeriePolar;
|
||||
|
||||
private void UpdateSeriePolarContext()
|
||||
{
|
||||
if (m_SeriePolar == null)
|
||||
return;
|
||||
|
||||
var needCheck = (chart.isPointerInChart && m_SeriePolar.IsPointerEnter()) || m_LegendEnter;
|
||||
var lineWidth = 0f;
|
||||
if (!needCheck)
|
||||
{
|
||||
if (m_LastCheckContextFlag != needCheck)
|
||||
{
|
||||
var needAnimation1 = false;
|
||||
lineWidth = serie.lineStyle.GetWidth(chart.theme.serie.lineWidth);
|
||||
m_LastCheckContextFlag = needCheck;
|
||||
serie.context.pointerItemDataIndex = -1;
|
||||
serie.context.pointerEnter = false;
|
||||
serie.interact.SetValue(ref needAnimation1, lineWidth, false);
|
||||
foreach (var serieData in serie.data)
|
||||
{
|
||||
var symbol = SerieHelper.GetSerieSymbol(serie, serieData);
|
||||
var symbolSize = symbol.GetSize(serieData.data, chart.theme.serie.lineSymbolSize);
|
||||
serieData.context.highlight = false;
|
||||
serieData.interact.SetValue(ref needAnimation1, symbolSize);
|
||||
}
|
||||
if (needAnimation1)
|
||||
{
|
||||
if (SeriesHelper.IsStack(chart.series))
|
||||
chart.RefreshTopPainter();
|
||||
else
|
||||
chart.RefreshPainter(serie);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
m_LastCheckContextFlag = needCheck;
|
||||
var themeSymbolSize = chart.theme.serie.lineSymbolSize;
|
||||
lineWidth = serie.lineStyle.GetWidth(chart.theme.serie.lineWidth);
|
||||
|
||||
var needInteract = false;
|
||||
if (m_LegendEnter)
|
||||
{
|
||||
serie.context.pointerEnter = true;
|
||||
serie.interact.SetValue(ref needInteract, lineWidth, true, chart.theme.serie.selectedRate);
|
||||
for (int i = 0; i < serie.dataCount; i++)
|
||||
{
|
||||
var serieData = serie.data[i];
|
||||
var size = SerieHelper.GetSysmbolSize(serie, serieData, chart.theme, themeSymbolSize, SerieState.Emphasis);
|
||||
serieData.context.highlight = true;
|
||||
serieData.interact.SetValue(ref needInteract, size);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
serie.context.pointerItemDataIndex = -1;
|
||||
serie.context.pointerEnter = false;
|
||||
var dir = chart.pointerPos - new Vector2(m_SeriePolar.context.center.x, m_SeriePolar.context.center.y);
|
||||
var pointerAngle = ChartHelper.GetAngle360(Vector2.up, dir);
|
||||
var pointerRadius = Vector2.Distance(chart.pointerPos, m_SeriePolar.context.center);
|
||||
Color32 color, toColor;
|
||||
for (int i = 0; i < serie.dataCount; i++)
|
||||
{
|
||||
var serieData = serie.data[i];
|
||||
if (pointerAngle >= serieData.context.startAngle &&
|
||||
pointerAngle < serieData.context.toAngle &&
|
||||
pointerRadius >= serieData.context.insideRadius &&
|
||||
pointerRadius < serieData.context.outsideRadius)
|
||||
{
|
||||
serie.context.pointerItemDataIndex = i;
|
||||
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)
|
||||
{
|
||||
if (SeriesHelper.IsStack(chart.series))
|
||||
chart.RefreshTopPainter();
|
||||
else
|
||||
chart.RefreshPainter(serie);
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawPolarHeatmap(VertexHelper vh, Serie serie)
|
||||
{
|
||||
var datas = serie.data;
|
||||
if (datas.Count <= 0)
|
||||
return;
|
||||
|
||||
m_SeriePolar = chart.GetChartComponent<PolarCoord>(serie.polarIndex);
|
||||
if (m_SeriePolar == null)
|
||||
return;
|
||||
|
||||
var m_AngleAxis = ComponentHelper.GetAngleAxis(chart.components, m_SeriePolar.index);
|
||||
var m_RadiusAxis = ComponentHelper.GetRadiusAxis(chart.components, m_SeriePolar.index);
|
||||
if (m_AngleAxis == null || m_RadiusAxis == null)
|
||||
return;
|
||||
var visualMap = chart.GetVisualMapOfSerie(serie);
|
||||
|
||||
var startAngle = m_AngleAxis.context.startAngle;
|
||||
var currDetailProgress = 0f;
|
||||
var totalDetailProgress = datas.Count;
|
||||
|
||||
var xCount = AxisHelper.GetTotalSplitGridNum(m_RadiusAxis);
|
||||
var yCount = AxisHelper.GetTotalSplitGridNum(m_AngleAxis);
|
||||
var xWidth = m_SeriePolar.context.radius / xCount;
|
||||
var yWidth = 360 / yCount;
|
||||
|
||||
serie.animation.InitProgress(currDetailProgress, totalDetailProgress);
|
||||
|
||||
var dimension = VisualMapHelper.GetDimension(visualMap, defaultDimension);
|
||||
if (visualMap.autoMinMax)
|
||||
{
|
||||
double maxValue, minValue;
|
||||
SerieHelper.GetMinMaxData(serie, dimension, out minValue, out maxValue);
|
||||
VisualMapHelper.SetMinMax(visualMap, minValue, maxValue);
|
||||
}
|
||||
var rangeMin = visualMap.rangeMin;
|
||||
var rangeMax = visualMap.rangeMax;
|
||||
var color = chart.theme.GetColor(serie.index);
|
||||
|
||||
float start, end;
|
||||
float inside, outside;
|
||||
double value, radiusValue, angleValue;
|
||||
for (int i = 0; i < datas.Count; i++)
|
||||
{
|
||||
if (serie.animation.CheckDetailBreak(i))
|
||||
break;
|
||||
var serieData = datas[i];
|
||||
var itemStyle = SerieHelper.GetItemStyle(serie, serieData);
|
||||
var borderWidth = itemStyle.borderWidth;
|
||||
var borderColor = itemStyle.borderColor;
|
||||
|
||||
radiusValue = serieData.GetData(0);
|
||||
angleValue = serieData.GetData(1);
|
||||
value = serieData.GetData(2);
|
||||
|
||||
var xIndex = AxisHelper.GetAxisValueSplitIndex(m_RadiusAxis, radiusValue, xCount);
|
||||
var yIndex = AxisHelper.GetAxisValueSplitIndex(m_AngleAxis, angleValue, yCount);
|
||||
|
||||
start = startAngle + yIndex * yWidth;
|
||||
end = start + yWidth;
|
||||
|
||||
inside = m_SeriePolar.context.insideRadius + xIndex * xWidth;
|
||||
outside = inside + xWidth;
|
||||
|
||||
serieData.context.startAngle = start;
|
||||
serieData.context.toAngle = end;
|
||||
serieData.context.halfAngle = (start + end) / 2;
|
||||
serieData.context.insideRadius = inside;
|
||||
serieData.context.outsideRadius = outside;
|
||||
|
||||
if ((value < rangeMin && rangeMin != visualMap.min) ||
|
||||
(value > rangeMax && rangeMax != visualMap.max))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (!visualMap.IsInSelectedValue(value)) continue;
|
||||
color = visualMap.GetColor(value);
|
||||
if (serieData.context.highlight)
|
||||
color = ChartHelper.GetHighlightColor(color);
|
||||
|
||||
var needRoundCap = serie.roundCap && inside > 0;
|
||||
|
||||
serieData.context.insideRadius = inside;
|
||||
serieData.context.outsideRadius = outside;
|
||||
serieData.context.areaCenter = m_SeriePolar.context.center;
|
||||
serieData.context.position = ChartHelper.GetPosition(m_SeriePolar.context.center, (start + end) / 2, (inside + outside) / 2);
|
||||
|
||||
UGL.DrawDoughnut(vh, m_SeriePolar.context.center, inside, outside, color, color,
|
||||
ColorUtil.clearColor32, start, end, borderWidth, borderColor, serie.gap / 2, chart.settings.cicleSmoothness,
|
||||
needRoundCap, true);
|
||||
}
|
||||
|
||||
if (!serie.animation.IsFinish())
|
||||
{
|
||||
serie.animation.CheckProgress(totalDetailProgress);
|
||||
serie.animation.CheckSymbol(serie.symbol.GetSize(null, chart.theme.serie.lineSymbolSize));
|
||||
chart.RefreshChart();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Runtime/Serie/Heatmap/HeatmapHandler.PolarCoord.cs.meta
Normal file
11
Runtime/Serie/Heatmap/HeatmapHandler.PolarCoord.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: baaa1d070b88a4b9bb7d1eed341041e0
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -6,7 +6,7 @@ using XUGL;
|
||||
namespace XCharts.Runtime
|
||||
{
|
||||
[UnityEngine.Scripting.Preserve]
|
||||
internal sealed class HeatmapHandler : SerieHandler<Heatmap>
|
||||
internal sealed partial class HeatmapHandler : SerieHandler<Heatmap>
|
||||
{
|
||||
private GridCoord m_SerieGrid;
|
||||
private Dictionary<int, int> m_CountDict = new Dictionary<int, int>();
|
||||
@@ -27,7 +27,10 @@ namespace XCharts.Runtime
|
||||
public override void Update()
|
||||
{
|
||||
base.Update();
|
||||
UpdateSerieContext();
|
||||
if (serie.IsUseCoord<GridCoord>())
|
||||
UpdateSerieContext();
|
||||
else if (serie.IsUseCoord<PolarCoord>())
|
||||
UpdateSeriePolarContext();
|
||||
}
|
||||
|
||||
public override void DrawSerie(VertexHelper vh)
|
||||
@@ -35,7 +38,16 @@ namespace XCharts.Runtime
|
||||
if (serie.heatmapType == HeatmapType.Count)
|
||||
DrawCountHeatmapSerie(vh, serie);
|
||||
else
|
||||
DrawDataHeatmapSerie(vh, serie);
|
||||
{
|
||||
if (serie.IsUseCoord<PolarCoord>())
|
||||
{
|
||||
DrawPolarHeatmap(vh, serie);
|
||||
}
|
||||
else if (serie.IsUseCoord<GridCoord>())
|
||||
{
|
||||
DrawDataHeatmapSerie(vh, serie);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void UpdateTooltipSerieParams(int dataIndex, bool showCategory, string category,
|
||||
@@ -416,7 +428,7 @@ namespace XCharts.Runtime
|
||||
|
||||
var pos = new Vector3(zeroX + (i + 0.5f) * xWidth,
|
||||
zeroY + (j + 0.5f) * yWidth);
|
||||
|
||||
|
||||
var rectWid = 0f;
|
||||
var rectHig = 0f;
|
||||
if (isRectSymbol)
|
||||
|
||||
Reference in New Issue
Block a user