海拔图和小地图
This commit is contained in:
1 parent
45801dff22
commit
c5bd9daba2
521 files changed
+1985033
-439
No files matched your search
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d5053a63a1ebdfe4f8972f194156c3d3
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,396 @@
|
||||
/************************************************/
|
||||
/* */
|
||||
/* Copyright (c) 2018 - 2021 monitor1394 */
|
||||
/* https://github.com/monitor1394 */
|
||||
/* */
|
||||
/************************************************/
|
||||
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using System;
|
||||
using UnityEngine.EventSystems;
|
||||
|
||||
namespace XCharts
|
||||
{
|
||||
[RequireComponent(typeof(CanvasRenderer))]
|
||||
public partial class BaseGraph : MaskableGraphic, IPointerDownHandler, IPointerUpHandler,
|
||||
IPointerEnterHandler, IPointerExitHandler, IBeginDragHandler, IPointerClickHandler,
|
||||
IDragHandler, IEndDragHandler, IScrollHandler
|
||||
{
|
||||
protected static readonly string s_BackgroundObjectName = "background";
|
||||
[SerializeField] protected bool m_MultiComponentMode = false;
|
||||
[SerializeField] protected bool m_DebugMode = false;
|
||||
[SerializeField] protected bool m_EnableTextMeshPro = false;
|
||||
[SerializeField] protected Background m_Background = Background.defaultBackground;
|
||||
protected Painter m_Painter;
|
||||
protected int m_SiblingIndex;
|
||||
|
||||
protected float m_GraphWidth;
|
||||
protected float m_GraphHeight;
|
||||
protected float m_GraphX;
|
||||
protected float m_GraphY;
|
||||
protected Vector3 m_GraphPosition = Vector3.zero;
|
||||
protected Vector2 m_GraphMinAnchor;
|
||||
protected Vector2 m_GraphMaxAnchor;
|
||||
protected Vector2 m_GraphPivot;
|
||||
protected Vector2 m_GraphSizeDelta;
|
||||
protected Vector2 m_GraphAnchoredPosition;
|
||||
protected Rect m_GraphRect = new Rect(0, 0, 0, 0);
|
||||
protected bool m_RefreshChart = false;
|
||||
protected bool m_ForceOpenRaycastTarget;
|
||||
protected bool m_IsControlledByLayout = false;
|
||||
protected bool m_PainerDirty = false;
|
||||
protected bool m_IsOnValidate = false;
|
||||
protected Vector3 m_LastLocalPosition;
|
||||
|
||||
protected Action<PointerEventData, BaseGraph> m_OnPointerClick;
|
||||
protected Action<PointerEventData, BaseGraph> m_OnPointerDown;
|
||||
protected Action<PointerEventData, BaseGraph> m_OnPointerUp;
|
||||
protected Action<PointerEventData, BaseGraph> m_OnPointerEnter;
|
||||
protected Action<PointerEventData, BaseGraph> m_OnPointerExit;
|
||||
protected Action<PointerEventData, BaseGraph> m_OnBeginDrag;
|
||||
protected Action<PointerEventData, BaseGraph> m_OnDrag;
|
||||
protected Action<PointerEventData, BaseGraph> m_OnEndDrag;
|
||||
protected Action<PointerEventData, BaseGraph> m_OnScroll;
|
||||
|
||||
protected Vector2 graphAnchorMax { get { return m_GraphMinAnchor; } }
|
||||
protected Vector2 graphAnchorMin { get { return m_GraphMaxAnchor; } }
|
||||
protected Vector2 graphPivot { get { return m_GraphPivot; } }
|
||||
internal HideFlags chartHideFlags { get { return m_DebugMode ? HideFlags.None : HideFlags.HideInHierarchy; } }
|
||||
|
||||
private ScrollRect m_ScrollRect;
|
||||
|
||||
|
||||
protected virtual void InitComponent()
|
||||
{
|
||||
InitPainter();
|
||||
InitBackground();
|
||||
}
|
||||
|
||||
protected override void Awake()
|
||||
{
|
||||
CheckTextMeshPro();
|
||||
m_SiblingIndex = 0;
|
||||
if (transform.parent != null)
|
||||
{
|
||||
m_IsControlledByLayout = transform.parent.GetComponent<LayoutGroup>() != null;
|
||||
}
|
||||
raycastTarget = false;
|
||||
m_LastLocalPosition = transform.localPosition;
|
||||
UpdateSize();
|
||||
InitComponent();
|
||||
CheckIsInScrollRect();
|
||||
}
|
||||
|
||||
protected override void Start()
|
||||
{
|
||||
m_RefreshChart = true;
|
||||
}
|
||||
|
||||
protected virtual void Update()
|
||||
{
|
||||
CheckSize();
|
||||
if (m_IsOnValidate)
|
||||
{
|
||||
m_IsOnValidate = false;
|
||||
m_RefreshChart = true;
|
||||
CheckTextMeshPro();
|
||||
InitComponent();
|
||||
}
|
||||
else
|
||||
{
|
||||
CheckComponent();
|
||||
}
|
||||
CheckPointerPos();
|
||||
CheckRefreshChart();
|
||||
CheckRefreshPainter();
|
||||
}
|
||||
|
||||
protected virtual void SetAllComponentDirty()
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
if (!Application.isPlaying)
|
||||
{
|
||||
m_IsOnValidate = true;
|
||||
Update();
|
||||
}
|
||||
#endif
|
||||
m_PainerDirty = true;
|
||||
m_Background.SetAllDirty();
|
||||
}
|
||||
|
||||
protected virtual void CheckComponent()
|
||||
{
|
||||
CheckComponentDirty(m_Background);
|
||||
if (m_PainerDirty)
|
||||
{
|
||||
InitPainter();
|
||||
m_PainerDirty = false;
|
||||
}
|
||||
}
|
||||
|
||||
private void CheckTextMeshPro()
|
||||
{
|
||||
#if dUI_TextMeshPro
|
||||
var enableTextMeshPro = true;
|
||||
#else
|
||||
var enableTextMeshPro = false;
|
||||
#endif
|
||||
if (m_EnableTextMeshPro != enableTextMeshPro)
|
||||
{
|
||||
m_EnableTextMeshPro = enableTextMeshPro;
|
||||
RemoveChartObject();
|
||||
}
|
||||
}
|
||||
|
||||
protected void CheckComponentDirty(ChartComponent component)
|
||||
{
|
||||
if (component.anyDirty)
|
||||
{
|
||||
if (component.componentDirty)
|
||||
{
|
||||
component.refreshComponent?.Invoke();
|
||||
}
|
||||
if (component.vertsDirty)
|
||||
{
|
||||
if (component.painter != null)
|
||||
{
|
||||
RefreshPainter(component.painter);
|
||||
}
|
||||
}
|
||||
component.ClearDirty();
|
||||
}
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
protected override void Reset()
|
||||
{
|
||||
}
|
||||
|
||||
protected override void OnValidate()
|
||||
{
|
||||
m_IsOnValidate = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
protected override void OnDestroy()
|
||||
{
|
||||
for (int i = transform.childCount - 1; i >= 0; i--)
|
||||
{
|
||||
DestroyImmediate(transform.GetChild(i).gameObject);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnPopulateMesh(VertexHelper vh)
|
||||
{
|
||||
vh.Clear();
|
||||
}
|
||||
|
||||
private void InitBackground()
|
||||
{
|
||||
m_Background.painter = m_Painter;
|
||||
m_Background.refreshComponent = delegate ()
|
||||
{
|
||||
var backgroundObj = ChartHelper.AddObject(s_BackgroundObjectName, transform, m_GraphMinAnchor,
|
||||
m_GraphMaxAnchor, m_GraphPivot, m_GraphSizeDelta);
|
||||
m_Background.gameObject = backgroundObj;
|
||||
backgroundObj.hideFlags = chartHideFlags;
|
||||
var backgroundImage = ChartHelper.GetOrAddComponent<Image>(backgroundObj);
|
||||
ChartHelper.UpdateRectTransform(backgroundObj, m_GraphMinAnchor,
|
||||
m_GraphMaxAnchor, m_GraphPivot, m_GraphSizeDelta);
|
||||
backgroundImage.sprite = m_Background.image;
|
||||
backgroundImage.type = m_Background.imageType;
|
||||
backgroundImage.color = m_Background.imageColor;
|
||||
backgroundObj.transform.SetSiblingIndex(0);
|
||||
backgroundObj.SetActive(m_Background.show);
|
||||
};
|
||||
m_Background.refreshComponent();
|
||||
}
|
||||
|
||||
protected virtual void InitPainter()
|
||||
{
|
||||
m_Painter = ChartHelper.AddPainterObject("painter_b", transform, m_GraphMinAnchor,
|
||||
m_GraphMaxAnchor, m_GraphPivot, new Vector2(m_GraphWidth, m_GraphHeight), chartHideFlags, 1);
|
||||
m_Painter.type = Painter.Type.Base;
|
||||
m_Painter.onPopulateMesh = OnDrawPainterBase;
|
||||
}
|
||||
|
||||
private void CheckSize()
|
||||
{
|
||||
var currWidth = rectTransform.rect.width;
|
||||
var currHeight = rectTransform.rect.height;
|
||||
|
||||
if (m_GraphWidth == 0 && m_GraphHeight == 0 && (currWidth != 0 || currHeight != 0))
|
||||
{
|
||||
Awake();
|
||||
}
|
||||
|
||||
if (m_GraphWidth != currWidth
|
||||
|| m_GraphHeight != currHeight
|
||||
|| m_GraphMinAnchor != rectTransform.anchorMin
|
||||
|| m_GraphMaxAnchor != rectTransform.anchorMax
|
||||
|| m_GraphAnchoredPosition != rectTransform.anchoredPosition)
|
||||
{
|
||||
UpdateSize();
|
||||
}
|
||||
if (!ChartHelper.IsValueEqualsVector3(m_LastLocalPosition, transform.localPosition))
|
||||
{
|
||||
m_LastLocalPosition = transform.localPosition;
|
||||
OnLocalPositionChanged();
|
||||
}
|
||||
}
|
||||
|
||||
protected void UpdateSize()
|
||||
{
|
||||
m_GraphWidth = rectTransform.rect.width;
|
||||
m_GraphHeight = rectTransform.rect.height;
|
||||
|
||||
m_GraphMaxAnchor = rectTransform.anchorMax;
|
||||
m_GraphMinAnchor = rectTransform.anchorMin;
|
||||
m_GraphSizeDelta = rectTransform.sizeDelta;
|
||||
m_GraphAnchoredPosition = rectTransform.anchoredPosition;
|
||||
|
||||
rectTransform.pivot = LayerHelper.ResetChartPositionAndPivot(m_GraphMinAnchor, m_GraphMaxAnchor,
|
||||
m_GraphWidth, m_GraphHeight, ref m_GraphX, ref m_GraphY);
|
||||
m_GraphPivot = rectTransform.pivot;
|
||||
|
||||
m_GraphRect.x = m_GraphX;
|
||||
m_GraphRect.y = m_GraphY;
|
||||
m_GraphRect.width = m_GraphWidth;
|
||||
m_GraphRect.height = m_GraphHeight;
|
||||
m_GraphPosition.x = m_GraphX;
|
||||
m_GraphPosition.y = m_GraphY;
|
||||
|
||||
OnSizeChanged();
|
||||
}
|
||||
|
||||
private void CheckPointerPos()
|
||||
{
|
||||
if (m_ForceOpenRaycastTarget) raycastTarget = true;
|
||||
if (IsNeedCheckPointerPos())
|
||||
{
|
||||
raycastTarget = true;
|
||||
if (canvas == null) return;
|
||||
Vector2 local;
|
||||
var cam = canvas.renderMode == RenderMode.ScreenSpaceOverlay ? null : canvas.worldCamera;
|
||||
if (!RectTransformUtility.ScreenPointToLocalPointInRectangle(rectTransform,
|
||||
Input.mousePosition, cam, out local))
|
||||
{
|
||||
pointerPos = Vector2.zero;
|
||||
}
|
||||
else
|
||||
{
|
||||
pointerPos = local;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
raycastTarget = false;
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void CheckIsInScrollRect()
|
||||
{
|
||||
m_ScrollRect = GetComponentInParent<ScrollRect>();
|
||||
}
|
||||
|
||||
protected virtual bool IsNeedCheckPointerPos()
|
||||
{
|
||||
return raycastTarget;
|
||||
}
|
||||
|
||||
protected virtual void CheckRefreshChart()
|
||||
{
|
||||
if (m_RefreshChart)
|
||||
{
|
||||
m_Painter.Refresh();
|
||||
m_RefreshChart = false;
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void CheckRefreshPainter()
|
||||
{
|
||||
m_Painter.CheckRefresh();
|
||||
}
|
||||
|
||||
internal virtual void RefreshPainter(Painter painter)
|
||||
{
|
||||
if (painter == null) return;
|
||||
painter.Refresh();
|
||||
}
|
||||
|
||||
protected virtual void OnSizeChanged()
|
||||
{
|
||||
m_RefreshChart = true;
|
||||
}
|
||||
|
||||
protected virtual void OnLocalPositionChanged()
|
||||
{
|
||||
}
|
||||
|
||||
protected virtual void OnDrawPainterBase(VertexHelper vh, Painter painter)
|
||||
{
|
||||
DrawBackground(vh);
|
||||
DrawPainterBase(vh);
|
||||
}
|
||||
|
||||
protected virtual void DrawPainterBase(VertexHelper vh)
|
||||
{
|
||||
}
|
||||
|
||||
protected virtual void DrawBackground(VertexHelper vh)
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void OnPointerClick(PointerEventData eventData)
|
||||
{
|
||||
if (m_OnPointerClick != null) m_OnPointerClick(eventData, this);
|
||||
}
|
||||
|
||||
public virtual void OnPointerDown(PointerEventData eventData)
|
||||
{
|
||||
if (m_OnPointerDown != null) m_OnPointerDown(eventData, this);
|
||||
}
|
||||
|
||||
public virtual void OnPointerUp(PointerEventData eventData)
|
||||
{
|
||||
if (m_OnPointerUp != null) m_OnPointerUp(eventData, this);
|
||||
}
|
||||
|
||||
public virtual void OnPointerEnter(PointerEventData eventData)
|
||||
{
|
||||
isPointerInChart = true;
|
||||
if (m_OnPointerEnter != null) m_OnPointerEnter(eventData, this);
|
||||
}
|
||||
|
||||
public virtual void OnPointerExit(PointerEventData eventData)
|
||||
{
|
||||
isPointerInChart = false;
|
||||
if (m_OnPointerExit != null) m_OnPointerExit(eventData, this);
|
||||
}
|
||||
|
||||
public virtual void OnBeginDrag(PointerEventData eventData)
|
||||
{
|
||||
if (m_ScrollRect != null) m_ScrollRect.OnBeginDrag(eventData);
|
||||
if (m_OnBeginDrag != null) m_OnBeginDrag(eventData, this);
|
||||
}
|
||||
|
||||
public virtual void OnEndDrag(PointerEventData eventData)
|
||||
{
|
||||
if (m_ScrollRect != null) m_ScrollRect.OnEndDrag(eventData);
|
||||
if (m_OnEndDrag != null) m_OnEndDrag(eventData, this);
|
||||
}
|
||||
|
||||
public virtual void OnDrag(PointerEventData eventData)
|
||||
{
|
||||
if (m_ScrollRect != null) m_ScrollRect.OnDrag(eventData);
|
||||
if (m_OnDrag != null) m_OnDrag(eventData, this);
|
||||
}
|
||||
|
||||
public virtual void OnScroll(PointerEventData eventData)
|
||||
{
|
||||
if (m_ScrollRect != null) m_ScrollRect.OnScroll(eventData);
|
||||
if (m_OnScroll != null) m_OnScroll(eventData, this);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4f059825ead3b4a7da7f1fbcebbf545e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c20b1e83703d1084c899f1f1b605c278
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,704 @@
|
||||
/************************************************/
|
||||
/* */
|
||||
/* Copyright (c) 2018 - 2021 monitor1394 */
|
||||
/* https://github.com/monitor1394 */
|
||||
/* */
|
||||
/************************************************/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.EventSystems;
|
||||
using UnityEngine.UI;
|
||||
using XUGL;
|
||||
|
||||
namespace XCharts
|
||||
{
|
||||
public partial class CoordinateChart
|
||||
{
|
||||
protected Action<PointerEventData, int> m_OnPointerClickBar;
|
||||
|
||||
protected void DrawYBarSerie(VertexHelper vh, Serie serie, int colorIndex)
|
||||
{
|
||||
if (!IsActive(serie.name)) return;
|
||||
if (serie.animation.HasFadeOut()) return;
|
||||
var xAxis = m_XAxes[serie.xAxisIndex];
|
||||
var yAxis = m_YAxes[serie.yAxisIndex];
|
||||
var grid = GetSerieGridOrDefault(serie);
|
||||
var showData = serie.GetDataList(dataZoom);
|
||||
float categoryWidth = AxisHelper.GetDataWidth(yAxis, grid.runtimeHeight, 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;
|
||||
var isStack = SeriesHelper.IsStack(m_Series, serie.stack, SerieType.Bar);
|
||||
m_StackSerieData.Clear();
|
||||
if (isStack) SeriesHelper.UpdateStackDataList(m_Series, serie, dataZoom, m_StackSerieData);
|
||||
|
||||
int maxCount = serie.maxShow > 0 ?
|
||||
(serie.maxShow > showData.Count ? showData.Count : serie.maxShow)
|
||||
: showData.Count;
|
||||
var isPercentStack = SeriesHelper.IsPercentStack(m_Series, serie.stack, SerieType.Bar);
|
||||
bool dataChanging = false;
|
||||
float dataChangeDuration = serie.animation.GetUpdateAnimationDuration();
|
||||
float xMinValue = xAxis.GetCurrMinValue(dataChangeDuration);
|
||||
float xMaxValue = xAxis.GetCurrMaxValue(dataChangeDuration);
|
||||
var isAllBarEnd = true;
|
||||
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);
|
||||
|
||||
serieData.canShowLabel = true;
|
||||
float value = showData[i].GetCurrData(1, dataChangeDuration, xAxis.inverse, xMinValue, xMaxValue);
|
||||
float borderWidth = value == 0 ? 0 : itemStyle.runtimeBorderWidth;
|
||||
if (showData[i].IsDataChanged()) dataChanging = true;
|
||||
float axisLineWidth = value == 0 ? 0
|
||||
: ((value < 0 ? -1 : 1) * yAxis.axisLine.GetWidth(m_Theme.axis.lineWidth));
|
||||
|
||||
float pY = grid.runtimeY + i * categoryWidth;
|
||||
if (!yAxis.boundaryGap) pY -= categoryWidth / 2;
|
||||
float pX = grid.runtimeX + xAxis.runtimeZeroXOffset + axisLineWidth;
|
||||
if (isStack)
|
||||
{
|
||||
for (int n = 0; n < m_StackSerieData.Count - 1; n++)
|
||||
{
|
||||
pX += m_StackSerieData[n][i].runtimeStackHig;
|
||||
}
|
||||
}
|
||||
|
||||
var barHig = 0f;
|
||||
var valueTotal = 0f;
|
||||
if (isPercentStack)
|
||||
{
|
||||
valueTotal = GetSameStackTotalValue(serie.stack, i);
|
||||
barHig = valueTotal != 0 ? (value / valueTotal * grid.runtimeWidth) : 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
valueTotal = xMaxValue - xMinValue;
|
||||
if (valueTotal != 0)
|
||||
barHig = (xMinValue > 0 ? value - xMinValue : value)
|
||||
/ valueTotal * grid.runtimeWidth;
|
||||
}
|
||||
serieData.runtimeStackHig = barHig;
|
||||
var isBarEnd = false;
|
||||
float currHig = CheckAnimation(serie, i, barHig, out isBarEnd);
|
||||
if (!isBarEnd) isAllBarEnd = false;
|
||||
Vector3 plt, prt, prb, plb, top;
|
||||
if (value < 0)
|
||||
{
|
||||
plt = new Vector3(pX - borderWidth, pY + space + barWidth - borderWidth);
|
||||
prt = new Vector3(pX + currHig + borderWidth, pY + space + barWidth - borderWidth);
|
||||
prb = new Vector3(pX + currHig + borderWidth, pY + space + borderWidth);
|
||||
plb = new Vector3(pX - borderWidth, pY + space + borderWidth);
|
||||
}
|
||||
else
|
||||
{
|
||||
plt = new Vector3(pX + borderWidth, pY + space + barWidth - borderWidth);
|
||||
prt = new Vector3(pX + currHig - borderWidth , pY + space + barWidth - borderWidth);
|
||||
prb = new Vector3(pX + currHig - borderWidth , pY + space + borderWidth);
|
||||
plb = new Vector3(pX + borderWidth, pY + space + borderWidth);
|
||||
}
|
||||
top = new Vector3(pX + currHig - borderWidth, pY + space + barWidth / 2);
|
||||
plt = ClampInGrid(grid, plt);
|
||||
prt = ClampInGrid(grid, prt);
|
||||
prb = ClampInGrid(grid, prb);
|
||||
plb = ClampInGrid(grid, plb);
|
||||
top = ClampInGrid(grid, top);
|
||||
serie.dataPoints.Add(top);
|
||||
if (serie.show)
|
||||
{
|
||||
switch (serie.barType)
|
||||
{
|
||||
case BarType.Normal:
|
||||
DrawNormalBar(vh, serie, serieData, itemStyle, colorIndex, highlight, space, barWidth,
|
||||
pX, pY, plb, plt, prt, prb, true, grid);
|
||||
break;
|
||||
case BarType.Zebra:
|
||||
DrawZebraBar(vh, serie, serieData, itemStyle, colorIndex, highlight, space, barWidth,
|
||||
pX, pY, plb, plt, prt, prb, true, grid);
|
||||
break;
|
||||
case BarType.Capsule:
|
||||
DrawCapsuleBar(vh, serie, serieData, itemStyle, colorIndex, highlight, space, barWidth,
|
||||
pX, pY, plb, plt, prt, prb, true, grid);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (isAllBarEnd) serie.animation.AllBarEnd();
|
||||
if (dataChanging)
|
||||
{
|
||||
RefreshPainter(serie);
|
||||
}
|
||||
}
|
||||
|
||||
private float CheckAnimation(Serie serie, int dataIndex, float barHig, out bool isBarEnd)
|
||||
{
|
||||
float currHig = serie.animation.CheckBarProgress(dataIndex, barHig, serie.dataCount, out isBarEnd);
|
||||
if (!serie.animation.IsFinish())
|
||||
{
|
||||
RefreshPainter(serie);
|
||||
m_IsPlayingAnimation = true;
|
||||
}
|
||||
return currHig;
|
||||
}
|
||||
|
||||
protected void DrawXBarSerie(VertexHelper vh, Serie serie, int colorIndex)
|
||||
{
|
||||
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);
|
||||
var isStack = SeriesHelper.IsStack(m_Series, serie.stack, SerieType.Bar);
|
||||
m_StackSerieData.Clear();
|
||||
if (isStack) SeriesHelper.UpdateStackDataList(m_Series, serie, dataZoom, m_StackSerieData);
|
||||
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;
|
||||
|
||||
var isPercentStack = SeriesHelper.IsPercentStack(m_Series, serie.stack, SerieType.Bar);
|
||||
bool dataChanging = false;
|
||||
float dataChangeDuration = serie.animation.GetUpdateAnimationDuration();
|
||||
float yMinValue = yAxis.GetCurrMinValue(dataChangeDuration);
|
||||
float yMaxValue = yAxis.GetCurrMaxValue(dataChangeDuration);
|
||||
var isAllBarEnd = true;
|
||||
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);
|
||||
float value = serieData.GetCurrData(1, dataChangeDuration, yAxis.inverse, yMinValue, yMaxValue);
|
||||
float borderWidth = value == 0 ? 0 : 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 axisLineWidth = value == 0 ? 0 :
|
||||
((value < 0 ? -1 : 1) * xAxis.axisLine.GetWidth(m_Theme.axis.lineWidth));
|
||||
float pY = zeroY + axisLineWidth;
|
||||
if (isStack)
|
||||
{
|
||||
for (int n = 0; n < m_StackSerieData.Count - 1; n++)
|
||||
{
|
||||
pY += m_StackSerieData[n][i].runtimeStackHig;
|
||||
}
|
||||
}
|
||||
|
||||
var barHig = 0f;
|
||||
var valueTotal = 0f;
|
||||
if (isPercentStack)
|
||||
{
|
||||
valueTotal = GetSameStackTotalValue(serie.stack, i);
|
||||
barHig = valueTotal != 0 ? (value / valueTotal * grid.runtimeHeight) : 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
valueTotal = yMaxValue - yMinValue;
|
||||
if (valueTotal != 0)
|
||||
{
|
||||
barHig = (yMinValue > 0 ? value - yMinValue : value) / 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;
|
||||
if (value < 0)
|
||||
{
|
||||
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);
|
||||
}
|
||||
else
|
||||
{
|
||||
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);
|
||||
if (serie.show && currHig != 0)
|
||||
{
|
||||
switch (serie.barType)
|
||||
{
|
||||
case BarType.Normal:
|
||||
DrawNormalBar(vh, serie, serieData, itemStyle, colorIndex, highlight, space, barWidth,
|
||||
pX, pY, plb, plt, prt, prb, false, grid);
|
||||
break;
|
||||
case BarType.Zebra:
|
||||
DrawZebraBar(vh, serie, serieData, itemStyle, colorIndex, highlight, space, barWidth,
|
||||
pX, pY, plb, plt, prt, prb, false, grid);
|
||||
break;
|
||||
case BarType.Capsule:
|
||||
DrawCapsuleBar(vh, serie, serieData, itemStyle, colorIndex, highlight, space, barWidth,
|
||||
pX, pY, plb, plt, prt, prb, false, grid);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (isAllBarEnd)
|
||||
{
|
||||
serie.animation.AllBarEnd();
|
||||
}
|
||||
if (dataChanging)
|
||||
{
|
||||
RefreshPainter(serie);
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawNormalBar(VertexHelper vh, Serie serie, SerieData serieData, ItemStyle itemStyle, int colorIndex,
|
||||
bool highlight, float space, float barWidth, float pX, float pY, Vector3 plb, Vector3 plt, Vector3 prt,
|
||||
Vector3 prb, bool isYAxis, Grid grid)
|
||||
{
|
||||
var areaColor = SerieHelper.GetItemColor(serie, serieData, m_Theme, colorIndex, highlight);
|
||||
var areaToColor = SerieHelper.GetItemToColor(serie, serieData, m_Theme, colorIndex, highlight);
|
||||
DrawBarBackground(vh, serie, serieData, itemStyle, colorIndex, highlight, pX, pY, space, barWidth, isYAxis, grid);
|
||||
var borderWidth = itemStyle.runtimeBorderWidth;
|
||||
if (isYAxis)
|
||||
{
|
||||
if (serie.clip)
|
||||
{
|
||||
prb = ClampInGrid(grid, prb);
|
||||
plb = ClampInGrid(grid, plb);
|
||||
plt = ClampInGrid(grid, plt);
|
||||
prt = ClampInGrid(grid, prt);
|
||||
}
|
||||
var borderColor = itemStyle.borderColor;
|
||||
var itemWidth = Mathf.Abs(prb.x - plt.x);
|
||||
var itemHeight = Mathf.Abs(prt.y - plb.y);
|
||||
var center = new Vector3((plt.x + prb.x) / 2, (prt.y + plb.y) / 2);
|
||||
if (itemWidth > 0 && itemHeight > 0)
|
||||
{
|
||||
if (ItemStyleHelper.IsNeedCorner(itemStyle))
|
||||
{
|
||||
UGL.DrawRoundRectangle(vh, center, itemWidth, itemHeight, areaColor, areaToColor, 0,
|
||||
itemStyle.cornerRadius, isYAxis);
|
||||
}
|
||||
else
|
||||
{
|
||||
CheckClipAndDrawPolygon(vh, plb, plt, prt, prb, areaColor, areaToColor, serie.clip, grid);
|
||||
}
|
||||
UGL.DrawBorder(vh, center, itemWidth, itemHeight, borderWidth, borderColor, 0,
|
||||
itemStyle.cornerRadius, isYAxis);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (serie.clip)
|
||||
{
|
||||
prb = ClampInGrid(grid, prb);
|
||||
plb = ClampInGrid(grid, plb);
|
||||
plt = ClampInGrid(grid, plt);
|
||||
prt = ClampInGrid(grid, prt);
|
||||
}
|
||||
var borderColor = itemStyle.borderColor;
|
||||
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);
|
||||
if (itemWidth > 0 && itemHeight > 0)
|
||||
{
|
||||
if (ItemStyleHelper.IsNeedCorner(itemStyle))
|
||||
{
|
||||
UGL.DrawRoundRectangle(vh, center, itemWidth, itemHeight, areaColor, areaToColor, 0,
|
||||
itemStyle.cornerRadius, isYAxis);
|
||||
}
|
||||
else
|
||||
{
|
||||
CheckClipAndDrawPolygon(vh, ref prb, ref plb, ref plt, ref prt, areaColor, areaToColor,
|
||||
serie.clip, grid);
|
||||
}
|
||||
UGL.DrawBorder(vh, center, itemWidth, itemHeight, borderWidth, borderColor, 0,
|
||||
itemStyle.cornerRadius, isYAxis);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawZebraBar(VertexHelper vh, Serie serie, SerieData serieData, ItemStyle itemStyle, int colorIndex,
|
||||
bool highlight, float space, float barWidth, float pX, float pY, Vector3 plb, Vector3 plt, Vector3 prt,
|
||||
Vector3 prb, bool isYAxis, Grid grid)
|
||||
{
|
||||
var areaColor = SerieHelper.GetItemColor(serie, serieData, m_Theme, colorIndex, highlight);
|
||||
DrawBarBackground(vh, serie, serieData, itemStyle, colorIndex, highlight, pX, pY, space, barWidth, isYAxis, grid);
|
||||
if (isYAxis)
|
||||
{
|
||||
plt = (plb + plt) / 2;
|
||||
prt = (prt + prb) / 2;
|
||||
CheckClipAndDrawZebraLine(vh, plt, prt, barWidth / 2, serie.barZebraWidth, serie.barZebraGap,
|
||||
areaColor, serie.clip, grid);
|
||||
}
|
||||
else
|
||||
{
|
||||
plb = (prb + plb) / 2;
|
||||
plt = (plt + prt) / 2;
|
||||
CheckClipAndDrawZebraLine(vh, plb, plt, barWidth / 2, serie.barZebraWidth, serie.barZebraGap,
|
||||
areaColor, serie.clip, grid);
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawCapsuleBar(VertexHelper vh, Serie serie, SerieData serieData, ItemStyle itemStyle, int colorIndex,
|
||||
bool highlight, float space, float barWidth, float pX, float pY, Vector3 plb, Vector3 plt, Vector3 prt,
|
||||
Vector3 prb, bool isYAxis, Grid grid)
|
||||
{
|
||||
var areaColor = SerieHelper.GetItemColor(serie, serieData, m_Theme, colorIndex, highlight);
|
||||
var areaToColor = SerieHelper.GetItemToColor(serie, serieData, m_Theme, colorIndex, highlight);
|
||||
DrawBarBackground(vh, serie, serieData, itemStyle, colorIndex, highlight, pX, pY, space, barWidth, isYAxis, grid);
|
||||
var borderWidth = itemStyle.runtimeBorderWidth;
|
||||
var radius = barWidth / 2 - borderWidth;
|
||||
var isGradient = !ChartHelper.IsValueEqualsColor(areaColor, areaToColor);
|
||||
if (isYAxis)
|
||||
{
|
||||
var diff = Vector3.right * radius;
|
||||
if (plt.x < prt.x)
|
||||
{
|
||||
var pcl = (plt + plb) / 2 + diff;
|
||||
var pcr = (prt + prb) / 2 - diff;
|
||||
if (pcr.x > pcl.x)
|
||||
{
|
||||
if (isGradient)
|
||||
{
|
||||
var barLen = prt.x - plt.x;
|
||||
var rectStartColor = Color32.Lerp(areaColor, areaToColor, radius / barLen);
|
||||
var rectEndColor = Color32.Lerp(areaColor, areaToColor, (barLen - radius) / barLen);
|
||||
CheckClipAndDrawPolygon(vh, plb + diff, plt + diff, prt - diff, prb - diff, rectStartColor,
|
||||
rectEndColor, serie.clip, grid);
|
||||
UGL.DrawSector(vh, pcl, radius, areaColor, rectStartColor, 180, 360, 1, isYAxis);
|
||||
UGL.DrawSector(vh, pcr, radius, rectEndColor, areaToColor, 0, 180, 1, isYAxis);
|
||||
}
|
||||
else
|
||||
{
|
||||
CheckClipAndDrawPolygon(vh, plb + diff, plt + diff, prt - diff, prb - diff, areaColor,
|
||||
areaToColor, serie.clip, grid);
|
||||
UGL.DrawSector(vh, pcl, radius, areaColor, 180, 360);
|
||||
UGL.DrawSector(vh, pcr, radius, areaToColor, 0, 180);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (plt.x > prt.x)
|
||||
{
|
||||
var pcl = (plt + plb) / 2 - diff;
|
||||
var pcr = (prt + prb) / 2 + diff;
|
||||
if (pcr.x < pcl.x)
|
||||
{
|
||||
if (isGradient)
|
||||
{
|
||||
var barLen = plt.x - prt.x;
|
||||
var rectStartColor = Color32.Lerp(areaColor, areaToColor, radius / barLen);
|
||||
var rectEndColor = Color32.Lerp(areaColor, areaToColor, (barLen - radius) / barLen);
|
||||
CheckClipAndDrawPolygon(vh, plb - diff, plt - diff, prt + diff, prb + diff, rectStartColor,
|
||||
rectEndColor, serie.clip, grid);
|
||||
UGL.DrawSector(vh, pcl, radius, rectStartColor, areaColor, 0, 180, 1, isYAxis);
|
||||
UGL.DrawSector(vh, pcr, radius, areaToColor, rectEndColor, 180, 360, 1, isYAxis);
|
||||
}
|
||||
else
|
||||
{
|
||||
CheckClipAndDrawPolygon(vh, plb - diff, plt - diff, prt + diff, prb + diff, areaColor,
|
||||
areaToColor, serie.clip, grid);
|
||||
UGL.DrawSector(vh, pcl, radius, areaColor, 0, 180);
|
||||
UGL.DrawSector(vh, pcr, radius, areaToColor, 180, 360);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var diff = Vector3.up * radius;
|
||||
if (plt.y > plb.y)
|
||||
{
|
||||
var pct = (plt + prt) / 2 - diff;
|
||||
var pcb = (plb + prb) / 2 + diff;
|
||||
if (pct.y > pcb.y)
|
||||
{
|
||||
if (isGradient)
|
||||
{
|
||||
var barLen = plt.y - plb.y;
|
||||
var rectStartColor = Color32.Lerp(areaColor, areaToColor, radius / barLen);
|
||||
var rectEndColor = Color32.Lerp(areaColor, areaToColor, (barLen - radius) / barLen);
|
||||
CheckClipAndDrawPolygon(vh, prb + diff, plb + diff, plt - diff, prt - diff, rectStartColor,
|
||||
rectEndColor, serie.clip, grid);
|
||||
UGL.DrawSector(vh, pct, radius, rectEndColor, areaToColor, 270, 450, 1, isYAxis);
|
||||
UGL.DrawSector(vh, pcb, radius, rectStartColor, areaColor, 90, 270, 1, isYAxis);
|
||||
}
|
||||
else
|
||||
{
|
||||
CheckClipAndDrawPolygon(vh, prb + diff, plb + diff, plt - diff, prt - diff, areaColor,
|
||||
areaToColor, serie.clip, grid);
|
||||
UGL.DrawSector(vh, pct, radius, areaToColor, 270, 450);
|
||||
UGL.DrawSector(vh, pcb, radius, areaColor, 90, 270);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (plt.y < plb.y)
|
||||
{
|
||||
var pct = (plt + prt) / 2 + diff;
|
||||
var pcb = (plb + prb) / 2 - diff;
|
||||
if (pct.y < pcb.y)
|
||||
{
|
||||
if (isGradient)
|
||||
{
|
||||
var barLen = plb.y - plt.y;
|
||||
var rectStartColor = Color32.Lerp(areaColor, areaToColor, radius / barLen);
|
||||
var rectEndColor = Color32.Lerp(areaColor, areaToColor, (barLen - radius) / barLen);
|
||||
CheckClipAndDrawPolygon(vh, prb - diff, plb - diff, plt + diff, prt + diff, rectStartColor,
|
||||
rectEndColor, serie.clip, grid);
|
||||
UGL.DrawSector(vh, pct, radius, rectEndColor, areaToColor, 90, 270, 1, isYAxis);
|
||||
UGL.DrawSector(vh, pcb, radius, rectStartColor, areaColor, 270, 450, 1, isYAxis);
|
||||
}
|
||||
else
|
||||
{
|
||||
CheckClipAndDrawPolygon(vh, prb - diff, plb - diff, plt + diff, prt + diff, areaColor,
|
||||
areaToColor, serie.clip, grid);
|
||||
UGL.DrawSector(vh, pct, radius, areaToColor, 90, 270);
|
||||
UGL.DrawSector(vh, pcb, radius, areaColor, 270, 450);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawBarBackground(VertexHelper vh, Serie serie, SerieData serieData, ItemStyle itemStyle,
|
||||
int colorIndex, bool highlight, float pX, float pY, float space, float barWidth, bool isYAxis, Grid grid)
|
||||
{
|
||||
var color = SerieHelper.GetItemBackgroundColor(serie, serieData, m_Theme, colorIndex, highlight, false);
|
||||
if (ChartHelper.IsClearColor(color)) return;
|
||||
if (isYAxis)
|
||||
{
|
||||
var axis = m_YAxes[serie.yAxisIndex];
|
||||
var axisWidth = axis.axisLine.GetWidth(m_Theme.axis.lineWidth);
|
||||
Vector3 plt = new Vector3(grid.runtimeX + axisWidth, pY + space + barWidth);
|
||||
Vector3 prt = new Vector3(grid.runtimeX + axisWidth + grid.runtimeWidth, pY + space + barWidth);
|
||||
Vector3 prb = new Vector3(grid.runtimeX + axisWidth + grid.runtimeWidth, pY + space);
|
||||
Vector3 plb = new Vector3(grid.runtimeX + axisWidth, pY + space);
|
||||
if (serie.barType == BarType.Capsule)
|
||||
{
|
||||
var radius = barWidth / 2;
|
||||
var diff = Vector3.right * radius;
|
||||
var pcl = (plt + plb) / 2 + diff;
|
||||
var pcr = (prt + prb) / 2 - diff;
|
||||
CheckClipAndDrawPolygon(vh, plb + diff, plt + diff, prt - diff, prb - diff, color, color, serie.clip, grid);
|
||||
UGL.DrawSector(vh, pcl, radius, color, 180, 360);
|
||||
UGL.DrawSector(vh, pcr, radius, color, 0, 180);
|
||||
if (itemStyle.NeedShowBorder())
|
||||
{
|
||||
var borderWidth = itemStyle.borderWidth;
|
||||
var borderColor = itemStyle.borderColor;
|
||||
var smoothness = settings.cicleSmoothness;
|
||||
var inRadius = radius - borderWidth;
|
||||
var outRadius = radius;
|
||||
var p1 = plb + diff + Vector3.up * borderWidth / 2;
|
||||
var p2 = prb - diff + Vector3.up * borderWidth / 2;
|
||||
var p3 = plt + diff - Vector3.up * borderWidth / 2;
|
||||
var p4 = prt - diff - Vector3.up * borderWidth / 2;
|
||||
UGL.DrawLine(vh, p1, p2, borderWidth / 2, borderColor);
|
||||
UGL.DrawLine(vh, p3, p4, borderWidth / 2, borderColor);
|
||||
UGL.DrawDoughnut(vh, pcl, inRadius, outRadius, borderColor, ChartConst.clearColor32,
|
||||
180, 360, smoothness);
|
||||
UGL.DrawDoughnut(vh, pcr, inRadius, outRadius, borderColor, ChartConst.clearColor32,
|
||||
0, 180, smoothness);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
CheckClipAndDrawPolygon(vh, ref plb, ref plt, ref prt, ref prb, color, color, serie.clip, grid);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var axis = m_XAxes[serie.xAxisIndex];
|
||||
var axisWidth = axis.axisLine.GetWidth(m_Theme.axis.lineWidth);
|
||||
Vector3 plb = new Vector3(pX + space, grid.runtimeY + axisWidth);
|
||||
Vector3 plt = new Vector3(pX + space, grid.runtimeY + grid.runtimeHeight + axisWidth);
|
||||
Vector3 prt = new Vector3(pX + space + barWidth, grid.runtimeY + grid.runtimeHeight + axisWidth);
|
||||
Vector3 prb = new Vector3(pX + space + barWidth, grid.runtimeY + axisWidth);
|
||||
if (serie.barType == BarType.Capsule)
|
||||
{
|
||||
var radius = barWidth / 2;
|
||||
var diff = Vector3.up * radius;
|
||||
var pct = (plt + prt) / 2 - diff;
|
||||
var pcb = (plb + prb) / 2 + diff;
|
||||
CheckClipAndDrawPolygon(vh, prb + diff, plb + diff, plt - diff, prt - diff, color, color,
|
||||
serie.clip, grid);
|
||||
UGL.DrawSector(vh, pct, radius, color, 270, 450);
|
||||
UGL.DrawSector(vh, pcb, radius, color, 90, 270);
|
||||
if (itemStyle.NeedShowBorder())
|
||||
{
|
||||
var borderWidth = itemStyle.borderWidth;
|
||||
var borderColor = itemStyle.borderColor;
|
||||
var smoothness = settings.cicleSmoothness;
|
||||
var inRadius = radius - borderWidth;
|
||||
var outRadius = radius;
|
||||
var p1 = plb + diff + Vector3.right * borderWidth / 2;
|
||||
var p2 = plt - diff + Vector3.right * borderWidth / 2;
|
||||
var p3 = prb + diff - Vector3.right * borderWidth / 2;
|
||||
var p4 = prt - diff - Vector3.right * borderWidth / 2;
|
||||
UGL.DrawLine(vh, p1, p2, borderWidth / 2, borderColor);
|
||||
UGL.DrawLine(vh, p3, p4, borderWidth / 2, borderColor);
|
||||
UGL.DrawDoughnut(vh, pct, inRadius, outRadius, borderColor, ChartConst.clearColor32,
|
||||
270, 450, smoothness);
|
||||
UGL.DrawDoughnut(vh, pcb, inRadius, outRadius, borderColor, ChartConst.clearColor32,
|
||||
90, 270, smoothness);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
CheckClipAndDrawPolygon(vh, ref prb, ref plb, ref plt, ref prt, color, color, serie.clip, grid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private float GetBarGap()
|
||||
{
|
||||
float gap = 0.3f;
|
||||
for (int i = 0; i < m_Series.Count; i++)
|
||||
{
|
||||
var serie = m_Series.list[i];
|
||||
if (serie.type == SerieType.Bar || serie.type == SerieType.Candlestick)
|
||||
{
|
||||
if (serie.barGap != 0)
|
||||
{
|
||||
gap = serie.barGap;
|
||||
}
|
||||
}
|
||||
}
|
||||
return gap;
|
||||
}
|
||||
|
||||
private float GetSameStackTotalValue(string stack, int dataIndex)
|
||||
{
|
||||
if (string.IsNullOrEmpty(stack)) return 0;
|
||||
float total = 0;
|
||||
foreach (var serie in m_Series.list)
|
||||
{
|
||||
if (serie.type == SerieType.Bar)
|
||||
{
|
||||
if (stack.Equals(serie.stack))
|
||||
{
|
||||
total += serie.data[dataIndex].data[1];
|
||||
}
|
||||
}
|
||||
}
|
||||
return total;
|
||||
}
|
||||
|
||||
|
||||
private HashSet<string> barStackSet = new HashSet<string>();
|
||||
private float GetBarTotalWidth(float categoryWidth, float gap)
|
||||
{
|
||||
float total = 0;
|
||||
float lastGap = 0;
|
||||
barStackSet.Clear();
|
||||
for (int i = 0; i < m_Series.Count; i++)
|
||||
{
|
||||
var serie = m_Series.list[i];
|
||||
if (!serie.show) continue;
|
||||
if (serie.type == SerieType.Bar || serie.type == SerieType.Candlestick)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(serie.stack))
|
||||
{
|
||||
if (barStackSet.Contains(serie.stack)) continue;
|
||||
barStackSet.Add(serie.stack);
|
||||
}
|
||||
var width = GetStackBarWidth(categoryWidth, serie);
|
||||
if (gap == -1)
|
||||
{
|
||||
if (width > total) total = width;
|
||||
}
|
||||
else
|
||||
{
|
||||
lastGap = width * gap;
|
||||
total += width;
|
||||
total += lastGap;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (total > 0 && gap != -1) total -= lastGap;
|
||||
return total;
|
||||
}
|
||||
|
||||
private float GetStackBarWidth(float categoryWidth, Serie now)
|
||||
{
|
||||
if (string.IsNullOrEmpty(now.stack)) return now.GetBarWidth(categoryWidth);
|
||||
float barWidth = 0;
|
||||
for (int i = 0; i < m_Series.Count; i++)
|
||||
{
|
||||
var serie = m_Series.list[i];
|
||||
if ((serie.type == SerieType.Bar && serie.type == SerieType.Candlestick)
|
||||
&& serie.show && now.stack.Equals(serie.stack))
|
||||
{
|
||||
if (serie.barWidth > barWidth) barWidth = serie.barWidth;
|
||||
}
|
||||
}
|
||||
if (barWidth > 1) return barWidth;
|
||||
else return barWidth * categoryWidth;
|
||||
}
|
||||
|
||||
private List<string> tempList = new List<string>();
|
||||
private int GetBarIndex(Serie currSerie)
|
||||
{
|
||||
tempList.Clear();
|
||||
int index = 0;
|
||||
for (int i = 0; i < m_Series.Count; i++)
|
||||
{
|
||||
var serie = m_Series.GetSerie(i);
|
||||
if (serie.type != SerieType.Bar) continue;
|
||||
if (string.IsNullOrEmpty(serie.stack))
|
||||
{
|
||||
if (serie.index == currSerie.index) return index;
|
||||
tempList.Add(string.Empty);
|
||||
index++;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!tempList.Contains(serie.stack))
|
||||
{
|
||||
if (serie.index == currSerie.index) return index;
|
||||
tempList.Add(serie.stack);
|
||||
index++;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (serie.index == currSerie.index) return tempList.IndexOf(serie.stack);
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2abce1026caf74ffbb653c6e1a8d1e3f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,148 @@
|
||||
/************************************************/
|
||||
/* */
|
||||
/* 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 barWidth = serie.GetBarWidth(categoryWidth);
|
||||
float space = (categoryWidth - barWidth) / 2;
|
||||
float barGapWidth = barWidth + barWidth * barGap;
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c404a9bbfdf51409e808fb354c438ca2
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,178 @@
|
||||
/************************************************/
|
||||
/* */
|
||||
/* Copyright (c) 2018 - 2021 monitor1394 */
|
||||
/* https://github.com/monitor1394 */
|
||||
/* */
|
||||
/************************************************/
|
||||
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using XUGL;
|
||||
|
||||
namespace XCharts
|
||||
{
|
||||
public partial class CoordinateChart
|
||||
{
|
||||
protected void DrawGanttSerie(VertexHelper vh, int colorIndex, Serie serie)
|
||||
{
|
||||
if (!IsActive(serie.index)) return;
|
||||
if (serie.animation.HasFadeOut()) return;
|
||||
var showData = serie.GetDataList(null);
|
||||
var yAxis = m_YAxes[serie.yAxisIndex];
|
||||
var xAxis = m_XAxes[serie.xAxisIndex];
|
||||
var grid = GetSerieGridOrDefault(serie);
|
||||
var xCategoryWidth = AxisHelper.GetDataWidth(xAxis, grid.runtimeWidth, showData.Count, dataZoom);
|
||||
var yCategoryWidth = AxisHelper.GetDataWidth(yAxis, grid.runtimeHeight, showData.Count, dataZoom);
|
||||
var barGap = GetBarGap();
|
||||
var barWidth = serie.GetBarWidth(yCategoryWidth);
|
||||
var space = (yCategoryWidth - barWidth) / 2;
|
||||
var dataChanging = false;
|
||||
var dataChangeDuration = serie.animation.GetUpdateAnimationDuration();
|
||||
var minValue = xAxis.GetCurrMinValue(dataChangeDuration);
|
||||
var maxValue = xAxis.GetCurrMaxValue(dataChangeDuration);
|
||||
var pX = grid.runtimeX + (xAxis.boundaryGap ? xCategoryWidth / 2 : 0);
|
||||
var pY = 0f;
|
||||
var startY = grid.runtimeY - (yAxis.boundaryGap ? 0 : yCategoryWidth / 2);
|
||||
var isTime = xAxis.type == Axis.AxisType.Time;
|
||||
|
||||
var categoryIndex = GetGanttSerieCategoryIndex(serie, grid.index);
|
||||
var dataCount = serie.data.Count;
|
||||
for (int i = 0; i < dataCount; i++)
|
||||
{
|
||||
var serieData = serie.data[i];
|
||||
pY = startY + (categoryIndex - 1 - i) * yCategoryWidth;
|
||||
DrawSerieData(vh, grid, serie, serieData, colorIndex, pX, pY, space, barWidth, isTime, minValue,
|
||||
maxValue, xCategoryWidth);
|
||||
}
|
||||
if (dataChanging)
|
||||
{
|
||||
RefreshPainter(serie);
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawSerieData(VertexHelper vh, Grid grid, Serie serie, SerieData serieData, int colorIndex,
|
||||
float pX, float pY, float space, float barWidth, bool isTime, float minValue, float maxValue,
|
||||
float xCategoryWidth)
|
||||
{
|
||||
var xStart = 0f;
|
||||
var xEnd = 0f;
|
||||
var xActualStart = 0f;
|
||||
var xActualEnd = 0f;
|
||||
var start = (int)serieData.GetData(0);
|
||||
var end = (int)serieData.GetData(1);
|
||||
var actualStart = (int)serieData.GetData(2);
|
||||
var actualEnd = (int)serieData.GetData(3);
|
||||
var enableActual = actualStart > 0 && actualEnd > 0;
|
||||
if (isTime)
|
||||
{
|
||||
var valueTotal = maxValue - minValue;
|
||||
xStart = pX + (start - minValue) / valueTotal * grid.runtimeWidth;
|
||||
xEnd = pX + (end - minValue) / valueTotal * grid.runtimeWidth;
|
||||
if (enableActual)
|
||||
{
|
||||
xActualStart = pX + (actualStart - minValue) / valueTotal * grid.runtimeWidth;
|
||||
xActualEnd = pX + (actualEnd - minValue) / valueTotal * grid.runtimeWidth;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
xStart = pX + start * xCategoryWidth;
|
||||
xEnd = pX + end * xCategoryWidth;
|
||||
if (enableActual)
|
||||
{
|
||||
xActualStart = pX + actualStart * xCategoryWidth;
|
||||
xActualEnd = pX + actualEnd * xCategoryWidth;
|
||||
}
|
||||
}
|
||||
var highlight = (serieData != null && serieData.highlighted)
|
||||
|| serie.highlighted;
|
||||
var itemStyle = SerieHelper.GetItemStyle(serie, serieData, highlight);
|
||||
var color = SerieHelper.GetItemColor(serie, serieData, m_Theme, colorIndex, highlight);
|
||||
var borderWidth = itemStyle.borderWidth;
|
||||
|
||||
var rect = DrawGanttBar(vh, grid, serie, serieData, itemStyle, color, pY, pY, space, barWidth, xStart,
|
||||
xEnd);
|
||||
if (enableActual)
|
||||
{
|
||||
var defaultActualColor = SerieHelper.GetItemColor(serie, serieData, m_Theme, colorIndex, true);
|
||||
var actualColor = SerieHelper.GetItemColor0(serie, serieData, m_Theme, highlight, defaultActualColor);
|
||||
var rect2 = DrawGanttBar(vh, grid, serie, serieData, itemStyle, actualColor, pY, pY, space, barWidth,
|
||||
xActualStart, xActualEnd);
|
||||
var rect3X = Mathf.Min(rect.x, rect2.x);
|
||||
var rect3Width = Mathf.Max(rect.x + rect.width, rect2.x + rect2.width) - rect3X;
|
||||
var rect3 = new Rect(rect3X, rect.y, rect3Width, rect.height);
|
||||
serie.dataPoints.Add(rect3.center);
|
||||
serieData.runtimePosition = rect3.center;
|
||||
serieData.labelPosition = rect3.center;
|
||||
serieData.runtimeRect = rect3;
|
||||
}
|
||||
else
|
||||
{
|
||||
serie.dataPoints.Add(rect.center);
|
||||
serieData.runtimePosition = rect.center;
|
||||
serieData.labelPosition = rect.center;
|
||||
serieData.runtimeRect = rect;
|
||||
}
|
||||
}
|
||||
|
||||
private Rect DrawGanttBar(VertexHelper vh, Grid grid, Serie serie, SerieData serieData, ItemStyle itemStyle,
|
||||
Color32 color, float pX, float pY, float space, float barWidth, float xStart, float xEnd)
|
||||
{
|
||||
|
||||
var borderWidth = itemStyle.borderWidth;
|
||||
var plb = new Vector3(xStart + borderWidth, pY + space + borderWidth);
|
||||
var plt = new Vector3(xStart + borderWidth, pY + space + barWidth - borderWidth);
|
||||
var prt = new Vector3(xEnd - borderWidth, pY + space + barWidth - borderWidth);
|
||||
var prb = new Vector3(xEnd - borderWidth, pY + space + borderWidth);
|
||||
var center = new Vector3((plb.x + prt.x) / 2, (plt.y + prb.y) / 2);
|
||||
var itemWidth = Mathf.Abs(prt.x - plb.x);
|
||||
var itemHeight = Mathf.Abs(plt.y - prb.y);
|
||||
if (serie.clip)
|
||||
{
|
||||
plb = ClampInGrid(grid, plb);
|
||||
plt = ClampInGrid(grid, plt);
|
||||
prt = ClampInGrid(grid, prt);
|
||||
prb = ClampInGrid(grid, prb);
|
||||
center = ClampInGrid(grid, center);
|
||||
}
|
||||
if (ItemStyleHelper.IsNeedCorner(itemStyle))
|
||||
{
|
||||
UGL.DrawRoundRectangle(vh, center, itemWidth, itemHeight, color, color, 0,
|
||||
itemStyle.cornerRadius, true, 0.5f);
|
||||
}
|
||||
else
|
||||
{
|
||||
CheckClipAndDrawPolygon(vh, ref prb, ref plb, ref plt, ref prt, color, color,
|
||||
serie.clip, grid);
|
||||
}
|
||||
if (borderWidth != 0)
|
||||
{
|
||||
UGL.DrawBorder(vh, center, itemWidth, itemHeight, borderWidth, itemStyle.borderColor, 0,
|
||||
itemStyle.cornerRadius, true, 0.5f);
|
||||
}
|
||||
return new Rect(plb.x, plb.y, xEnd - xStart, barWidth);
|
||||
}
|
||||
|
||||
private int GetGanttSerieCategoryIndex(Serie currSerie, int gridIndex)
|
||||
{
|
||||
var count = m_Series.Count;
|
||||
var index = 0;
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
var serie = m_Series.GetSerie(i);
|
||||
if (serie.type != SerieType.Gantt) continue;
|
||||
var grid = GetSerieGridOrDefault(serie);
|
||||
if (grid.index != gridIndex) continue;
|
||||
foreach (var serieData in serie.data)
|
||||
{
|
||||
index++;
|
||||
}
|
||||
if (serie.index == currSerie.index)
|
||||
{
|
||||
return index;
|
||||
}
|
||||
}
|
||||
return index;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 81895b3c97e684e8090572c7e64b396e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,405 @@
|
||||
/************************************************/
|
||||
/* */
|
||||
/* Copyright (c) 2018 - 2021 monitor1394 */
|
||||
/* https://github.com/monitor1394 */
|
||||
/* */
|
||||
/************************************************/
|
||||
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using XUGL;
|
||||
|
||||
namespace XCharts
|
||||
{
|
||||
public partial class CoordinateChart
|
||||
{
|
||||
private bool m_VisualMapMinDrag;
|
||||
private bool m_VisualMapMaxDrag;
|
||||
|
||||
protected void CheckVisualMap()
|
||||
{
|
||||
if (visualMap == null || !visualMap.enable || !visualMap.show) return;
|
||||
Vector2 local;
|
||||
if (canvas == null) return;
|
||||
|
||||
if (!RectTransformUtility.ScreenPointToLocalPointInRectangle(rectTransform,
|
||||
Input.mousePosition, canvas.worldCamera, out local))
|
||||
{
|
||||
if (visualMap.runtimeSelectedIndex >= 0)
|
||||
{
|
||||
visualMap.runtimeSelectedIndex = -1;
|
||||
RefreshChart();
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (local.x < chartX || local.x > chartX + chartWidth ||
|
||||
local.y < chartY || local.y > chartY + chartHeight ||
|
||||
!visualMap.IsInRangeRect(local, chartRect))
|
||||
{
|
||||
if (visualMap.runtimeSelectedIndex >= 0)
|
||||
{
|
||||
visualMap.runtimeSelectedIndex = -1;
|
||||
RefreshChart();
|
||||
}
|
||||
return;
|
||||
}
|
||||
var pos1 = Vector3.zero;
|
||||
var pos2 = Vector3.zero;
|
||||
var halfHig = visualMap.itemHeight / 2;
|
||||
var centerPos = chartPosition + visualMap.location.GetPosition(chartWidth, chartHeight);
|
||||
var selectedIndex = -1;
|
||||
var value = 0f;
|
||||
switch (visualMap.orient)
|
||||
{
|
||||
case Orient.Horizonal:
|
||||
pos1 = centerPos + Vector3.left * halfHig;
|
||||
pos2 = centerPos + Vector3.right * halfHig;
|
||||
value = visualMap.min + (local.x - pos1.x) / (pos2.x - pos1.x) * (visualMap.max - visualMap.min);
|
||||
selectedIndex = visualMap.GetIndex(value);
|
||||
break;
|
||||
case Orient.Vertical:
|
||||
pos1 = centerPos + Vector3.down * halfHig;
|
||||
pos2 = centerPos + Vector3.up * halfHig;
|
||||
value = visualMap.min + (local.y - pos1.y) / (pos2.y - pos1.y) * (visualMap.max - visualMap.min);
|
||||
selectedIndex = visualMap.GetIndex(value);
|
||||
break;
|
||||
}
|
||||
visualMap.runtimeSelectedValue = value;
|
||||
visualMap.runtimeSelectedIndex = selectedIndex;
|
||||
RefreshChart();
|
||||
}
|
||||
|
||||
protected void OnDragVisualMapStart()
|
||||
{
|
||||
if (!visualMap.enable || !visualMap.show || !visualMap.calculable) return;
|
||||
var inMinRect = visualMap.IsInRangeMinRect(pointerPos, chartRect, m_Theme.visualMap.triangeLen);
|
||||
var inMaxRect = visualMap.IsInRangeMaxRect(pointerPos, chartRect, m_Theme.visualMap.triangeLen);
|
||||
if (inMinRect || inMaxRect)
|
||||
{
|
||||
if (inMinRect)
|
||||
{
|
||||
m_VisualMapMinDrag = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_VisualMapMaxDrag = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void OnDragVisualMap()
|
||||
{
|
||||
if (!visualMap.enable || !visualMap.show || !visualMap.calculable) return;
|
||||
if (!m_VisualMapMinDrag && !m_VisualMapMaxDrag) return;
|
||||
|
||||
var value = visualMap.GetValue(pointerPos, chartRect);
|
||||
if (m_VisualMapMinDrag)
|
||||
{
|
||||
visualMap.rangeMin = value;
|
||||
}
|
||||
else
|
||||
{
|
||||
visualMap.rangeMax = value;
|
||||
}
|
||||
RefreshChart();
|
||||
}
|
||||
|
||||
protected void OnDragVisualMapEnd()
|
||||
{
|
||||
if (!visualMap.enable || !visualMap.show || !visualMap.calculable) return;
|
||||
if (m_VisualMapMinDrag || m_VisualMapMaxDrag)
|
||||
{
|
||||
RefreshChart();
|
||||
m_VisualMapMinDrag = false;
|
||||
m_VisualMapMaxDrag = false;
|
||||
}
|
||||
}
|
||||
|
||||
protected void DrawHeatmapSerie(VertexHelper vh, int colorIndex, Serie serie)
|
||||
{
|
||||
if (serie.animation.HasFadeOut()) return;
|
||||
var yAxis = m_YAxes[serie.yAxisIndex];
|
||||
var xAxis = m_XAxes[serie.xAxisIndex];
|
||||
xAxis.boundaryGap = true;
|
||||
yAxis.boundaryGap = true;
|
||||
var grid = GetSerieGridOrDefault(serie);
|
||||
var xCount = xAxis.data.Count;
|
||||
var yCount = yAxis.data.Count;
|
||||
var xWidth = grid.runtimeWidth / xCount;
|
||||
var yWidth = grid.runtimeHeight / yCount;
|
||||
|
||||
var zeroX = grid.runtimeX;
|
||||
var zeroY = grid.runtimeY;
|
||||
var dataList = serie.GetDataList();
|
||||
var rangeMin = visualMap.rangeMin;
|
||||
var rangeMax = visualMap.rangeMax;
|
||||
var color = m_Theme.GetColor(serie.index);
|
||||
var borderWidth = serie.itemStyle.show ? serie.itemStyle.borderWidth : 0;
|
||||
var borderColor = serie.itemStyle.opacity > 0 ? serie.itemStyle.borderColor : ChartConst.clearColor32;
|
||||
borderColor.a = (byte)(borderColor.a * serie.itemStyle.opacity);
|
||||
serie.dataPoints.Clear();
|
||||
serie.animation.InitProgress(1, 0, xCount);
|
||||
var animationIndex = serie.animation.GetCurrIndex();
|
||||
var dataChangeDuration = serie.animation.GetUpdateAnimationDuration();
|
||||
var dataChanging = false;
|
||||
for (int i = 0; i < xCount; i++)
|
||||
{
|
||||
for (int j = 0; j < yCount; j++)
|
||||
{
|
||||
var dataIndex = i * yCount + j;
|
||||
if (dataIndex >= dataList.Count) continue;
|
||||
var serieData = dataList[dataIndex];
|
||||
var dimension = VisualMapHelper.GetDimension(visualMap, serieData.data.Count);
|
||||
if (serie.IsIgnoreIndex(dataIndex, dimension))
|
||||
{
|
||||
serie.dataPoints.Add(Vector3.zero);
|
||||
continue;
|
||||
}
|
||||
var value = serieData.GetCurrData(dimension, dataChangeDuration, yAxis.inverse,
|
||||
yAxis.runtimeMinValue, yAxis.runtimeMaxValue);
|
||||
if (serieData.IsDataChanged()) dataChanging = true;
|
||||
var pos = new Vector3(zeroX + (i + (xAxis.boundaryGap ? 0.5f : 0)) * xWidth,
|
||||
zeroY + (j + (yAxis.boundaryGap ? 0.5f : 0)) * yWidth);
|
||||
serie.dataPoints.Add(pos);
|
||||
serieData.canShowLabel = false;
|
||||
if (value == 0) continue;
|
||||
if (visualMap.enable)
|
||||
{
|
||||
if ((value < rangeMin && rangeMin != visualMap.min)
|
||||
|| (value > rangeMax && rangeMax != visualMap.max))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (!visualMap.IsInSelectedValue(value)) continue;
|
||||
color = visualMap.GetColor(value);
|
||||
}
|
||||
if (animationIndex >= 0 && i > animationIndex) continue;
|
||||
serieData.canShowLabel = true;
|
||||
var emphasis = (tooltip.show
|
||||
&& i == (int)tooltip.runtimeXValues[0]
|
||||
&& j == (int)tooltip.runtimeYValues[0])
|
||||
|| visualMap.runtimeSelectedIndex > 0;
|
||||
var rectWid = xWidth - 2 * borderWidth;
|
||||
var rectHig = yWidth - 2 * borderWidth;
|
||||
UGL.DrawRectangle(vh, pos, rectWid / 2, rectHig / 2, color);
|
||||
if (borderWidth > 0 && !ChartHelper.IsClearColor(borderColor))
|
||||
{
|
||||
UGL.DrawBorder(vh, pos, rectWid, rectHig, borderWidth, borderColor);
|
||||
}
|
||||
if (visualMap.hoverLink && emphasis && serie.emphasis.show
|
||||
&& serie.emphasis.itemStyle.borderWidth > 0)
|
||||
{
|
||||
var emphasisBorderWidth = serie.emphasis.itemStyle.borderWidth;
|
||||
var emphasisBorderColor = serie.emphasis.itemStyle.opacity > 0
|
||||
? serie.emphasis.itemStyle.borderColor : ChartConst.clearColor32;
|
||||
UGL.DrawBorder(vh, pos, rectWid, rectHig, emphasisBorderWidth, emphasisBorderColor);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!serie.animation.IsFinish())
|
||||
{
|
||||
serie.animation.CheckProgress(xCount);
|
||||
m_IsPlayingAnimation = true;
|
||||
RefreshPainter(serie);
|
||||
}
|
||||
if (dataChanging)
|
||||
{
|
||||
RefreshPainter(serie);
|
||||
}
|
||||
}
|
||||
|
||||
protected void DrawVisualMap(VertexHelper vh)
|
||||
{
|
||||
if (!visualMap.enable || !visualMap.show) return;
|
||||
var centerPos = chartPosition + visualMap.location.GetPosition(chartWidth, chartHeight);
|
||||
|
||||
var pos1 = Vector3.zero;
|
||||
var pos2 = Vector3.zero;
|
||||
var dir = Vector3.zero;
|
||||
var halfWid = visualMap.itemWidth / 2;
|
||||
var halfHig = visualMap.itemHeight / 2;
|
||||
var xRadius = 0f;
|
||||
var yRadius = 0f;
|
||||
var splitNum = visualMap.runtimeInRange.Count;
|
||||
var splitWid = visualMap.itemHeight / (splitNum - 1);
|
||||
var isVertical = false;
|
||||
var colors = visualMap.runtimeInRange;
|
||||
var triangeLen = m_Theme.visualMap.triangeLen;
|
||||
switch (visualMap.orient)
|
||||
{
|
||||
case Orient.Horizonal:
|
||||
pos1 = centerPos + Vector3.left * halfHig;
|
||||
pos2 = centerPos + Vector3.right * halfHig;
|
||||
dir = Vector3.right;
|
||||
xRadius = splitWid / 2;
|
||||
yRadius = halfWid;
|
||||
isVertical = false;
|
||||
if (visualMap.calculable)
|
||||
{
|
||||
var p0 = pos1 + Vector3.right * visualMap.runtimeRangeMinHeight;
|
||||
var p1 = p0 + Vector3.up * halfWid;
|
||||
var p2 = p0 + Vector3.up * (halfWid + triangeLen);
|
||||
var p3 = p2 + Vector3.left * triangeLen;
|
||||
var color = visualMap.GetColor(visualMap.rangeMin);
|
||||
UGL.DrawTriangle(vh, p1, p2, p3, color);
|
||||
p0 = pos1 + Vector3.right * visualMap.runtimeRangeMaxHeight;
|
||||
p1 = p0 + Vector3.up * halfWid;
|
||||
p2 = p0 + Vector3.up * (halfWid + triangeLen);
|
||||
p3 = p2 + Vector3.right * triangeLen;
|
||||
color = visualMap.GetColor(visualMap.rangeMax);
|
||||
UGL.DrawTriangle(vh, p1, p2, p3, color);
|
||||
}
|
||||
break;
|
||||
case Orient.Vertical:
|
||||
pos1 = centerPos + Vector3.down * halfHig;
|
||||
pos2 = centerPos + Vector3.up * halfHig;
|
||||
dir = Vector3.up;
|
||||
xRadius = halfWid;
|
||||
yRadius = splitWid / 2;
|
||||
isVertical = true;
|
||||
if (visualMap.calculable)
|
||||
{
|
||||
var p0 = pos1 + Vector3.up * visualMap.runtimeRangeMinHeight;
|
||||
var p1 = p0 + Vector3.right * halfWid;
|
||||
var p2 = p0 + Vector3.right * (halfWid + triangeLen);
|
||||
var p3 = p2 + Vector3.down * triangeLen;
|
||||
var color = visualMap.GetColor(visualMap.rangeMin);
|
||||
UGL.DrawTriangle(vh, p1, p2, p3, color);
|
||||
p0 = pos1 + Vector3.up * visualMap.runtimeRangeMaxHeight;
|
||||
p1 = p0 + Vector3.right * halfWid;
|
||||
p2 = p0 + Vector3.right * (halfWid + triangeLen);
|
||||
p3 = p2 + Vector3.up * triangeLen;
|
||||
color = visualMap.GetColor(visualMap.rangeMax);
|
||||
UGL.DrawTriangle(vh, p1, p2, p3, color);
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (visualMap.calculable && (visualMap.rangeMin > visualMap.min
|
||||
|| visualMap.rangeMax < visualMap.max))
|
||||
{
|
||||
var rangeMin = visualMap.rangeMin;
|
||||
var rangeMax = visualMap.rangeMax;
|
||||
var diff = (visualMap.max - visualMap.min) / (splitNum - 1);
|
||||
for (int i = 1; i < splitNum; i++)
|
||||
{
|
||||
var splitMin = visualMap.min + (i - 1) * diff;
|
||||
var splitMax = splitMin + diff;
|
||||
if (rangeMin > splitMax || rangeMax < splitMin)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
else if (rangeMin <= splitMin && rangeMax >= splitMax)
|
||||
{
|
||||
var splitPos = pos1 + dir * (i - 1 + 0.5f) * splitWid;
|
||||
var startColor = colors[i - 1];
|
||||
var toColor = visualMap.IsPiecewise() ? startColor : colors[i];
|
||||
UGL.DrawRectangle(vh, splitPos, xRadius, yRadius, startColor, toColor, isVertical);
|
||||
}
|
||||
else if (rangeMin > splitMin && rangeMax >= splitMax)
|
||||
{
|
||||
var p0 = pos1 + dir * visualMap.runtimeRangeMinHeight;
|
||||
var splitMaxPos = pos1 + dir * i * splitWid;
|
||||
var splitPos = p0 + (splitMaxPos - p0) / 2;
|
||||
var startColor = visualMap.GetColor(visualMap.rangeMin);
|
||||
var toColor = visualMap.IsPiecewise() ? startColor : colors[i];
|
||||
var yRadius1 = Vector3.Distance(p0, splitMaxPos) / 2;
|
||||
if (visualMap.orient == Orient.Vertical)
|
||||
UGL.DrawRectangle(vh, splitPos, xRadius, yRadius1, startColor, toColor, isVertical);
|
||||
else
|
||||
UGL.DrawRectangle(vh, splitPos, yRadius1, yRadius, startColor, toColor, isVertical);
|
||||
}
|
||||
else if (rangeMax < splitMax && rangeMin <= splitMin)
|
||||
{
|
||||
var p0 = pos1 + dir * visualMap.runtimeRangeMaxHeight;
|
||||
var splitMinPos = pos1 + dir * (i - 1) * splitWid;
|
||||
var splitPos = splitMinPos + (p0 - splitMinPos) / 2;
|
||||
var startColor = colors[i - 1];
|
||||
var toColor = visualMap.IsPiecewise() ? startColor : visualMap.GetColor(visualMap.rangeMax);
|
||||
var yRadius1 = Vector3.Distance(p0, splitMinPos) / 2;
|
||||
if (visualMap.orient == Orient.Vertical)
|
||||
UGL.DrawRectangle(vh, splitPos, xRadius, yRadius1, startColor, toColor, isVertical);
|
||||
else
|
||||
UGL.DrawRectangle(vh, splitPos, yRadius1, yRadius, startColor, toColor, isVertical);
|
||||
}
|
||||
else
|
||||
{
|
||||
var p0 = pos1 + dir * visualMap.runtimeRangeMinHeight;
|
||||
var p1 = pos1 + dir * visualMap.runtimeRangeMaxHeight;
|
||||
var splitPos = (p0 + p1) / 2;
|
||||
var startColor = visualMap.GetColor(visualMap.rangeMin);
|
||||
var toColor = visualMap.GetColor(visualMap.rangeMax);
|
||||
var yRadius1 = Vector3.Distance(p0, p1) / 2;
|
||||
if (visualMap.orient == Orient.Vertical)
|
||||
UGL.DrawRectangle(vh, splitPos, xRadius, yRadius1, startColor, toColor, isVertical);
|
||||
else
|
||||
UGL.DrawRectangle(vh, splitPos, yRadius1, yRadius, startColor, toColor, isVertical);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 1; i < splitNum; i++)
|
||||
{
|
||||
var splitPos = pos1 + dir * (i - 1 + 0.5f) * splitWid;
|
||||
var startColor = colors[i - 1];
|
||||
var toColor = visualMap.IsPiecewise() ? startColor : colors[i];
|
||||
UGL.DrawRectangle(vh, splitPos, xRadius, yRadius, startColor, toColor, isVertical);
|
||||
}
|
||||
}
|
||||
|
||||
if (visualMap.rangeMin > visualMap.min)
|
||||
{
|
||||
var p0 = pos1 + dir * visualMap.runtimeRangeMinHeight;
|
||||
UGL.DrawRectangle(vh, pos1, p0, visualMap.itemWidth / 2, m_Theme.visualMap.backgroundColor);
|
||||
}
|
||||
if (visualMap.rangeMax < visualMap.max)
|
||||
{
|
||||
var p1 = pos1 + dir * visualMap.runtimeRangeMaxHeight;
|
||||
UGL.DrawRectangle(vh, p1, pos2, visualMap.itemWidth / 2, m_Theme.visualMap.backgroundColor);
|
||||
}
|
||||
|
||||
if (visualMap.hoverLink)
|
||||
{
|
||||
if (visualMap.runtimeSelectedIndex >= 0)
|
||||
{
|
||||
var p0 = pos1 + dir * visualMap.runtimeRangeMinHeight;
|
||||
var p1 = pos1 + dir * visualMap.runtimeRangeMaxHeight;
|
||||
|
||||
if (visualMap.orient == Orient.Vertical)
|
||||
{
|
||||
var p2 = new Vector3(centerPos.x + halfWid, Mathf.Clamp(pointerPos.y + (triangeLen / 2), p0.y, p1.y));
|
||||
var p3 = new Vector3(centerPos.x + halfWid, Mathf.Clamp(pointerPos.y - (triangeLen / 2), p0.y, p1.y));
|
||||
var p4 = new Vector3(centerPos.x + halfWid + triangeLen / 2, pointerPos.y);
|
||||
UGL.DrawTriangle(vh, p2, p3, p4, colors[visualMap.runtimeSelectedIndex]);
|
||||
}
|
||||
else
|
||||
{
|
||||
var p2 = new Vector3(Mathf.Clamp(pointerPos.x + (triangeLen / 2), p0.x, p1.x), centerPos.y + halfWid);
|
||||
var p3 = new Vector3(Mathf.Clamp(pointerPos.x - (triangeLen / 2), p0.x, p1.x), centerPos.y + halfWid);
|
||||
var p4 = new Vector3(pointerPos.x, centerPos.y + halfWid + triangeLen / 2);
|
||||
UGL.DrawTriangle(vh, p2, p3, p4, colors[visualMap.runtimeSelectedIndex]);
|
||||
}
|
||||
}
|
||||
else if (tooltip.show && tooltip.runtimeXValues[0] >= 0 && tooltip.runtimeYValues[0] >= 0)
|
||||
{
|
||||
// var p0 = pos1 + dir * m_VisualMap.rangeMinHeight;
|
||||
// var p1 = pos1 + dir * m_VisualMap.rangeMaxHeight;
|
||||
// if (m_VisualMap.orient == Orient.Vertical)
|
||||
// {
|
||||
// var p2 = new Vector3(centerPos.x + halfWid, Mathf.Clamp(pointerPos.y + (triangeLen / 2), p0.y, p1.y));
|
||||
// var p3 = new Vector3(centerPos.x + halfWid, Mathf.Clamp(pointerPos.y - (triangeLen / 2), p0.y, p1.y));
|
||||
// var p4 = new Vector3(centerPos.x + halfWid + triangeLen / 2, pointerPos.y);
|
||||
// UGL.DrawTriangle(vh, p2, p3, p4, colors[m_VisualMap.rtSelectedIndex]);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// var p2 = new Vector3(Mathf.Clamp(pointerPos.x + (triangeLen / 2), p0.x, p1.x), centerPos.y + halfWid);
|
||||
// var p3 = new Vector3(Mathf.Clamp(pointerPos.x - (triangeLen / 2), p0.x, p1.x), centerPos.y + halfWid);
|
||||
// var p4 = new Vector3(pointerPos.x, centerPos.y + halfWid + triangeLen / 2);
|
||||
// UGL.DrawTriangle(vh, p2, p3, p4, colors[m_VisualMap.rtSelectedIndex]);
|
||||
// }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2713cb84109d8491aa61bf37d1fa850e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e81383a033c064b2cbc5f63387113bb3
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,102 @@
|
||||
/************************************************/
|
||||
/* */
|
||||
/* Copyright (c) 2018 - 2021 monitor1394 */
|
||||
/* https://github.com/monitor1394 */
|
||||
/* */
|
||||
/************************************************/
|
||||
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace XCharts
|
||||
{
|
||||
public partial class CoordinateChart
|
||||
{
|
||||
protected void DrawScatterSerie(VertexHelper vh, int colorIndex, Serie serie)
|
||||
{
|
||||
if (serie.animation.HasFadeOut()) return;
|
||||
if (!serie.show) return;
|
||||
var yAxis = m_YAxes[serie.yAxisIndex];
|
||||
var xAxis = m_XAxes[serie.xAxisIndex];
|
||||
var grid = GetSerieGridOrDefault(serie);
|
||||
int maxCount = serie.maxShow > 0 ?
|
||||
(serie.maxShow > serie.dataCount ? serie.dataCount : serie.maxShow)
|
||||
: serie.dataCount;
|
||||
serie.animation.InitProgress(1, 0, 1);
|
||||
var rate = serie.animation.GetCurrRate();
|
||||
var dataChangeDuration = serie.animation.GetUpdateAnimationDuration();
|
||||
var dataChanging = false;
|
||||
var dataList = serie.GetDataList(dataZoom);
|
||||
foreach (var serieData in dataList)
|
||||
{
|
||||
var symbol = SerieHelper.GetSerieSymbol(serie, serieData);
|
||||
if (!symbol.ShowSymbol(serieData.index, maxCount)) continue;
|
||||
var highlight = serie.highlighted || serieData.highlighted;
|
||||
var color = SerieHelper.GetItemColor(serie, serieData, m_Theme, colorIndex, highlight);
|
||||
var toColor = SerieHelper.GetItemToColor(serie, serieData, m_Theme, colorIndex, highlight);
|
||||
var symbolBorder = SerieHelper.GetSymbolBorder(serie, serieData, m_Theme, highlight);
|
||||
var cornerRadius = SerieHelper.GetSymbolCornerRadius(serie, serieData, highlight);
|
||||
float xValue = serieData.GetCurrData(0, dataChangeDuration, xAxis.inverse);
|
||||
float yValue = serieData.GetCurrData(1, dataChangeDuration, yAxis.inverse);
|
||||
if (serieData.IsDataChanged()) dataChanging = true;
|
||||
float pX = grid.runtimeX + xAxis.axisLine.GetWidth(m_Theme.axis.lineWidth);
|
||||
float pY = grid.runtimeY + yAxis.axisLine.GetWidth(m_Theme.axis.lineWidth);
|
||||
float xDataHig = GetDataHig(xAxis, xValue, grid.runtimeWidth);
|
||||
float yDataHig = GetDataHig(yAxis, yValue, grid.runtimeHeight);
|
||||
var pos = new Vector3(pX + xDataHig, pY + yDataHig);
|
||||
serie.dataPoints.Add(pos);
|
||||
serieData.runtimePosition = pos;
|
||||
var datas = serieData.data;
|
||||
float symbolSize = 0;
|
||||
if (serie.highlighted || serieData.highlighted)
|
||||
{
|
||||
symbolSize = symbol.GetSelectedSize(datas, m_Theme.serie.scatterSymbolSelectedSize);
|
||||
}
|
||||
else
|
||||
{
|
||||
symbolSize = symbol.GetSize(datas, m_Theme.serie.scatterSymbolSize);
|
||||
}
|
||||
symbolSize *= rate;
|
||||
if (symbolSize > 100) symbolSize = 100;
|
||||
if (serie.type == SerieType.EffectScatter)
|
||||
{
|
||||
for (int count = 0; count < symbol.animationSize.Count; count++)
|
||||
{
|
||||
var nowSize = symbol.animationSize[count];
|
||||
color.a = (byte)(255 * (symbolSize - nowSize) / symbolSize);
|
||||
DrawSymbol(vh, symbol.type, nowSize, symbolBorder, pos, color, toColor, symbol.gap, cornerRadius);
|
||||
}
|
||||
RefreshPainter(serie);
|
||||
}
|
||||
else
|
||||
{
|
||||
DrawSymbol(vh, symbol.type, symbolSize, symbolBorder, pos, color, toColor, symbol.gap, cornerRadius);
|
||||
}
|
||||
}
|
||||
if (!serie.animation.IsFinish())
|
||||
{
|
||||
serie.animation.CheckProgress(1);
|
||||
m_IsPlayingAnimation = true;
|
||||
RefreshPainter(serie);
|
||||
}
|
||||
if (dataChanging)
|
||||
{
|
||||
RefreshPainter(serie);
|
||||
}
|
||||
}
|
||||
|
||||
private float GetDataHig(Axis axis, float value, float totalWidth)
|
||||
{
|
||||
if (axis.IsLog())
|
||||
{
|
||||
int minIndex = axis.runtimeMinLogIndex;
|
||||
float nowIndex = axis.GetLogValue(value);
|
||||
return (nowIndex - minIndex) / (axis.splitNumber - 1) * totalWidth;
|
||||
}
|
||||
else
|
||||
{
|
||||
return (value - axis.runtimeMinValue) / (axis.runtimeMaxValue - axis.runtimeMinValue) * totalWidth;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2f06734940c9e4f92897bb83573394a7
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,408 @@
|
||||
/************************************************/
|
||||
/* */
|
||||
/* Copyright (c) 2018 - 2021 monitor1394 */
|
||||
/* https://github.com/monitor1394 */
|
||||
/* */
|
||||
/************************************************/
|
||||
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using UnityEngine.EventSystems;
|
||||
using XUGL;
|
||||
|
||||
namespace XCharts
|
||||
{
|
||||
internal class DrawSerieGauge : IDrawSerie
|
||||
{
|
||||
public BaseChart chart;
|
||||
|
||||
private static readonly string s_SerieLabelObjectName = "label";
|
||||
private static readonly string s_AxisLabelObjectName = "axis_label";
|
||||
private bool m_UpdateTitleText = false;
|
||||
private bool m_UpdateLabelText = false;
|
||||
|
||||
public DrawSerieGauge(BaseChart chart)
|
||||
{
|
||||
this.chart = chart;
|
||||
}
|
||||
|
||||
public void InitComponent()
|
||||
{
|
||||
InitAxisLabel();
|
||||
}
|
||||
|
||||
public void CheckComponent()
|
||||
{
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
if (m_UpdateTitleText)
|
||||
{
|
||||
m_UpdateTitleText = false;
|
||||
|
||||
foreach (var serie in chart.series.list)
|
||||
{
|
||||
if (serie.type == SerieType.Gauge)
|
||||
{
|
||||
TitleStyleHelper.UpdateTitleText(serie);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (m_UpdateLabelText)
|
||||
{
|
||||
m_UpdateLabelText = false;
|
||||
foreach (var serie in chart.series.list)
|
||||
{
|
||||
if (serie.type == SerieType.Gauge)
|
||||
{
|
||||
SerieLabelHelper.SetGaugeLabelText(serie);
|
||||
UpdateAxisLabel(serie);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void DrawBase(VertexHelper vh)
|
||||
{
|
||||
}
|
||||
|
||||
public void DrawSerie(VertexHelper vh, Serie serie)
|
||||
{
|
||||
if (serie.type != SerieType.Gauge) return;
|
||||
DrawGauge(vh, serie);
|
||||
}
|
||||
|
||||
public void RefreshLabel()
|
||||
{
|
||||
}
|
||||
|
||||
public bool CheckTootipArea(Vector2 local)
|
||||
{
|
||||
var serie = GetPointerInSerieIndex(chart.series, local);
|
||||
if (serie != null)
|
||||
{
|
||||
chart.tooltip.runtimeDataIndex.Clear();
|
||||
chart.tooltip.runtimeDataIndex.Add(serie.index);
|
||||
chart.tooltip.UpdateContentPos(local + chart.tooltip.offset);
|
||||
UpdateTooltip();
|
||||
return true;
|
||||
}
|
||||
else if (chart.tooltip.IsActive())
|
||||
{
|
||||
chart.tooltip.SetActive(false);
|
||||
chart.RefreshChart();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool OnLegendButtonClick(int index, string legendName, bool show)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool OnLegendButtonEnter(int index, string legendName)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool OnLegendButtonExit(int index, string legendName)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public void OnPointerDown(PointerEventData eventData)
|
||||
{
|
||||
}
|
||||
|
||||
private void InitAxisLabel()
|
||||
{
|
||||
if (!SeriesHelper.ContainsSerie(chart.series, SerieType.Gauge)) return;
|
||||
var labelObject = ChartHelper.AddObject(s_AxisLabelObjectName, chart.transform, chart.chartMinAnchor,
|
||||
chart.chartMaxAnchor, chart.chartPivot, chart.chartSizeDelta);
|
||||
labelObject.hideFlags = chart.chartHideFlags;
|
||||
SerieLabelPool.ReleaseAll(labelObject.transform);
|
||||
for (int i = 0; i < chart.series.Count; i++)
|
||||
{
|
||||
var serie = chart.series.list[i];
|
||||
var serieLabel = serie.gaugeAxis.axisLabel;
|
||||
var count = serie.splitNumber > 36 ? 36 : (serie.splitNumber + 1);
|
||||
var startAngle = serie.startAngle;
|
||||
serie.gaugeAxis.ClearLabelObject();
|
||||
SerieHelper.UpdateCenter(serie, chart.chartPosition, chart.chartWidth, chart.chartHeight);
|
||||
for (int j = 0; j < count; j++)
|
||||
{
|
||||
var textName = ChartCached.GetSerieLabelName(s_SerieLabelObjectName, i, j);
|
||||
var color = Color.grey;
|
||||
var labelObj = SerieLabelPool.Get(textName, labelObject.transform, serieLabel, color, 100, 100, chart.theme);
|
||||
var iconImage = labelObj.transform.Find("Icon").GetComponent<Image>();
|
||||
var isAutoSize = serieLabel.backgroundWidth == 0 || serieLabel.backgroundHeight == 0;
|
||||
var item = new ChartLabel();
|
||||
item.SetLabel(labelObj, isAutoSize, serieLabel.paddingLeftRight, serieLabel.paddingTopBottom);
|
||||
item.SetIcon(iconImage);
|
||||
item.SetIconActive(false);
|
||||
serie.gaugeAxis.AddLabelObject(item);
|
||||
}
|
||||
UpdateAxisLabel(serie);
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateAxisLabel()
|
||||
{
|
||||
foreach (var serie in chart.series.list)
|
||||
{
|
||||
if (serie.type == SerieType.Gauge)
|
||||
{
|
||||
UpdateAxisLabel(serie);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateAxisLabel(Serie serie)
|
||||
{
|
||||
var show = serie.gaugeAxis.show && serie.gaugeAxis.axisLabel.show;
|
||||
serie.gaugeAxis.SetLabelObjectActive(show);
|
||||
if (!show)
|
||||
{
|
||||
return;
|
||||
}
|
||||
var count = serie.splitNumber > 36 ? 36 : serie.splitNumber;
|
||||
var startAngle = serie.startAngle;
|
||||
var totalAngle = serie.endAngle - serie.startAngle;
|
||||
var totalValue = serie.max - serie.min;
|
||||
var diffAngle = totalAngle / count;
|
||||
var diffValue = totalValue / count;
|
||||
var radius = serie.runtimeInsideRadius - serie.gaugeAxis.axisLabel.margin;
|
||||
var serieData = serie.GetSerieData(0);
|
||||
var customLabelText = serie.gaugeAxis.axisLabelText;
|
||||
for (int j = 0; j <= count; j++)
|
||||
{
|
||||
var angle = serie.startAngle + j * diffAngle;
|
||||
var value = serie.min + j * diffValue;
|
||||
var pos = ChartHelper.GetPosition(serie.runtimeCenterPos, angle, radius);
|
||||
var text = customLabelText != null && j < customLabelText.Count ? customLabelText[j] :
|
||||
SerieLabelHelper.GetFormatterContent(serie, serieData, value, totalValue, serie.gaugeAxis.axisLabel);
|
||||
serie.gaugeAxis.SetLabelObjectText(j, text);
|
||||
serie.gaugeAxis.SetLabelObjectPosition(j, pos);
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawGauge(VertexHelper vh, Serie serie)
|
||||
{
|
||||
SerieHelper.UpdateCenter(serie, chart.chartPosition, chart.chartWidth, chart.chartHeight);
|
||||
var destAngle = GetCurrAngle(serie, true);
|
||||
serie.animation.InitProgress(0, serie.startAngle, destAngle);
|
||||
var currAngle = serie.animation.IsFinish() ? GetCurrAngle(serie, false) : serie.animation.GetCurrDetail();
|
||||
DrawProgressBar(vh, serie, currAngle);
|
||||
DrawStageColor(vh, serie);
|
||||
DrawLineStyle(vh, serie);
|
||||
DrawAxisTick(vh, serie);
|
||||
DrawPointer(vh, serie, currAngle);
|
||||
TitleStyleHelper.CheckTitle(serie, ref chart.m_ReinitTitle, ref m_UpdateTitleText);
|
||||
SerieLabelHelper.CheckLabel(serie, ref chart.m_ReinitLabel, ref m_UpdateLabelText);
|
||||
CheckAnimation(serie);
|
||||
if (!serie.animation.IsFinish())
|
||||
{
|
||||
serie.animation.CheckProgress(destAngle - serie.startAngle);
|
||||
chart.RefreshPainter(serie);
|
||||
}
|
||||
else if (NeedRefresh(serie))
|
||||
{
|
||||
chart.RefreshPainter(serie);
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawProgressBar(VertexHelper vh, Serie serie, float currAngle)
|
||||
{
|
||||
if (serie.gaugeType != GaugeType.ProgressBar) return;
|
||||
if (!serie.gaugeAxis.show || !serie.gaugeAxis.axisLine.show) return;
|
||||
var color = serie.gaugeAxis.GetAxisLineColor(chart.theme, serie.index);
|
||||
var backgroundColor = serie.gaugeAxis.GetAxisLineBackgroundColor(chart.theme, serie.index);
|
||||
var lineWidth = serie.gaugeAxis.axisLine.GetWidth(chart.theme.gauge.lineWidth);
|
||||
var outsideRadius = serie.runtimeInsideRadius + lineWidth;
|
||||
var borderWidth = serie.itemStyle.borderWidth;
|
||||
var borderColor = serie.itemStyle.borderColor;
|
||||
UGL.DrawDoughnut(vh, serie.runtimeCenterPos, serie.runtimeInsideRadius, outsideRadius,
|
||||
backgroundColor, backgroundColor, Color.clear, serie.startAngle, serie.endAngle, 0, Color.clear,
|
||||
0, chart.settings.cicleSmoothness, serie.roundCap);
|
||||
UGL.DrawDoughnut(vh, serie.runtimeCenterPos, serie.runtimeInsideRadius, outsideRadius,
|
||||
color, color, Color.clear, serie.startAngle, currAngle, 0, Color.clear,
|
||||
0, chart.settings.cicleSmoothness, serie.roundCap);
|
||||
}
|
||||
|
||||
private void DrawStageColor(VertexHelper vh, Serie serie)
|
||||
{
|
||||
if (serie.gaugeType != GaugeType.Pointer) return;
|
||||
if (!serie.gaugeAxis.show || !serie.gaugeAxis.axisLine.show) return;
|
||||
var totalAngle = serie.endAngle - serie.startAngle;
|
||||
var tempStartAngle = serie.startAngle;
|
||||
var tempEndAngle = serie.startAngle;
|
||||
var lineWidth = serie.gaugeAxis.axisLine.GetWidth(chart.theme.gauge.lineWidth);
|
||||
var outsideRadius = serie.runtimeInsideRadius + lineWidth;
|
||||
serie.gaugeAxis.runtimeStageAngle.Clear();
|
||||
for (int i = 0; i < serie.gaugeAxis.axisLine.stageColor.Count; i++)
|
||||
{
|
||||
var stageColor = serie.gaugeAxis.axisLine.stageColor[i];
|
||||
tempEndAngle = serie.startAngle + totalAngle * stageColor.percent;
|
||||
serie.gaugeAxis.runtimeStageAngle.Add(tempEndAngle);
|
||||
UGL.DrawDoughnut(vh, serie.runtimeCenterPos, serie.runtimeInsideRadius, outsideRadius,
|
||||
stageColor.color, stageColor.color, Color.clear, tempStartAngle, tempEndAngle, 0, Color.clear,
|
||||
0, chart.settings.cicleSmoothness);
|
||||
tempStartAngle = tempEndAngle;
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawPointer(VertexHelper vh, Serie serie, float currAngle)
|
||||
{
|
||||
if (!serie.gaugePointer.show) return;
|
||||
var pointerColor = serie.gaugeAxis.GetPointerColor(chart.theme, serie.index, currAngle, serie.itemStyle);
|
||||
var pointerToColor = !ChartHelper.IsClearColor(serie.itemStyle.toColor) ? serie.itemStyle.toColor : pointerColor;
|
||||
var len = serie.gaugePointer.length < 1 && serie.gaugePointer.length > -1 ?
|
||||
serie.runtimeInsideRadius * serie.gaugePointer.length :
|
||||
serie.gaugePointer.length;
|
||||
var p1 = ChartHelper.GetPosition(serie.runtimeCenterPos, currAngle, len);
|
||||
var p2 = ChartHelper.GetPosition(serie.runtimeCenterPos, currAngle + 180, serie.gaugePointer.width);
|
||||
var p3 = ChartHelper.GetPosition(serie.runtimeCenterPos, currAngle - 90, serie.gaugePointer.width / 2);
|
||||
var p4 = ChartHelper.GetPosition(serie.runtimeCenterPos, currAngle + 90, serie.gaugePointer.width / 2);
|
||||
UGL.DrawTriangle(vh, p2, p3, p1, pointerColor, pointerColor, pointerToColor);
|
||||
UGL.DrawTriangle(vh, p4, p2, p1, pointerColor, pointerColor, pointerToColor);
|
||||
}
|
||||
|
||||
private void DrawLineStyle(VertexHelper vh, Serie serie)
|
||||
{
|
||||
if (serie.gaugeType != GaugeType.Pointer) return;
|
||||
if (!serie.gaugeAxis.show || !serie.gaugeAxis.splitLine.show) return;
|
||||
if (serie.splitNumber <= 0) return;
|
||||
var splitLine = serie.gaugeAxis.splitLine;
|
||||
var totalAngle = serie.endAngle - serie.startAngle;
|
||||
var diffAngle = totalAngle / serie.splitNumber;
|
||||
var lineWidth = serie.gaugeAxis.axisLine.GetWidth(chart.theme.gauge.lineWidth);
|
||||
var splitLineWidth = splitLine.GetWidth(chart.theme.gauge.splitLineWidth);
|
||||
var splitLineLength = splitLine.GetLength(chart.theme.gauge.splitLineLength);
|
||||
var outsideRadius = serie.runtimeInsideRadius + lineWidth;
|
||||
var insideRadius = outsideRadius - splitLineLength;
|
||||
for (int i = 0; i < serie.splitNumber + 1; i++)
|
||||
{
|
||||
var angle = serie.startAngle + i * diffAngle;
|
||||
var lineColor = serie.gaugeAxis.GetSplitLineColor(chart.theme.gauge.splitLineColor, serie.index, angle);
|
||||
var p1 = ChartHelper.GetPosition(serie.runtimeCenterPos, angle, insideRadius);
|
||||
var p2 = ChartHelper.GetPosition(serie.runtimeCenterPos, angle, outsideRadius);
|
||||
UGL.DrawLine(vh, p1, p2, splitLineWidth, lineColor);
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawAxisTick(VertexHelper vh, Serie serie)
|
||||
{
|
||||
if (serie.gaugeType != GaugeType.Pointer) return;
|
||||
if (!serie.gaugeAxis.show || !serie.gaugeAxis.axisTick.show) return;
|
||||
if (serie.splitNumber <= 0) return;
|
||||
var axisTick = serie.gaugeAxis.axisTick;
|
||||
var totalAngle = serie.endAngle - serie.startAngle;
|
||||
var diffAngle = totalAngle / serie.splitNumber;
|
||||
var lineWidth = serie.gaugeAxis.axisLine.GetWidth(chart.theme.gauge.lineWidth);
|
||||
var tickWidth = axisTick.GetWidth(chart.theme.gauge.tickWidth);
|
||||
var tickLength = axisTick.GetLength(chart.theme.gauge.tickLength);
|
||||
var outsideRadius = serie.runtimeInsideRadius + lineWidth;
|
||||
|
||||
var insideRadius = outsideRadius - (tickLength < 1 ? lineWidth * tickLength : tickLength);
|
||||
for (int i = 0; i < serie.splitNumber; i++)
|
||||
{
|
||||
for (int j = 1; j < axisTick.splitNumber; j++)
|
||||
{
|
||||
var angle = serie.startAngle + i * diffAngle + j * (diffAngle / axisTick.splitNumber);
|
||||
var lineColor = serie.gaugeAxis.GetSplitLineColor(chart.theme.gauge.tickColor, serie.index, angle);
|
||||
var p1 = ChartHelper.GetPosition(serie.runtimeCenterPos, angle, insideRadius);
|
||||
var p2 = ChartHelper.GetPosition(serie.runtimeCenterPos, angle, outsideRadius);
|
||||
UGL.DrawLine(vh, p1, p2, tickWidth, lineColor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private float GetCurrAngle(Serie serie, bool dest)
|
||||
{
|
||||
if (serie.animation.HasFadeOut())
|
||||
{
|
||||
return serie.animation.GetCurrDetail();
|
||||
}
|
||||
float rangeValue = serie.max - serie.min;
|
||||
float rangeAngle = serie.endAngle - serie.startAngle;
|
||||
float value = 0;
|
||||
float angle = serie.startAngle;
|
||||
if (serie.dataCount > 0)
|
||||
{
|
||||
var serieData = serie.data[0];
|
||||
serieData.labelPosition = serie.runtimeCenterPos + serie.label.offset;
|
||||
value = dest ? serieData.GetData(1)
|
||||
: serieData.GetCurrData(1, serie.animation.GetUpdateAnimationDuration());
|
||||
value = Mathf.Clamp(value, serie.min, serie.max);
|
||||
}
|
||||
if (rangeValue > 0)
|
||||
{
|
||||
angle += rangeAngle * value / rangeValue;
|
||||
}
|
||||
return angle;
|
||||
}
|
||||
|
||||
private void CheckAnimation(Serie serie)
|
||||
{
|
||||
var serieData = serie.GetSerieData(0);
|
||||
if (serieData != null)
|
||||
{
|
||||
var value = serieData.GetCurrData(1, serie.animation.GetUpdateAnimationDuration());
|
||||
var data = serieData.GetData(1);
|
||||
if (value != data) chart.RefreshPainter(serie);
|
||||
}
|
||||
}
|
||||
|
||||
private bool NeedRefresh(Serie serie)
|
||||
{
|
||||
if (serie.type == SerieType.Gauge)
|
||||
{
|
||||
var serieData = serie.GetSerieData(0);
|
||||
if (serieData != null)
|
||||
{
|
||||
var destValue = serieData.GetData(1);
|
||||
var currValue = serieData.GetCurrData(1, serie.animation.GetUpdateAnimationDuration());
|
||||
return destValue != currValue;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private Serie GetPointerInSerieIndex(Series series, Vector2 local)
|
||||
{
|
||||
foreach (var serie in series.list)
|
||||
{
|
||||
if (serie.type != SerieType.Gauge) continue;
|
||||
if (!serie.gaugePointer.show) continue;
|
||||
var len = serie.gaugePointer.length < 1 && serie.gaugePointer.length > -1
|
||||
? serie.runtimeInsideRadius * serie.gaugePointer.length
|
||||
: serie.gaugePointer.length;
|
||||
if (Vector3.Distance(local, serie.runtimeCenterPos) > len) continue;
|
||||
var currAngle = serie.animation.IsFinish() ? GetCurrAngle(serie, false) : serie.animation.GetCurrDetail();
|
||||
var p1 = ChartHelper.GetPosition(serie.runtimeCenterPos, currAngle, len);
|
||||
var p2 = ChartHelper.GetPosition(serie.runtimeCenterPos, currAngle + 180, serie.gaugePointer.width);
|
||||
var p3 = ChartHelper.GetPosition(serie.runtimeCenterPos, currAngle - 90, serie.gaugePointer.width / 2);
|
||||
var p4 = ChartHelper.GetPosition(serie.runtimeCenterPos, currAngle + 90, serie.gaugePointer.width / 2);
|
||||
if (ChartHelper.IsPointInQuadrilateral(local, p1, p3, p2, p4))
|
||||
{
|
||||
return serie;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void UpdateTooltip()
|
||||
{
|
||||
int index = chart.tooltip.runtimeDataIndex[0];
|
||||
if (index < 0)
|
||||
{
|
||||
chart.tooltip.SetActive(false);
|
||||
return;
|
||||
}
|
||||
var content = TooltipHelper.GetFormatterContent(chart.tooltip, index, chart.series, chart.theme);
|
||||
TooltipHelper.SetContentAndPosition(chart.tooltip, content.TrimStart(), chart.chartRect);
|
||||
chart.tooltip.SetActive(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ca6e74d36e80c4daabf80b165986dfbb
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,259 @@
|
||||
/************************************************/
|
||||
/* */
|
||||
/* Copyright (c) 2018 - 2021 monitor1394 */
|
||||
/* https://github.com/monitor1394 */
|
||||
/* */
|
||||
/************************************************/
|
||||
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using UnityEngine.EventSystems;
|
||||
using XUGL;
|
||||
|
||||
namespace XCharts
|
||||
{
|
||||
internal class DrawSerieLiquid : IDrawSerie
|
||||
{
|
||||
public BaseChart chart;
|
||||
private bool m_UpdateLabelText = false;
|
||||
|
||||
public DrawSerieLiquid(BaseChart chart)
|
||||
{
|
||||
this.chart = chart;
|
||||
}
|
||||
|
||||
public void InitComponent()
|
||||
{
|
||||
//UpdateRuntimeData();
|
||||
//SerieLabelHelper.UpdateLabelText(chart.series, chart.theme, m_LegendRealShowName);
|
||||
}
|
||||
|
||||
public void CheckComponent()
|
||||
{
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
if (m_UpdateLabelText)
|
||||
{
|
||||
m_UpdateLabelText = false;
|
||||
foreach (var serie in chart.series.list)
|
||||
{
|
||||
if (serie.type == SerieType.Liquid)
|
||||
{
|
||||
var colorIndex = chart.m_LegendRealShowName.IndexOf(serie.name);
|
||||
SerieLabelHelper.SetLiquidLabelText(serie, chart.theme, colorIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void DrawBase(VertexHelper vh)
|
||||
{
|
||||
}
|
||||
|
||||
public void DrawSerie(VertexHelper vh, Serie serie)
|
||||
{
|
||||
if (serie.type != SerieType.Liquid) return;
|
||||
UpdateRuntimeData(serie);
|
||||
DrawVesselBackground(vh, serie);
|
||||
DrawLiquid(vh, serie);
|
||||
DrawVessel(vh, serie);
|
||||
}
|
||||
|
||||
public void RefreshLabel()
|
||||
{
|
||||
}
|
||||
|
||||
public bool CheckTootipArea(Vector2 local)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool OnLegendButtonClick(int index, string legendName, bool show)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool OnLegendButtonEnter(int index, string legendName)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool OnLegendButtonExit(int index, string legendName)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public void OnPointerDown(PointerEventData eventData)
|
||||
{
|
||||
}
|
||||
|
||||
private void UpdateRuntimeData()
|
||||
{
|
||||
foreach (var vessel in chart.vessels)
|
||||
{
|
||||
VesselHelper.UpdateVesselCenter(vessel, chart.chartPosition, chart.chartWidth, chart.chartHeight);
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateRuntimeData(Serie serie)
|
||||
{
|
||||
var vessel = chart.GetVessel(serie.vesselIndex);
|
||||
if (vessel != null)
|
||||
{
|
||||
VesselHelper.UpdateVesselCenter(vessel, chart.chartPosition, chart.chartWidth, chart.chartHeight);
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawVesselBackground(VertexHelper vh, Serie serie)
|
||||
{
|
||||
var vessel = chart.GetVessel(serie.vesselIndex);
|
||||
if (vessel != null)
|
||||
{
|
||||
if (vessel.backgroundColor.a != 0)
|
||||
{
|
||||
var cenPos = vessel.runtimeCenterPos;
|
||||
var radius = vessel.runtimeRadius;
|
||||
UGL.DrawCricle(vh, cenPos, vessel.runtimeInnerRadius, vessel.backgroundColor, chart.settings.cicleSmoothness);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawVessel(VertexHelper vh, Serie serie)
|
||||
{
|
||||
var vessel = chart.GetVessel(serie.vesselIndex);
|
||||
if (vessel != null)
|
||||
{
|
||||
DrawCirleVessel(vh, vessel);
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawCirleVessel(VertexHelper vh, Vessel vessel)
|
||||
{
|
||||
var cenPos = vessel.runtimeCenterPos;
|
||||
var radius = vessel.runtimeRadius;
|
||||
var serie = SeriesHelper.GetSerieByVesselIndex(chart.series, vessel.index);
|
||||
var vesselColor = VesselHelper.GetColor(vessel, serie, chart.theme, chart.m_LegendRealShowName);
|
||||
UGL.DrawDoughnut(vh, cenPos, radius - vessel.shapeWidth, radius, vesselColor, Color.clear, chart.settings.cicleSmoothness);
|
||||
}
|
||||
|
||||
private void DrawLiquid(VertexHelper vh, Serie serie)
|
||||
{
|
||||
if (!serie.show) return;
|
||||
if (serie.animation.HasFadeOut()) return;
|
||||
var vessel = chart.GetVessel(serie.vesselIndex);
|
||||
if (vessel == null) return;
|
||||
var cenPos = vessel.runtimeCenterPos;
|
||||
var radius = vessel.runtimeInnerRadius;
|
||||
var serieData = serie.GetSerieData(0);
|
||||
if (serieData == null) return;
|
||||
var dataChangeDuration = serie.animation.GetUpdateAnimationDuration();
|
||||
var value = serieData.GetCurrData(1, dataChangeDuration);
|
||||
if (serie.runtimeCheckValue != value)
|
||||
{
|
||||
serie.runtimeCheckValue = value;
|
||||
m_UpdateLabelText = true;
|
||||
}
|
||||
if (serieData.labelPosition != cenPos)
|
||||
{
|
||||
serieData.labelPosition = cenPos;
|
||||
m_UpdateLabelText = true;
|
||||
}
|
||||
if (value == 0) return;
|
||||
var colorIndex = chart.m_LegendRealShowName.IndexOf(serie.name);
|
||||
|
||||
var realHig = (value - serie.min) / (serie.max - serie.min) * radius * 2;
|
||||
serie.animation.InitProgress(1, 0, realHig);
|
||||
|
||||
var hig = serie.animation.IsFinish() ? realHig : serie.animation.GetCurrDetail();
|
||||
var a = Mathf.Abs(radius - hig + (hig > radius ? serie.waveHeight : -serie.waveHeight));
|
||||
var diff = Mathf.Sqrt(radius * radius - Mathf.Pow(a, 2));
|
||||
|
||||
var color = SerieHelper.GetItemColor(serie, serieData, chart.theme, colorIndex, false);
|
||||
var toColor = SerieHelper.GetItemToColor(serie, serieData, chart.theme, colorIndex, false);
|
||||
var isNeedGradient = !ChartHelper.IsValueEqualsColor(color, toColor);
|
||||
var isFull = hig >= 2 * radius;
|
||||
if (hig >= 2 * radius) hig = 2 * radius;
|
||||
if (isFull && !isNeedGradient)
|
||||
{
|
||||
UGL.DrawCricle(vh, cenPos, radius, toColor, chart.settings.cicleSmoothness);
|
||||
}
|
||||
else
|
||||
{
|
||||
var startY = cenPos.y - radius + hig;
|
||||
var waveStartPos = new Vector3(cenPos.x - diff, startY);
|
||||
var waveEndPos = new Vector3(cenPos.x + diff, startY);
|
||||
var startX = hig > radius ? cenPos.x - radius : waveStartPos.x;
|
||||
var endX = hig > radius ? cenPos.x + radius : waveEndPos.x;
|
||||
|
||||
var step = vessel.smoothness;
|
||||
if (step < 0.5f) step = 0.5f;
|
||||
var lup = hig > radius ? new Vector3(cenPos.x - radius, cenPos.y) : waveStartPos;
|
||||
var ldp = lup;
|
||||
var nup = Vector3.zero;
|
||||
var ndp = Vector3.zero;
|
||||
var angle = 0f;
|
||||
serie.runtimeWaveSpeed += serie.waveSpeed * Time.deltaTime;
|
||||
var isStarted = false;
|
||||
var isEnded = false;
|
||||
var waveHeight = isFull ? 0 : serie.waveHeight;
|
||||
while (startX < endX)
|
||||
{
|
||||
startX += step;
|
||||
if (startX > endX) startX = endX;
|
||||
if (startX > waveStartPos.x && !isStarted)
|
||||
{
|
||||
startX = waveStartPos.x;
|
||||
isStarted = true;
|
||||
}
|
||||
if (startX > waveEndPos.x && !isEnded)
|
||||
{
|
||||
startX = waveEndPos.x;
|
||||
isEnded = true;
|
||||
}
|
||||
var py = Mathf.Sqrt(Mathf.Pow(radius, 2) - Mathf.Pow(Mathf.Abs(cenPos.x - startX), 2));
|
||||
if (startX < waveStartPos.x || startX > waveEndPos.x)
|
||||
{
|
||||
nup = new Vector3(startX, cenPos.y + py);
|
||||
}
|
||||
else
|
||||
{
|
||||
var py2 = waveHeight * Mathf.Sin(1 / serie.waveLength * angle + serie.runtimeWaveSpeed + serie.waveOffset);
|
||||
var nupY = waveStartPos.y + py2;
|
||||
if (nupY > cenPos.y + py) nupY = cenPos.y + py;
|
||||
else if (nupY < cenPos.y - py) nupY = cenPos.y - py;
|
||||
nup = new Vector3(startX, nupY);
|
||||
angle += step;
|
||||
}
|
||||
ndp = new Vector3(startX, cenPos.y - py);
|
||||
if (!ChartHelper.IsValueEqualsColor(color, toColor))
|
||||
{
|
||||
var colorMin = cenPos.y - radius;
|
||||
var colorMax = startY + serie.waveHeight;
|
||||
var tcolor1 = Color32.Lerp(color, toColor, 1 - (lup.y - colorMin) / (colorMax - colorMin));
|
||||
var tcolor2 = Color32.Lerp(color, toColor, 1 - (ldp.y - colorMin) / (colorMax - colorMin));
|
||||
UGL.DrawQuadrilateral(vh, lup, nup, ndp, ldp, tcolor1, tcolor2);
|
||||
}
|
||||
else
|
||||
{
|
||||
UGL.DrawQuadrilateral(vh, lup, nup, ndp, ldp, color);
|
||||
}
|
||||
lup = nup;
|
||||
ldp = ndp;
|
||||
}
|
||||
}
|
||||
|
||||
if (serie.waveSpeed != 0 && Application.isPlaying && !isFull)
|
||||
{
|
||||
chart.RefreshPainter(serie);
|
||||
}
|
||||
if (!serie.animation.IsFinish())
|
||||
{
|
||||
serie.animation.CheckProgress(realHig);
|
||||
chart.m_IsPlayingAnimation = true;
|
||||
chart.RefreshPainter(serie);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5e68718d39a3042ffb8162149246ef5e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,608 @@
|
||||
/************************************************/
|
||||
/* */
|
||||
/* Copyright (c) 2018 - 2021 monitor1394 */
|
||||
/* https://github.com/monitor1394 */
|
||||
/* */
|
||||
/************************************************/
|
||||
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using UnityEngine.EventSystems;
|
||||
using XUGL;
|
||||
|
||||
namespace XCharts
|
||||
{
|
||||
internal class DrawSeriePie : IDrawSerie
|
||||
{
|
||||
public BaseChart chart;
|
||||
protected bool m_IsEnterPieLegendButtom;
|
||||
|
||||
public DrawSeriePie(BaseChart chart)
|
||||
{
|
||||
this.chart = chart;
|
||||
}
|
||||
|
||||
public void InitComponent()
|
||||
{
|
||||
}
|
||||
|
||||
public void CheckComponent()
|
||||
{
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
}
|
||||
|
||||
public void DrawBase(VertexHelper vh)
|
||||
{
|
||||
}
|
||||
|
||||
public void DrawSerie(VertexHelper vh, Serie serie)
|
||||
{
|
||||
if (serie.type != SerieType.Pie) return;
|
||||
UpdateRuntimeData(serie);
|
||||
DrawPieLabelLine(vh, serie);
|
||||
DrawPie(vh, serie);
|
||||
DrawPieLabelBackground(vh, serie);
|
||||
}
|
||||
|
||||
public void RefreshLabel()
|
||||
{
|
||||
int serieNameCount = -1;
|
||||
for (int i = 0; i < chart.series.Count; i++)
|
||||
{
|
||||
var serie = chart.series.list[i];
|
||||
serie.index = i;
|
||||
if (!serie.show || serie.type != SerieType.Pie) continue;
|
||||
var data = serie.data;
|
||||
for (int n = 0; n < data.Count; n++)
|
||||
{
|
||||
var serieData = data[n];
|
||||
if (!serieData.canShowLabel || serie.IsIgnoreValue(serieData.GetData(1)))
|
||||
{
|
||||
serieData.SetLabelActive(false);
|
||||
continue;
|
||||
}
|
||||
if (!serieData.show) continue;
|
||||
|
||||
serieNameCount = chart.m_LegendRealShowName.IndexOf(serieData.name);
|
||||
Color color = chart.theme.GetColor(serieNameCount);
|
||||
DrawPieLabel(serie, n, serieData, color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool CheckTootipArea(Vector2 local)
|
||||
{
|
||||
if (!PointerIsInPieSerie(chart.series, local)) return false;
|
||||
bool selected = false;
|
||||
chart.tooltip.runtimeDataIndex.Clear();
|
||||
foreach (var serie in chart.series.list)
|
||||
{
|
||||
int index = GetPiePosIndex(serie, local);
|
||||
chart.tooltip.runtimeDataIndex.Add(index);
|
||||
if (serie.type != SerieType.Pie) continue;
|
||||
bool refresh = false;
|
||||
for (int j = 0; j < serie.data.Count; j++)
|
||||
{
|
||||
var serieData = serie.data[j];
|
||||
if (serieData.highlighted != (j == index)) refresh = true;
|
||||
serieData.highlighted = j == index;
|
||||
}
|
||||
if (index >= 0) selected = true;
|
||||
if (refresh) chart.RefreshChart();
|
||||
}
|
||||
if (selected)
|
||||
{
|
||||
chart.tooltip.UpdateContentPos(local + chart.tooltip.offset);
|
||||
UpdatePieTooltip();
|
||||
}
|
||||
else if (chart.tooltip.IsActive())
|
||||
{
|
||||
chart.tooltip.SetActive(false);
|
||||
chart.RefreshChart();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool OnLegendButtonClick(int index, string legendName, bool show)
|
||||
{
|
||||
if (!SeriesHelper.ContainsSerie(chart.series, SerieType.Pie)) return false;
|
||||
if (!LegendHelper.IsSerieLegend(chart.series, legendName, SerieType.Pie)) return false;
|
||||
LegendHelper.CheckDataShow(chart.series, legendName, show);
|
||||
chart.UpdateLegendColor(legendName, show);
|
||||
chart.RefreshChart();
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool OnLegendButtonEnter(int index, string legendName)
|
||||
{
|
||||
if (!SeriesHelper.ContainsSerie(chart.series, SerieType.Pie)) return false;
|
||||
if (!LegendHelper.IsSerieLegend(chart.series, legendName, SerieType.Pie)) return false;
|
||||
m_IsEnterPieLegendButtom = true;
|
||||
LegendHelper.CheckDataHighlighted(chart.series, legendName, true);
|
||||
chart.RefreshChart();
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool OnLegendButtonExit(int index, string legendName)
|
||||
{
|
||||
if (!SeriesHelper.ContainsSerie(chart.series, SerieType.Pie)) return false;
|
||||
if (!LegendHelper.IsSerieLegend(chart.series, legendName, SerieType.Pie)) return false;
|
||||
m_IsEnterPieLegendButtom = false;
|
||||
LegendHelper.CheckDataHighlighted(chart.series, legendName, false);
|
||||
chart.RefreshChart();
|
||||
return true;
|
||||
}
|
||||
|
||||
public void OnPointerDown(PointerEventData eventData)
|
||||
{
|
||||
if (!SeriesHelper.ContainsSerie(chart.series, SerieType.Pie)) return;
|
||||
if (chart.pointerPos == Vector2.zero) return;
|
||||
var refresh = false;
|
||||
for (int i = 0; i < chart.series.Count; i++)
|
||||
{
|
||||
var serie = chart.series.GetSerie(i);
|
||||
if (serie.type != SerieType.Pie) continue;
|
||||
var index = GetPiePosIndex(serie, chart.pointerPos);
|
||||
if (index >= 0)
|
||||
{
|
||||
refresh = true;
|
||||
for (int j = 0; j < serie.data.Count; j++)
|
||||
{
|
||||
if (j == index) serie.data[j].selected = !serie.data[j].selected;
|
||||
else serie.data[j].selected = false;
|
||||
}
|
||||
if (chart.onPointerClickPie != null)
|
||||
{
|
||||
chart.onPointerClickPie(eventData, i, index);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (refresh) chart.RefreshChart();
|
||||
}
|
||||
|
||||
private void UpdateRuntimeData(Serie serie)
|
||||
{
|
||||
var data = serie.data;
|
||||
serie.runtimeDataMax = serie.yMax;
|
||||
serie.runtimePieDataTotal = serie.yTotal;
|
||||
|
||||
SerieHelper.UpdateCenter(serie, chart.chartPosition, chart.chartWidth, chart.chartHeight);
|
||||
float totalDegree = 0;
|
||||
float startDegree = 0;
|
||||
float zeroReplaceValue = 0;
|
||||
int showdataCount = 0;
|
||||
foreach (var sd in serie.data)
|
||||
{
|
||||
if (sd.show && serie.pieRoseType == RoseType.Area) showdataCount++;
|
||||
sd.canShowLabel = false;
|
||||
}
|
||||
float dataChangeDuration = serie.animation.GetUpdateAnimationDuration();
|
||||
bool isAllZeroValue = SerieHelper.IsAllZeroValue(serie, 1);
|
||||
var dataTotalFilterMinAngle = serie.runtimePieDataTotal;
|
||||
if (isAllZeroValue)
|
||||
{
|
||||
totalDegree = 360;
|
||||
zeroReplaceValue = totalDegree / data.Count;
|
||||
serie.runtimeDataMax = zeroReplaceValue;
|
||||
serie.runtimePieDataTotal = 360;
|
||||
}
|
||||
else
|
||||
{
|
||||
dataTotalFilterMinAngle = GetTotalAngle(serie, serie.runtimePieDataTotal, ref totalDegree);
|
||||
}
|
||||
serie.animation.InitProgress(data.Count, 0, 360);
|
||||
for (int n = 0; n < data.Count; n++)
|
||||
{
|
||||
var serieData = data[n];
|
||||
serieData.index = n;
|
||||
float value = isAllZeroValue ? zeroReplaceValue : serieData.GetCurrData(1, dataChangeDuration);
|
||||
serieData.runtimePieStartAngle = startDegree;
|
||||
serieData.runtimePieToAngle = startDegree;
|
||||
serieData.runtimePieHalfAngle = startDegree;
|
||||
serieData.runtimePieCurrAngle = startDegree;
|
||||
if (!serieData.show)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
float degree = serie.pieRoseType == RoseType.Area
|
||||
? (totalDegree / showdataCount)
|
||||
: (totalDegree * value / dataTotalFilterMinAngle);
|
||||
if (serie.minAngle > 0 && degree < serie.minAngle) degree = serie.minAngle;
|
||||
serieData.runtimePieToAngle = startDegree + degree;
|
||||
serieData.runtimePieOutsideRadius = serie.pieRoseType > 0 ?
|
||||
serie.runtimeInsideRadius +
|
||||
(serie.runtimeOutsideRadius - serie.runtimeInsideRadius) * value / serie.runtimeDataMax :
|
||||
serie.runtimeOutsideRadius;
|
||||
if (serieData.highlighted)
|
||||
{
|
||||
serieData.runtimePieOutsideRadius += chart.theme.serie.pieTooltipExtraRadius;
|
||||
}
|
||||
var offset = 0f;
|
||||
if (serie.pieClickOffset && serieData.selected)
|
||||
{
|
||||
offset += chart.theme.serie.pieSelectedOffset;
|
||||
}
|
||||
if (serie.animation.CheckDetailBreak(serieData.runtimePieToAngle))
|
||||
{
|
||||
serieData.runtimePieCurrAngle = serie.animation.GetCurrDetail();
|
||||
}
|
||||
else
|
||||
{
|
||||
serieData.runtimePieCurrAngle = serieData.runtimePieToAngle;
|
||||
}
|
||||
var halfDegree = (serieData.runtimePieToAngle - startDegree) / 2;
|
||||
serieData.runtimePieHalfAngle = startDegree + halfDegree;
|
||||
serieData.runtiemPieOffsetCenter = serie.runtimeCenterPos;
|
||||
serieData.runtimePieInsideRadius = serie.runtimeInsideRadius;
|
||||
if (offset > 0)
|
||||
{
|
||||
var currRad = serieData.runtimePieHalfAngle * Mathf.Deg2Rad;
|
||||
var currSin = Mathf.Sin(currRad);
|
||||
var currCos = Mathf.Cos(currRad);
|
||||
serieData.runtimePieOffsetRadius = 0;
|
||||
serieData.runtimePieInsideRadius -= serieData.runtimePieOffsetRadius;
|
||||
serieData.runtimePieOutsideRadius -= serieData.runtimePieOffsetRadius;
|
||||
if (serie.pieClickOffset && serieData.selected)
|
||||
{
|
||||
serieData.runtimePieOffsetRadius += chart.theme.serie.pieSelectedOffset;
|
||||
if (serieData.runtimePieInsideRadius > 0)
|
||||
{
|
||||
serieData.runtimePieInsideRadius += chart.theme.serie.pieSelectedOffset;
|
||||
}
|
||||
serieData.runtimePieOutsideRadius += chart.theme.serie.pieSelectedOffset;
|
||||
}
|
||||
serieData.runtiemPieOffsetCenter = new Vector3(
|
||||
serie.runtimeCenterPos.x + serieData.runtimePieOffsetRadius * currSin,
|
||||
serie.runtimeCenterPos.y + serieData.runtimePieOffsetRadius * currCos);
|
||||
}
|
||||
serieData.canShowLabel = serieData.runtimePieCurrAngle >= serieData.runtimePieHalfAngle;
|
||||
startDegree = serieData.runtimePieToAngle;
|
||||
SerieLabelHelper.UpdatePieLabelPosition(serie, serieData);
|
||||
}
|
||||
SerieLabelHelper.AvoidLabelOverlap(serie);
|
||||
}
|
||||
|
||||
private float GetTotalAngle(Serie serie, float dataTotal, ref float totalAngle)
|
||||
{
|
||||
totalAngle = 360f;
|
||||
if (serie.minAngle > 0)
|
||||
{
|
||||
var rate = serie.minAngle / 360;
|
||||
var minAngleValue = dataTotal * rate;
|
||||
foreach (var serieData in serie.data)
|
||||
{
|
||||
var value = serieData.GetData(1);
|
||||
if (value < minAngleValue)
|
||||
{
|
||||
totalAngle -= serie.minAngle;
|
||||
dataTotal -= value;
|
||||
}
|
||||
}
|
||||
return dataTotal;
|
||||
}
|
||||
else
|
||||
{
|
||||
return dataTotal;
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawPieCenter(VertexHelper vh, Serie serie, ItemStyle itemStyle, float insideRadius)
|
||||
{
|
||||
if (!ChartHelper.IsClearColor(itemStyle.centerColor))
|
||||
{
|
||||
var radius = insideRadius - itemStyle.centerGap;
|
||||
UGL.DrawCricle(vh, serie.runtimeCenterPos, radius, itemStyle.centerColor, chart.settings.cicleSmoothness);
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawPie(VertexHelper vh, Serie serie)
|
||||
{
|
||||
var data = serie.data;
|
||||
serie.animation.InitProgress(data.Count, 0, 360);
|
||||
if (!serie.show || serie.animation.HasFadeOut())
|
||||
{
|
||||
return;
|
||||
}
|
||||
bool dataChanging = false;
|
||||
for (int n = 0; n < data.Count; n++)
|
||||
{
|
||||
var serieData = data[n];
|
||||
if (!serieData.show)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
var itemStyle = SerieHelper.GetItemStyle(serie, serieData, serieData.highlighted);
|
||||
if (serieData.IsDataChanged()) dataChanging = true;
|
||||
var serieNameCount = chart.m_LegendRealShowName.IndexOf(serieData.legendName);
|
||||
var color = SerieHelper.GetItemColor(serie, serieData, chart.theme, serieNameCount,
|
||||
serieData.highlighted);
|
||||
var toColor = SerieHelper.GetItemToColor(serie, serieData, chart.theme, serieNameCount,
|
||||
serieData.highlighted);
|
||||
var borderWidth = itemStyle.borderWidth;
|
||||
var borderColor = itemStyle.borderColor;
|
||||
|
||||
if (serie.pieClickOffset && serieData.selected)
|
||||
{
|
||||
var drawEndDegree = serieData.runtimePieCurrAngle;
|
||||
var needRoundCap = serie.roundCap && serieData.runtimePieInsideRadius > 0;
|
||||
UGL.DrawDoughnut(vh, serieData.runtiemPieOffsetCenter, serieData.runtimePieInsideRadius,
|
||||
serieData.runtimePieOutsideRadius, color, toColor, Color.clear, serieData.runtimePieStartAngle,
|
||||
drawEndDegree, borderWidth, borderColor, serie.pieSpace / 2, chart.settings.cicleSmoothness,
|
||||
needRoundCap, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
var drawEndDegree = serieData.runtimePieCurrAngle;
|
||||
var needRoundCap = serie.roundCap && serieData.runtimePieInsideRadius > 0;
|
||||
UGL.DrawDoughnut(vh, serie.runtimeCenterPos, serieData.runtimePieInsideRadius,
|
||||
serieData.runtimePieOutsideRadius, color, toColor, Color.clear, serieData.runtimePieStartAngle,
|
||||
drawEndDegree, borderWidth, borderColor, serie.pieSpace / 2, chart.settings.cicleSmoothness,
|
||||
needRoundCap, true);
|
||||
DrawPieCenter(vh, serie, itemStyle, serieData.runtimePieInsideRadius);
|
||||
}
|
||||
if (!serie.animation.CheckDetailBreak(serieData.runtimePieToAngle)) serie.animation.SetDataFinish(n);
|
||||
else break;
|
||||
}
|
||||
if (!serie.animation.IsFinish())
|
||||
{
|
||||
serie.animation.CheckProgress(360);
|
||||
serie.animation.CheckSymbol(serie.symbol.GetSize(null, chart.theme.serie.lineSymbolSize));
|
||||
chart.RefreshPainter(serie);
|
||||
}
|
||||
if (dataChanging)
|
||||
{
|
||||
chart.RefreshPainter(serie);
|
||||
}
|
||||
chart.raycastTarget = IsAnyPieClickOffset() || IsAnyPieDataHighlight();
|
||||
}
|
||||
|
||||
private bool IsAnyPieClickOffset()
|
||||
{
|
||||
foreach (var serie in chart.series.list)
|
||||
{
|
||||
if (serie.type == SerieType.Pie && serie.pieClickOffset) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private bool IsAnyPieDataHighlight()
|
||||
{
|
||||
foreach (var serie in chart.series.list)
|
||||
{
|
||||
if (serie.type == SerieType.Pie)
|
||||
{
|
||||
foreach (var serieData in serie.data)
|
||||
{
|
||||
if (serieData.highlighted) return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void DrawPieLabelLine(VertexHelper vh, Serie serie)
|
||||
{
|
||||
foreach (var serieData in serie.data)
|
||||
{
|
||||
var serieLabel = SerieHelper.GetSerieLabel(serie, serieData);
|
||||
if (SerieLabelHelper.CanShowLabel(serie, serieData, serieLabel, 1))
|
||||
{
|
||||
int colorIndex = chart.m_LegendRealShowName.IndexOf(serieData.name);
|
||||
Color color = chart.theme.GetColor(colorIndex);
|
||||
DrawPieLabelLine(vh, serie, serieData, color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawPieLabelBackground(VertexHelper vh, Serie serie)
|
||||
{
|
||||
if (serie.avoidLabelOverlap) return;
|
||||
foreach (var serieData in serie.data)
|
||||
{
|
||||
var serieLabel = SerieHelper.GetSerieLabel(serie, serieData);
|
||||
if (SerieLabelHelper.CanShowLabel(serie, serieData, serieLabel, 1))
|
||||
{
|
||||
SerieLabelHelper.UpdatePieLabelPosition(serie, serieData);
|
||||
chart.DrawLabelBackground(vh, serie, serieData);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawPieLabelLine(VertexHelper vh, Serie serie, SerieData serieData, Color color)
|
||||
{
|
||||
var serieLabel = SerieHelper.GetSerieLabel(serie, serieData);
|
||||
if (serieLabel.show
|
||||
&& serieLabel.position == SerieLabel.Position.Outside
|
||||
&& serieLabel.line)
|
||||
{
|
||||
var insideRadius = serieData.runtimePieInsideRadius;
|
||||
var outSideRadius = serieData.runtimePieOutsideRadius;
|
||||
var center = serie.runtimeCenterPos;
|
||||
var currAngle = serieData.runtimePieHalfAngle;
|
||||
if (!ChartHelper.IsClearColor(serieLabel.lineColor)) color = serieLabel.lineColor;
|
||||
else if (serieLabel.lineType == SerieLabel.LineType.HorizontalLine) color *= color;
|
||||
float currSin = Mathf.Sin(currAngle * Mathf.Deg2Rad);
|
||||
float currCos = Mathf.Cos(currAngle * Mathf.Deg2Rad);
|
||||
var radius1 = serieLabel.lineType == SerieLabel.LineType.HorizontalLine ?
|
||||
serie.runtimeOutsideRadius : outSideRadius;
|
||||
var radius2 = serie.runtimeOutsideRadius + serieLabel.lineLength1;
|
||||
var radius3 = insideRadius + (outSideRadius - insideRadius) / 2;
|
||||
if (radius1 < serie.runtimeInsideRadius) radius1 = serie.runtimeInsideRadius;
|
||||
radius1 -= 0.1f;
|
||||
var pos0 = new Vector3(center.x + radius3 * currSin, center.y + radius3 * currCos);
|
||||
var pos1 = new Vector3(center.x + radius1 * currSin, center.y + radius1 * currCos);
|
||||
var pos2 = serieData.labelPosition;
|
||||
if (pos2.x == 0)
|
||||
{
|
||||
pos2 = new Vector3(center.x + radius2 * currSin, center.y + radius2 * currCos);
|
||||
}
|
||||
Vector3 pos4, pos6;
|
||||
var horizontalLineCircleRadius = serieLabel.lineWidth * 4f;
|
||||
var lineCircleDiff = horizontalLineCircleRadius - 0.3f;
|
||||
if (currAngle < 90)
|
||||
{
|
||||
var r4 = Mathf.Sqrt(radius1 * radius1 - Mathf.Pow(currCos * radius3, 2)) - currSin * radius3;
|
||||
r4 += serieLabel.lineLength1 - lineCircleDiff;
|
||||
pos6 = pos0 + Vector3.right * lineCircleDiff;
|
||||
pos4 = pos6 + Vector3.right * r4;
|
||||
}
|
||||
else if (currAngle < 180)
|
||||
{
|
||||
var r4 = Mathf.Sqrt(radius1 * radius1 - Mathf.Pow(currCos * radius3, 2)) - currSin * radius3;
|
||||
r4 += serieLabel.lineLength1 - lineCircleDiff;
|
||||
pos6 = pos0 + Vector3.right * lineCircleDiff;
|
||||
pos4 = pos6 + Vector3.right * r4;
|
||||
}
|
||||
else if (currAngle < 270)
|
||||
{
|
||||
var currSin1 = Mathf.Sin((360 - currAngle) * Mathf.Deg2Rad);
|
||||
var currCos1 = Mathf.Cos((360 - currAngle) * Mathf.Deg2Rad);
|
||||
var r4 = Mathf.Sqrt(radius1 * radius1 - Mathf.Pow(currCos1 * radius3, 2)) - currSin1 * radius3;
|
||||
r4 += serieLabel.lineLength1 - lineCircleDiff;
|
||||
pos6 = pos0 + Vector3.left * lineCircleDiff;
|
||||
pos4 = pos6 + Vector3.left * r4;
|
||||
}
|
||||
else
|
||||
{
|
||||
var currSin1 = Mathf.Sin((360 - currAngle) * Mathf.Deg2Rad);
|
||||
var currCos1 = Mathf.Cos((360 - currAngle) * Mathf.Deg2Rad);
|
||||
var r4 = Mathf.Sqrt(radius1 * radius1 - Mathf.Pow(currCos1 * radius3, 2)) - currSin1 * radius3;
|
||||
r4 += serieLabel.lineLength1 - lineCircleDiff;
|
||||
pos6 = pos0 + Vector3.left * lineCircleDiff;
|
||||
pos4 = pos6 + Vector3.left * r4;
|
||||
}
|
||||
var pos5X = currAngle > 180 ? pos2.x - serieLabel.lineLength2 : pos2.x + serieLabel.lineLength2;
|
||||
var pos5 = new Vector3(pos5X, pos2.y);
|
||||
switch (serieLabel.lineType)
|
||||
{
|
||||
case SerieLabel.LineType.BrokenLine:
|
||||
UGL.DrawLine(vh, pos1, pos2, pos5, serieLabel.lineWidth, color);
|
||||
break;
|
||||
case SerieLabel.LineType.Curves:
|
||||
UGL.DrawCurves(vh, pos1, pos5, pos1, pos2, serieLabel.lineWidth, color,
|
||||
chart.settings.lineSmoothness);
|
||||
break;
|
||||
case SerieLabel.LineType.HorizontalLine:
|
||||
UGL.DrawCricle(vh, pos0, horizontalLineCircleRadius, color);
|
||||
UGL.DrawLine(vh, pos6, pos4, serieLabel.lineWidth, color);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
private void DrawPieLabel(Serie serie, int dataIndex, SerieData serieData, Color serieColor)
|
||||
{
|
||||
if (serieData.labelObject == null) return;
|
||||
var currAngle = serieData.runtimePieHalfAngle;
|
||||
var isHighlight = (serieData.highlighted && serie.emphasis.label.show);
|
||||
var serieLabel = SerieHelper.GetSerieLabel(serie, serieData);
|
||||
var showLabel = ((serieLabel.show || isHighlight) && serieData.canShowLabel);
|
||||
|
||||
if (showLabel || serieData.iconStyle.show)
|
||||
{
|
||||
serieData.SetLabelActive(showLabel);
|
||||
float rotate = 0;
|
||||
bool isInsidePosition = serieLabel.position == SerieLabel.Position.Inside;
|
||||
if (serieLabel.textStyle.rotate > 0 && isInsidePosition)
|
||||
{
|
||||
if (currAngle > 180) rotate += 270 - currAngle;
|
||||
else rotate += -(currAngle - 90);
|
||||
}
|
||||
Color color = serieColor;
|
||||
if (isHighlight)
|
||||
{
|
||||
if (!ChartHelper.IsClearColor(serie.emphasis.label.textStyle.color))
|
||||
{
|
||||
color = serie.emphasis.label.textStyle.color;
|
||||
}
|
||||
}
|
||||
else if (!ChartHelper.IsClearColor(serieLabel.textStyle.color))
|
||||
{
|
||||
color = serieLabel.textStyle.color;
|
||||
}
|
||||
else
|
||||
{
|
||||
color = isInsidePosition ? Color.white : serieColor;
|
||||
}
|
||||
var fontSize = isHighlight
|
||||
? serie.emphasis.label.textStyle.GetFontSize(chart.theme.common)
|
||||
: serieLabel.textStyle.GetFontSize(chart.theme.common);
|
||||
var fontStyle = isHighlight
|
||||
? serie.emphasis.label.textStyle.fontStyle
|
||||
: serieLabel.textStyle.fontStyle;
|
||||
|
||||
serieData.labelObject.label.SetColor(color);
|
||||
serieData.labelObject.label.SetFontSize(fontSize);
|
||||
serieData.labelObject.label.SetFontStyle(fontStyle);
|
||||
serieData.labelObject.SetLabelRotate(rotate);
|
||||
if (!string.IsNullOrEmpty(serieLabel.formatter))
|
||||
{
|
||||
var value = serieData.data[1];
|
||||
var total = serie.yTotal;
|
||||
var content = SerieLabelHelper.GetFormatterContent(serie, serieData, value, total, serieLabel);
|
||||
if (serieData.labelObject.SetText(content)) chart.RefreshPainter(serie);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (serieData.labelObject.SetText(serieData.name)) chart.RefreshPainter(serie);
|
||||
}
|
||||
serieData.labelObject.SetPosition(SerieLabelHelper.GetRealLabelPosition(serieData, serieLabel));
|
||||
if (showLabel) serieData.labelObject.SetLabelPosition(serieLabel.offset);
|
||||
else serieData.SetLabelActive(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
serieData.SetLabelActive(false);
|
||||
}
|
||||
serieData.labelObject.UpdateIcon(serieData.iconStyle);
|
||||
}
|
||||
|
||||
protected int GetPiePosIndex(Serie serie, Vector2 local)
|
||||
{
|
||||
if (serie.type != SerieType.Pie) return -1;
|
||||
var dist = Vector2.Distance(local, serie.runtimeCenterPos);
|
||||
if (dist < serie.runtimeInsideRadius || dist > serie.runtimeOutsideRadius) return -1;
|
||||
Vector2 dir = local - new Vector2(serie.runtimeCenterPos.x, serie.runtimeCenterPos.y);
|
||||
float angle = ChartHelper.GetAngle360(Vector2.up, dir);
|
||||
for (int i = 0; i < serie.data.Count; i++)
|
||||
{
|
||||
var serieData = serie.data[i];
|
||||
if (angle >= serieData.runtimePieStartAngle && angle <= serieData.runtimePieToAngle)
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
private bool PointerIsInPieSerie(Series series, Vector2 local)
|
||||
{
|
||||
foreach (var serie in series.list)
|
||||
{
|
||||
if (serie.type != SerieType.Pie) continue;
|
||||
var dist = Vector2.Distance(local, serie.runtimeCenterPos);
|
||||
if (dist >= serie.runtimeInsideRadius && dist <= serie.runtimeOutsideRadius) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected void UpdatePieTooltip()
|
||||
{
|
||||
bool showTooltip = false;
|
||||
foreach (var serie in chart.series.list)
|
||||
{
|
||||
int index = chart.tooltip.runtimeDataIndex[serie.index];
|
||||
if (index < 0) continue;
|
||||
showTooltip = true;
|
||||
var content = TooltipHelper.GetFormatterContent(chart.tooltip, index, chart.series, chart.theme);
|
||||
TooltipHelper.SetContentAndPosition(chart.tooltip, content.TrimStart(), chart.chartRect);
|
||||
}
|
||||
chart.tooltip.SetActive(showTooltip);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d5fa46fc54af9401796fc8691221e526
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,757 @@
|
||||
/************************************************/
|
||||
/* */
|
||||
/* Copyright (c) 2018 - 2021 monitor1394 */
|
||||
/* https://github.com/monitor1394 */
|
||||
/* */
|
||||
/************************************************/
|
||||
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using UnityEngine.EventSystems;
|
||||
using XUGL;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace XCharts
|
||||
{
|
||||
internal class DrawSerieRadar : IDrawSerie
|
||||
{
|
||||
public BaseChart chart;
|
||||
private const string INDICATOR_TEXT = "indicator";
|
||||
private bool m_IsEnterLegendButtom;
|
||||
Dictionary<string, int> serieNameSet = new Dictionary<string, int>();
|
||||
|
||||
public DrawSerieRadar(BaseChart chart)
|
||||
{
|
||||
this.chart = chart;
|
||||
}
|
||||
|
||||
public void InitComponent()
|
||||
{
|
||||
InitRadars();
|
||||
}
|
||||
|
||||
public void CheckComponent()
|
||||
{
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
}
|
||||
|
||||
public void DrawBase(VertexHelper vh)
|
||||
{
|
||||
serieNameSet.Clear();
|
||||
for (int i = 0; i < chart.radars.Count; i++)
|
||||
{
|
||||
var radar = chart.radars[i];
|
||||
if (!radar.show) continue;
|
||||
radar.index = i;
|
||||
radar.UpdateRadarCenter(chart.chartPosition, chart.chartWidth, chart.chartHeight);
|
||||
if (radar.shape == Radar.Shape.Circle)
|
||||
{
|
||||
DrawCricleRadar(vh, radar);
|
||||
}
|
||||
else
|
||||
{
|
||||
DrawRadar(vh, radar);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void DrawSerie(VertexHelper vh, Serie serie)
|
||||
{
|
||||
if (serie.type != SerieType.Radar) return;
|
||||
if (!serie.show) return;
|
||||
switch (serie.radarType)
|
||||
{
|
||||
case RadarType.Multiple:
|
||||
DrawMutipleRadar(vh, serie, serie.index);
|
||||
break;
|
||||
case RadarType.Single:
|
||||
DrawSingleRadar(vh, serie, serie.index);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public void RefreshLabel()
|
||||
{
|
||||
for (int i = 0; i < chart.series.Count; i++)
|
||||
{
|
||||
var serie = chart.series.GetSerie(i);
|
||||
if (serie.type != SerieType.Radar) continue;
|
||||
if (!serie.show && serie.radarType != RadarType.Single) continue;
|
||||
var radar = chart.GetRadar(serie.radarIndex);
|
||||
if (radar == null) continue;
|
||||
var center = radar.runtimeCenterPos;
|
||||
for (int n = 0; n < serie.dataCount; n++)
|
||||
{
|
||||
var serieData = serie.data[n];
|
||||
if (serieData.labelObject == null) continue;
|
||||
var serieLabel = SerieHelper.GetSerieLabel(serie, serieData);
|
||||
var labelPos = serieData.labelPosition;
|
||||
if (serieLabel.margin != 0)
|
||||
{
|
||||
labelPos += serieLabel.margin * (labelPos - center).normalized;
|
||||
}
|
||||
serieData.labelObject.SetPosition(labelPos);
|
||||
serieData.labelObject.UpdateIcon(serieData.iconStyle);
|
||||
if (serie.show && serieLabel.show && serieData.canShowLabel)
|
||||
{
|
||||
var value = serieData.GetCurrData(1);
|
||||
var max = radar.GetIndicatorMax(n);
|
||||
SerieLabelHelper.ResetLabel(serieData.labelObject.label, serieLabel, chart.theme, i);
|
||||
serieData.SetLabelActive(serieData.labelPosition != Vector3.zero);
|
||||
serieData.labelObject.SetLabelPosition(serieLabel.offset);
|
||||
var content = SerieLabelHelper.GetFormatterContent(serie, serieData, value, max, serieLabel);
|
||||
if (serieData.labelObject.SetText(content))
|
||||
{
|
||||
chart.RefreshPainter(serie);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
serieData.SetLabelActive(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool CheckTootipArea(Vector2 local)
|
||||
{
|
||||
if (m_IsEnterLegendButtom) return false;
|
||||
if (!IsInRadar(local)) return false;
|
||||
bool highlight = false;
|
||||
chart.tooltip.ClearValue();
|
||||
for (int i = 0; i < chart.series.Count; i++)
|
||||
{
|
||||
var serie = chart.series.GetSerie(i);
|
||||
if (!serie.show || serie.type != SerieType.Radar) continue;
|
||||
var radar = chart.radars[serie.radarIndex];
|
||||
var dist = Vector2.Distance(radar.runtimeCenterPos, local);
|
||||
if (dist > radar.runtimeRadius + serie.symbol.GetSize(null, chart.theme.serie.lineSymbolSize))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
switch (serie.radarType)
|
||||
{
|
||||
case RadarType.Multiple:
|
||||
for (int n = 0; n < serie.data.Count; n++)
|
||||
{
|
||||
var posKey = i * 1000 + n;
|
||||
if (radar.runtimeDataPosList.ContainsKey(posKey))
|
||||
{
|
||||
var posList = radar.runtimeDataPosList[posKey];
|
||||
var symbolSize = serie.symbol.GetSize(serie.data[n].data, chart.theme.serie.lineSymbolSize);
|
||||
for (int k = 0; k < posList.Count; k++)
|
||||
{
|
||||
if (Vector2.Distance(posList[k], local) <= symbolSize * 1.3f)
|
||||
{
|
||||
chart.tooltip.runtimeDataIndex[0] = i;
|
||||
chart.tooltip.runtimeDataIndex[1] = n;
|
||||
if (chart.tooltip.runtimeDataIndex.Count >= 3)
|
||||
chart.tooltip.runtimeDataIndex[2] = k;
|
||||
else
|
||||
chart.tooltip.runtimeDataIndex.Add(k);
|
||||
highlight = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case RadarType.Single:
|
||||
for (int n = 0; n < serie.data.Count; n++)
|
||||
{
|
||||
var serieData = serie.data[n];
|
||||
var symbolSize = serie.symbol.GetSize(serie.data[n].data, chart.theme.serie.lineSymbolSize);
|
||||
if (Vector2.Distance(serieData.labelPosition, local) <= symbolSize * 1.3f)
|
||||
{
|
||||
chart.tooltip.runtimeDataIndex[0] = i;
|
||||
chart.tooltip.runtimeDataIndex[1] = n;
|
||||
highlight = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (!highlight)
|
||||
{
|
||||
if (chart.tooltip.IsActive())
|
||||
{
|
||||
chart.tooltip.SetActive(false);
|
||||
chart.RefreshChart();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
chart.tooltip.UpdateContentPos(local + chart.tooltip.offset);
|
||||
UpdateTooltip();
|
||||
chart.RefreshChart();
|
||||
}
|
||||
return highlight;
|
||||
}
|
||||
|
||||
public bool OnLegendButtonClick(int index, string legendName, bool show)
|
||||
{
|
||||
if (!SeriesHelper.ContainsSerie(chart.series, SerieType.Radar)) return false;
|
||||
if (!LegendHelper.IsSerieLegend(chart.series, legendName, SerieType.Radar)) return false;
|
||||
LegendHelper.CheckDataShow(chart.series, legendName, show);
|
||||
chart.UpdateLegendColor(legendName, show);
|
||||
chart.RefreshChart();
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool OnLegendButtonEnter(int index, string legendName)
|
||||
{
|
||||
if (!SeriesHelper.ContainsSerie(chart.series, SerieType.Radar)) return false;
|
||||
if (!LegendHelper.IsSerieLegend(chart.series, legendName, SerieType.Radar)) return false;
|
||||
m_IsEnterLegendButtom = true;
|
||||
LegendHelper.CheckDataHighlighted(chart.series, legendName, true);
|
||||
chart.RefreshChart();
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool OnLegendButtonExit(int index, string legendName)
|
||||
{
|
||||
if (!SeriesHelper.ContainsSerie(chart.series, SerieType.Radar)) return false;
|
||||
if (!LegendHelper.IsSerieLegend(chart.series, legendName, SerieType.Radar)) return false;
|
||||
m_IsEnterLegendButtom = false;
|
||||
LegendHelper.CheckDataHighlighted(chart.series, legendName, false);
|
||||
chart.RefreshChart();
|
||||
return true;
|
||||
}
|
||||
|
||||
public void OnPointerDown(PointerEventData eventData)
|
||||
{
|
||||
}
|
||||
|
||||
private void InitRadars()
|
||||
{
|
||||
for (int n = 0; n < chart.radars.Count; n++)
|
||||
{
|
||||
Radar radar = chart.radars[n];
|
||||
radar.index = n;
|
||||
InitRadar(radar);
|
||||
}
|
||||
}
|
||||
|
||||
private void InitRadar(Radar radar)
|
||||
{
|
||||
float txtWid = 100;
|
||||
float txtHig = 20;
|
||||
radar.painter = chart.GetPainter(radar.index);
|
||||
radar.refreshComponent = delegate ()
|
||||
{
|
||||
ChartHelper.HideAllObject(chart.transform, INDICATOR_TEXT + "_" + radar.index);
|
||||
radar.UpdateRadarCenter(chart.chartPosition, chart.chartWidth, chart.chartHeight);
|
||||
for (int i = 0; i < radar.indicatorList.Count; i++)
|
||||
{
|
||||
var indicator = radar.indicatorList[i];
|
||||
var pos = radar.GetIndicatorPosition(i);
|
||||
var textStyle = indicator.textStyle;
|
||||
var objName = INDICATOR_TEXT + "_" + radar.index + "_" + i;
|
||||
var txt = ChartHelper.AddTextObject(objName, chart.transform, new Vector2(0.5f, 0.5f),
|
||||
new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(txtWid, txtHig),
|
||||
textStyle, chart.theme.radar);
|
||||
txt.gameObject.hideFlags = chart.chartHideFlags;
|
||||
txt.SetAlignment(TextAnchor.MiddleCenter);
|
||||
txt.SetText(radar.indicatorList[i].name);
|
||||
txt.SetActive(radar.indicator);
|
||||
var offset = new Vector3(textStyle.offset.x, textStyle.offset.y);
|
||||
AxisHelper.AdjustCircleLabelPos(txt, pos, radar.runtimeCenterPos, txtHig, offset);
|
||||
}
|
||||
chart.RefreshBasePainter();
|
||||
};
|
||||
radar.refreshComponent?.Invoke();
|
||||
}
|
||||
|
||||
private void DrawMutipleRadar(VertexHelper vh, Serie serie, int i)
|
||||
{
|
||||
if (!serie.show) return;
|
||||
var radar = chart.GetRadar(serie.radarIndex);
|
||||
if (radar == null) return;
|
||||
var startPoint = Vector3.zero;
|
||||
var toPoint = Vector3.zero;
|
||||
var firstPoint = Vector3.zero;
|
||||
var indicatorNum = radar.indicatorList.Count;
|
||||
var angle = 2 * Mathf.PI / indicatorNum;
|
||||
var centerPos = radar.runtimeCenterPos;
|
||||
var serieNameCount = -1;
|
||||
serie.animation.InitProgress(1, 0, 1);
|
||||
if (!chart.IsActive(i) || serie.animation.HasFadeOut())
|
||||
{
|
||||
return;
|
||||
}
|
||||
var rate = serie.animation.GetCurrRate();
|
||||
var dataChanging = false;
|
||||
var dataChangeDuration = serie.animation.GetUpdateAnimationDuration();
|
||||
SerieHelper.GetAllMinMaxData(serie, radar.ceilRate);
|
||||
for (int j = 0; j < serie.data.Count; j++)
|
||||
{
|
||||
var serieData = serie.data[j];
|
||||
int key = i * 1000 + j;
|
||||
if (!radar.runtimeDataPosList.ContainsKey(key))
|
||||
{
|
||||
radar.runtimeDataPosList.Add(i * 1000 + j, new List<Vector3>(serieData.data.Count));
|
||||
}
|
||||
else
|
||||
{
|
||||
radar.runtimeDataPosList[key].Clear();
|
||||
}
|
||||
string dataName = serieData.name;
|
||||
int serieIndex = 0;
|
||||
if (string.IsNullOrEmpty(dataName))
|
||||
{
|
||||
serieNameCount++;
|
||||
serieIndex = serieNameCount;
|
||||
}
|
||||
else if (!serieNameSet.ContainsKey(dataName))
|
||||
{
|
||||
serieNameSet.Add(dataName, serieNameCount);
|
||||
serieNameCount++;
|
||||
serieIndex = serieNameCount;
|
||||
}
|
||||
else
|
||||
{
|
||||
serieIndex = serieNameSet[dataName];
|
||||
}
|
||||
if (!serieData.show)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
var isHighlight = IsHighlight(radar, serie, serieData, j, 0);
|
||||
var areaColor = SerieHelper.GetAreaColor(serie, chart.theme, serieIndex, isHighlight);
|
||||
var areaToColor = SerieHelper.GetAreaToColor(serie, chart.theme, serieIndex, isHighlight);
|
||||
var lineColor = SerieHelper.GetLineColor(serie, chart.theme, serieIndex, isHighlight);
|
||||
var lineWidth = serie.lineStyle.GetWidth(chart.theme.serie.lineWidth);
|
||||
int dataCount = radar.indicatorList.Count;
|
||||
List<Vector3> pointList = radar.runtimeDataPosList[key];
|
||||
for (int n = 0; n < dataCount; n++)
|
||||
{
|
||||
if (n >= serieData.data.Count) break;
|
||||
float max = radar.GetIndicatorMax(n);
|
||||
float value = serieData.GetCurrData(n, dataChangeDuration);
|
||||
if (serieData.IsDataChanged()) dataChanging = true;
|
||||
if (max == 0)
|
||||
{
|
||||
max = serie.runtimeDataMax;
|
||||
}
|
||||
var radius = max < 0 ? radar.runtimeDataRadius - radar.runtimeDataRadius * value / max
|
||||
: radar.runtimeDataRadius * value / max;
|
||||
var currAngle = (n + (radar.positionType == Radar.PositionType.Between ? 0.5f : 0)) * angle;
|
||||
radius *= rate;
|
||||
if (n == 0)
|
||||
{
|
||||
startPoint = new Vector3(centerPos.x + radius * Mathf.Sin(currAngle),
|
||||
centerPos.y + radius * Mathf.Cos(currAngle));
|
||||
firstPoint = startPoint;
|
||||
}
|
||||
else
|
||||
{
|
||||
toPoint = new Vector3(centerPos.x + radius * Mathf.Sin(currAngle),
|
||||
centerPos.y + radius * Mathf.Cos(currAngle));
|
||||
if (serie.areaStyle.show)
|
||||
{
|
||||
UGL.DrawTriangle(vh, startPoint, toPoint, centerPos, areaColor, areaColor, areaToColor);
|
||||
}
|
||||
if (serie.lineStyle.show)
|
||||
{
|
||||
ChartDrawer.DrawLineStyle(vh, serie.lineStyle.type, lineWidth, startPoint, toPoint, lineColor);
|
||||
}
|
||||
startPoint = toPoint;
|
||||
}
|
||||
pointList.Add(startPoint);
|
||||
}
|
||||
if (serie.areaStyle.show)
|
||||
{
|
||||
UGL.DrawTriangle(vh, startPoint, firstPoint, centerPos, areaColor, areaColor, areaToColor);
|
||||
}
|
||||
if (serie.lineStyle.show)
|
||||
{
|
||||
ChartDrawer.DrawLineStyle(vh, serie.lineStyle.type, lineWidth, startPoint, firstPoint, lineColor);
|
||||
}
|
||||
if (serie.symbol.show && serie.symbol.type != SerieSymbolType.None)
|
||||
{
|
||||
for (int m = 0; m < pointList.Count; m++)
|
||||
{
|
||||
var point = pointList[m];
|
||||
isHighlight = IsHighlight(radar, serie, serieData, j, m);
|
||||
var symbolSize = isHighlight
|
||||
? serie.symbol.GetSelectedSize(null, chart.theme.serie.lineSymbolSelectedSize)
|
||||
: serie.symbol.GetSize(null, chart.theme.serie.lineSymbolSize);
|
||||
var symbolColor = SerieHelper.GetItemColor(serie, serieData, chart.theme, serieIndex, isHighlight);
|
||||
var symbolToColor = SerieHelper.GetItemToColor(serie, serieData, chart.theme, serieIndex, isHighlight);
|
||||
var symbolBorder = SerieHelper.GetSymbolBorder(serie, serieData, chart.theme, isHighlight);
|
||||
var cornerRadius = SerieHelper.GetSymbolCornerRadius(serie, serieData, isHighlight);
|
||||
chart.DrawSymbol(vh, serie.symbol.type, symbolSize, symbolBorder, point, symbolColor,
|
||||
symbolToColor, serie.symbol.gap, cornerRadius);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!serie.animation.IsFinish())
|
||||
{
|
||||
serie.animation.CheckProgress(1);
|
||||
chart.RefreshPainter(serie);
|
||||
}
|
||||
if (dataChanging)
|
||||
{
|
||||
chart.RefreshPainter(serie);
|
||||
}
|
||||
}
|
||||
|
||||
private bool IsHighlight(Radar radar, Serie serie, SerieData serieData, int dataIndex, int dimension)
|
||||
{
|
||||
if (serie.highlighted || serieData.highlighted) return true;
|
||||
if (!chart.tooltip.show) return false;
|
||||
var selectedSerieIndex = chart.tooltip.runtimeDataIndex[0];
|
||||
if (selectedSerieIndex < 0) return false;
|
||||
if (chart.series.GetSerie(selectedSerieIndex).radarIndex != serie.radarIndex) return false;
|
||||
switch (serie.radarType)
|
||||
{
|
||||
case RadarType.Multiple:
|
||||
if (radar.isAxisTooltip)
|
||||
{
|
||||
var selectedDimension = chart.tooltip.runtimeDataIndex[2];
|
||||
return selectedDimension == dimension;
|
||||
}
|
||||
else if (chart.tooltip.runtimeDataIndex.Count >= 2)
|
||||
{
|
||||
return chart.tooltip.runtimeDataIndex[0] == serie.index && chart.tooltip.runtimeDataIndex[1] == dataIndex;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
case RadarType.Single:
|
||||
return chart.tooltip.runtimeDataIndex[1] == dataIndex;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void DrawSingleRadar(VertexHelper vh, Serie serie, int i)
|
||||
{
|
||||
var startPoint = Vector3.zero;
|
||||
var toPoint = Vector3.zero;
|
||||
var firstPoint = Vector3.zero;
|
||||
|
||||
var radar = chart.radars[serie.radarIndex];
|
||||
var indicatorNum = radar.indicatorList.Count;
|
||||
var angle = 2 * Mathf.PI / indicatorNum;
|
||||
var centerPos = radar.runtimeCenterPos;
|
||||
var serieNameCount = -1;
|
||||
serie.animation.InitProgress(1, 0, 1);
|
||||
if (!chart.IsActive(i) || serie.animation.HasFadeOut())
|
||||
{
|
||||
return;
|
||||
}
|
||||
var rate = serie.animation.GetCurrRate();
|
||||
var dataChanging = false;
|
||||
var dataChangeDuration = serie.animation.GetUpdateAnimationDuration();
|
||||
int key = i * 1000;
|
||||
if (!radar.runtimeDataPosList.ContainsKey(key))
|
||||
{
|
||||
radar.runtimeDataPosList.Add(i * 1000, new List<Vector3>(serie.dataCount));
|
||||
}
|
||||
else
|
||||
{
|
||||
radar.runtimeDataPosList[key].Clear();
|
||||
}
|
||||
var pointList = radar.runtimeDataPosList[key];
|
||||
var startIndex = GetStartShowIndex(serie);
|
||||
var endIndex = GetEndShowIndex(serie);
|
||||
SerieHelper.UpdateMinMaxData(serie, 1, radar.ceilRate);
|
||||
for (int j = 0; j < serie.data.Count; j++)
|
||||
{
|
||||
var serieData = serie.data[j];
|
||||
serieData.index = j;
|
||||
string dataName = serieData.name;
|
||||
int serieIndex = 0;
|
||||
if (string.IsNullOrEmpty(dataName))
|
||||
{
|
||||
serieNameCount++;
|
||||
serieIndex = serieNameCount;
|
||||
}
|
||||
else if (!serieNameSet.ContainsKey(dataName))
|
||||
{
|
||||
serieNameSet.Add(dataName, serieNameCount);
|
||||
serieNameCount++;
|
||||
serieIndex = serieNameCount;
|
||||
}
|
||||
else
|
||||
{
|
||||
serieIndex = serieNameSet[dataName];
|
||||
}
|
||||
if (!serieData.show)
|
||||
{
|
||||
serieData.labelPosition = Vector3.zero;
|
||||
continue;
|
||||
}
|
||||
var isHighlight = IsHighlight(radar, serie, serieData, j, 0);
|
||||
var areaColor = SerieHelper.GetAreaColor(serie, chart.theme, serieIndex, isHighlight);
|
||||
var areaToColor = SerieHelper.GetAreaToColor(serie, chart.theme, serieIndex, isHighlight);
|
||||
var lineColor = SerieHelper.GetLineColor(serie, chart.theme, serieIndex, isHighlight);
|
||||
int dataCount = radar.indicatorList.Count;
|
||||
var index = serieData.index;
|
||||
var p = radar.runtimeCenterPos;
|
||||
var max = radar.GetIndicatorMax(index);
|
||||
var value = serieData.GetCurrData(1, dataChangeDuration);
|
||||
if (serieData.IsDataChanged()) dataChanging = true;
|
||||
if (max == 0)
|
||||
{
|
||||
max = serie.runtimeDataMax;
|
||||
}
|
||||
var radius = max < 0 ? radar.runtimeDataRadius - radar.runtimeDataRadius * value / max
|
||||
: radar.runtimeDataRadius * value / max;
|
||||
var currAngle = (index + (radar.positionType == Radar.PositionType.Between ? 0.5f : 0)) * angle;
|
||||
radius *= rate;
|
||||
if (index == startIndex)
|
||||
{
|
||||
startPoint = new Vector3(p.x + radius * Mathf.Sin(currAngle),
|
||||
p.y + radius * Mathf.Cos(currAngle));
|
||||
firstPoint = startPoint;
|
||||
}
|
||||
else
|
||||
{
|
||||
toPoint = new Vector3(p.x + radius * Mathf.Sin(currAngle),
|
||||
p.y + radius * Mathf.Cos(currAngle));
|
||||
if (serie.areaStyle.show)
|
||||
{
|
||||
UGL.DrawTriangle(vh, startPoint, toPoint, p, areaColor, areaColor, areaToColor);
|
||||
}
|
||||
if (serie.lineStyle.show)
|
||||
{
|
||||
ChartDrawer.DrawLineStyle(vh, serie.lineStyle, startPoint, toPoint, lineColor,
|
||||
chart.theme.serie.lineWidth, LineStyle.Type.Solid);
|
||||
}
|
||||
startPoint = toPoint;
|
||||
}
|
||||
serieData.labelPosition = startPoint;
|
||||
pointList.Add(startPoint);
|
||||
|
||||
if (serie.areaStyle.show && j == endIndex)
|
||||
{
|
||||
UGL.DrawTriangle(vh, startPoint, firstPoint, centerPos, areaColor, areaColor, areaToColor);
|
||||
}
|
||||
if (serie.lineStyle.show && j == endIndex)
|
||||
{
|
||||
ChartDrawer.DrawLineStyle(vh, serie.lineStyle, startPoint, firstPoint, lineColor,
|
||||
chart.theme.serie.lineWidth, LineStyle.Type.Solid);
|
||||
}
|
||||
}
|
||||
if (serie.symbol.show && serie.symbol.type != SerieSymbolType.None)
|
||||
{
|
||||
for (int j = 0; j < serie.data.Count; j++)
|
||||
{
|
||||
var serieData = serie.data[j];
|
||||
if (!serieData.show) continue;
|
||||
var isHighlight = serie.highlighted || serieData.highlighted ||
|
||||
(chart.tooltip.show && chart.tooltip.runtimeDataIndex[0] == i && chart.tooltip.runtimeDataIndex[1] == j);
|
||||
var serieIndex = serieData.index;
|
||||
var symbolSize = isHighlight
|
||||
? serie.symbol.GetSelectedSize(serieData.data, chart.theme.serie.lineSymbolSelectedSize)
|
||||
: serie.symbol.GetSize(serieData.data, chart.theme.serie.lineSymbolSize);
|
||||
var symbolColor = SerieHelper.GetItemColor(serie, serieData, chart.theme, serieIndex, isHighlight);
|
||||
var symbolToColor = SerieHelper.GetItemToColor(serie, serieData, chart.theme, serieIndex, isHighlight);
|
||||
var symbolBorder = SerieHelper.GetSymbolBorder(serie, serieData, chart.theme, isHighlight);
|
||||
var cornerRadius = SerieHelper.GetSymbolCornerRadius(serie, serieData, isHighlight);
|
||||
chart.DrawSymbol(vh, serie.symbol.type, symbolSize, symbolBorder, serieData.labelPosition, symbolColor,
|
||||
symbolToColor, serie.symbol.gap, cornerRadius);
|
||||
}
|
||||
}
|
||||
if (!serie.animation.IsFinish())
|
||||
{
|
||||
serie.animation.CheckProgress(1);
|
||||
chart.RefreshPainter(serie);
|
||||
}
|
||||
if (dataChanging)
|
||||
{
|
||||
chart.RefreshPainter(serie);
|
||||
}
|
||||
}
|
||||
|
||||
private int GetStartShowIndex(Serie serie)
|
||||
{
|
||||
for (int i = 0; i < serie.dataCount; i++)
|
||||
{
|
||||
if (serie.data[i].show) return i;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
private int GetEndShowIndex(Serie serie)
|
||||
{
|
||||
for (int i = serie.dataCount - 1; i >= 0; i--)
|
||||
{
|
||||
if (serie.data[i].show) return i;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
private void DrawRadarSymbol(VertexHelper vh, Serie serie, SerieData serieData, int serieIndex, bool isHighlight,
|
||||
List<Vector3> pointList)
|
||||
{
|
||||
if (serie.symbol.show && serie.symbol.type != SerieSymbolType.None)
|
||||
{
|
||||
var symbolSize = isHighlight
|
||||
? serie.symbol.GetSelectedSize(serieData.data, chart.theme.serie.lineSymbolSelectedSize)
|
||||
: serie.symbol.GetSize(serieData.data, chart.theme.serie.lineSymbolSize);
|
||||
var symbolColor = SerieHelper.GetItemColor(serie, serieData, chart.theme, serieIndex, isHighlight);
|
||||
var symbolToColor = SerieHelper.GetItemToColor(serie, serieData, chart.theme, serieIndex, isHighlight);
|
||||
var symbolBorder = SerieHelper.GetSymbolBorder(serie, serieData, chart.theme, isHighlight);
|
||||
var cornerRadius = SerieHelper.GetSymbolCornerRadius(serie, serieData, isHighlight);
|
||||
foreach (var point in pointList)
|
||||
{
|
||||
chart.DrawSymbol(vh, serie.symbol.type, symbolSize, symbolBorder, point, symbolColor,
|
||||
symbolToColor, serie.symbol.gap, cornerRadius);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawRadar(VertexHelper vh, Radar radar)
|
||||
{
|
||||
if (!radar.splitLine.show && !radar.splitArea.show)
|
||||
{
|
||||
return;
|
||||
}
|
||||
float insideRadius = 0, outsideRadius = 0;
|
||||
float block = radar.runtimeRadius / radar.splitNumber;
|
||||
int indicatorNum = radar.indicatorList.Count;
|
||||
Vector3 p1, p2, p3, p4;
|
||||
Vector3 p = radar.runtimeCenterPos;
|
||||
float angle = 2 * Mathf.PI / indicatorNum;
|
||||
var lineColor = radar.axisLine.GetColor(chart.theme.radar.lineColor);
|
||||
var lineWidth = radar.axisLine.GetWidth(chart.theme.radar.lineWidth);
|
||||
var lineType = radar.axisLine.GetType(chart.theme.radar.lineType);
|
||||
var splitLineColor = radar.splitLine.GetColor(chart.theme.radar.splitLineColor);
|
||||
var splitLineWidth = radar.splitLine.GetWidth(chart.theme.radar.splitLineWidth);
|
||||
var splitLineType = radar.splitLine.GetType(chart.theme.radar.splitLineType);
|
||||
for (int i = 0; i < radar.splitNumber; i++)
|
||||
{
|
||||
var isLast = i == radar.splitNumber - 1;
|
||||
var color = radar.splitArea.GetColor(i, chart.theme.radar);
|
||||
outsideRadius = insideRadius + block;
|
||||
p1 = new Vector3(p.x + insideRadius * Mathf.Sin(0), p.y + insideRadius * Mathf.Cos(0));
|
||||
p2 = new Vector3(p.x + outsideRadius * Mathf.Sin(0), p.y + outsideRadius * Mathf.Cos(0));
|
||||
for (int j = 0; j <= indicatorNum; j++)
|
||||
{
|
||||
float currAngle = j * angle;
|
||||
p3 = new Vector3(p.x + outsideRadius * Mathf.Sin(currAngle),
|
||||
p.y + outsideRadius * Mathf.Cos(currAngle));
|
||||
p4 = new Vector3(p.x + insideRadius * Mathf.Sin(currAngle),
|
||||
p.y + insideRadius * Mathf.Cos(currAngle));
|
||||
if (radar.splitArea.show)
|
||||
{
|
||||
UGL.DrawQuadrilateral(vh, p1, p2, p3, p4, color);
|
||||
}
|
||||
if (radar.splitLine.NeedShow(i))
|
||||
{
|
||||
if (isLast)
|
||||
ChartDrawer.DrawLineStyle(vh, lineType, lineWidth, p2, p3, lineColor);
|
||||
else
|
||||
ChartDrawer.DrawLineStyle(vh, splitLineType, splitLineWidth, p2, p3, splitLineColor);
|
||||
}
|
||||
p1 = p4;
|
||||
p2 = p3;
|
||||
}
|
||||
insideRadius = outsideRadius;
|
||||
}
|
||||
for (int j = 0; j <= indicatorNum; j++)
|
||||
{
|
||||
float currAngle = j * angle;
|
||||
p3 = new Vector3(p.x + outsideRadius * Mathf.Sin(currAngle),
|
||||
p.y + outsideRadius * Mathf.Cos(currAngle));
|
||||
if (radar.splitLine.show)
|
||||
{
|
||||
ChartDrawer.DrawLineStyle(vh, splitLineType, splitLineWidth, p, p3, splitLineColor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawCricleRadar(VertexHelper vh, Radar radar)
|
||||
{
|
||||
if (!radar.splitLine.show && !radar.splitArea.show)
|
||||
{
|
||||
return;
|
||||
}
|
||||
float insideRadius = 0, outsideRadius = 0;
|
||||
float block = radar.runtimeRadius / radar.splitNumber;
|
||||
int indicatorNum = radar.indicatorList.Count;
|
||||
Vector3 p = radar.runtimeCenterPos;
|
||||
Vector3 p1;
|
||||
float angle = 2 * Mathf.PI / indicatorNum;
|
||||
var lineColor = radar.axisLine.GetColor(chart.theme.radar.lineColor);
|
||||
var lineWidth = radar.splitLine.GetWidth(chart.theme.radar.splitLineWidth);
|
||||
for (int i = 0; i < radar.splitNumber; i++)
|
||||
{
|
||||
Color color = radar.splitArea.color[i % radar.splitArea.color.Count];
|
||||
outsideRadius = insideRadius + block;
|
||||
if (radar.splitArea.show)
|
||||
{
|
||||
UGL.DrawDoughnut(vh, p, insideRadius, outsideRadius, color, Color.clear,
|
||||
0, 360, chart.settings.cicleSmoothness);
|
||||
}
|
||||
if (radar.splitLine.show)
|
||||
{
|
||||
UGL.DrawEmptyCricle(vh, p, outsideRadius, lineWidth, lineColor,
|
||||
Color.clear, chart.settings.cicleSmoothness);
|
||||
}
|
||||
insideRadius = outsideRadius;
|
||||
}
|
||||
for (int j = 0; j <= indicatorNum; j++)
|
||||
{
|
||||
float currAngle = j * angle;
|
||||
p1 = new Vector3(p.x + outsideRadius * Mathf.Sin(currAngle),
|
||||
p.y + outsideRadius * Mathf.Cos(currAngle));
|
||||
if (radar.splitLine.show)
|
||||
{
|
||||
UGL.DrawLine(vh, p, p1, lineWidth / 2, lineColor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private bool IsInRadar(Vector2 local)
|
||||
{
|
||||
foreach (var radar in chart.radars)
|
||||
{
|
||||
var dist = Vector2.Distance(radar.runtimeCenterPos, local);
|
||||
if (dist < radar.runtimeRadius + chart.theme.serie.lineSymbolSize)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected void UpdateTooltip()
|
||||
{
|
||||
int serieIndex = chart.tooltip.runtimeDataIndex[0];
|
||||
if (serieIndex < 0)
|
||||
{
|
||||
if (chart.tooltip.IsActive())
|
||||
{
|
||||
chart.tooltip.SetActive(false);
|
||||
chart.RefreshChart();
|
||||
}
|
||||
return;
|
||||
}
|
||||
chart.tooltip.SetActive(true);
|
||||
var serie = chart.series.GetSerie(serieIndex);
|
||||
var radar = chart.radars[serie.radarIndex];
|
||||
var dataIndex = chart.tooltip.runtimeDataIndex[1];
|
||||
var content = TooltipHelper.GetFormatterContent(chart.tooltip, dataIndex, chart.series, chart.theme,
|
||||
null, null, false, radar);
|
||||
TooltipHelper.SetContentAndPosition(chart.tooltip, content, chart.chartRect);
|
||||
}
|
||||
|
||||
private bool IsAnyRadarDirty()
|
||||
{
|
||||
foreach (var radar in chart.radars)
|
||||
{
|
||||
if (radar.anyDirty) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8b5a823d3c59a461f872211f9580a28c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,361 @@
|
||||
/************************************************/
|
||||
/* */
|
||||
/* Copyright (c) 2018 - 2021 monitor1394 */
|
||||
/* https://github.com/monitor1394 */
|
||||
/* */
|
||||
/************************************************/
|
||||
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using UnityEngine.EventSystems;
|
||||
using XUGL;
|
||||
|
||||
namespace XCharts
|
||||
{
|
||||
internal class DrawSerieRing : IDrawSerie
|
||||
{
|
||||
public BaseChart chart;
|
||||
private bool m_UpdateTitleText = false;
|
||||
private bool m_UpdateLabelText = false;
|
||||
private bool m_IsEnterLegendButtom;
|
||||
|
||||
public DrawSerieRing(BaseChart chart)
|
||||
{
|
||||
this.chart = chart;
|
||||
}
|
||||
|
||||
public void InitComponent()
|
||||
{
|
||||
}
|
||||
|
||||
public void CheckComponent()
|
||||
{
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
if (m_UpdateTitleText)
|
||||
{
|
||||
m_UpdateTitleText = false;
|
||||
foreach (var serie in chart.series.list)
|
||||
{
|
||||
if (serie.type == SerieType.Ring)
|
||||
{
|
||||
TitleStyleHelper.UpdateTitleText(serie);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (m_UpdateLabelText)
|
||||
{
|
||||
m_UpdateLabelText = false;
|
||||
foreach (var serie in chart.series.list)
|
||||
{
|
||||
if (serie.type == SerieType.Ring)
|
||||
{
|
||||
SerieLabelHelper.SetRingLabelText(serie, chart.theme);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void DrawBase(VertexHelper vh)
|
||||
{
|
||||
}
|
||||
|
||||
public void DrawSerie(VertexHelper vh, Serie serie)
|
||||
{
|
||||
if (serie.type != SerieType.Ring) return;
|
||||
if (!serie.show || serie.animation.HasFadeOut()) return;
|
||||
var data = serie.data;
|
||||
serie.animation.InitProgress(data.Count, serie.startAngle, serie.startAngle + 360);
|
||||
SerieHelper.UpdateCenter(serie, chart.chartPosition, chart.chartWidth, chart.chartHeight);
|
||||
TitleStyleHelper.CheckTitle(serie, ref chart.m_ReinitTitle, ref m_UpdateTitleText);
|
||||
SerieLabelHelper.CheckLabel(serie, ref chart.m_ReinitLabel, ref m_UpdateLabelText);
|
||||
var dataChangeDuration = serie.animation.GetUpdateAnimationDuration();
|
||||
var ringWidth = serie.runtimeOutsideRadius - serie.runtimeInsideRadius;
|
||||
var dataChanging = false;
|
||||
for (int j = 0; j < data.Count; j++)
|
||||
{
|
||||
var serieData = data[j];
|
||||
if (!serieData.show) continue;
|
||||
if (serieData.IsDataChanged()) dataChanging = true;
|
||||
var value = serieData.GetFirstData(dataChangeDuration);
|
||||
var max = serieData.GetLastData();
|
||||
var degree = 360 * value / max;
|
||||
var startDegree = GetStartAngle(serie);
|
||||
var toDegree = GetToAngle(serie, degree);
|
||||
var itemStyle = SerieHelper.GetItemStyle(serie, serieData, serieData.highlighted);
|
||||
var itemColor = SerieHelper.GetItemColor(serie, serieData, chart.theme, j, serieData.highlighted);
|
||||
var itemToColor = SerieHelper.GetItemToColor(serie, serieData, chart.theme, j, serieData.highlighted);
|
||||
var outsideRadius = serie.runtimeOutsideRadius - j * (ringWidth + serie.ringGap);
|
||||
var insideRadius = outsideRadius - ringWidth;
|
||||
var centerRadius = (outsideRadius + insideRadius) / 2;
|
||||
var borderWidth = itemStyle.borderWidth;
|
||||
var borderColor = itemStyle.borderColor;
|
||||
var roundCap = serie.roundCap && insideRadius > 0;
|
||||
|
||||
serieData.runtimePieStartAngle = serie.clockwise ? startDegree : toDegree;
|
||||
serieData.runtimePieToAngle = serie.clockwise ? toDegree : startDegree;
|
||||
serieData.runtimePieInsideRadius = insideRadius;
|
||||
serieData.runtimePieOutsideRadius = outsideRadius;
|
||||
UGL.DrawDoughnut(vh, serie.runtimeCenterPos, insideRadius, outsideRadius, itemColor, itemToColor,
|
||||
Color.clear, startDegree, toDegree, borderWidth, borderColor, 0, chart.settings.cicleSmoothness,
|
||||
roundCap, serie.clockwise);
|
||||
DrawCenter(vh, serie, serieData, insideRadius, j == data.Count - 1);
|
||||
UpateLabelPosition(serie, serieData, j, startDegree, toDegree, centerRadius);
|
||||
}
|
||||
if (!serie.animation.IsFinish())
|
||||
{
|
||||
serie.animation.CheckProgress(360);
|
||||
chart.RefreshChart();
|
||||
}
|
||||
if (dataChanging)
|
||||
{
|
||||
chart.RefreshChart();
|
||||
}
|
||||
}
|
||||
|
||||
public void RefreshLabel()
|
||||
{
|
||||
}
|
||||
|
||||
public bool CheckTootipArea(Vector2 local)
|
||||
{
|
||||
if (!PointerIsInRingSerie(chart.series, local)) return false;
|
||||
if (m_IsEnterLegendButtom) return false;
|
||||
bool selected = false;
|
||||
chart.tooltip.runtimeDataIndex.Clear();
|
||||
foreach (var serie in chart.series.list)
|
||||
{
|
||||
int index = GetRingIndex(serie, local);
|
||||
chart.tooltip.runtimeDataIndex.Add(index);
|
||||
if (serie.type != SerieType.Ring) continue;
|
||||
bool refresh = false;
|
||||
for (int j = 0; j < serie.data.Count; j++)
|
||||
{
|
||||
var serieData = serie.data[j];
|
||||
if (serieData.highlighted != (j == index)) refresh = true;
|
||||
serieData.highlighted = j == index;
|
||||
}
|
||||
if (index >= 0) selected = true;
|
||||
if (refresh) chart.RefreshChart();
|
||||
}
|
||||
if (selected)
|
||||
{
|
||||
chart.tooltip.UpdateContentPos(local + chart.tooltip.offset);
|
||||
UpdateTooltip();
|
||||
}
|
||||
else if (chart.tooltip.IsActive())
|
||||
{
|
||||
chart.tooltip.SetActive(false);
|
||||
chart.RefreshChart();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool OnLegendButtonClick(int index, string legendName, bool show)
|
||||
{
|
||||
if (!SeriesHelper.ContainsSerie(chart.series, SerieType.Ring)) return false;
|
||||
if (!LegendHelper.IsSerieLegend(chart.series, legendName, SerieType.Ring)) return false;
|
||||
LegendHelper.CheckDataShow(chart.series, legendName, show);
|
||||
chart.UpdateLegendColor(legendName, show);
|
||||
chart.RefreshChart();
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool OnLegendButtonEnter(int index, string legendName)
|
||||
{
|
||||
if (!SeriesHelper.ContainsSerie(chart.series, SerieType.Ring)) return false;
|
||||
if (!LegendHelper.IsSerieLegend(chart.series, legendName, SerieType.Ring)) return false;
|
||||
m_IsEnterLegendButtom = true;
|
||||
LegendHelper.CheckDataHighlighted(chart.series, legendName, true);
|
||||
chart.RefreshChart();
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool OnLegendButtonExit(int index, string legendName)
|
||||
{
|
||||
if (!SeriesHelper.ContainsSerie(chart.series, SerieType.Ring)) return false;
|
||||
if (!LegendHelper.IsSerieLegend(chart.series, legendName, SerieType.Ring)) return false;
|
||||
m_IsEnterLegendButtom = false;
|
||||
LegendHelper.CheckDataHighlighted(chart.series, legendName, false);
|
||||
chart.RefreshChart();
|
||||
return true;
|
||||
}
|
||||
|
||||
public void OnPointerDown(PointerEventData eventData)
|
||||
{
|
||||
}
|
||||
|
||||
private float GetStartAngle(Serie serie)
|
||||
{
|
||||
return serie.clockwise ? serie.startAngle : 360 - serie.startAngle;
|
||||
}
|
||||
|
||||
private float GetToAngle(Serie serie, float angle)
|
||||
{
|
||||
var toAngle = angle + serie.startAngle;
|
||||
if (!serie.clockwise)
|
||||
{
|
||||
toAngle = 360 - angle - serie.startAngle;
|
||||
}
|
||||
if (!serie.animation.IsFinish())
|
||||
{
|
||||
var currAngle = serie.animation.GetCurrDetail();
|
||||
if (serie.clockwise)
|
||||
{
|
||||
toAngle = toAngle > currAngle ? currAngle : toAngle;
|
||||
}
|
||||
else
|
||||
{
|
||||
toAngle = toAngle < 360 - currAngle ? 360 - currAngle : toAngle;
|
||||
}
|
||||
}
|
||||
return toAngle;
|
||||
}
|
||||
|
||||
private void DrawCenter(VertexHelper vh, Serie serie, SerieData serieData, float insideRadius, bool last)
|
||||
{
|
||||
var itemStyle = SerieHelper.GetItemStyle(serie, serieData);
|
||||
if (!ChartHelper.IsClearColor(itemStyle.centerColor) && last)
|
||||
{
|
||||
var radius = insideRadius - itemStyle.centerGap;
|
||||
var smoothness = chart.settings.cicleSmoothness;
|
||||
UGL.DrawCricle(vh, serie.runtimeCenterPos, radius, itemStyle.centerColor, smoothness);
|
||||
}
|
||||
}
|
||||
|
||||
private void UpateLabelPosition(Serie serie, SerieData serieData, int index, float startAngle,
|
||||
float toAngle, float centerRadius)
|
||||
{
|
||||
if (!serie.label.show) return;
|
||||
if (serieData.labelObject == null) return;
|
||||
switch (serie.label.position)
|
||||
{
|
||||
case SerieLabel.Position.Center:
|
||||
serieData.labelPosition = serie.runtimeCenterPos + serie.label.offset;
|
||||
break;
|
||||
case SerieLabel.Position.Bottom:
|
||||
var px1 = Mathf.Sin(startAngle * Mathf.Deg2Rad) * centerRadius;
|
||||
var py1 = Mathf.Cos(startAngle * Mathf.Deg2Rad) * centerRadius;
|
||||
var xDiff = serie.clockwise ? -serie.label.margin : serie.label.margin;
|
||||
serieData.labelPosition = serie.runtimeCenterPos + new Vector3(px1 + xDiff, py1);
|
||||
break;
|
||||
case SerieLabel.Position.Top:
|
||||
startAngle += serie.clockwise ? -serie.label.margin : serie.label.margin;
|
||||
toAngle += serie.clockwise ? serie.label.margin : -serie.label.margin;
|
||||
var px2 = Mathf.Sin(toAngle * Mathf.Deg2Rad) * centerRadius;
|
||||
var py2 = Mathf.Cos(toAngle * Mathf.Deg2Rad) * centerRadius;
|
||||
serieData.labelPosition = serie.runtimeCenterPos + new Vector3(px2, py2);
|
||||
break;
|
||||
}
|
||||
serieData.labelObject.SetLabelPosition(serieData.labelPosition);
|
||||
}
|
||||
|
||||
private void DrawBackground(VertexHelper vh, Serie serie, SerieData serieData, int index, float insideRadius, float outsideRadius)
|
||||
{
|
||||
var itemStyle = SerieHelper.GetItemStyle(serie, serieData);
|
||||
var backgroundColor = SerieHelper.GetItemBackgroundColor(serie, serieData, chart.theme, index, false);
|
||||
if (itemStyle.backgroundWidth != 0)
|
||||
{
|
||||
var centerRadius = (outsideRadius + insideRadius) / 2;
|
||||
var inradius = centerRadius - itemStyle.backgroundWidth / 2;
|
||||
var outradius = centerRadius + itemStyle.backgroundWidth / 2;
|
||||
UGL.DrawDoughnut(vh, serie.runtimeCenterPos, inradius,
|
||||
outradius, backgroundColor, Color.clear, chart.settings.cicleSmoothness);
|
||||
}
|
||||
else
|
||||
{
|
||||
UGL.DrawDoughnut(vh, serie.runtimeCenterPos, insideRadius,
|
||||
outsideRadius, backgroundColor, Color.clear, chart.settings.cicleSmoothness);
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawBorder(VertexHelper vh, Serie serie, SerieData serieData, float insideRadius, float outsideRadius)
|
||||
{
|
||||
var itemStyle = SerieHelper.GetItemStyle(serie, serieData);
|
||||
if (itemStyle.show && itemStyle.borderWidth > 0 && !ChartHelper.IsClearColor(itemStyle.borderColor))
|
||||
{
|
||||
UGL.DrawDoughnut(vh, serie.runtimeCenterPos, outsideRadius,
|
||||
outsideRadius + itemStyle.borderWidth, itemStyle.borderColor,
|
||||
Color.clear, chart.settings.cicleSmoothness);
|
||||
UGL.DrawDoughnut(vh, serie.runtimeCenterPos, insideRadius,
|
||||
insideRadius + itemStyle.borderWidth, itemStyle.borderColor,
|
||||
Color.clear, chart.settings.cicleSmoothness);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void DrawRoundCap(VertexHelper vh, Serie serie, Vector3 centerPos, Color color,
|
||||
float insideRadius, float outsideRadius, ref float drawStartDegree, ref float drawEndDegree)
|
||||
{
|
||||
if (serie.roundCap && insideRadius > 0 && drawStartDegree != drawEndDegree)
|
||||
{
|
||||
var width = (outsideRadius - insideRadius) / 2;
|
||||
var radius = insideRadius + width;
|
||||
|
||||
var diffDegree = Mathf.Asin(width / radius) * Mathf.Rad2Deg;
|
||||
drawStartDegree += serie.clockwise ? diffDegree : -diffDegree;
|
||||
drawEndDegree -= serie.clockwise ? diffDegree : -diffDegree;
|
||||
UGL.DrawRoundCap(vh, centerPos, width, radius, drawStartDegree, serie.clockwise, color, false);
|
||||
UGL.DrawRoundCap(vh, centerPos, width, radius, drawEndDegree, serie.clockwise, color, true);
|
||||
}
|
||||
}
|
||||
|
||||
private int GetRingIndex(Serie serie, Vector2 local)
|
||||
{
|
||||
if (serie.type != SerieType.Ring) return -1;
|
||||
var dist = Vector2.Distance(local, serie.runtimeCenterPos);
|
||||
if (dist > serie.runtimeOutsideRadius) return -1;
|
||||
Vector2 dir = local - new Vector2(serie.runtimeCenterPos.x, serie.runtimeCenterPos.y);
|
||||
float angle = VectorAngle(Vector2.up, dir);
|
||||
for (int i = 0; i < serie.data.Count; i++)
|
||||
{
|
||||
var serieData = serie.data[i];
|
||||
if (dist >= serieData.runtimePieInsideRadius &&
|
||||
dist <= serieData.runtimePieOutsideRadius &&
|
||||
angle >= serieData.runtimePieStartAngle &&
|
||||
angle <= serieData.runtimePieToAngle)
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
private bool PointerIsInRingSerie(Series series, Vector2 local)
|
||||
{
|
||||
foreach (var serie in series.list)
|
||||
{
|
||||
if (serie.type != SerieType.Ring) continue;
|
||||
if (GetRingIndex(serie, local) >= 0) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private float VectorAngle(Vector2 from, Vector2 to)
|
||||
{
|
||||
float angle;
|
||||
|
||||
Vector3 cross = Vector3.Cross(from, to);
|
||||
angle = Vector2.Angle(from, to);
|
||||
angle = cross.z > 0 ? -angle : angle;
|
||||
angle = (angle + 360) % 360;
|
||||
return angle;
|
||||
}
|
||||
|
||||
private void UpdateTooltip()
|
||||
{
|
||||
bool showTooltip = false;
|
||||
foreach (var serie in chart.series.list)
|
||||
{
|
||||
int index = chart.tooltip.runtimeDataIndex[serie.index];
|
||||
if (index < 0) continue;
|
||||
showTooltip = true;
|
||||
var content = TooltipHelper.GetFormatterContent(chart.tooltip, index, chart.series, chart.theme);
|
||||
TooltipHelper.SetContentAndPosition(chart.tooltip, content.TrimStart(), chart.chartRect);
|
||||
}
|
||||
chart.tooltip.SetActive(showTooltip);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 27eff3714a61b44d2968104598e3566e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,71 @@
|
||||
/************************************************/
|
||||
/* */
|
||||
/* Copyright (c) 2018 - 2021 monitor1394 */
|
||||
/* https://github.com/monitor1394 */
|
||||
/* */
|
||||
/************************************************/
|
||||
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using UnityEngine.EventSystems;
|
||||
using XUGL;
|
||||
|
||||
namespace XCharts
|
||||
{
|
||||
internal class DrawSerieTemplate : IDrawSerie
|
||||
{
|
||||
public BaseChart chart;
|
||||
|
||||
public DrawSerieTemplate(BaseChart chart)
|
||||
{
|
||||
this.chart = chart;
|
||||
}
|
||||
|
||||
public void InitComponent()
|
||||
{
|
||||
}
|
||||
public void CheckComponent()
|
||||
{
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
}
|
||||
|
||||
public void DrawBase(VertexHelper vh)
|
||||
{
|
||||
}
|
||||
|
||||
public void DrawSerie(VertexHelper vh, Serie serie)
|
||||
{
|
||||
}
|
||||
|
||||
public void RefreshLabel()
|
||||
{
|
||||
}
|
||||
|
||||
public bool CheckTootipArea(Vector2 local)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool OnLegendButtonClick(int index, string legendName, bool show)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool OnLegendButtonEnter(int index, string legendName)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool OnLegendButtonExit(int index, string legendName)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public void OnPointerDown(PointerEventData eventData)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 35f409612108b4fdead9ddce4426c9b0
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b3dbff4f83d24491da3a8a88e3e3ace4
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,412 @@
|
||||
/************************************************/
|
||||
/* */
|
||||
/* Copyright (c) 2018 - 2021 monitor1394 */
|
||||
/* https://github.com/monitor1394 */
|
||||
/* */
|
||||
/************************************************/
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace XCharts
|
||||
{
|
||||
public static class AxisHelper
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// 包含箭头偏移的轴线长度
|
||||
/// </summary>
|
||||
/// <param name="axis"></param>
|
||||
/// <returns></returns>
|
||||
public static float GetAxisLineSymbolOffset(Axis axis)
|
||||
{
|
||||
if (axis.axisLine.show && axis.axisLine.showArrow && axis.axisLine.arrow.offset > 0)
|
||||
{
|
||||
return axis.axisLine.arrow.offset;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获得分割段数
|
||||
/// </summary>
|
||||
/// <param name="dataZoom"></param>
|
||||
/// <returns></returns>
|
||||
public static int GetSplitNumber(Axis axis, float coordinateWid, DataZoom dataZoom)
|
||||
{
|
||||
if (axis.type == Axis.AxisType.Value)
|
||||
{
|
||||
if (axis.interval > 0)
|
||||
{
|
||||
if (coordinateWid <= 0) return 0;
|
||||
int num = Mathf.CeilToInt(axis.runtimeMinMaxRange / axis.interval);
|
||||
int maxNum = Mathf.CeilToInt(coordinateWid / 15);
|
||||
if (num > maxNum)
|
||||
{
|
||||
axis.interval *= 2;
|
||||
num = Mathf.CeilToInt(axis.runtimeMinMaxRange / axis.interval);
|
||||
}
|
||||
return num;
|
||||
}
|
||||
else
|
||||
{
|
||||
return axis.splitNumber > 0 ? axis.splitNumber : 4;
|
||||
}
|
||||
}
|
||||
else if (axis.type == Axis.AxisType.Time)
|
||||
{
|
||||
if (axis.interval > 0)
|
||||
{
|
||||
if (coordinateWid <= 0) return 0;
|
||||
int num = Mathf.CeilToInt(axis.runtimeMinMaxRange / axis.interval);
|
||||
int maxNum = Mathf.CeilToInt(coordinateWid / 15);
|
||||
if (num > maxNum)
|
||||
{
|
||||
axis.interval *= 2;
|
||||
num = Mathf.CeilToInt(axis.runtimeMinMaxRange / axis.interval);
|
||||
}
|
||||
return num;
|
||||
}
|
||||
else
|
||||
{
|
||||
return axis.splitNumber > 0 ? axis.splitNumber : 4;
|
||||
}
|
||||
}
|
||||
else if (axis.type == Axis.AxisType.Log)
|
||||
{
|
||||
return axis.splitNumber > 0 ? axis.splitNumber : 4;
|
||||
}
|
||||
else if (axis.type == Axis.AxisType.Category)
|
||||
{
|
||||
int dataCount = axis.GetDataList(dataZoom).Count;
|
||||
if (axis.splitNumber <= 0 || axis.splitNumber > dataCount) return dataCount;
|
||||
if (dataCount >= axis.splitNumber * 2) return axis.splitNumber;
|
||||
else return dataCount;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获得分割段的宽度
|
||||
/// </summary>
|
||||
/// <param name="coordinateWidth"></param>
|
||||
/// <param name="dataZoom"></param>
|
||||
/// <returns></returns>
|
||||
public static float GetSplitWidth(Axis axis, float coordinateWidth, DataZoom dataZoom)
|
||||
{
|
||||
int split = GetSplitNumber(axis, coordinateWidth, dataZoom);
|
||||
int segment = (axis.boundaryGap ? split : split - 1);
|
||||
segment = segment <= 0 ? 1 : segment;
|
||||
return coordinateWidth / segment;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获得一个类目数据在坐标系中代表的宽度
|
||||
/// </summary>
|
||||
/// <param name="coordinateWidth"></param>
|
||||
/// <param name="dataZoom"></param>
|
||||
/// <returns></returns>
|
||||
public static float GetDataWidth(Axis axis, float coordinateWidth, int dataCount, DataZoom dataZoom)
|
||||
{
|
||||
if (dataCount < 1) dataCount = 1;
|
||||
var categoryCount = axis.GetDataNumber(dataZoom);
|
||||
int segment = (axis.boundaryGap ? categoryCount : categoryCount - 1);
|
||||
segment = segment <= 0 ? dataCount : segment;
|
||||
if (segment <= 0) segment = 1;
|
||||
return coordinateWidth / segment;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获得标签显示的名称
|
||||
/// </summary>
|
||||
/// <param name="index"></param>
|
||||
/// <param name="minValue"></param>
|
||||
/// <param name="maxValue"></param>
|
||||
/// <param name="dataZoom"></param>
|
||||
/// <returns></returns>
|
||||
internal static string GetLabelName(Axis axis, float coordinateWidth, int index, float minValue, float maxValue,
|
||||
DataZoom dataZoom, bool forcePercent)
|
||||
{
|
||||
int split = GetSplitNumber(axis, coordinateWidth, dataZoom);
|
||||
if (axis.type == Axis.AxisType.Value)
|
||||
{
|
||||
if (minValue == 0 && maxValue == 0) return string.Empty;
|
||||
var value = 0f;
|
||||
if (forcePercent) maxValue = 100;
|
||||
if (axis.interval > 0)
|
||||
{
|
||||
if (index == split) value = maxValue;
|
||||
else value = minValue + index * axis.interval;
|
||||
}
|
||||
else
|
||||
{
|
||||
value = minValue + (maxValue - minValue) * index / split;
|
||||
if (!axis.clockwise && value != minValue) value = maxValue - value;
|
||||
}
|
||||
if (axis.inverse)
|
||||
{
|
||||
value = -value;
|
||||
minValue = -minValue;
|
||||
maxValue = -maxValue;
|
||||
}
|
||||
|
||||
if (forcePercent) return string.Format("{0}%", (int)value);
|
||||
else return axis.axisLabel.GetFormatterContent(value, minValue, maxValue);
|
||||
}
|
||||
else if (axis.type == Axis.AxisType.Log)
|
||||
{
|
||||
float value = axis.logBaseE ? Mathf.Exp(axis.runtimeMinLogIndex + index) :
|
||||
Mathf.Pow(axis.logBase, axis.runtimeMinLogIndex + index);
|
||||
if (axis.inverse)
|
||||
{
|
||||
value = -value;
|
||||
minValue = -minValue;
|
||||
maxValue = -maxValue;
|
||||
}
|
||||
return axis.axisLabel.GetFormatterContent(value, minValue, maxValue, true);
|
||||
}
|
||||
else if (axis.type == Axis.AxisType.Time)
|
||||
{
|
||||
if (minValue == 0 && maxValue == 0) return string.Empty;
|
||||
var value = 0f;
|
||||
if (axis.interval > 0)
|
||||
{
|
||||
if (index == split) value = maxValue;
|
||||
else value = minValue + index * axis.interval;
|
||||
}
|
||||
else
|
||||
{
|
||||
value = minValue + (maxValue - minValue) * index / split;
|
||||
}
|
||||
var timestamp = (int)value;
|
||||
var dateTime = DateTimeUtil.GetDateTime(timestamp);
|
||||
return axis.axisLabel.GetFormatterDateTime(dateTime);
|
||||
}
|
||||
var showData = axis.GetDataList(dataZoom);
|
||||
int dataCount = showData.Count;
|
||||
if (dataCount <= 0) return "";
|
||||
int rate = Mathf.RoundToInt(dataCount * 1f / split);
|
||||
int newIndex = index * rate;
|
||||
if (newIndex <= dataCount - 1)
|
||||
{
|
||||
return axis.axisLabel.GetFormatterContent(showData[newIndex]);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (rate == 1) return string.Empty;
|
||||
else if (axis.boundaryGap && coordinateWidth / dataCount > 10) return string.Empty;
|
||||
else
|
||||
{
|
||||
if ((index - 1) * rate > dataCount - 1) return string.Empty;
|
||||
else return axis.axisLabel.GetFormatterContent(showData[dataCount - 1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获得分割线条数
|
||||
/// </summary>
|
||||
/// <param name="dataZoom"></param>
|
||||
/// <returns></returns>
|
||||
internal static int GetScaleNumber(Axis axis, float coordinateWidth, DataZoom dataZoom = null)
|
||||
{
|
||||
int splitNum = GetSplitNumber(axis, coordinateWidth, dataZoom);
|
||||
if (axis.IsCategory())
|
||||
{
|
||||
var data = axis.GetDataList();
|
||||
int tick = Mathf.RoundToInt(data.Count * 1f / splitNum);
|
||||
if (axis.boundaryGap)
|
||||
return Mathf.CeilToInt(data.Count * 1.0f / tick) + 1;
|
||||
else
|
||||
return Mathf.CeilToInt(data.Count * 1.0f / tick);
|
||||
}
|
||||
else
|
||||
{
|
||||
return splitNum + 1;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获得分割段宽度
|
||||
/// </summary>
|
||||
/// <param name="coordinateWidth"></param>
|
||||
/// <param name="dataZoom"></param>
|
||||
/// <returns></returns>
|
||||
internal static float GetScaleWidth(Axis axis, float coordinateWidth, int index, DataZoom dataZoom = null)
|
||||
{
|
||||
if (index < 0) return 0;
|
||||
int num = GetScaleNumber(axis, coordinateWidth, dataZoom);
|
||||
int splitNum = GetSplitNumber(axis, coordinateWidth, dataZoom);
|
||||
if (num <= 0) num = 1;
|
||||
if (axis.type == Axis.AxisType.Value && axis.interval > 0)
|
||||
{
|
||||
if (axis.runtimeMinMaxRange <= 0) return 0;
|
||||
if (index >= splitNum) return coordinateWidth - (index - 1) * axis.interval * coordinateWidth / axis.runtimeMinMaxRange;
|
||||
else return axis.interval * coordinateWidth / axis.runtimeMinMaxRange;
|
||||
}
|
||||
else
|
||||
{
|
||||
var data = axis.GetDataList();
|
||||
if (axis.IsCategory() && data.Count > 0)
|
||||
{
|
||||
int tick = Mathf.RoundToInt(data.Count * 1f / splitNum);
|
||||
var count = axis.boundaryGap ? data.Count : data.Count - 1;
|
||||
if (count <= 0) return 0;
|
||||
var each = coordinateWidth / count;
|
||||
if (index >= num - 1)
|
||||
{
|
||||
if (axis.axisTick.alignWithLabel) return each * tick;
|
||||
else return coordinateWidth - each * tick * (index - 1);
|
||||
}
|
||||
else return each * tick;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (splitNum <= 0) return 0;
|
||||
else return coordinateWidth / splitNum;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal static float GetEachWidth(Axis axis, float coordinateWidth, DataZoom dataZoom = null)
|
||||
{
|
||||
var data = axis.GetDataList();
|
||||
if (data.Count > 0)
|
||||
{
|
||||
var count = axis.boundaryGap ? data.Count : data.Count - 1;
|
||||
return count > 0 ? coordinateWidth / count : coordinateWidth;
|
||||
}
|
||||
else
|
||||
{
|
||||
int num = GetScaleNumber(axis, coordinateWidth, dataZoom) - 1;
|
||||
return num > 0 ? coordinateWidth / num : coordinateWidth;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 调整最大最小值
|
||||
/// </summary>
|
||||
/// <param name="minValue"></param>
|
||||
/// <param name="maxValue"></param>
|
||||
internal static void AdjustMinMaxValue(Axis axis, ref float minValue, ref float maxValue, bool needFormat, int ceilRate = 0)
|
||||
{
|
||||
if (axis.type == Axis.AxisType.Log)
|
||||
{
|
||||
int minSplit = 0;
|
||||
int maxSplit = 0;
|
||||
maxValue = ChartHelper.GetMaxLogValue(maxValue, axis.logBase, axis.logBaseE, out maxSplit);
|
||||
minValue = ChartHelper.GetMinLogValue(minValue, axis.logBase, axis.logBaseE, out minSplit);
|
||||
axis.splitNumber = (minSplit > 0 && maxSplit > 0) ? (maxSplit + minSplit - 1) : (maxSplit + minSplit);
|
||||
return;
|
||||
}
|
||||
if (axis.minMaxType == Axis.AxisMinMaxType.Custom)
|
||||
{
|
||||
if (axis.min != 0 || axis.max != 0)
|
||||
{
|
||||
if (axis.inverse)
|
||||
{
|
||||
minValue = -axis.max;
|
||||
maxValue = -axis.min;
|
||||
}
|
||||
else
|
||||
{
|
||||
minValue = axis.min;
|
||||
maxValue = axis.max;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ceilRate == 0) ceilRate = axis.ceilRate;
|
||||
switch (axis.minMaxType)
|
||||
{
|
||||
case Axis.AxisMinMaxType.Default:
|
||||
if (minValue == 0 && maxValue == 0)
|
||||
{
|
||||
}
|
||||
else if (minValue > 0 && maxValue > 0)
|
||||
{
|
||||
minValue = 0;
|
||||
maxValue = needFormat ? ChartHelper.GetMaxDivisibleValue(maxValue, ceilRate) : maxValue;
|
||||
}
|
||||
else if (minValue < 0 && maxValue < 0)
|
||||
{
|
||||
minValue = needFormat ? ChartHelper.GetMinDivisibleValue(minValue, ceilRate) : minValue;
|
||||
maxValue = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
minValue = needFormat ? ChartHelper.GetMinDivisibleValue(minValue, ceilRate) : minValue;
|
||||
maxValue = needFormat ? ChartHelper.GetMaxDivisibleValue(maxValue, ceilRate) : maxValue;
|
||||
}
|
||||
break;
|
||||
case Axis.AxisMinMaxType.MinMax:
|
||||
minValue = needFormat ? ChartHelper.GetMinDivisibleValue(minValue, ceilRate) : minValue;
|
||||
maxValue = needFormat ? ChartHelper.GetMaxDivisibleValue(maxValue, ceilRate) : maxValue;
|
||||
break;
|
||||
}
|
||||
}
|
||||
var tempRange = maxValue - minValue;
|
||||
if (axis.runtimeMinMaxRange != tempRange)
|
||||
{
|
||||
axis.runtimeMinMaxRange = tempRange;
|
||||
if (axis.type == Axis.AxisType.Value && axis.interval > 0)
|
||||
{
|
||||
axis.SetComponentDirty();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal static bool NeedShowSplit(Axis axis)
|
||||
{
|
||||
if (!axis.show) return false;
|
||||
if (axis.IsCategory() && axis.GetDataList().Count <= 0) return false;
|
||||
else if (axis.IsValue() && axis.runtimeMinValue == 0 && axis.runtimeMaxValue == 0) return false;
|
||||
else return true;
|
||||
}
|
||||
|
||||
internal static void AdjustCircleLabelPos(ChartText txt, Vector3 pos, Vector3 cenPos, float txtHig, Vector3 offset)
|
||||
{
|
||||
var txtWidth = txt.GetPreferredWidth();
|
||||
var sizeDelta = new Vector2(txtWidth, txt.GetPreferredHeight());
|
||||
txt.SetSizeDelta(sizeDelta);
|
||||
var diff = pos.x - cenPos.x;
|
||||
if (diff < -1f) //left
|
||||
{
|
||||
pos = new Vector3(pos.x - txtWidth / 2, pos.y);
|
||||
}
|
||||
else if (diff > 1f) //right
|
||||
{
|
||||
pos = new Vector3(pos.x + txtWidth / 2, pos.y);
|
||||
}
|
||||
else
|
||||
{
|
||||
float y = pos.y > cenPos.y ? pos.y + txtHig / 2 : pos.y - txtHig / 2;
|
||||
pos = new Vector3(pos.x, y);
|
||||
}
|
||||
txt.SetLocalPosition(pos + offset);
|
||||
}
|
||||
|
||||
internal static void AdjustRadiusAxisLabelPos(ChartText txt, Vector3 pos, Vector3 cenPos, float txtHig, Vector3 offset)
|
||||
{
|
||||
var txtWidth = txt.GetPreferredWidth();
|
||||
var sizeDelta = new Vector2(txtWidth, txt.GetPreferredHeight());
|
||||
txt.SetSizeDelta(sizeDelta);
|
||||
var diff = pos.y - cenPos.y;
|
||||
if (diff > 20f) //left
|
||||
{
|
||||
pos = new Vector3(pos.x - txtWidth / 2, pos.y);
|
||||
}
|
||||
else if (diff < -20f) //right
|
||||
{
|
||||
pos = new Vector3(pos.x + txtWidth / 2, pos.y);
|
||||
}
|
||||
else
|
||||
{
|
||||
float y = pos.y > cenPos.y ? pos.y + txtHig / 2 : pos.y - txtHig / 2;
|
||||
pos = new Vector3(pos.x, y);
|
||||
}
|
||||
txt.SetLocalPosition(pos);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 502c2be6d197b40f59ae65d9c659700f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,24 @@
|
||||
/************************************************/
|
||||
/* */
|
||||
/* Copyright (c) 2018 - 2021 monitor1394 */
|
||||
/* https://github.com/monitor1394 */
|
||||
/* */
|
||||
/************************************************/
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace XCharts
|
||||
{
|
||||
internal static class ItemStyleHelper
|
||||
{
|
||||
public static bool IsNeedCorner(ItemStyle itemStyle)
|
||||
{
|
||||
if (itemStyle.cornerRadius == null) return false;
|
||||
foreach (var value in itemStyle.cornerRadius)
|
||||
{
|
||||
if (value != 0) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 14c20b85c2c6d44b08f57c928307080d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,307 @@
|
||||
/************************************************/
|
||||
/* */
|
||||
/* Copyright (c) 2018 - 2021 monitor1394 */
|
||||
/* https://github.com/monitor1394 */
|
||||
/* */
|
||||
/************************************************/
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace XCharts
|
||||
{
|
||||
internal static class LegendHelper
|
||||
{
|
||||
public static Color GetContentColor(Legend legend, ChartTheme theme, bool active)
|
||||
{
|
||||
var textStyle = legend.textStyle;
|
||||
if (active) return !ChartHelper.IsClearColor(textStyle.color) ? textStyle.color : theme.legend.textColor;
|
||||
else return theme.legend.unableColor;
|
||||
}
|
||||
|
||||
public static Color GetIconColor(Legend legend, int readIndex, ChartTheme theme, Series series, string legendName, bool active)
|
||||
{
|
||||
if (active)
|
||||
{
|
||||
if (legend.itemAutoColor || legend.GetIcon(readIndex) == null)
|
||||
{
|
||||
return SeriesHelper.GetNameColor(series, readIndex, legendName, theme);
|
||||
}
|
||||
else
|
||||
return Color.white;
|
||||
}
|
||||
else return theme.legend.unableColor;
|
||||
}
|
||||
|
||||
public static LegendItem AddLegendItem(Legend legend, int i, string legendName, Transform parent,
|
||||
ChartTheme theme, string content, Color itemColor, bool active)
|
||||
{
|
||||
var objName = i + "_" + legendName;
|
||||
var anchorMin = new Vector2(0, 0.5f);
|
||||
var anchorMax = new Vector2(0, 0.5f);
|
||||
var pivot = new Vector2(0, 0.5f);
|
||||
var sizeDelta = new Vector2(100, 30);
|
||||
var iconSizeDelta = new Vector2(legend.itemWidth, legend.itemHeight);
|
||||
var textStyle = legend.textStyle;
|
||||
var contentColor = GetContentColor(legend, theme, active);
|
||||
|
||||
var objAnchorMin = new Vector2(0, 1);
|
||||
var objAnchorMax = new Vector2(0, 1);
|
||||
var objPivot = new Vector2(0, 1);
|
||||
var btnObj = ChartHelper.AddObject(objName, parent, objAnchorMin, objAnchorMax, objPivot, sizeDelta, i);
|
||||
var iconObj = ChartHelper.AddObject("icon", btnObj.transform, anchorMin, anchorMax, pivot, iconSizeDelta);
|
||||
var contentObj = ChartHelper.AddObject("content", btnObj.transform, anchorMin, anchorMax, pivot, sizeDelta);
|
||||
var img = ChartHelper.GetOrAddComponent<Image>(btnObj);
|
||||
img.color = Color.clear;
|
||||
ChartHelper.GetOrAddComponent<Button>(btnObj);
|
||||
ChartHelper.GetOrAddComponent<Image>(iconObj);
|
||||
ChartHelper.GetOrAddComponent<Image>(contentObj);
|
||||
var txt = ChartHelper.AddTextObject("Text", contentObj.transform, anchorMin, anchorMax, pivot, sizeDelta,
|
||||
textStyle, theme.legend);
|
||||
txt.SetAlignment(TextAnchor.MiddleLeft);
|
||||
txt.SetColor(contentColor);
|
||||
var item = new LegendItem();
|
||||
item.index = i;
|
||||
item.name = objName;
|
||||
item.legendName = legendName;
|
||||
item.SetObject(btnObj);
|
||||
item.SetIconSize(legend.itemWidth, legend.itemHeight);
|
||||
item.SetIconColor(itemColor);
|
||||
item.SetIconImage(legend.GetIcon(i));
|
||||
item.SetContentPosition(textStyle.offsetv3);
|
||||
item.SetContent(content);
|
||||
item.SetContentBackgroundColor(textStyle.backgroundColor);
|
||||
return item;
|
||||
}
|
||||
|
||||
public static void ResetItemPosition(Legend legend, Vector3 chartPos, float chartWidth, float chartHeight)
|
||||
{
|
||||
var startX = 0f;
|
||||
var startY = 0f;
|
||||
var legendMaxWidth = chartWidth - legend.location.left - legend.location.right;
|
||||
var legendMaxHeight = chartHeight - legend.location.top - legend.location.bottom;
|
||||
UpdateLegendWidthAndHeight(legend, legendMaxWidth, legendMaxHeight);
|
||||
var legendRuntimeWidth = legend.runtimeWidth;
|
||||
var legendRuntimeHeight = legend.runtimeHeight;
|
||||
var isVertical = legend.orient == Orient.Vertical;
|
||||
switch (legend.location.align)
|
||||
{
|
||||
case Location.Align.TopCenter:
|
||||
startX = chartPos.x + chartWidth / 2 - legendRuntimeWidth / 2;
|
||||
startY = chartPos.y + chartHeight - legend.location.top;
|
||||
break;
|
||||
case Location.Align.TopLeft:
|
||||
startX = chartPos.x + legend.location.left;
|
||||
startY = chartPos.y + chartHeight - legend.location.top;
|
||||
break;
|
||||
case Location.Align.TopRight:
|
||||
startX = chartPos.x + chartWidth - legendRuntimeWidth - legend.location.right;
|
||||
startY = chartPos.y + chartHeight - legend.location.top;
|
||||
break;
|
||||
case Location.Align.Center:
|
||||
startX = chartPos.x + chartWidth / 2 - legendRuntimeWidth / 2;
|
||||
startY = chartPos.y + chartHeight / 2 + legendRuntimeHeight / 2;
|
||||
break;
|
||||
case Location.Align.CenterLeft:
|
||||
startX = chartPos.x + legend.location.left;
|
||||
startY = chartPos.y + chartHeight / 2 + legendRuntimeHeight / 2;
|
||||
break;
|
||||
case Location.Align.CenterRight:
|
||||
startX = chartPos.x + chartWidth - legendRuntimeWidth - legend.location.right;
|
||||
startY = chartPos.y + chartHeight / 2 + legendRuntimeHeight / 2;
|
||||
break;
|
||||
case Location.Align.BottomCenter:
|
||||
startX = chartPos.x + chartWidth / 2 - legendRuntimeWidth / 2;
|
||||
startY = chartPos.y + legendRuntimeHeight + legend.location.bottom;
|
||||
break;
|
||||
case Location.Align.BottomLeft:
|
||||
startX = chartPos.x + legend.location.left;
|
||||
startY = chartPos.y + legendRuntimeHeight + legend.location.bottom;
|
||||
break;
|
||||
case Location.Align.BottomRight:
|
||||
startX = chartPos.x + chartWidth - legendRuntimeWidth - legend.location.right;
|
||||
startY = chartPos.y + legendRuntimeHeight + legend.location.bottom;
|
||||
break;
|
||||
}
|
||||
if (isVertical) SetVerticalItemPosition(legend, legendMaxHeight, startX, startY);
|
||||
else SetHorizonalItemPosition(legend, legendMaxWidth, startX, startY);
|
||||
}
|
||||
|
||||
private static void SetVerticalItemPosition(Legend legend, float legendMaxHeight, float startX, float startY)
|
||||
{
|
||||
var currHeight = 0f;
|
||||
var offsetX = 0f;
|
||||
var row = 0;
|
||||
foreach (var kv in legend.buttonList)
|
||||
{
|
||||
var item = kv.Value;
|
||||
if (currHeight + item.height > legendMaxHeight)
|
||||
{
|
||||
currHeight = 0;
|
||||
offsetX += legend.runtimeEachWidth[row];
|
||||
row++;
|
||||
}
|
||||
item.SetPosition(new Vector3(startX + offsetX, startY - currHeight));
|
||||
currHeight += item.height + legend.itemGap;
|
||||
}
|
||||
}
|
||||
private static void SetHorizonalItemPosition(Legend legend, float legendMaxWidth, float startX, float startY)
|
||||
{
|
||||
var currWidth = 0f;
|
||||
var offsetY = 0f;
|
||||
foreach (var kv in legend.buttonList)
|
||||
{
|
||||
var item = kv.Value;
|
||||
if (currWidth + item.width > legendMaxWidth)
|
||||
{
|
||||
currWidth = 0;
|
||||
offsetY += legend.runtimeEachHeight;
|
||||
}
|
||||
item.SetPosition(new Vector3(startX + currWidth, startY - offsetY));
|
||||
currWidth += item.width + legend.itemGap;
|
||||
}
|
||||
}
|
||||
|
||||
private static void UpdateLegendWidthAndHeight(Legend legend, float maxWidth, float maxHeight)
|
||||
{
|
||||
var width = 0f;
|
||||
var height = 0f;
|
||||
var realHeight = 0f;
|
||||
var realWidth = 0f;
|
||||
legend.runtimeEachWidth.Clear();
|
||||
legend.runtimeEachHeight = 0;
|
||||
if (legend.orient == Orient.Horizonal)
|
||||
{
|
||||
foreach (var kv in legend.buttonList)
|
||||
{
|
||||
if (width + kv.Value.width > maxWidth)
|
||||
{
|
||||
realWidth = width - legend.itemGap;
|
||||
realHeight += height + legend.itemGap;
|
||||
if (legend.runtimeEachHeight < height + legend.itemGap)
|
||||
{
|
||||
legend.runtimeEachHeight = height + legend.itemGap;
|
||||
}
|
||||
height = 0;
|
||||
width = 0;
|
||||
}
|
||||
width += kv.Value.width + legend.itemGap;
|
||||
if (kv.Value.height > height)
|
||||
height = kv.Value.height;
|
||||
}
|
||||
width -= legend.itemGap;
|
||||
legend.runtimeHeight = realHeight + height;
|
||||
legend.runtimeWidth = realWidth > 0 ? realWidth : width;
|
||||
}
|
||||
else
|
||||
{
|
||||
var row = 0;
|
||||
foreach (var kv in legend.buttonList)
|
||||
{
|
||||
if (height + kv.Value.height > maxHeight)
|
||||
{
|
||||
realHeight = height - legend.itemGap;
|
||||
realWidth += width + legend.itemGap;
|
||||
legend.runtimeEachWidth[row] = width + legend.itemGap;
|
||||
row++;
|
||||
height = 0;
|
||||
width = 0;
|
||||
}
|
||||
height += kv.Value.height + legend.itemGap;
|
||||
if (kv.Value.width > width)
|
||||
width = kv.Value.width;
|
||||
}
|
||||
height -= legend.itemGap;
|
||||
legend.runtimeHeight = realHeight > 0 ? realHeight : height;
|
||||
legend.runtimeWidth = realWidth + width;
|
||||
}
|
||||
}
|
||||
|
||||
private static bool IsBeyondWidth(Legend legend, float maxWidth)
|
||||
{
|
||||
var totalWidth = 0f;
|
||||
foreach (var kv in legend.buttonList)
|
||||
{
|
||||
var item = kv.Value;
|
||||
totalWidth += item.width + legend.itemGap;
|
||||
if (totalWidth > maxWidth) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static bool CheckDataShow(Series series, string legendName, bool show)
|
||||
{
|
||||
bool needShow = false;
|
||||
foreach (var serie in series.list)
|
||||
{
|
||||
if (legendName.Equals(serie.name))
|
||||
{
|
||||
serie.show = show;
|
||||
serie.highlighted = false;
|
||||
if (serie.show) needShow = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var data in serie.data)
|
||||
{
|
||||
if (legendName.Equals(data.name))
|
||||
{
|
||||
data.show = show;
|
||||
data.highlighted = false;
|
||||
if (data.show) needShow = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return needShow;
|
||||
}
|
||||
|
||||
public static bool CheckDataHighlighted(Series series, string legendName, bool heighlight)
|
||||
{
|
||||
bool show = false;
|
||||
foreach (var serie in series.list)
|
||||
{
|
||||
if (legendName.Equals(serie.name))
|
||||
{
|
||||
serie.highlighted = heighlight;
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var data in serie.data)
|
||||
{
|
||||
if (legendName.Equals(data.name))
|
||||
{
|
||||
data.highlighted = heighlight;
|
||||
if (data.highlighted) show = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return show;
|
||||
}
|
||||
|
||||
public static bool IsSerieLegend(Series series, string legendName, SerieType type)
|
||||
{
|
||||
foreach (var serie in series.list)
|
||||
{
|
||||
if (serie.type == type)
|
||||
{
|
||||
switch (serie.type)
|
||||
{
|
||||
case SerieType.Pie:
|
||||
case SerieType.Radar:
|
||||
case SerieType.Ring:
|
||||
foreach (var serieData in serie.data)
|
||||
{
|
||||
if (legendName.Equals(serieData.name)) return true;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (legendName.Equals(serie.name)) return true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d03ce7a11ecde41b6930883612bf8f05
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,34 @@
|
||||
/************************************************/
|
||||
/* */
|
||||
/* Copyright (c) 2018 - 2021 monitor1394 */
|
||||
/* https://github.com/monitor1394 */
|
||||
/* */
|
||||
/************************************************/
|
||||
|
||||
using UnityEngine;
|
||||
|
||||
namespace XCharts
|
||||
{
|
||||
internal static class PolarHelper
|
||||
{
|
||||
internal static void UpdatePolarCenter(Polar polar, Vector3 chartPosition, float chartWidth, float chartHeight)
|
||||
{
|
||||
if (polar.center.Length < 2) return;
|
||||
var centerX = polar.center[0] <= 1 ? chartWidth * polar.center[0] : polar.center[0];
|
||||
var centerY = polar.center[1] <= 1 ? chartHeight * polar.center[1] : polar.center[1];
|
||||
polar.runtimeCenterPos = chartPosition + new Vector3(centerX, centerY);
|
||||
if (polar.radius <= 0)
|
||||
{
|
||||
polar.runtimeRadius = 0;
|
||||
}
|
||||
else if (polar.radius <= 1)
|
||||
{
|
||||
polar.runtimeRadius = Mathf.Min(chartWidth, chartHeight) * polar.radius;
|
||||
}
|
||||
else
|
||||
{
|
||||
polar.runtimeRadius = polar.radius;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 64e494d13836f430ea7f4fe3e2a716b0
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,443 @@
|
||||
/************************************************/
|
||||
/* */
|
||||
/* Copyright (c) 2018 - 2021 monitor1394 */
|
||||
/* https://github.com/monitor1394 */
|
||||
/* */
|
||||
/************************************************/
|
||||
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace XCharts
|
||||
{
|
||||
public static partial class SerieHelper
|
||||
{
|
||||
internal static Color32 GetItemBackgroundColor(Serie serie, SerieData serieData, ChartTheme theme, int index,
|
||||
bool highlight, bool useDefault = true)
|
||||
{
|
||||
var color = ChartConst.clearColor32;
|
||||
if (highlight)
|
||||
{
|
||||
var itemStyleEmphasis = GetItemStyleEmphasis(serie, serieData);
|
||||
if (itemStyleEmphasis != null && !ChartHelper.IsClearColor(itemStyleEmphasis.backgroundColor))
|
||||
{
|
||||
color = itemStyleEmphasis.backgroundColor;
|
||||
ChartHelper.SetColorOpacity(ref color, itemStyleEmphasis.opacity);
|
||||
return color;
|
||||
}
|
||||
}
|
||||
var itemStyle = GetItemStyle(serie, serieData);
|
||||
if (!ChartHelper.IsClearColor(itemStyle.backgroundColor))
|
||||
{
|
||||
color = itemStyle.backgroundColor;
|
||||
if (highlight) color = ChartHelper.GetHighlightColor(color);
|
||||
ChartHelper.SetColorOpacity(ref color, itemStyle.opacity);
|
||||
return color;
|
||||
}
|
||||
else if (useDefault)
|
||||
{
|
||||
color = theme.GetColor(index);
|
||||
if (highlight) color = ChartHelper.GetHighlightColor(color);
|
||||
color.a = 50;
|
||||
return color;
|
||||
}
|
||||
return color;
|
||||
}
|
||||
|
||||
internal static Color32 GetItemColor(Serie serie, SerieData serieData, ChartTheme theme, int index, bool highlight)
|
||||
{
|
||||
if (serie == null) return ChartConst.clearColor32;
|
||||
if (highlight)
|
||||
{
|
||||
var itemStyleEmphasis = GetItemStyleEmphasis(serie, serieData);
|
||||
if (itemStyleEmphasis != null && !ChartHelper.IsClearColor(itemStyleEmphasis.color))
|
||||
{
|
||||
var color = itemStyleEmphasis.color;
|
||||
ChartHelper.SetColorOpacity(ref color, itemStyleEmphasis.opacity);
|
||||
return color;
|
||||
}
|
||||
}
|
||||
var itemStyle = GetItemStyle(serie, serieData);
|
||||
if (!ChartHelper.IsClearColor(itemStyle.color))
|
||||
{
|
||||
return itemStyle.GetColor();
|
||||
}
|
||||
else
|
||||
{
|
||||
var color = theme.GetColor(index);
|
||||
if (highlight) color = ChartHelper.GetHighlightColor(color);
|
||||
ChartHelper.SetColorOpacity(ref color, itemStyle.opacity);
|
||||
return color;
|
||||
}
|
||||
}
|
||||
internal static Color32 GetItemColor0(Serie serie, SerieData serieData, ChartTheme theme, bool highlight, Color32 defaultColor)
|
||||
{
|
||||
if (serie == null) return ChartConst.clearColor32;
|
||||
if (highlight)
|
||||
{
|
||||
var itemStyleEmphasis = GetItemStyleEmphasis(serie, serieData);
|
||||
if (itemStyleEmphasis != null && !ChartHelper.IsClearColor(itemStyleEmphasis.color))
|
||||
{
|
||||
var color = itemStyleEmphasis.color0;
|
||||
ChartHelper.SetColorOpacity(ref color, itemStyleEmphasis.opacity);
|
||||
return color;
|
||||
}
|
||||
}
|
||||
var itemStyle = GetItemStyle(serie, serieData);
|
||||
if (!ChartHelper.IsClearColor(itemStyle.color0))
|
||||
{
|
||||
return itemStyle.GetColor0();
|
||||
}
|
||||
else
|
||||
{
|
||||
var color = defaultColor;
|
||||
if (highlight) color = ChartHelper.GetHighlightColor(color);
|
||||
ChartHelper.SetColorOpacity(ref color, itemStyle.opacity);
|
||||
return color;
|
||||
}
|
||||
}
|
||||
|
||||
internal static Color32 GetItemToColor(Serie serie, SerieData serieData, ChartTheme theme, int index, bool highlight)
|
||||
{
|
||||
if (highlight)
|
||||
{
|
||||
var itemStyleEmphasis = GetItemStyleEmphasis(serie, serieData);
|
||||
if (itemStyleEmphasis != null && !ChartHelper.IsClearColor(itemStyleEmphasis.toColor))
|
||||
{
|
||||
return itemStyleEmphasis.GetColor();
|
||||
}
|
||||
}
|
||||
var itemStyle = GetItemStyle(serie, serieData, highlight);
|
||||
if (itemStyle == null) itemStyle = serieData.itemStyle;
|
||||
if (!ChartHelper.IsClearColor(itemStyle.toColor))
|
||||
{
|
||||
var color = itemStyle.toColor;
|
||||
if (highlight) color = ChartHelper.GetHighlightColor(color);
|
||||
ChartHelper.SetColorOpacity(ref color, itemStyle.opacity);
|
||||
return color;
|
||||
}
|
||||
if (!ChartHelper.IsClearColor(itemStyle.color))
|
||||
{
|
||||
var color = itemStyle.color;
|
||||
if (highlight) color = ChartHelper.GetHighlightColor(color);
|
||||
ChartHelper.SetColorOpacity(ref color, itemStyle.opacity);
|
||||
return color;
|
||||
}
|
||||
else
|
||||
{
|
||||
var color = theme.GetColor(index);
|
||||
if (highlight) color = ChartHelper.GetHighlightColor(color);
|
||||
ChartHelper.SetColorOpacity(ref color, itemStyle.opacity);
|
||||
return color;
|
||||
}
|
||||
}
|
||||
|
||||
internal static bool IsDownPoint(Serie serie, int index)
|
||||
{
|
||||
var dataPoints = serie.dataPoints;
|
||||
if (dataPoints.Count < 2) return false;
|
||||
else if (index > 0 && index < dataPoints.Count - 1)
|
||||
{
|
||||
var lp = dataPoints[index - 1];
|
||||
var np = dataPoints[index + 1];
|
||||
var cp = dataPoints[index];
|
||||
var dot = Vector3.Cross(np - lp, cp - np);
|
||||
return dot.z < 0;
|
||||
}
|
||||
else if (index == 0)
|
||||
{
|
||||
return dataPoints[0].y < dataPoints[1].y;
|
||||
}
|
||||
else if (index == dataPoints.Count - 1)
|
||||
{
|
||||
return dataPoints[index].y < dataPoints[index - 1].y;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
internal static ItemStyle GetItemStyle(Serie serie, SerieData serieData, bool highlight = false)
|
||||
{
|
||||
if (highlight)
|
||||
{
|
||||
var style = GetItemStyleEmphasis(serie, serieData);
|
||||
if (style == null) return GetItemStyle(serie, serieData, false);
|
||||
else return style;
|
||||
}
|
||||
else if (serie.IsPerformanceMode()) return serie.itemStyle;
|
||||
else if (serieData != null && serieData.enableItemStyle) return serieData.itemStyle;
|
||||
else return serie.itemStyle;
|
||||
}
|
||||
|
||||
internal static ItemStyle GetItemStyleEmphasis(Serie serie, SerieData serieData)
|
||||
{
|
||||
if (!serie.IsPerformanceMode() && serieData != null && serieData.enableEmphasis && serieData.emphasis.show)
|
||||
return serieData.emphasis.itemStyle;
|
||||
else if (serie.emphasis.show) return serie.emphasis.itemStyle;
|
||||
else return null;
|
||||
}
|
||||
|
||||
internal static SerieLabel GetSerieLabel(Serie serie, SerieData serieData, bool highlight = false)
|
||||
{
|
||||
if (highlight)
|
||||
{
|
||||
if (!serie.IsPerformanceMode() && serieData.enableEmphasis && serieData.emphasis.show)
|
||||
return serieData.emphasis.label;
|
||||
else if (serie.emphasis.show) return serie.emphasis.label;
|
||||
else return serie.label;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!serie.IsPerformanceMode() && serieData.enableLabel) return serieData.label;
|
||||
else return serie.label;
|
||||
}
|
||||
}
|
||||
|
||||
internal static SerieSymbol GetSerieSymbol(Serie serie, SerieData serieData)
|
||||
{
|
||||
if (!serie.IsPerformanceMode() && serieData.enableSymbol) return serieData.symbol;
|
||||
else return serie.symbol;
|
||||
}
|
||||
|
||||
internal static Color32 GetAreaColor(Serie serie, ChartTheme theme, int index, bool highlight)
|
||||
{
|
||||
var areaStyle = serie.areaStyle;
|
||||
var color = !ChartHelper.IsClearColor(areaStyle.color) ? areaStyle.color : theme.GetColor(index);
|
||||
if (highlight)
|
||||
{
|
||||
if (!ChartHelper.IsClearColor(areaStyle.highlightColor)) color = areaStyle.highlightColor;
|
||||
else color = ChartHelper.GetHighlightColor(color);
|
||||
}
|
||||
ChartHelper.SetColorOpacity(ref color, areaStyle.opacity);
|
||||
return color;
|
||||
}
|
||||
|
||||
internal static Color32 GetAreaToColor(Serie serie, ChartTheme theme, int index, bool highlight)
|
||||
{
|
||||
var areaStyle = serie.areaStyle;
|
||||
if (!ChartHelper.IsClearColor(areaStyle.toColor))
|
||||
{
|
||||
var color = areaStyle.toColor;
|
||||
if (highlight)
|
||||
{
|
||||
if (!ChartHelper.IsClearColor(areaStyle.highlightToColor)) color = areaStyle.highlightToColor;
|
||||
else color = ChartHelper.GetHighlightColor(color);
|
||||
}
|
||||
ChartHelper.SetColorOpacity(ref color, areaStyle.opacity);
|
||||
return color;
|
||||
}
|
||||
else
|
||||
{
|
||||
return GetAreaColor(serie, theme, index, highlight);
|
||||
}
|
||||
}
|
||||
|
||||
internal static Color32 GetLineColor(Serie serie, ChartTheme theme, int index, bool highlight)
|
||||
{
|
||||
Color32 color = ChartConst.clearColor32;
|
||||
if (highlight)
|
||||
{
|
||||
var itemStyleEmphasis = GetItemStyleEmphasis(serie, null);
|
||||
if (itemStyleEmphasis != null && !ChartHelper.IsClearColor(itemStyleEmphasis.color))
|
||||
{
|
||||
color = itemStyleEmphasis.color;
|
||||
ChartHelper.SetColorOpacity(ref color, itemStyleEmphasis.opacity);
|
||||
return color;
|
||||
}
|
||||
}
|
||||
if (!ChartHelper.IsClearColor(serie.lineStyle.color)) color = serie.lineStyle.GetColor();
|
||||
else if (!ChartHelper.IsClearColor(serie.itemStyle.color)) color = serie.itemStyle.GetColor();
|
||||
if (ChartHelper.IsClearColor(color))
|
||||
{
|
||||
color = theme.GetColor(index);
|
||||
ChartHelper.SetColorOpacity(ref color, serie.lineStyle.opacity);
|
||||
}
|
||||
if (highlight) color = ChartHelper.GetHighlightColor(color);
|
||||
return color;
|
||||
}
|
||||
|
||||
internal static float GetSymbolBorder(Serie serie, SerieData serieData, ChartTheme theme, bool highlight, bool useLineWidth = true)
|
||||
{
|
||||
var itemStyle = GetItemStyle(serie, serieData, highlight);
|
||||
if (itemStyle != null && itemStyle.borderWidth != 0) return itemStyle.borderWidth;
|
||||
else return serie.lineStyle.GetWidth(theme.serie.lineWidth);
|
||||
}
|
||||
|
||||
internal static float[] GetSymbolCornerRadius(Serie serie, SerieData serieData, bool highlight)
|
||||
{
|
||||
var itemStyle = GetItemStyle(serie, serieData, highlight);
|
||||
if (itemStyle != null) return itemStyle.cornerRadius;
|
||||
else return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新运行时中心点和半径
|
||||
/// </summary>
|
||||
/// <param name="chartWidth"></param>
|
||||
/// <param name="chartHeight"></param>
|
||||
internal static void UpdateCenter(Serie serie, Vector3 chartPosition, float chartWidth, float chartHeight)
|
||||
{
|
||||
if (serie.center.Length < 2) return;
|
||||
var centerX = serie.center[0] <= 1 ? chartWidth * serie.center[0] : serie.center[0];
|
||||
var centerY = serie.center[1] <= 1 ? chartHeight * serie.center[1] : serie.center[1];
|
||||
serie.runtimeCenterPos = chartPosition + new Vector3(centerX, centerY);
|
||||
var minWidth = Mathf.Min(chartWidth, chartHeight);
|
||||
serie.runtimeInsideRadius = serie.radius[0] <= 1 ? minWidth * serie.radius[0] : serie.radius[0];
|
||||
serie.runtimeOutsideRadius = serie.radius[1] <= 1 ? minWidth * serie.radius[1] : serie.radius[1];
|
||||
}
|
||||
|
||||
internal static string GetNumericFormatter(Serie serie, SerieData serieData)
|
||||
{
|
||||
var itemStyle = SerieHelper.GetItemStyle(serie, serieData);
|
||||
if (!string.IsNullOrEmpty(itemStyle.numericFormatter)) return itemStyle.numericFormatter;
|
||||
else return string.Empty;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获得指定维数的最大最小值
|
||||
/// </summary>
|
||||
/// <param name="dimension"></param>
|
||||
/// <param name="dataZoom"></param>
|
||||
/// <returns></returns>
|
||||
internal static void UpdateMinMaxData(Serie serie, int dimension, int ceilRate = 0, DataZoom dataZoom = null)
|
||||
{
|
||||
float min = 0, max = 0;
|
||||
GetMinMaxData(serie, dimension, out min, out max, dataZoom);
|
||||
if (ceilRate < 0)
|
||||
{
|
||||
serie.runtimeDataMin = min;
|
||||
serie.runtimeDataMax = max;
|
||||
}
|
||||
else
|
||||
{
|
||||
serie.runtimeDataMin = ChartHelper.GetMinDivisibleValue(min, ceilRate);
|
||||
serie.runtimeDataMax = ChartHelper.GetMaxDivisibleValue(max, ceilRate);
|
||||
}
|
||||
}
|
||||
|
||||
internal static void GetAllMinMaxData(Serie serie, int ceilRate = 0, DataZoom dataZoom = null)
|
||||
{
|
||||
float min = 0, max = 0;
|
||||
GetMinMaxData(serie, out min, out max, dataZoom);
|
||||
if (ceilRate < 0)
|
||||
{
|
||||
serie.runtimeDataMin = min;
|
||||
serie.runtimeDataMax = max;
|
||||
}
|
||||
else
|
||||
{
|
||||
serie.runtimeDataMin = ChartHelper.GetMinDivisibleValue(min, ceilRate);
|
||||
serie.runtimeDataMax = ChartHelper.GetMaxDivisibleValue(max, ceilRate);
|
||||
}
|
||||
}
|
||||
|
||||
private static List<SerieData> emptyFilter = new List<SerieData>();
|
||||
/// <summary>
|
||||
/// 根据dataZoom更新数据列表缓存
|
||||
/// </summary>
|
||||
/// <param name="dataZoom"></param>
|
||||
internal static void UpdateFilterData(Serie serie, DataZoom dataZoom)
|
||||
{
|
||||
if (dataZoom == null || !dataZoom.enable) return;
|
||||
if (dataZoom.xAxisIndexs.Contains(serie.xAxisIndex))
|
||||
{
|
||||
if (dataZoom.IsXAxisIndexValue(serie.xAxisIndex))
|
||||
{
|
||||
float min = 0, max = 0;
|
||||
dataZoom.GetXAxisIndexValue(serie.xAxisIndex, out min, out max);
|
||||
UpdateFilterData_XAxisValue(serie, dataZoom, 0, min, max);
|
||||
}
|
||||
else
|
||||
{
|
||||
UpdateFilterData_Category(serie, dataZoom);
|
||||
}
|
||||
}
|
||||
else if (dataZoom.yAxisIndexs.Contains(serie.yAxisIndex))
|
||||
{
|
||||
if (dataZoom.IsYAxisIndexValue(serie.yAxisIndex))
|
||||
{
|
||||
float min = 0, max = 0;
|
||||
dataZoom.GetYAxisIndexValue(serie.yAxisIndex, out min, out max);
|
||||
UpdateFilterData_XAxisValue(serie, dataZoom, 0, min, max);
|
||||
}
|
||||
else
|
||||
{
|
||||
UpdateFilterData_Category(serie, dataZoom);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void UpdateFilterData_XAxisValue(Serie serie, DataZoom dataZoom, int dimension, float min, float max)
|
||||
{
|
||||
var data = serie.data;
|
||||
var startValue = min + (max - min) * dataZoom.start / 100;
|
||||
var endValue = min + (max - min) * dataZoom.end / 100;
|
||||
if (endValue < startValue) endValue = startValue;
|
||||
|
||||
if (startValue != serie.m_FilterStartValue || endValue != serie.m_FilterEndValue
|
||||
|| dataZoom.minShowNum != serie.m_FilterMinShow || serie.m_NeedUpdateFilterData)
|
||||
{
|
||||
serie.m_FilterStartValue = startValue;
|
||||
serie.m_FilterEndValue = endValue;
|
||||
serie.m_FilterMinShow = dataZoom.minShowNum;
|
||||
serie.m_NeedUpdateFilterData = false;
|
||||
|
||||
serie.m_FilterData.Clear();
|
||||
foreach (var serieData in data)
|
||||
{
|
||||
var value = serieData.GetData(dimension);
|
||||
if (value >= startValue && value <= endValue)
|
||||
{
|
||||
serie.m_FilterData.Add(serieData);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (endValue == 0)
|
||||
{
|
||||
serie.m_FilterData = emptyFilter;
|
||||
}
|
||||
}
|
||||
|
||||
private static void UpdateFilterData_Category(Serie serie, DataZoom dataZoom)
|
||||
{
|
||||
var data = serie.data;
|
||||
var startIndex = (int)((data.Count - 1) * dataZoom.start / 100);
|
||||
var endIndex = (int)((data.Count - 1) * dataZoom.end / 100);
|
||||
if (endIndex < startIndex) endIndex = startIndex;
|
||||
|
||||
if (startIndex != serie.m_FilterStart || endIndex != serie.m_FilterEnd
|
||||
|| dataZoom.minShowNum != serie.m_FilterMinShow || serie.m_NeedUpdateFilterData)
|
||||
{
|
||||
serie.m_FilterStart = startIndex;
|
||||
serie.m_FilterEnd = endIndex;
|
||||
serie.m_FilterMinShow = dataZoom.minShowNum;
|
||||
serie.m_NeedUpdateFilterData = false;
|
||||
var count = endIndex == startIndex ? 1 : endIndex - startIndex + 1;
|
||||
if (count < dataZoom.minShowNum)
|
||||
{
|
||||
if (dataZoom.minShowNum > data.Count) count = data.Count;
|
||||
else count = dataZoom.minShowNum;
|
||||
}
|
||||
if (data.Count > 0)
|
||||
{
|
||||
if (startIndex + count > data.Count)
|
||||
{
|
||||
int start = endIndex - count;
|
||||
data = data.GetRange(start < 0 ? 0 : start, count);
|
||||
}
|
||||
else serie.m_FilterData = data.GetRange(startIndex, count);
|
||||
}
|
||||
else
|
||||
{
|
||||
serie.m_FilterData = data;
|
||||
}
|
||||
}
|
||||
else if (endIndex == 0)
|
||||
{
|
||||
serie.m_FilterData = emptyFilter;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e5c421b17fb6f45a283f4f57efce686f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,315 @@
|
||||
/************************************************/
|
||||
/* */
|
||||
/* Copyright (c) 2018 - 2021 monitor1394 */
|
||||
/* https://github.com/monitor1394 */
|
||||
/* */
|
||||
/************************************************/
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace XCharts
|
||||
{
|
||||
internal static class SerieLabelHelper
|
||||
{
|
||||
public static void CheckLabel(Serie serie, ref bool m_ReinitLabel, ref bool m_UpdateLabelText)
|
||||
{
|
||||
switch (serie.type)
|
||||
{
|
||||
case SerieType.Gauge:
|
||||
case SerieType.Ring:
|
||||
var serieData = serie.GetSerieData(0);
|
||||
if (serieData != null)
|
||||
{
|
||||
if (serie.label.show && serie.show)
|
||||
{
|
||||
if (serieData.labelObject != null)
|
||||
{
|
||||
serieData.SetLabelActive(true);
|
||||
m_UpdateLabelText = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_ReinitLabel = true;
|
||||
}
|
||||
}
|
||||
else if (serieData.labelObject != null)
|
||||
{
|
||||
serieData.SetLabelActive(false);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public static void UpdateLabelText(Series series, ChartTheme theme, List<string> legendRealShowName)
|
||||
{
|
||||
foreach (var serie in series.list)
|
||||
{
|
||||
if (!serie.label.show) continue;
|
||||
var colorIndex = legendRealShowName.IndexOf(serie.name);
|
||||
switch (serie.type)
|
||||
{
|
||||
case SerieType.Gauge:
|
||||
SetGaugeLabelText(serie);
|
||||
break;
|
||||
case SerieType.Ring:
|
||||
SetRingLabelText(serie, theme);
|
||||
break;
|
||||
case SerieType.Liquid:
|
||||
SetLiquidLabelText(serie, theme, colorIndex);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static Color GetLabelColor(Serie serie, ChartTheme theme, int index)
|
||||
{
|
||||
if (!ChartHelper.IsClearColor(serie.label.textStyle.color))
|
||||
{
|
||||
return serie.label.textStyle.color;
|
||||
}
|
||||
else
|
||||
{
|
||||
return theme.GetColor(index);
|
||||
}
|
||||
}
|
||||
|
||||
public static void ResetLabel(ChartText labelObject, SerieLabel label, ChartTheme theme, int colorIndex)
|
||||
{
|
||||
if (labelObject == null) return;
|
||||
labelObject.SetColor(!ChartHelper.IsClearColor(label.textStyle.color) ? label.textStyle.color :
|
||||
(Color)theme.GetColor(colorIndex));
|
||||
labelObject.SetFontSize(label.textStyle.GetFontSize(theme.common));
|
||||
labelObject.SetFontStyle(label.textStyle.fontStyle);
|
||||
}
|
||||
|
||||
public static bool CanShowLabel(Serie serie, SerieData serieData, SerieLabel label, int dimesion)
|
||||
{
|
||||
return serie.show && serieData.canShowLabel && !serie.IsIgnoreValue(serieData.GetData(dimesion));
|
||||
}
|
||||
|
||||
public static string GetFormatterContent(Serie serie, SerieData serieData,
|
||||
float dataValue, float dataTotal, SerieLabel serieLabel = null)
|
||||
{
|
||||
if (serieLabel == null)
|
||||
{
|
||||
serieLabel = SerieHelper.GetSerieLabel(serie, serieData);
|
||||
}
|
||||
var numericFormatter = serieLabel == null ? serie.label.numericFormatter : serieLabel.numericFormatter;
|
||||
var serieName = serie.name;
|
||||
var dataName = serieData != null ? serieData.name : null;
|
||||
if (string.IsNullOrEmpty(serieLabel.formatter))
|
||||
return ChartCached.NumberToStr(dataValue, numericFormatter);
|
||||
else
|
||||
{
|
||||
var content = serieLabel.formatter;
|
||||
FormatterHelper.ReplaceSerieLabelContent(ref content, numericFormatter, dataValue,
|
||||
dataTotal, serieName, dataName);
|
||||
return content;
|
||||
}
|
||||
}
|
||||
|
||||
public static void SetGaugeLabelText(Serie serie)
|
||||
{
|
||||
var serieData = serie.GetSerieData(0);
|
||||
if (serieData == null) return;
|
||||
if (serieData.labelObject == null) return;
|
||||
var value = serieData.GetData(1);
|
||||
var total = serie.max;
|
||||
var content = SerieLabelHelper.GetFormatterContent(serie, serieData, value, total);
|
||||
serieData.labelObject.SetText(content);
|
||||
serieData.labelObject.SetLabelPosition(serie.runtimeCenterPos + serie.label.offset);
|
||||
if (!ChartHelper.IsClearColor(serie.label.textStyle.color))
|
||||
{
|
||||
serieData.labelObject.label.SetColor(serie.label.textStyle.color);
|
||||
}
|
||||
}
|
||||
|
||||
public static void SetRingLabelText(Serie serie, ChartTheme theme)
|
||||
{
|
||||
for (int i = 0; i < serie.dataCount; i++)
|
||||
{
|
||||
var serieData = serie.data[i];
|
||||
var serieLabel = SerieHelper.GetSerieLabel(serie, serieData, serieData.highlighted);
|
||||
if (serieLabel.show && serieData.labelObject != null)
|
||||
{
|
||||
if (!serie.show || !serieData.show)
|
||||
{
|
||||
serieData.SetLabelActive(false);
|
||||
continue;
|
||||
}
|
||||
var value = serieData.GetData(0);
|
||||
var total = serieData.GetData(1);
|
||||
var content = SerieLabelHelper.GetFormatterContent(serie, serieData, value, total);
|
||||
serieData.SetLabelActive(true);
|
||||
serieData.labelObject.SetText(content);
|
||||
serieData.labelObject.SetLabelColor(GetLabelColor(serie, theme, i));
|
||||
|
||||
if (serie.label.position == SerieLabel.Position.Bottom)
|
||||
{
|
||||
var labelWidth = serieData.GetLabelWidth();
|
||||
if (serie.clockwise)
|
||||
serieData.labelObject.SetLabelPosition(serieData.labelPosition - new Vector3(labelWidth / 2, 0));
|
||||
else
|
||||
serieData.labelObject.SetLabelPosition(serieData.labelPosition + new Vector3(labelWidth / 2, 0));
|
||||
}
|
||||
else
|
||||
{
|
||||
serieData.labelObject.SetLabelPosition(serieData.labelPosition);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void SetLiquidLabelText(Serie serie, ChartTheme theme, int colorIndex)
|
||||
{
|
||||
var serieData = serie.GetSerieData(0);
|
||||
if (serieData == null) return;
|
||||
var serieLabel = SerieHelper.GetSerieLabel(serie, serieData, serieData.highlighted);
|
||||
if (serieLabel.show && serieData.labelObject != null)
|
||||
{
|
||||
if (!serie.show || !serieData.show)
|
||||
{
|
||||
serieData.SetLabelActive(false);
|
||||
return;
|
||||
}
|
||||
var value = serieData.GetData(1);
|
||||
var total = serie.max - serie.min;
|
||||
var content = SerieLabelHelper.GetFormatterContent(serie, serieData, value, total);
|
||||
serieData.SetLabelActive(true);
|
||||
serieData.labelObject.SetText(content);
|
||||
serieData.labelObject.SetLabelColor(GetLabelColor(serie, theme, colorIndex));
|
||||
serieData.labelObject.SetLabelPosition(serieData.labelPosition + serieLabel.offset);
|
||||
}
|
||||
}
|
||||
|
||||
public static void UpdatePieLabelPosition(Serie serie, SerieData serieData)
|
||||
{
|
||||
if (serieData.labelObject == null) return;
|
||||
var currAngle = serieData.runtimePieHalfAngle;
|
||||
var currRad = currAngle * Mathf.Deg2Rad;
|
||||
var offsetRadius = serieData.runtimePieOffsetRadius;
|
||||
var insideRadius = serieData.runtimePieInsideRadius;
|
||||
var outsideRadius = serieData.runtimePieOutsideRadius;
|
||||
var serieLabel = SerieHelper.GetSerieLabel(serie, serieData);
|
||||
switch (serieLabel.position)
|
||||
{
|
||||
case SerieLabel.Position.Center:
|
||||
serieData.labelPosition = serie.runtimeCenterPos;
|
||||
break;
|
||||
case SerieLabel.Position.Inside:
|
||||
var labelRadius = offsetRadius + insideRadius + (outsideRadius - insideRadius) / 2;
|
||||
var labelCenter = new Vector2(serie.runtimeCenterPos.x + labelRadius * Mathf.Sin(currRad),
|
||||
serie.runtimeCenterPos.y + labelRadius * Mathf.Cos(currRad));
|
||||
serieData.labelPosition = labelCenter;
|
||||
break;
|
||||
case SerieLabel.Position.Outside:
|
||||
if (serieLabel.lineType == SerieLabel.LineType.HorizontalLine)
|
||||
{
|
||||
var radius1 = serie.runtimeOutsideRadius;
|
||||
var radius3 = insideRadius + (outsideRadius - insideRadius) / 2;
|
||||
var currSin = Mathf.Sin(currRad);
|
||||
var currCos = Mathf.Cos(currRad);
|
||||
var pos0 = new Vector3(serie.runtimeCenterPos.x + radius3 * currSin, serie.runtimeCenterPos.y + radius3 * currCos);
|
||||
if (currAngle > 180)
|
||||
{
|
||||
currSin = Mathf.Sin((360 - currAngle) * Mathf.Deg2Rad);
|
||||
currCos = Mathf.Cos((360 - currAngle) * Mathf.Deg2Rad);
|
||||
}
|
||||
var r4 = Mathf.Sqrt(radius1 * radius1 - Mathf.Pow(currCos * radius3, 2)) - currSin * radius3;
|
||||
r4 += serieLabel.lineLength1 + serieLabel.lineWidth * 4;
|
||||
r4 += serieData.labelObject.label.GetPreferredWidth() / 2;
|
||||
serieData.labelPosition = pos0 + (currAngle > 180 ? Vector3.left : Vector3.right) * r4;
|
||||
}
|
||||
else
|
||||
{
|
||||
labelRadius = serie.runtimeOutsideRadius + serieLabel.lineLength1;
|
||||
labelCenter = new Vector2(serie.runtimeCenterPos.x + labelRadius * Mathf.Sin(currRad),
|
||||
serie.runtimeCenterPos.y + labelRadius * Mathf.Cos(currRad));
|
||||
serieData.labelPosition = labelCenter;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
internal static void AvoidLabelOverlap(Serie serie)
|
||||
{
|
||||
if (!serie.avoidLabelOverlap) return;
|
||||
var lastCheckPos = Vector3.zero;
|
||||
var data = serie.data;
|
||||
var splitCount = 0;
|
||||
for (int n = 0; n < data.Count; n++)
|
||||
{
|
||||
var serieData = data[n];
|
||||
if (serieData.labelPosition.x != 0 && serieData.labelPosition.x < serie.runtimeCenterPos.x)
|
||||
{
|
||||
splitCount = n;
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (int n = 0; n < splitCount; n++)
|
||||
{
|
||||
var serieData = data[n];
|
||||
CheckSerieDataLabel(serie, serieData, false, ref lastCheckPos);
|
||||
}
|
||||
lastCheckPos = Vector3.zero;
|
||||
for (int n = data.Count - 1; n >= splitCount; n--)
|
||||
{
|
||||
var serieData = data[n];
|
||||
CheckSerieDataLabel(serie, serieData, true, ref lastCheckPos);
|
||||
}
|
||||
}
|
||||
|
||||
private static void CheckSerieDataLabel(Serie serie, SerieData serieData, bool isLeft, ref Vector3 lastCheckPos)
|
||||
{
|
||||
if (!serieData.canShowLabel)
|
||||
{
|
||||
serieData.SetLabelActive(false);
|
||||
return;
|
||||
}
|
||||
if (!serieData.show) return;
|
||||
var serieLabel = SerieHelper.GetSerieLabel(serie, serieData);
|
||||
if (!serieLabel.show) return;
|
||||
if (serieLabel.position != SerieLabel.Position.Outside) return;
|
||||
if (lastCheckPos == Vector3.zero)
|
||||
{
|
||||
lastCheckPos = serieData.labelPosition;
|
||||
}
|
||||
else if (serieData.labelPosition.x != 0)
|
||||
{
|
||||
float hig = serieLabel.textStyle.fontSize;
|
||||
if (lastCheckPos.y - serieData.labelPosition.y < hig)
|
||||
{
|
||||
var labelRadius = serie.runtimeOutsideRadius + serieLabel.lineLength1;
|
||||
var y1 = lastCheckPos.y - hig;
|
||||
var cy = serie.runtimeCenterPos.y;
|
||||
var diff = Mathf.Abs(y1 - cy);
|
||||
var diffX = labelRadius * labelRadius - diff * diff;
|
||||
diffX = diffX <= 0 ? 0 : diffX;
|
||||
var x1 = serie.runtimeCenterPos.x + Mathf.Sqrt(diffX) * (isLeft ? -1 : 1);
|
||||
serieData.labelPosition = new Vector3(x1, y1);
|
||||
}
|
||||
lastCheckPos = serieData.labelPosition;
|
||||
serieData.labelObject.SetPosition(SerieLabelHelper.GetRealLabelPosition(serieData, serieLabel));
|
||||
}
|
||||
}
|
||||
|
||||
internal static Vector3 GetRealLabelPosition(SerieData serieData, SerieLabel label)
|
||||
{
|
||||
if (label.position == SerieLabel.Position.Outside && label.lineType != SerieLabel.LineType.HorizontalLine)
|
||||
{
|
||||
var currAngle = serieData.runtimePieHalfAngle;
|
||||
var offset = label.lineLength2 + serieData.labelObject.GetLabelWidth() / 2;
|
||||
if (currAngle > 180)
|
||||
return serieData.labelPosition + new Vector3(-offset, 0, 0);
|
||||
else
|
||||
return serieData.labelPosition + new Vector3(offset, 0, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
return serieData.labelPosition;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bbd57df98f6f145f299cf942b04229a4
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,548 @@
|
||||
/************************************************/
|
||||
/* */
|
||||
/* Copyright (c) 2018 - 2021 monitor1394 */
|
||||
/* https://github.com/monitor1394 */
|
||||
/* */
|
||||
/************************************************/
|
||||
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace XCharts
|
||||
{
|
||||
public static class SeriesHelper
|
||||
{
|
||||
public static bool IsNeedLabelUpdate(Series series)
|
||||
{
|
||||
foreach (var serie in series.list)
|
||||
{
|
||||
if (serie.label.vertsDirty) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static bool IsLabelDirty(Series series)
|
||||
{
|
||||
if (series.labelDirty) return true;
|
||||
foreach (var serie in series.list)
|
||||
{
|
||||
if (serie.label.componentDirty) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static bool IsNameDirty(Series series)
|
||||
{
|
||||
foreach (var serie in series.list)
|
||||
{
|
||||
if (serie.nameDirty) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static void ClearNameDirty(Series series)
|
||||
{
|
||||
foreach (var serie in series.list)
|
||||
{
|
||||
serie.ClearNameDirty();
|
||||
}
|
||||
}
|
||||
|
||||
public static bool IsLegalLegendName(string name)
|
||||
{
|
||||
int numName = -1;
|
||||
if (int.TryParse(name, out numName))
|
||||
{
|
||||
if (numName >= 0 && numName < 100) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static List<string> GetLegalSerieNameList(Series series)
|
||||
{
|
||||
var list = new List<string>();
|
||||
for (int n = 0; n < series.list.Count; n++)
|
||||
{
|
||||
var serie = series.GetSerie(n);
|
||||
switch (serie.type)
|
||||
{
|
||||
case SerieType.Pie:
|
||||
case SerieType.Radar:
|
||||
case SerieType.Ring:
|
||||
for (int i = 0; i < serie.data.Count; i++)
|
||||
{
|
||||
var dataName = serie.data[i].name;
|
||||
if (!string.IsNullOrEmpty(dataName) && IsLegalLegendName(dataName) && !list.Contains(dataName))
|
||||
list.Add(dataName);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (!string.IsNullOrEmpty(serie.name) && !list.Contains(serie.name) && IsLegalLegendName(serie.name))
|
||||
list.Add(serie.name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获得所有系列名,不包含空名字。
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
internal static void UpdateSerieNameList(Series series, ref List<string> serieNameList)
|
||||
{
|
||||
serieNameList.Clear();
|
||||
for (int n = 0; n < series.list.Count; n++)
|
||||
{
|
||||
var serie = series.GetSerie(n);
|
||||
switch (serie.type)
|
||||
{
|
||||
case SerieType.Pie:
|
||||
case SerieType.Radar:
|
||||
case SerieType.Ring:
|
||||
for (int i = 0; i < serie.data.Count; i++)
|
||||
{
|
||||
if (serie.type == SerieType.Pie && serie.IsIgnoreValue(serie.data[i].GetData(1))) continue;
|
||||
if (string.IsNullOrEmpty(serie.data[i].name))
|
||||
serieNameList.Add(ChartCached.IntToStr(i));
|
||||
else if (!serieNameList.Contains(serie.data[i].name))
|
||||
serieNameList.Add(serie.data[i].name);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (string.IsNullOrEmpty(serie.name))
|
||||
serieNameList.Add(ChartCached.IntToStr(n));
|
||||
else if (!serieNameList.Contains(serie.name))
|
||||
serieNameList.Add(serie.name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal static Color GetNameColor(Series series, int index, string name, ChartTheme theme)
|
||||
{
|
||||
Serie destSerie = null;
|
||||
SerieData destSerieData = null;
|
||||
|
||||
for (int n = 0; n < series.list.Count; n++)
|
||||
{
|
||||
var serie = series.GetSerie(n);
|
||||
if (serie.type == SerieType.Pie || serie.type == SerieType.Radar || serie.type == SerieType.Ring)
|
||||
{
|
||||
bool found = false;
|
||||
for (int i = 0; i < serie.data.Count; i++)
|
||||
{
|
||||
if (name.Equals(serie.data[i].name))
|
||||
{
|
||||
destSerie = serie;
|
||||
destSerieData = serie.data[i];
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (found) break;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (name.Equals(serie.name))
|
||||
{
|
||||
destSerie = serie;
|
||||
destSerieData = null;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return SerieHelper.GetItemColor(destSerie, destSerieData, theme, index, false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 同堆叠的serie是否有渐变色的。
|
||||
/// </summary>
|
||||
/// <param name="stack"></param>
|
||||
/// <returns></returns>
|
||||
internal static bool IsAnyGradientSerie(Series series, string stack)
|
||||
{
|
||||
if (string.IsNullOrEmpty(stack)) return false;
|
||||
foreach (var serie in series.list)
|
||||
{
|
||||
if (serie.show && serie.areaStyle.show && stack.Equals(serie.stack))
|
||||
{
|
||||
if (!ChartHelper.IsValueEqualsColor(serie.areaStyle.color, serie.areaStyle.toColor)
|
||||
&& !ChartHelper.IsClearColor(serie.areaStyle.toColor))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 是否有需裁剪的serie。
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
internal static bool IsAnyClipSerie(Series series)
|
||||
{
|
||||
foreach (var serie in series.list)
|
||||
{
|
||||
if (serie.clip) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
internal static bool ContainsSerie(Series series, SerieType type)
|
||||
{
|
||||
foreach (var serie in series.list)
|
||||
{
|
||||
if (serie.type == type) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
internal static bool IsAnyUpdateAnimationSerie(Series series)
|
||||
{
|
||||
foreach (var serie in series.list)
|
||||
{
|
||||
if (serie.animation.enable && serie.animation.dataChangeEnable)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获得上一个同堆叠且显示的serie。
|
||||
/// </summary>
|
||||
/// <param name="serie"></param>
|
||||
/// <returns></returns>
|
||||
internal static Serie GetLastStackSerie(Series series, Serie serie)
|
||||
{
|
||||
if (serie == null || string.IsNullOrEmpty(serie.stack)) return null;
|
||||
for (int i = serie.index - 1; i >= 0; i--)
|
||||
{
|
||||
var temp = series.list[i];
|
||||
if (temp.show && serie.stack.Equals(temp.stack)) return temp;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获得上一个同堆叠且显示的serie。
|
||||
/// </summary>
|
||||
/// <param name="index"></param>
|
||||
/// <returns></returns>
|
||||
internal static Serie GetLastStackSerie(Series series, int index)
|
||||
{
|
||||
var serie = series.GetSerie(index);
|
||||
return GetLastStackSerie(series, serie);
|
||||
}
|
||||
|
||||
internal static Serie GetSerieByVesselIndex(Series series, int vesselIndex)
|
||||
{
|
||||
foreach (var serie in series.list)
|
||||
{
|
||||
if (serie.vesselIndex == vesselIndex) return serie;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static HashSet<string> _setForStack = new HashSet<string>();
|
||||
/// <summary>
|
||||
/// 是否由数据堆叠
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
internal static bool IsStack(Series series)
|
||||
{
|
||||
_setForStack.Clear();
|
||||
foreach (var serie in series.list)
|
||||
{
|
||||
if (string.IsNullOrEmpty(serie.stack)) continue;
|
||||
if (_setForStack.Contains(serie.stack)) return true;
|
||||
else
|
||||
{
|
||||
_setForStack.Add(serie.stack);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 是否堆叠
|
||||
/// </summary>
|
||||
/// <param name="stackName"></param>
|
||||
/// <param name="type"></param>
|
||||
/// <returns></returns>
|
||||
internal static bool IsStack(Series series, string stackName, SerieType type)
|
||||
{
|
||||
if (string.IsNullOrEmpty(stackName)) return false;
|
||||
int count = 0;
|
||||
foreach (var serie in series.list)
|
||||
{
|
||||
if (serie.show && serie.type == type)
|
||||
{
|
||||
if (stackName.Equals(serie.stack)) count++;
|
||||
if (count >= 2) return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 是否时百分比堆叠
|
||||
/// </summary>
|
||||
/// <param name="type"></param>
|
||||
/// <returns></returns>
|
||||
internal static bool IsPercentStack(Series series, SerieType type)
|
||||
{
|
||||
int count = 0;
|
||||
bool isPercentStack = false;
|
||||
foreach (var serie in series.list)
|
||||
{
|
||||
if (serie.show && serie.type == type)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(serie.stack))
|
||||
{
|
||||
count++;
|
||||
if (serie.barPercentStack) isPercentStack = true;
|
||||
}
|
||||
if (count >= 2 && isPercentStack) return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 是否时百分比堆叠
|
||||
/// </summary>
|
||||
/// <param name="stackName"></param>
|
||||
/// <param name="type"></param>
|
||||
/// <returns></returns>
|
||||
internal static bool IsPercentStack(Series series, string stackName, SerieType type)
|
||||
{
|
||||
if (string.IsNullOrEmpty(stackName)) return false;
|
||||
int count = 0;
|
||||
bool isPercentStack = false;
|
||||
foreach (var serie in series.list)
|
||||
{
|
||||
if (serie.show && serie.type == type)
|
||||
{
|
||||
if (stackName.Equals(serie.stack))
|
||||
{
|
||||
count++;
|
||||
if (serie.barPercentStack) isPercentStack = true;
|
||||
}
|
||||
if (count >= 2 && isPercentStack) return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static Dictionary<string, int> sets = new Dictionary<string, int>();
|
||||
/// <summary>
|
||||
/// 获得堆叠系列列表
|
||||
/// </summary>
|
||||
/// <param name="Dictionary<int"></param>
|
||||
/// <param name="stackSeries"></param>
|
||||
internal static void GetStackSeries(Series series, ref Dictionary<int, List<Serie>> stackSeries)
|
||||
{
|
||||
int count = 0;
|
||||
var serieCount = series.list.Count;
|
||||
sets.Clear();
|
||||
if (stackSeries == null)
|
||||
{
|
||||
stackSeries = new Dictionary<int, List<Serie>>(serieCount);
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var kv in stackSeries)
|
||||
{
|
||||
kv.Value.Clear();
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < serieCount; i++)
|
||||
{
|
||||
var serie = series.GetSerie(i);
|
||||
serie.index = i;
|
||||
if (string.IsNullOrEmpty(serie.stack))
|
||||
{
|
||||
if (!stackSeries.ContainsKey(count))
|
||||
stackSeries[count] = new List<Serie>(serieCount);
|
||||
stackSeries[count].Add(serie);
|
||||
count++;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!sets.ContainsKey(serie.stack))
|
||||
{
|
||||
sets.Add(serie.stack, count);
|
||||
if (!stackSeries.ContainsKey(count))
|
||||
stackSeries[count] = new List<Serie>(serieCount);
|
||||
stackSeries[count].Add(serie);
|
||||
count++;
|
||||
}
|
||||
else
|
||||
{
|
||||
int stackIndex = sets[serie.stack];
|
||||
stackSeries[stackIndex].Add(serie);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal static void UpdateStackDataList(Series series, Serie currSerie, DataZoom dataZoom, List<List<SerieData>> dataList)
|
||||
{
|
||||
dataList.Clear();
|
||||
for (int i = 0; i <= currSerie.index; i++)
|
||||
{
|
||||
var serie = series.list[i];
|
||||
if (serie.type == currSerie.type && ChartHelper.IsValueEqualsString(serie.stack, currSerie.stack))
|
||||
{
|
||||
dataList.Add(serie.GetDataList(dataZoom));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获得维度X的最大最小值
|
||||
/// </summary>
|
||||
/// <param name="dataZoom"></param>
|
||||
/// <param name="axisIndex"></param>
|
||||
/// <param name="minVaule"></param>
|
||||
/// <param name="maxValue"></param>
|
||||
internal static void GetXMinMaxValue(Series series, DataZoom dataZoom, int axisIndex, bool isValueAxis,
|
||||
bool inverse, out float minVaule, out float maxValue, bool isPolar = false)
|
||||
{
|
||||
GetMinMaxValue(series, dataZoom, axisIndex, isValueAxis, inverse, false, out minVaule, out maxValue, isPolar);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获得维度Y的最大最小值
|
||||
/// </summary>
|
||||
/// <param name="dataZoom"></param>
|
||||
/// <param name="axisIndex"></param>
|
||||
/// <param name="minVaule"></param>
|
||||
/// <param name="maxValue"></param>
|
||||
internal static void GetYMinMaxValue(Series series, DataZoom dataZoom, int axisIndex, bool isValueAxis,
|
||||
bool inverse, out float minVaule, out float maxValue, bool isPolar = false)
|
||||
{
|
||||
GetMinMaxValue(series, dataZoom, axisIndex, isValueAxis, inverse, true, out minVaule, out maxValue, isPolar);
|
||||
}
|
||||
|
||||
private static Dictionary<int, List<Serie>> _stackSeriesForMinMax = new Dictionary<int, List<Serie>>();
|
||||
private static Dictionary<int, float> _serieTotalValueForMinMax = new Dictionary<int, float>();
|
||||
internal static void GetMinMaxValue(Series series, DataZoom dataZoom, int axisIndex, bool isValueAxis,
|
||||
bool inverse, bool yValue, out float minVaule, out float maxValue, bool isPolar = false)
|
||||
{
|
||||
float min = int.MaxValue;
|
||||
float max = int.MinValue;
|
||||
var isPercentStack = SeriesHelper.IsPercentStack(series, SerieType.Bar);
|
||||
if (!SeriesHelper.IsStack(series) || (isValueAxis && !yValue))
|
||||
{
|
||||
for (int i = 0; i < series.list.Count; i++)
|
||||
{
|
||||
var serie = series.GetSerie(i);
|
||||
if ((isPolar && serie.polarIndex != axisIndex)
|
||||
|| (!isPolar && serie.yAxisIndex != axisIndex)) continue;
|
||||
if (series.IsActive(i))
|
||||
{
|
||||
if (isPercentStack && SeriesHelper.IsPercentStack(series, serie.name, SerieType.Bar))
|
||||
{
|
||||
if (100 > max) max = 100;
|
||||
if (0 < min) min = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
var showData = serie.GetDataList(dataZoom);
|
||||
foreach (var data in showData)
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
SeriesHelper.GetStackSeries(series, ref _stackSeriesForMinMax);
|
||||
foreach (var ss in _stackSeriesForMinMax)
|
||||
{
|
||||
_serieTotalValueForMinMax.Clear();
|
||||
for (int i = 0; i < ss.Value.Count; i++)
|
||||
{
|
||||
var serie = ss.Value[i];
|
||||
if ((isPolar && serie.polarIndex != axisIndex)
|
||||
|| (!isPolar && serie.yAxisIndex != axisIndex)
|
||||
|| !series.IsActive(i)) continue;
|
||||
var showData = serie.GetDataList(dataZoom);
|
||||
if (SeriesHelper.IsPercentStack(series, serie.stack, SerieType.Bar))
|
||||
{
|
||||
for (int j = 0; j < showData.Count; j++)
|
||||
{
|
||||
_serieTotalValueForMinMax[j] = 100;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int j = 0; j < showData.Count; j++)
|
||||
{
|
||||
if (!_serieTotalValueForMinMax.ContainsKey(j))
|
||||
_serieTotalValueForMinMax[j] = 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
float tmax = int.MinValue;
|
||||
float tmin = int.MaxValue;
|
||||
foreach (var tt in _serieTotalValueForMinMax)
|
||||
{
|
||||
if (tt.Value > tmax) tmax = tt.Value;
|
||||
if (tt.Value < tmin) tmin = tt.Value;
|
||||
}
|
||||
if (tmax > max) max = tmax;
|
||||
if (tmin < min) min = tmin;
|
||||
}
|
||||
}
|
||||
if (max == int.MinValue && min == int.MaxValue)
|
||||
{
|
||||
minVaule = 0;
|
||||
maxValue = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
minVaule = min > 1 ? Mathf.FloorToInt(min) : min;
|
||||
maxValue = max > 1 ? Mathf.CeilToInt(max) : max;
|
||||
}
|
||||
}
|
||||
|
||||
public static int GetMaxSerieDataCount(Series series)
|
||||
{
|
||||
int max = 0;
|
||||
foreach (var serie in series.list)
|
||||
{
|
||||
if (serie.dataCount > max) max = serie.dataCount;
|
||||
}
|
||||
return max;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e7411a13172764cf89b10e643089c832
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,20 @@
|
||||
/************************************************/
|
||||
/* */
|
||||
/* Copyright (c) 2018 - 2021 monitor1394 */
|
||||
/* https://github.com/monitor1394 */
|
||||
/* */
|
||||
/************************************************/
|
||||
|
||||
using UnityEngine;
|
||||
|
||||
namespace XCharts
|
||||
{
|
||||
internal static class ThemeHelper
|
||||
{
|
||||
public static Color32 GetBackgroundColor(ChartTheme theme, Background background)
|
||||
{
|
||||
if (background.show && background.hideThemeBackgroundColor) return ChartConst.clearColor32;
|
||||
else return theme.backgroundColor;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5093880c2dbba4c01bb0231653ed3252
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,43 @@
|
||||
/************************************************/
|
||||
/* */
|
||||
/* Copyright (c) 2018 - 2021 monitor1394 */
|
||||
/* https://github.com/monitor1394 */
|
||||
/* */
|
||||
/************************************************/
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace XCharts
|
||||
{
|
||||
internal static class TitleStyleHelper
|
||||
{
|
||||
public static void CheckTitle(Serie serie, ref bool m_ReinitTitle, ref bool m_UpdateTitleText)
|
||||
{
|
||||
if (serie.titleStyle.show)
|
||||
{
|
||||
if (serie.titleStyle.IsInited())
|
||||
{
|
||||
serie.titleStyle.UpdatePosition(serie.runtimeCenterPos);
|
||||
m_UpdateTitleText = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_ReinitTitle = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void UpdateTitleText(Series series)
|
||||
{
|
||||
foreach (var serie in series.list) UpdateTitleText(serie);
|
||||
}
|
||||
|
||||
public static void UpdateTitleText(Serie serie)
|
||||
{
|
||||
if (serie.titleStyle.show)
|
||||
{
|
||||
serie.titleStyle.SetText(serie.name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 35fa58aecc0f4414e8a2f03195b66175
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,571 @@
|
||||
/************************************************/
|
||||
/* */
|
||||
/* Copyright (c) 2018 - 2021 monitor1394 */
|
||||
/* https://github.com/monitor1394 */
|
||||
/* */
|
||||
/************************************************/
|
||||
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
|
||||
namespace XCharts
|
||||
{
|
||||
internal static class TooltipHelper
|
||||
{
|
||||
private static void InitScatterTooltip(ref StringBuilder sb, Tooltip tooltip, Serie serie, int index,
|
||||
ChartTheme theme)
|
||||
{
|
||||
if (!tooltip.runtimeSerieIndex.ContainsKey(serie.index)) return;
|
||||
var dataIndexList = tooltip.runtimeSerieIndex[serie.index];
|
||||
if (!string.IsNullOrEmpty(serie.name))
|
||||
{
|
||||
sb.Append(serie.name).Append(FormatterHelper.PH_NN);
|
||||
}
|
||||
for (int i = 0; i < dataIndexList.Count; i++)
|
||||
{
|
||||
var dataIndex = dataIndexList[i];
|
||||
var serieData = serie.GetSerieData(dataIndex);
|
||||
var numericFormatter = GetItemNumericFormatter(tooltip, serie, serieData);
|
||||
float xValue, yValue;
|
||||
serie.GetXYData(dataIndex, null, out xValue, out yValue);
|
||||
|
||||
sb.Append("<color=#").Append(theme.GetColorStr(serie.index)).Append(">● </color>");
|
||||
if (!string.IsNullOrEmpty(serieData.name))
|
||||
sb.Append(serieData.name).Append(": ");
|
||||
sb.AppendFormat("({0},{1})", ChartCached.FloatToStr(xValue, numericFormatter),
|
||||
ChartCached.FloatToStr(yValue, numericFormatter));
|
||||
if (i != dataIndexList.Count - 1)
|
||||
{
|
||||
sb.Append("\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static void InitPieTooltip(ref StringBuilder sb, Tooltip tooltip, Serie serie, int index,
|
||||
ChartTheme theme)
|
||||
{
|
||||
if (tooltip.runtimeDataIndex[serie.index] < 0) return;
|
||||
string key = serie.data[index].name;
|
||||
var serieData = serie.GetSerieData(index);
|
||||
var numericFormatter = GetItemNumericFormatter(tooltip, serie, serieData);
|
||||
|
||||
float value = serieData.GetData(1);
|
||||
sb.Length = 0;
|
||||
if (!string.IsNullOrEmpty(serie.name))
|
||||
{
|
||||
sb.Append(serie.name).Append(FormatterHelper.PH_NN);
|
||||
}
|
||||
sb.Append("<color=#").Append(theme.GetColorStr(index)).Append(">● </color>");
|
||||
if (!string.IsNullOrEmpty(key))
|
||||
sb.Append(key).Append(": ");
|
||||
sb.Append(ChartCached.FloatToStr(value, numericFormatter));
|
||||
}
|
||||
|
||||
private static void InitRingTooltip(ref StringBuilder sb, Tooltip tooltip, Serie serie, int index,
|
||||
ChartTheme theme)
|
||||
{
|
||||
var serieData = serie.GetSerieData(index);
|
||||
var numericFormatter = GetItemNumericFormatter(tooltip, serie, serieData);
|
||||
float value = serieData.GetFirstData();
|
||||
sb.Length = 0;
|
||||
if (!string.IsNullOrEmpty(serieData.name))
|
||||
{
|
||||
sb.Append("<color=#").Append(theme.GetColorStr(index)).Append(">● </color>")
|
||||
.Append(serieData.name).Append(": ").Append(ChartCached.FloatToStr(value, numericFormatter));
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.Append(ChartCached.FloatToStr(value, numericFormatter));
|
||||
}
|
||||
}
|
||||
private static void InitGaugeTooltip(ref StringBuilder sb, Tooltip tooltip, Serie serie, int index,
|
||||
ChartTheme theme)
|
||||
{
|
||||
if (tooltip.runtimeGridIndex >= 0) return;
|
||||
if (serie.index != index || serie.type != SerieType.Gauge) return;
|
||||
var serieData = serie.GetSerieData(0);
|
||||
var numericFormatter = GetItemNumericFormatter(tooltip, serie, serieData);
|
||||
float value = serieData.data[1];
|
||||
sb.Length = 0;
|
||||
if (!string.IsNullOrEmpty(serie.name))
|
||||
{
|
||||
sb.Append(serie.name).Append("\n");
|
||||
}
|
||||
if (!string.IsNullOrEmpty(serieData.name))
|
||||
{
|
||||
//sb.Append("<color=#").Append(theme.GetColorStr(index)).Append(">● </color>")
|
||||
sb.Append(serieData.name).Append(": ").Append(ChartCached.FloatToStr(value, numericFormatter));
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.Append(ChartCached.FloatToStr(value, numericFormatter));
|
||||
}
|
||||
}
|
||||
|
||||
public static void InitRadarTooltip(ref StringBuilder sb, Tooltip tooltip, Serie serie, Radar radar,
|
||||
ChartTheme theme)
|
||||
{
|
||||
if (radar == null) return;
|
||||
if (!serie.show) return;
|
||||
if (tooltip.runtimeGridIndex >= 0) return;
|
||||
if (serie.radarIndex != radar.index) return;
|
||||
var dataIndex = tooltip.runtimeDataIndex[1];
|
||||
var serieData = serie.GetSerieData(dataIndex);
|
||||
if (!serieData.show) return;
|
||||
var numericFormatter = GetItemNumericFormatter(tooltip, serie, serieData);
|
||||
switch (serie.radarType)
|
||||
{
|
||||
case RadarType.Multiple:
|
||||
if (radar.isAxisTooltip)
|
||||
{
|
||||
var dimension = tooltip.runtimeDataIndex[2];
|
||||
if (!string.IsNullOrEmpty(serie.name))
|
||||
sb.Append(serie.name).Append("\n");
|
||||
var total = serie.GetDataTotal(dimension);
|
||||
var first = true;
|
||||
for (int i = 0; i < serie.dataCount; i++)
|
||||
{
|
||||
var sd = serie.GetSerieData(i);
|
||||
if (!sd.show) continue;
|
||||
var key = sd.name;
|
||||
var value = sd.GetData(dimension);
|
||||
var itemFormatter = GetItemFormatter(tooltip, serie, sd);
|
||||
numericFormatter = GetItemNumericFormatter(tooltip, serie, sd);
|
||||
if (!first) sb.Append("\n");
|
||||
first = false;
|
||||
sb.Append("<color=#").Append(theme.GetColorStr(i)).Append(">● </color>");
|
||||
if (string.IsNullOrEmpty(itemFormatter))
|
||||
{
|
||||
if (string.IsNullOrEmpty(key)) key = radar.indicatorList[dataIndex].name;
|
||||
if (string.IsNullOrEmpty(key))
|
||||
sb.AppendFormat("{0}\n", ChartCached.FloatToStr(value, numericFormatter));
|
||||
else
|
||||
sb.AppendFormat("{0}: {1}\n", key, ChartCached.FloatToStr(value, numericFormatter));
|
||||
}
|
||||
else
|
||||
{
|
||||
string content = itemFormatter;
|
||||
FormatterHelper.ReplaceSerieLabelContent(ref content, numericFormatter, value, total, serie.name, sd.name);
|
||||
sb.Append(content);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (serie.index != tooltip.runtimeDataIndex[0]) return;
|
||||
sb.Append(serieData.name);
|
||||
for (int i = 0; i < radar.indicatorList.Count; i++)
|
||||
{
|
||||
string key = radar.indicatorList[i].name;
|
||||
float value = serieData.GetData(i);
|
||||
if ((i == 0 && !string.IsNullOrEmpty(serieData.name)) || i > 0) sb.Append(FormatterHelper.PH_NN);
|
||||
sb.AppendFormat("{0}: {1}", key, ChartCached.FloatToStr(value, numericFormatter));
|
||||
}
|
||||
}
|
||||
break;
|
||||
case RadarType.Single:
|
||||
var key2 = serieData.name;
|
||||
var value2 = serieData.GetData(1);
|
||||
var total2 = serie.GetDataTotal(1);
|
||||
var itemFormatter2 = GetItemFormatter(tooltip, serie, serieData);
|
||||
if (string.IsNullOrEmpty(itemFormatter2))
|
||||
{
|
||||
if (string.IsNullOrEmpty(key2))
|
||||
{
|
||||
key2 = radar.indicatorList[dataIndex].name;
|
||||
}
|
||||
sb.AppendFormat("{0}: {1}", key2, ChartCached.FloatToStr(value2, numericFormatter));
|
||||
}
|
||||
else
|
||||
{
|
||||
string content = itemFormatter2;
|
||||
FormatterHelper.ReplaceSerieLabelContent(ref content, numericFormatter, value2, total2, serie.name, serieData.name);
|
||||
sb.Append(content);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private static void InitCoordinateTooltip(ref StringBuilder sb, Tooltip tooltip, Serie serie, int index,
|
||||
ChartTheme theme, bool isCartesian, DataZoom dataZoom = null)
|
||||
{
|
||||
string key = serie.name;
|
||||
float xValue, yValue;
|
||||
serie.GetXYData(index, dataZoom, out xValue, out yValue);
|
||||
var isIngore = serie.IsIgnorePoint(index);
|
||||
var serieData = serie.GetSerieData(index, dataZoom);
|
||||
var numericFormatter = GetItemNumericFormatter(tooltip, serie, serieData);
|
||||
if (isCartesian)
|
||||
{
|
||||
if (serieData != null && serieData.highlighted)
|
||||
{
|
||||
sb.Append(key).Append(!string.IsNullOrEmpty(key) ? " : " : "");
|
||||
sb.Append("[").Append(ChartCached.FloatToStr(xValue, numericFormatter)).Append(",")
|
||||
.Append(ChartCached.FloatToStr(yValue, numericFormatter)).Append("]");
|
||||
}
|
||||
}
|
||||
else if (!isIngore || (isIngore && tooltip.ignoreDataShow))
|
||||
{
|
||||
var valueTxt = isIngore ? tooltip.ignoreDataDefaultContent :
|
||||
ChartCached.FloatToStr(yValue, numericFormatter);
|
||||
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);
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.Append(key).Append(!string.IsNullOrEmpty(key) ? " : " : "");
|
||||
sb.Append(valueTxt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void InitGanttTooltip(ref StringBuilder sb, Tooltip tooltip, Serie serie, int index,
|
||||
ChartTheme theme, string category)
|
||||
{
|
||||
//if (tooltip.runtimeGridIndex >= 0) return;
|
||||
//if (serie.index != index || serie.type != SerieType.Gantt) return;
|
||||
sb.Append(serie.name);
|
||||
}
|
||||
|
||||
private static void InitDefaultContent(ref StringBuilder sb, Tooltip tooltip, Serie serie, int index,
|
||||
string category, ChartTheme theme = null, DataZoom dataZoom = null, bool isCartesian = false,
|
||||
Radar radar = null)
|
||||
{
|
||||
switch (serie.type)
|
||||
{
|
||||
case SerieType.Line:
|
||||
case SerieType.Bar:
|
||||
case SerieType.Candlestick:
|
||||
InitCoordinateTooltip(ref sb, tooltip, serie, index, theme, isCartesian, dataZoom);
|
||||
break;
|
||||
case SerieType.Scatter:
|
||||
case SerieType.EffectScatter:
|
||||
InitScatterTooltip(ref sb, tooltip, serie, index, theme);
|
||||
break;
|
||||
case SerieType.Radar:
|
||||
InitRadarTooltip(ref sb, tooltip, serie, radar, theme);
|
||||
break;
|
||||
case SerieType.Pie:
|
||||
InitPieTooltip(ref sb, tooltip, serie, index, theme);
|
||||
break;
|
||||
case SerieType.Ring:
|
||||
InitRingTooltip(ref sb, tooltip, serie, index, theme);
|
||||
break;
|
||||
case SerieType.Heatmap:
|
||||
break;
|
||||
case SerieType.Gauge:
|
||||
InitGaugeTooltip(ref sb, tooltip, serie, index, theme);
|
||||
break;
|
||||
case SerieType.Gantt:
|
||||
InitGanttTooltip(ref sb, tooltip, serie, index, theme, category);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public static void SetContentAndPosition(Tooltip tooltip, string content, Rect chartRect)
|
||||
{
|
||||
tooltip.UpdateContentText(content);
|
||||
var pos = tooltip.GetContentPos();
|
||||
if (pos.x + tooltip.runtimeWidth > chartRect.x + chartRect.width)
|
||||
{
|
||||
pos.x = chartRect.x + chartRect.width - tooltip.runtimeWidth;
|
||||
}
|
||||
if (pos.y - tooltip.runtimeHeight < chartRect.y)
|
||||
{
|
||||
pos.y = chartRect.y + tooltip.runtimeHeight;
|
||||
}
|
||||
tooltip.UpdateContentPos(pos);
|
||||
}
|
||||
|
||||
public static string GetPolarFormatterContent(Tooltip tooltip, Series series, ChartTheme theme, AngleAxis angleAxis)
|
||||
{
|
||||
if (string.IsNullOrEmpty(tooltip.formatter))
|
||||
{
|
||||
var sb = ChartHelper.sb;
|
||||
sb.Length = 0;
|
||||
var title = tooltip.titleFormatter;
|
||||
var formatTitle = !string.IsNullOrEmpty(title);
|
||||
if ("{i}".Equals(tooltip.titleFormatter))
|
||||
{
|
||||
title = string.Empty;
|
||||
formatTitle = false;
|
||||
}
|
||||
else if (string.IsNullOrEmpty(title))
|
||||
{
|
||||
var angle = angleAxis.clockwise ? tooltip.runtimeAngle : 360 - tooltip.runtimeAngle;
|
||||
title = ChartCached.FloatToStr(angle);
|
||||
}
|
||||
foreach (var serie in series.list)
|
||||
{
|
||||
if (serie.show && IsSelectedSerie(tooltip, serie.index))
|
||||
{
|
||||
if (formatTitle)
|
||||
{
|
||||
FormatterHelper.ReplaceContent(ref title, 0, tooltip.numericFormatter, serie, series, theme, null, null);
|
||||
}
|
||||
var dataIndexList = tooltip.runtimeSerieIndex[serie.index];
|
||||
|
||||
for (int i = 0; i < dataIndexList.Count; i++)
|
||||
{
|
||||
var dataIndex = dataIndexList[i];
|
||||
var serieData = serie.GetSerieData(dataIndex);
|
||||
var itemFormatter = GetItemFormatter(tooltip, serie, serieData);
|
||||
var numericFormatter = GetItemNumericFormatter(tooltip, serie, serieData);
|
||||
float xValue, yValue;
|
||||
serie.GetXYData(dataIndex, null, out xValue, out yValue);
|
||||
if (string.IsNullOrEmpty(itemFormatter))
|
||||
{
|
||||
sb.Append("<color=#").Append(theme.GetColorStr(serie.index)).Append(">● </color>");
|
||||
if (!string.IsNullOrEmpty(serie.name))
|
||||
sb.Append(serie.name).Append(": ");
|
||||
sb.AppendFormat("{0}", ChartCached.FloatToStr(xValue, numericFormatter));
|
||||
if (i != dataIndexList.Count - 1)
|
||||
{
|
||||
sb.Append(FormatterHelper.PH_NN);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
string content = itemFormatter;
|
||||
FormatterHelper.ReplaceContent(ref content, dataIndex, tooltip.numericFormatter, serie, series, theme, null, null);
|
||||
var dotColorIndex = serie.type == SerieType.Pie || serie.type == SerieType.Radar || serie.type == SerieType.Ring ? dataIndex : serie.index;
|
||||
sb.Append(ChartCached.ColorToDotStr(theme.GetColor(dotColorIndex)));
|
||||
sb.Append(content);
|
||||
}
|
||||
}
|
||||
sb.Append(FormatterHelper.PH_NN);
|
||||
}
|
||||
}
|
||||
if (string.IsNullOrEmpty(title))
|
||||
{
|
||||
return FormatterHelper.TrimAndReplaceLine(sb);
|
||||
}
|
||||
else
|
||||
{
|
||||
title = FormatterHelper.TrimAndReplaceLine(title);
|
||||
return title + FormatterHelper.PH_NN + FormatterHelper.TrimAndReplaceLine(sb);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
string content = tooltip.formatter;
|
||||
FormatterHelper.ReplaceContent(ref content, 0, tooltip.numericFormatter, null, series, theme, null, null);
|
||||
return content;
|
||||
}
|
||||
}
|
||||
|
||||
public static string GetFormatterContent(Tooltip tooltip, int dataIndex, Series series, ChartTheme theme,
|
||||
string category = null, DataZoom dataZoom = null, bool isCartesian = false, Radar radar = null)
|
||||
{
|
||||
if (string.IsNullOrEmpty(tooltip.formatter))
|
||||
{
|
||||
var sb = ChartHelper.sb;
|
||||
var title = tooltip.titleFormatter;
|
||||
var formatTitle = !string.IsNullOrEmpty(title);
|
||||
var titleIsIgnroe = false;
|
||||
var needCategory = false;
|
||||
var first = true;
|
||||
var isScatter = false;
|
||||
sb.Length = 0;
|
||||
if ("{i}".Equals(tooltip.titleFormatter))
|
||||
{
|
||||
title = string.Empty;
|
||||
formatTitle = false;
|
||||
titleIsIgnroe = true;
|
||||
}
|
||||
for (int i = 0; i < series.Count; i++)
|
||||
{
|
||||
var serie = series.GetSerie(i);
|
||||
if (tooltip.runtimeGridIndex >= 0 && serie.runtimeGridIndex != tooltip.runtimeGridIndex) continue;
|
||||
if (serie.type == SerieType.Scatter || serie.type == SerieType.EffectScatter)
|
||||
{
|
||||
if (serie.show && IsSelectedSerie(tooltip, serie.index))
|
||||
{
|
||||
isScatter = true;
|
||||
var itemFormatter = GetItemFormatter(tooltip, serie, null);
|
||||
if (string.IsNullOrEmpty(itemFormatter))
|
||||
{
|
||||
if (!first) sb.Append(FormatterHelper.PH_NN);
|
||||
InitDefaultContent(ref sb, tooltip, serie, dataIndex, category, theme, dataZoom, isCartesian, radar);
|
||||
first = false;
|
||||
continue;
|
||||
}
|
||||
var itemTitle = title;
|
||||
if (!string.IsNullOrEmpty(itemTitle))
|
||||
{
|
||||
FormatterHelper.ReplaceContent(ref itemTitle, dataIndex, tooltip.numericFormatter, serie, series, theme, category, dataZoom);
|
||||
sb.Append(itemTitle).Append(FormatterHelper.PH_NN);
|
||||
}
|
||||
var dataIndexList = tooltip.runtimeSerieIndex[serie.index];
|
||||
foreach (var tempIndex in dataIndexList)
|
||||
{
|
||||
string content = itemFormatter;
|
||||
var foundDot = FormatterHelper.ReplaceContent(ref content, tempIndex, tooltip.numericFormatter, serie, series, theme, category, dataZoom);
|
||||
if (!foundDot)
|
||||
{
|
||||
sb.Append(ChartCached.ColorToDotStr(theme.GetColor(serie.index)));
|
||||
}
|
||||
sb.Append(content).Append(FormatterHelper.PH_NN);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (IsNeedTooltipSerie(serie, tooltip))
|
||||
{
|
||||
var itemFormatter = string.Empty;
|
||||
if (serie.type == SerieType.Gauge)
|
||||
{
|
||||
var serieData = serie.GetSerieData(0, dataZoom);
|
||||
if (serieData == null) continue;
|
||||
itemFormatter = GetItemFormatter(tooltip, serie, serieData);
|
||||
}
|
||||
else
|
||||
{
|
||||
var serieData = serie.GetSerieData(dataIndex, dataZoom);
|
||||
if (serieData == null) continue;
|
||||
itemFormatter = GetItemFormatter(tooltip, serie, serieData);
|
||||
}
|
||||
needCategory = needCategory || (serie.type == SerieType.Line || serie.type == SerieType.Bar);
|
||||
if (formatTitle)
|
||||
{
|
||||
FormatterHelper.ReplaceContent(ref title, dataIndex, tooltip.numericFormatter, serie, series, theme, category, dataZoom);
|
||||
}
|
||||
if (serie.show)
|
||||
{
|
||||
if (string.IsNullOrEmpty(itemFormatter) || serie.type == SerieType.Radar)
|
||||
{
|
||||
if (!first) sb.Append(FormatterHelper.PH_NN);
|
||||
InitDefaultContent(ref sb, tooltip, serie, dataIndex, category, theme, dataZoom, isCartesian, radar);
|
||||
first = false;
|
||||
continue;
|
||||
}
|
||||
string content = itemFormatter;
|
||||
FormatterHelper.ReplaceContent(ref content, dataIndex, tooltip.numericFormatter, serie, series, theme, category, dataZoom);
|
||||
if (!first) sb.Append(FormatterHelper.PH_NN);
|
||||
var dotColorIndex = serie.type == SerieType.Pie || serie.type == SerieType.Radar || serie.type == SerieType.Ring ? dataIndex : i;
|
||||
sb.Append(ChartCached.ColorToDotStr(theme.GetColor(dotColorIndex)));
|
||||
sb.Append(content);
|
||||
first = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (isScatter)
|
||||
{
|
||||
return FormatterHelper.TrimAndReplaceLine(sb);
|
||||
}
|
||||
else if (string.IsNullOrEmpty(title))
|
||||
{
|
||||
if (needCategory && !titleIsIgnroe)
|
||||
return category + FormatterHelper.PH_NN + FormatterHelper.TrimAndReplaceLine(sb);
|
||||
else
|
||||
return FormatterHelper.TrimAndReplaceLine(sb);
|
||||
}
|
||||
else
|
||||
{
|
||||
title = FormatterHelper.TrimAndReplaceLine(title);
|
||||
return title + FormatterHelper.PH_NN + FormatterHelper.TrimAndReplaceLine(sb);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
string content = tooltip.formatter;
|
||||
FormatterHelper.ReplaceContent(ref content, dataIndex, tooltip.numericFormatter, null, series, theme, category, dataZoom);
|
||||
return content;
|
||||
}
|
||||
}
|
||||
|
||||
private static bool IsNeedTooltipSerie(Serie serie, Tooltip tooltip)
|
||||
{
|
||||
//if (serie.type == SerieType.Pie || serie.type == SerieType.Radar || serie.type == SerieType.Ring)
|
||||
if (serie.type == SerieType.Pie || serie.type == SerieType.Ring)
|
||||
{
|
||||
if (serie.index < tooltip.runtimeDataIndex.Count)
|
||||
return tooltip.runtimeDataIndex[serie.index] >= 0;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
else if (serie.type == SerieType.Gauge)
|
||||
{
|
||||
return serie.index == tooltip.runtimeDataIndex[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private static bool IsSelectedSerie(Tooltip tooltip, int serieIndex)
|
||||
{
|
||||
if (tooltip.runtimeSerieIndex.ContainsKey(serieIndex))
|
||||
{
|
||||
return tooltip.runtimeSerieIndex[serieIndex].Count > 0;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static string GetItemFormatter(Tooltip tooltip, Serie serie, SerieData serieData)
|
||||
{
|
||||
var itemStyle = SerieHelper.GetItemStyle(serie, serieData);
|
||||
if (!string.IsNullOrEmpty(itemStyle.tooltipFormatter)) return itemStyle.tooltipFormatter;
|
||||
else return tooltip.itemFormatter;
|
||||
}
|
||||
|
||||
private static string GetItemNumericFormatter(Tooltip tooltip, Serie serie, SerieData serieData)
|
||||
{
|
||||
var itemStyle = SerieHelper.GetItemStyle(serie, serieData);
|
||||
if (!string.IsNullOrEmpty(itemStyle.numericFormatter)) return itemStyle.numericFormatter;
|
||||
else return tooltip.numericFormatter;
|
||||
}
|
||||
|
||||
public static Color32 GetLineColor(Tooltip tooltip, ChartTheme theme)
|
||||
{
|
||||
var lineStyle = tooltip.lineStyle;
|
||||
if (!ChartHelper.IsClearColor(lineStyle.color))
|
||||
{
|
||||
return lineStyle.GetColor();
|
||||
}
|
||||
else
|
||||
{
|
||||
var color = theme.tooltip.lineColor;
|
||||
ChartHelper.SetColorOpacity(ref color, lineStyle.opacity);
|
||||
return color;
|
||||
}
|
||||
}
|
||||
|
||||
public static Color GetTexColor(Tooltip tooltip, ComponentTheme theme)
|
||||
{
|
||||
if (!ChartHelper.IsClearColor(tooltip.textStyle.color))
|
||||
{
|
||||
return tooltip.textStyle.color;
|
||||
}
|
||||
else
|
||||
{
|
||||
return theme.textColor;
|
||||
}
|
||||
}
|
||||
|
||||
public static Color GetTexBackgroundColor(Tooltip tooltip, ComponentTheme theme)
|
||||
{
|
||||
if (!ChartHelper.IsClearColor(tooltip.textStyle.backgroundColor))
|
||||
{
|
||||
return tooltip.textStyle.backgroundColor;
|
||||
}
|
||||
else
|
||||
{
|
||||
return theme.textBackgroundColor;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f0fa1b19683a8424bb335802de5c9726
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,39 @@
|
||||
/************************************************/
|
||||
/* */
|
||||
/* Copyright (c) 2018 - 2021 monitor1394 */
|
||||
/* https://github.com/monitor1394 */
|
||||
/* */
|
||||
/************************************************/
|
||||
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace XCharts
|
||||
{
|
||||
public static class VesselHelper
|
||||
{
|
||||
internal static Color32 GetColor(Vessel vessel, Serie serie, ChartTheme theme, List<string> legendRealShowName)
|
||||
{
|
||||
if (serie != null && vessel.autoColor)
|
||||
{
|
||||
var colorIndex = legendRealShowName.IndexOf(serie.name);
|
||||
return SerieHelper.GetItemColor(serie, null, theme, colorIndex, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
return vessel.color;
|
||||
}
|
||||
}
|
||||
|
||||
internal static void UpdateVesselCenter(Vessel vessel, Vector3 chartPosition, float chartWidth, float chartHeight)
|
||||
{
|
||||
if (vessel.center.Length < 2) return;
|
||||
var centerX = vessel.center[0] <= 1 ? chartWidth * vessel.center[0] : vessel.center[0];
|
||||
var centerY = vessel.center[1] <= 1 ? chartHeight * vessel.center[1] : vessel.center[1];
|
||||
var checkWidth = Mathf.Min(chartWidth, chartHeight);
|
||||
vessel.runtimeCenterPos = chartPosition + new Vector3(centerX, centerY);
|
||||
vessel.runtimeRadius = ChartHelper.GetRuntimeRelativeOrAbsoluteValue(vessel.radius, checkWidth);
|
||||
vessel.runtimeInnerRadius = vessel.runtimeRadius - vessel.shapeWidth - vessel.gap;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c0c82cb73437a4004bf946cf4dcaa567
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,142 @@
|
||||
/************************************************/
|
||||
/* */
|
||||
/* Copyright (c) 2018 - 2021 monitor1394 */
|
||||
/* https://github.com/monitor1394 */
|
||||
/* */
|
||||
/************************************************/
|
||||
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
namespace XCharts
|
||||
{
|
||||
public static class VisualMapHelper
|
||||
{
|
||||
public static void AutoSetLineMinMax(VisualMap visualMap, Serie serie, XAxis xAxis, YAxis yAxis)
|
||||
{
|
||||
if (!IsNeedGradient(visualMap) || !visualMap.autoMinMax) return;
|
||||
float min = 0;
|
||||
float max = 0;
|
||||
switch (visualMap.direction)
|
||||
{
|
||||
case VisualMap.Direction.Default:
|
||||
case VisualMap.Direction.X:
|
||||
min = xAxis.IsCategory() ? 0 : xAxis.runtimeMinValue;
|
||||
max = xAxis.IsCategory() ? serie.dataCount : xAxis.runtimeMaxValue;
|
||||
SetMinMax(visualMap, min, max);
|
||||
break;
|
||||
case VisualMap.Direction.Y:
|
||||
min = yAxis.IsCategory() ? 0 : yAxis.runtimeMinValue;
|
||||
max = yAxis.IsCategory() ? serie.dataCount : yAxis.runtimeMaxValue;
|
||||
SetMinMax(visualMap, min, max);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public static void SetMinMax(VisualMap visualMap, float min, float max)
|
||||
{
|
||||
if (visualMap.enable && (visualMap.min != min || visualMap.max != max))
|
||||
{
|
||||
if (max >= min)
|
||||
{
|
||||
visualMap.min = min;
|
||||
visualMap.max = max;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception("SetMinMax:max < min:" + min + "," + max);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void GetLineGradientColor(VisualMap visualMap, float xValue, float yValue,
|
||||
out Color32 startColor, out Color32 toColor)
|
||||
{
|
||||
startColor = ChartConst.clearColor32;
|
||||
toColor = ChartConst.clearColor32;
|
||||
switch (visualMap.direction)
|
||||
{
|
||||
case VisualMap.Direction.Default:
|
||||
case VisualMap.Direction.X:
|
||||
startColor = visualMap.IsPiecewise() ? visualMap.GetColor(xValue) : visualMap.GetColor(xValue - 1);
|
||||
toColor = visualMap.IsPiecewise() ? startColor : visualMap.GetColor(xValue);
|
||||
break;
|
||||
case VisualMap.Direction.Y:
|
||||
startColor = visualMap.IsPiecewise() ? visualMap.GetColor(yValue) : visualMap.GetColor(yValue - 1);
|
||||
toColor = visualMap.IsPiecewise() ? startColor : visualMap.GetColor(yValue);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
internal static Color32 GetLineGradientColor(VisualMap visualMap, Vector3 pos, CoordinateChart chart, Axis axis, Color32 defaultColor)
|
||||
{
|
||||
float value = 0;
|
||||
switch (visualMap.direction)
|
||||
{
|
||||
case VisualMap.Direction.Default:
|
||||
case VisualMap.Direction.X:
|
||||
var min = axis.runtimeMinValue;
|
||||
var max = axis.runtimeMaxValue;
|
||||
var grid = chart.GetAxisGridOrDefault(axis);
|
||||
value = min + (pos.x - grid.runtimeX) / grid.runtimeWidth * (max - min);
|
||||
break;
|
||||
case VisualMap.Direction.Y:
|
||||
if (axis is YAxis)
|
||||
{
|
||||
var yAxis = chart.xAxes[axis.index];
|
||||
min = yAxis.runtimeMinValue;
|
||||
max = yAxis.runtimeMaxValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
var yAxis = chart.yAxes[axis.index];
|
||||
min = yAxis.runtimeMinValue;
|
||||
max = yAxis.runtimeMaxValue;
|
||||
}
|
||||
grid = chart.GetAxisGridOrDefault(axis);
|
||||
value = min + (pos.y - grid.runtimeY) / grid.runtimeHeight * (max - min);
|
||||
break;
|
||||
}
|
||||
var color = visualMap.GetColor(value);
|
||||
if (ChartHelper.IsClearColor(color)) return defaultColor;
|
||||
else return color;
|
||||
}
|
||||
|
||||
internal static Color32 GetItemStyleGradientColor(ItemStyle itemStyle, Vector3 pos, CoordinateChart chart, Axis axis, Color32 defaultColor)
|
||||
{
|
||||
var min = axis.runtimeMinValue;
|
||||
var max = axis.runtimeMaxValue;
|
||||
var grid = chart.GetAxisGridOrDefault(axis);
|
||||
var value = min + (pos.x - grid.runtimeX) / grid.runtimeWidth * (max - min);
|
||||
var rate = (value - min) / (max - min);
|
||||
var color = itemStyle.GetGradientColor(rate, defaultColor);
|
||||
if (ChartHelper.IsClearColor(color)) return defaultColor;
|
||||
else return color;
|
||||
}
|
||||
|
||||
internal static Color32 GetLineStyleGradientColor(LineStyle lineStyle, Vector3 pos, CoordinateChart chart, Axis axis, Color32 defaultColor)
|
||||
{
|
||||
var min = axis.runtimeMinValue;
|
||||
var max = axis.runtimeMaxValue;
|
||||
var grid = chart.GetAxisGridOrDefault(axis);
|
||||
var value = min + (pos.x - grid.runtimeX) / grid.runtimeWidth * (max - min);
|
||||
var rate = (value - min) / (max - min);
|
||||
var color = lineStyle.GetGradientColor(rate, defaultColor);
|
||||
if (ChartHelper.IsClearColor(color)) return defaultColor;
|
||||
else return color;
|
||||
}
|
||||
|
||||
public static bool IsNeedGradient(VisualMap visualMap)
|
||||
{
|
||||
if (!visualMap.enable || visualMap.inRange.Count <= 0) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
public static int GetDimension(VisualMap visualMap, int serieDataCount)
|
||||
{
|
||||
var dimension = visualMap.enable && visualMap.dimension >= 0 ? visualMap.dimension : serieDataCount - 1;
|
||||
if (dimension > serieDataCount - 1) dimension = serieDataCount - 1;
|
||||
return dimension;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 15e5106bd46f5484596429d512f6af5d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4e4276d289bef4136b22e6cc8b207d99
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,28 @@
|
||||
/************************************************/
|
||||
/* */
|
||||
/* Copyright (c) 2018 - 2021 monitor1394 */
|
||||
/* https://github.com/monitor1394 */
|
||||
/* */
|
||||
/************************************************/
|
||||
|
||||
using UnityEngine;
|
||||
using UnityEngine.EventSystems;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace XCharts
|
||||
{
|
||||
public interface IDrawSerie
|
||||
{
|
||||
void InitComponent();
|
||||
void CheckComponent();
|
||||
void Update();
|
||||
void DrawBase(VertexHelper vh);
|
||||
void DrawSerie(VertexHelper vh, Serie serie);
|
||||
void RefreshLabel();
|
||||
bool CheckTootipArea(Vector2 local);
|
||||
bool OnLegendButtonClick(int index, string legendName, bool show);
|
||||
bool OnLegendButtonEnter(int index, string legendName);
|
||||
bool OnLegendButtonExit(int index, string legendName);
|
||||
void OnPointerDown(PointerEventData eventData);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0c4b04c07f5704c06a54b54193558c1b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,18 @@
|
||||
/************************************************/
|
||||
/* */
|
||||
/* Copyright (c) 2018 - 2021 monitor1394 */
|
||||
/* https://github.com/monitor1394 */
|
||||
/* */
|
||||
/************************************************/
|
||||
|
||||
namespace XCharts
|
||||
{
|
||||
/// <summary>
|
||||
/// 属性变更接口
|
||||
/// </summary>
|
||||
public interface IPropertyChanged
|
||||
{
|
||||
void OnChanged();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 24f32e2d632f08245ae885545f14a2a3
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3d225ec4fe992405d91714722649cc93
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,155 @@
|
||||
/************************************************/
|
||||
/* */
|
||||
/* Copyright (c) 2018 - 2021 monitor1394 */
|
||||
/* https://github.com/monitor1394 */
|
||||
/* */
|
||||
/************************************************/
|
||||
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace XCharts
|
||||
{
|
||||
public class ChartLabel : ChartObject
|
||||
{
|
||||
private bool m_LabelAutoSize = true;
|
||||
private float m_LabelPaddingLeftRight = 3f;
|
||||
private float m_LabelPaddingTopBottom = 3f;
|
||||
private ChartText m_LabelText;
|
||||
private RectTransform m_LabelRect;
|
||||
private RectTransform m_IconRect;
|
||||
private RectTransform m_ObjectRect;
|
||||
|
||||
private Image m_IconImage;
|
||||
|
||||
public GameObject gameObject { get { return m_GameObject; } }
|
||||
public Image icon { get { return m_IconImage; } }
|
||||
public ChartText label { get { return m_LabelText; } }
|
||||
|
||||
public ChartLabel()
|
||||
{
|
||||
}
|
||||
|
||||
public void SetLabel(GameObject labelObj, bool autoSize, float paddingLeftRight, float paddingTopBottom)
|
||||
{
|
||||
m_GameObject = labelObj;
|
||||
m_LabelAutoSize = autoSize;
|
||||
m_LabelPaddingLeftRight = paddingLeftRight;
|
||||
m_LabelPaddingTopBottom = paddingTopBottom;
|
||||
m_LabelText = new ChartText(labelObj);
|
||||
m_LabelRect = m_LabelText.gameObject.GetComponent<RectTransform>();
|
||||
m_ObjectRect = labelObj.GetComponent<RectTransform>();
|
||||
}
|
||||
|
||||
public void SetIcon(Image image)
|
||||
{
|
||||
m_IconImage = image;
|
||||
if (image != null)
|
||||
{
|
||||
m_IconRect = m_IconImage.GetComponent<RectTransform>();
|
||||
}
|
||||
}
|
||||
|
||||
public void SetIconSprite(Sprite sprite)
|
||||
{
|
||||
if (m_IconImage != null) m_IconImage.sprite = sprite;
|
||||
}
|
||||
|
||||
public void SetIconSize(float width, float height)
|
||||
{
|
||||
if (m_IconRect != null) m_IconRect.sizeDelta = new Vector3(width, height);
|
||||
}
|
||||
|
||||
public void UpdateIcon(IconStyle iconStyle)
|
||||
{
|
||||
if (m_IconImage == null) return;
|
||||
if (iconStyle.show)
|
||||
{
|
||||
ChartHelper.SetActive(m_IconImage.gameObject, true);
|
||||
m_IconImage.sprite = iconStyle.sprite;
|
||||
m_IconImage.color = iconStyle.color;
|
||||
m_IconRect.sizeDelta = new Vector2(iconStyle.width, iconStyle.height);
|
||||
m_IconImage.transform.localPosition = iconStyle.offset;
|
||||
if (iconStyle.layer == IconStyle.Layer.UnderLabel)
|
||||
m_IconRect.SetSiblingIndex(0);
|
||||
else
|
||||
m_IconRect.SetSiblingIndex(m_GameObject.transform.childCount - 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
ChartHelper.SetActive(m_IconImage.gameObject, false);
|
||||
}
|
||||
}
|
||||
|
||||
public float GetLabelWidth()
|
||||
{
|
||||
if (m_LabelRect) return m_LabelRect.sizeDelta.x;
|
||||
else return 0;
|
||||
}
|
||||
|
||||
public float GetLabelHeight()
|
||||
{
|
||||
if (m_LabelRect) return m_LabelRect.sizeDelta.y;
|
||||
return 0;
|
||||
}
|
||||
|
||||
public void SetLabelColor(Color color)
|
||||
{
|
||||
if (m_LabelText != null) m_LabelText.SetColor(color);
|
||||
}
|
||||
|
||||
public void SetLabelRotate(float rotate)
|
||||
{
|
||||
if (m_LabelText != null) m_LabelText.SetLocalEulerAngles(new Vector3(0, 0, rotate));
|
||||
}
|
||||
|
||||
public void SetPosition(Vector3 position)
|
||||
{
|
||||
if (m_GameObject != null)
|
||||
{
|
||||
m_GameObject.transform.localPosition = position;
|
||||
}
|
||||
}
|
||||
|
||||
public void SetLabelPosition(Vector3 position)
|
||||
{
|
||||
if (m_LabelRect) m_LabelRect.localPosition = position;
|
||||
}
|
||||
|
||||
public void SetActive(bool flag)
|
||||
{
|
||||
if (m_GameObject) ChartHelper.SetActive(m_GameObject, flag);
|
||||
}
|
||||
public void SetLabelActive(bool flag)
|
||||
{
|
||||
if (m_LabelText != null) m_LabelText.SetActive(flag);
|
||||
}
|
||||
public void SetIconActive(bool flag)
|
||||
{
|
||||
if (m_IconImage) ChartHelper.SetActive(m_IconImage, flag);
|
||||
}
|
||||
|
||||
public bool SetText(string text)
|
||||
{
|
||||
if (m_LabelRect == null) return false;
|
||||
if (m_LabelText != null && !m_LabelText.GetText().Equals(text))
|
||||
{
|
||||
m_LabelText.SetText(text);
|
||||
if (m_LabelAutoSize)
|
||||
{
|
||||
var newSize = string.IsNullOrEmpty(text) ? Vector2.zero :
|
||||
new Vector2(m_LabelText.GetPreferredWidth() + m_LabelPaddingLeftRight * 2,
|
||||
m_LabelText.GetPreferredHeight() + m_LabelPaddingTopBottom * 2);
|
||||
var sizeChange = newSize.x != m_LabelRect.sizeDelta.x || newSize.y != m_LabelRect.sizeDelta.y;
|
||||
if (sizeChange)
|
||||
{
|
||||
m_LabelRect.sizeDelta = newSize;
|
||||
m_ObjectRect.sizeDelta = newSize;
|
||||
}
|
||||
return sizeChange;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 61287841bdc4142caba8e77985cd8715
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,22 @@
|
||||
/************************************************/
|
||||
/* */
|
||||
/* Copyright (c) 2018 - 2021 monitor1394 */
|
||||
/* https://github.com/monitor1394 */
|
||||
/* */
|
||||
/************************************************/
|
||||
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
namespace XCharts
|
||||
{
|
||||
public class ChartObject
|
||||
{
|
||||
protected GameObject m_GameObject;
|
||||
|
||||
public virtual void Destroy()
|
||||
{
|
||||
GameObject.Destroy(m_GameObject);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0fe3102b0eea042938d30af910ca86d6
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,255 @@
|
||||
/************************************************/
|
||||
/* */
|
||||
/* Copyright (c) 2018 - 2021 monitor1394 */
|
||||
/* https://github.com/monitor1394 */
|
||||
/* */
|
||||
/************************************************/
|
||||
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
#if dUI_TextMeshPro
|
||||
using TMPro;
|
||||
#endif
|
||||
|
||||
namespace XCharts
|
||||
{
|
||||
public class ChartText
|
||||
{
|
||||
private Text m_Text;
|
||||
private TextGenerationSettings m_RelatedTextSettings;
|
||||
public Text text
|
||||
{
|
||||
get { return m_Text; }
|
||||
set
|
||||
{
|
||||
m_Text = value;
|
||||
if (value != null)
|
||||
{
|
||||
m_RelatedTextSettings = m_Text.GetGenerationSettings(Vector2.zero);
|
||||
}
|
||||
}
|
||||
}
|
||||
#if dUI_TextMeshPro
|
||||
private TextMeshProUGUI m_TMPText;
|
||||
public TextMeshProUGUI tmpText { get { return m_TMPText; } set { m_TMPText = value; } }
|
||||
#endif
|
||||
public GameObject gameObject
|
||||
{
|
||||
get
|
||||
{
|
||||
#if dUI_TextMeshPro
|
||||
if (m_TMPText != null) return m_TMPText.gameObject;
|
||||
#else
|
||||
if (m_Text != null) return m_Text.gameObject;
|
||||
#endif
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public ChartText()
|
||||
{
|
||||
}
|
||||
|
||||
public ChartText(GameObject textParent)
|
||||
{
|
||||
#if dUI_TextMeshPro
|
||||
m_TMPText = textParent.GetComponentInChildren<TextMeshProUGUI>();
|
||||
if (m_TMPText == null)
|
||||
{
|
||||
Debug.LogError("can't find TextMeshProUGUI component:" + textParent);
|
||||
}
|
||||
#else
|
||||
m_Text = textParent.GetComponentInChildren<Text>();
|
||||
if (m_Text == null)
|
||||
{
|
||||
Debug.LogError("can't find Text component:" + textParent);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
public void SetFontSize(float fontSize)
|
||||
{
|
||||
#if dUI_TextMeshPro
|
||||
if (m_TMPText != null) m_TMPText.fontSize = fontSize;
|
||||
#else
|
||||
if (m_Text != null) m_Text.fontSize = (int)fontSize;
|
||||
#endif
|
||||
}
|
||||
|
||||
public void SetText(string text)
|
||||
{
|
||||
if (text == null) text = string.Empty;
|
||||
else text = text.Replace("\\n", "\n");
|
||||
#if dUI_TextMeshPro
|
||||
if(m_TMPText != null) m_TMPText.text = text;
|
||||
#else
|
||||
if (m_Text != null) m_Text.text = text;
|
||||
#endif
|
||||
}
|
||||
|
||||
public string GetText()
|
||||
{
|
||||
#if dUI_TextMeshPro
|
||||
if (m_TMPText != null) return m_TMPText.text;
|
||||
#else
|
||||
if (m_Text != null) return m_Text.text;
|
||||
#endif
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
public void SetColor(Color color)
|
||||
{
|
||||
#if dUI_TextMeshPro
|
||||
if (m_TMPText != null) m_TMPText.color = color;
|
||||
#else
|
||||
if (m_Text != null) m_Text.color = color;
|
||||
#endif
|
||||
}
|
||||
|
||||
public void SetLineSpacing(float lineSpacing)
|
||||
{
|
||||
#if dUI_TextMeshPro
|
||||
if (m_TMPText != null) m_TMPText.lineSpacing = lineSpacing;
|
||||
#else
|
||||
if (m_Text != null) m_Text.lineSpacing = lineSpacing;
|
||||
#endif
|
||||
}
|
||||
|
||||
public void SetActive(bool flag)
|
||||
{
|
||||
#if dUI_TextMeshPro
|
||||
//m_TMPText.gameObject.SetActive(flag);
|
||||
if (m_TMPText != null) ChartHelper.SetActive(m_TMPText.gameObject, flag);
|
||||
#else
|
||||
//m_Text.gameObject.SetActive(flag);
|
||||
if (m_Text != null) ChartHelper.SetActive(m_Text.gameObject, flag);
|
||||
#endif
|
||||
}
|
||||
|
||||
public void SetLocalPosition(Vector3 position)
|
||||
{
|
||||
#if dUI_TextMeshPro
|
||||
if (m_TMPText != null) m_TMPText.transform.localPosition = position;
|
||||
#else
|
||||
if (m_Text != null) m_Text.transform.localPosition = position;
|
||||
#endif
|
||||
}
|
||||
public void SetSizeDelta(Vector2 sizeDelta)
|
||||
{
|
||||
#if dUI_TextMeshPro
|
||||
if (m_TMPText != null) m_TMPText.GetComponent<RectTransform>().sizeDelta = sizeDelta;
|
||||
#else
|
||||
if (m_Text != null) m_Text.GetComponent<RectTransform>().sizeDelta = sizeDelta;
|
||||
#endif
|
||||
}
|
||||
|
||||
public void SetLocalEulerAngles(Vector3 position)
|
||||
{
|
||||
#if dUI_TextMeshPro
|
||||
if (m_TMPText != null) m_TMPText.transform.localEulerAngles = position;
|
||||
#else
|
||||
if (m_Text != null) m_Text.transform.localEulerAngles = position;
|
||||
#endif
|
||||
}
|
||||
|
||||
public void SetAlignment(TextAnchor alignment)
|
||||
{
|
||||
#if dUI_TextMeshPro
|
||||
if (m_TMPText == null) return;
|
||||
switch (alignment)
|
||||
{
|
||||
case TextAnchor.LowerCenter: m_TMPText.alignment = TextAlignmentOptions.Bottom; break;
|
||||
case TextAnchor.LowerLeft: m_TMPText.alignment = TextAlignmentOptions.BottomLeft; break;
|
||||
case TextAnchor.LowerRight: m_TMPText.alignment = TextAlignmentOptions.BottomRight; break;
|
||||
case TextAnchor.MiddleCenter: m_TMPText.alignment = TextAlignmentOptions.Center; break;
|
||||
case TextAnchor.MiddleLeft: m_TMPText.alignment = TextAlignmentOptions.Left; break;
|
||||
case TextAnchor.MiddleRight: m_TMPText.alignment = TextAlignmentOptions.Right; break;
|
||||
case TextAnchor.UpperCenter: m_TMPText.alignment = TextAlignmentOptions.Top; break;
|
||||
case TextAnchor.UpperLeft: m_TMPText.alignment = TextAlignmentOptions.TopLeft; break;
|
||||
case TextAnchor.UpperRight: m_TMPText.alignment = TextAlignmentOptions.TopRight; break;
|
||||
}
|
||||
#else
|
||||
if (m_Text != null) m_Text.alignment = alignment;
|
||||
#endif
|
||||
}
|
||||
|
||||
public void SetFont(Font font)
|
||||
{
|
||||
if (m_Text) m_Text.font = font;
|
||||
}
|
||||
|
||||
public void SetFontStyle(FontStyle fontStyle)
|
||||
{
|
||||
#if dUI_TextMeshPro
|
||||
if (m_TMPText == null) return;
|
||||
switch (fontStyle)
|
||||
{
|
||||
case FontStyle.Normal: m_TMPText.fontStyle = FontStyles.Normal; break;
|
||||
case FontStyle.Bold: m_TMPText.fontStyle = FontStyles.Bold; break;
|
||||
case FontStyle.BoldAndItalic: m_TMPText.fontStyle = FontStyles.Bold | FontStyles.Italic; break;
|
||||
case FontStyle.Italic: m_TMPText.fontStyle = FontStyles.Italic; break;
|
||||
}
|
||||
#else
|
||||
if (m_Text != null) m_Text.fontStyle = fontStyle;
|
||||
#endif
|
||||
}
|
||||
|
||||
public void SetFontAndSizeAndStyle(TextStyle textStyle, ComponentTheme theme)
|
||||
{
|
||||
#if dUI_TextMeshPro
|
||||
if (m_TMPText == null) return;
|
||||
m_TMPText.font = textStyle.tmpFont == null ? theme.tmpFont : textStyle.tmpFont;
|
||||
m_TMPText.fontSize = textStyle.fontSize == 0 ? theme.fontSize : textStyle.fontSize;
|
||||
m_TMPText.fontStyle = textStyle.tmpFontStyle;
|
||||
#else
|
||||
if (m_Text != null)
|
||||
{
|
||||
m_Text.font = textStyle.font == null ? theme.font : textStyle.font;
|
||||
m_Text.fontSize = textStyle.fontSize == 0 ? theme.fontSize : textStyle.fontSize;
|
||||
m_Text.fontStyle = textStyle.fontStyle;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
public float GetPreferredWidth(string content)
|
||||
{
|
||||
#if dUI_TextMeshPro
|
||||
if (m_TMPText != null) return 0; // TODO:
|
||||
#else
|
||||
if (m_Text != null) return m_Text.cachedTextGenerator.GetPreferredWidth(content, m_RelatedTextSettings);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
public float GetPreferredWidth()
|
||||
{
|
||||
#if dUI_TextMeshPro
|
||||
if (m_TMPText != null) return m_TMPText.preferredWidth;
|
||||
#else
|
||||
if (m_Text != null) return m_Text.preferredWidth;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
public float GetPreferredHeight()
|
||||
{
|
||||
#if dUI_TextMeshPro
|
||||
if (m_TMPText != null) return m_TMPText.preferredHeight;
|
||||
#else
|
||||
if (m_Text != null) return m_Text.preferredHeight;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if dUI_TextMeshPro
|
||||
public void SetAlignment(TextAlignmentOptions alignment)
|
||||
{
|
||||
if (m_TMPText != null) m_TMPText.alignment = alignment;
|
||||
}
|
||||
|
||||
public void SetFont(TMP_FontAsset font)
|
||||
{
|
||||
if (m_TMPText != null) m_TMPText.font = font;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4e2466c1fe5874bea8373b071405a930
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,220 @@
|
||||
/************************************************/
|
||||
/* */
|
||||
/* Copyright (c) 2018 - 2021 monitor1394 */
|
||||
/* https://github.com/monitor1394 */
|
||||
/* */
|
||||
/************************************************/
|
||||
using System;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace XCharts
|
||||
{
|
||||
public class LegendItem
|
||||
{
|
||||
private int m_Index;
|
||||
private string m_Name;
|
||||
private string m_LegendName;
|
||||
private GameObject m_GameObject;
|
||||
private Button m_Button;
|
||||
private Image m_Icon;
|
||||
private ChartText m_Text;
|
||||
private Image m_TextBackground;
|
||||
private RectTransform m_Rect;
|
||||
private RectTransform m_IconRect;
|
||||
private RectTransform m_TextRect;
|
||||
private RectTransform m_TextBackgroundRect;
|
||||
private float m_Gap = 0f;
|
||||
private float m_LabelPaddingLeftRight = 0f;
|
||||
private float m_LabelPaddingTopBottom = 0f;
|
||||
private bool m_LabelAutoSize = true;
|
||||
|
||||
public int index { get { return m_Index; } set { m_Index = value; } }
|
||||
public string name { get { return m_Name; } set { m_Name = value; } }
|
||||
public string legendName { get { return m_LegendName; } set { m_LegendName = value; } }
|
||||
public GameObject gameObject { get { return m_GameObject; } }
|
||||
public Button button { get { return m_Button; } }
|
||||
public float width
|
||||
{
|
||||
get
|
||||
{
|
||||
if (m_IconRect && m_TextBackgroundRect)
|
||||
{
|
||||
return m_IconRect.sizeDelta.x + m_Gap + m_TextBackgroundRect.sizeDelta.x;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public float height
|
||||
{
|
||||
get
|
||||
{
|
||||
if (m_IconRect && m_TextBackgroundRect)
|
||||
{
|
||||
return Mathf.Max(m_IconRect.sizeDelta.y, m_TextBackgroundRect.sizeDelta.y);
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void SetObject(GameObject obj)
|
||||
{
|
||||
m_GameObject = obj;
|
||||
m_Button = obj.GetComponent<Button>();
|
||||
m_Rect = obj.GetComponent<RectTransform>();
|
||||
m_Icon = obj.transform.Find("icon").gameObject.GetComponent<Image>();
|
||||
m_TextBackground = obj.transform.Find("content").gameObject.GetComponent<Image>();
|
||||
m_Text = new ChartText(obj);
|
||||
m_IconRect = m_Icon.gameObject.GetComponent<RectTransform>();
|
||||
m_TextRect = m_Text.gameObject.GetComponent<RectTransform>();
|
||||
m_TextBackgroundRect = m_TextBackground.gameObject.GetComponent<RectTransform>();
|
||||
}
|
||||
|
||||
public void SetButton(Button button)
|
||||
{
|
||||
m_Button = button;
|
||||
}
|
||||
|
||||
public void SetIcon(Image icon)
|
||||
{
|
||||
m_Icon = icon;
|
||||
}
|
||||
|
||||
public void SetText(ChartText text)
|
||||
{
|
||||
m_Text = text;
|
||||
}
|
||||
|
||||
public void SetTextBackground(Image image)
|
||||
{
|
||||
m_TextBackground = image;
|
||||
}
|
||||
|
||||
public void SetIconSize(float width, float height)
|
||||
{
|
||||
if (m_IconRect)
|
||||
{
|
||||
m_IconRect.sizeDelta = new Vector2(width, height);
|
||||
}
|
||||
}
|
||||
|
||||
public Rect GetIconRect()
|
||||
{
|
||||
if (m_GameObject && m_IconRect)
|
||||
{
|
||||
var pos = m_GameObject.transform.localPosition;
|
||||
var sizeDelta = m_IconRect.sizeDelta;
|
||||
var y = pos.y - (m_Rect.sizeDelta.y - sizeDelta.y) / 2 - sizeDelta.y;
|
||||
return new Rect(pos.x, y, m_IconRect.sizeDelta.x, m_IconRect.sizeDelta.y);
|
||||
}
|
||||
else
|
||||
{
|
||||
return Rect.zero;
|
||||
}
|
||||
}
|
||||
|
||||
public Color GetIconColor()
|
||||
{
|
||||
if (m_Icon) return m_Icon.color;
|
||||
else return Color.clear;
|
||||
}
|
||||
|
||||
|
||||
public void SetIconColor(Color color)
|
||||
{
|
||||
if (m_Icon)
|
||||
{
|
||||
m_Icon.color = color;
|
||||
}
|
||||
}
|
||||
|
||||
public void SetIconImage(Sprite image)
|
||||
{
|
||||
if (m_Icon)
|
||||
{
|
||||
m_Icon.sprite = image;
|
||||
}
|
||||
}
|
||||
|
||||
public void SetIconActive(bool active)
|
||||
{
|
||||
if (m_Icon)
|
||||
{
|
||||
m_Icon.gameObject.SetActive(active);
|
||||
}
|
||||
}
|
||||
|
||||
public void SetContentColor(Color color)
|
||||
{
|
||||
if (m_Text != null)
|
||||
{
|
||||
m_Text.SetColor(color);
|
||||
}
|
||||
}
|
||||
|
||||
public void SetContentBackgroundColor(Color color)
|
||||
{
|
||||
if (m_TextBackground)
|
||||
{
|
||||
m_TextBackground.color = color;
|
||||
}
|
||||
}
|
||||
|
||||
public void SetContentPosition(Vector3 offset)
|
||||
{
|
||||
m_Gap = offset.x;
|
||||
if (m_TextBackgroundRect)
|
||||
{
|
||||
var posX = m_IconRect.sizeDelta.x + offset.x;
|
||||
m_TextBackgroundRect.anchoredPosition3D = new Vector3(posX, offset.y, 0);
|
||||
}
|
||||
}
|
||||
|
||||
public bool SetContent(string content)
|
||||
{
|
||||
if (m_Text != null && !m_Text.GetText().Equals(content))
|
||||
{
|
||||
m_Text.SetText(content);
|
||||
if (m_LabelAutoSize)
|
||||
{
|
||||
var newSize = string.IsNullOrEmpty(content) ? Vector2.zero :
|
||||
new Vector2(m_Text.GetPreferredWidth(), m_Text.GetPreferredHeight());
|
||||
var sizeChange = newSize.x != m_TextRect.sizeDelta.x || newSize.y != m_TextRect.sizeDelta.y;
|
||||
if (sizeChange)
|
||||
{
|
||||
m_TextRect.sizeDelta = newSize;
|
||||
m_TextRect.anchoredPosition3D = new Vector3(m_LabelPaddingLeftRight, 0);
|
||||
m_TextBackgroundRect.sizeDelta = new Vector2(m_Text.GetPreferredWidth() + m_LabelPaddingLeftRight * 2,
|
||||
m_Text.GetPreferredHeight() + m_LabelPaddingTopBottom * 2 - 4);
|
||||
m_Rect.sizeDelta = new Vector3(width, height);
|
||||
}
|
||||
return sizeChange;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void SetPosition(Vector3 position)
|
||||
{
|
||||
if (m_GameObject)
|
||||
{
|
||||
m_GameObject.transform.localPosition = position;
|
||||
}
|
||||
}
|
||||
|
||||
public void SetActive(bool active)
|
||||
{
|
||||
if (m_GameObject)
|
||||
{
|
||||
m_GameObject.SetActive(active);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3e5abcb8f339f41f5b3680ecdab67509
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,79 @@
|
||||
/************************************************/
|
||||
/* */
|
||||
/* Copyright (c) 2018 - 2021 monitor1394 */
|
||||
/* https://github.com/monitor1394 */
|
||||
/* */
|
||||
/************************************************/
|
||||
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using System;
|
||||
|
||||
namespace XCharts
|
||||
{
|
||||
[RequireComponent(typeof(CanvasRenderer))]
|
||||
public class Painter : MaskableGraphic
|
||||
{
|
||||
public enum Type
|
||||
{
|
||||
Base,
|
||||
Serie,
|
||||
Top
|
||||
}
|
||||
protected int m_Index = -1;
|
||||
protected Type m_Type = Type.Base;
|
||||
protected bool m_Refresh;
|
||||
protected Action<VertexHelper, Painter> m_OnPopulateMesh;
|
||||
|
||||
public Action<VertexHelper, Painter> onPopulateMesh { set { m_OnPopulateMesh = value; } }
|
||||
public int index { get { return m_Index; } set { m_Index = value; } }
|
||||
public Type type { get { return m_Type; } set { m_Type = value; } }
|
||||
public void Refresh()
|
||||
{
|
||||
if (gameObject == null) return;
|
||||
if (!gameObject.activeSelf) return;
|
||||
m_Refresh = true;
|
||||
}
|
||||
|
||||
public void Init()
|
||||
{
|
||||
raycastTarget = false;
|
||||
}
|
||||
|
||||
public void SetActive(bool flag, bool isDebugMode = false)
|
||||
{
|
||||
if (gameObject.activeInHierarchy != flag)
|
||||
{
|
||||
gameObject.SetActive(flag);
|
||||
}
|
||||
// var higFlags = !flag || !isDebugMode ? HideFlags.HideInHierarchy : HideFlags.None;
|
||||
// if (gameObject.hideFlags != higFlags)
|
||||
// {
|
||||
// gameObject.hideFlags = hideFlags;
|
||||
// }
|
||||
}
|
||||
|
||||
protected override void Awake()
|
||||
{
|
||||
Init();
|
||||
}
|
||||
|
||||
internal void CheckRefresh()
|
||||
{
|
||||
if (m_Refresh && gameObject.activeSelf)
|
||||
{
|
||||
m_Refresh = false;
|
||||
SetVerticesDirty();
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnPopulateMesh(VertexHelper vh)
|
||||
{
|
||||
vh.Clear();
|
||||
if (m_OnPopulateMesh != null)
|
||||
{
|
||||
m_OnPopulateMesh(vh, this);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 01c85cd323a9f4dfb803470695bd0944
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 576ce681815d348d0a2abbbadf3dd9f7
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,39 @@
|
||||
/************************************************/
|
||||
/* */
|
||||
/* Copyright (c) 2018 - 2021 monitor1394 */
|
||||
/* https://github.com/monitor1394 */
|
||||
/* */
|
||||
/************************************************/
|
||||
|
||||
namespace XCharts
|
||||
{
|
||||
internal static class XAxisPool
|
||||
{
|
||||
private static readonly ObjectPool<XAxis> s_ListPool = new ObjectPool<XAxis>(null, null);
|
||||
|
||||
public static XAxis Get()
|
||||
{
|
||||
return s_ListPool.Get();
|
||||
}
|
||||
|
||||
public static void Release(XAxis toRelease)
|
||||
{
|
||||
s_ListPool.Release(toRelease);
|
||||
}
|
||||
}
|
||||
|
||||
internal static class YAxisPool
|
||||
{
|
||||
private static readonly ObjectPool<YAxis> s_ListPool = new ObjectPool<YAxis>(null, null);
|
||||
|
||||
public static YAxis Get()
|
||||
{
|
||||
return s_ListPool.Get();
|
||||
}
|
||||
|
||||
public static void Release(YAxis toRelease)
|
||||
{
|
||||
s_ListPool.Release(toRelease);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3a709ca44e9a445bd86bde1bbfae80de
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,43 @@
|
||||
/************************************************/
|
||||
/* */
|
||||
/* Copyright (c) 2018 - 2021 monitor1394 */
|
||||
/* https://github.com/monitor1394 */
|
||||
/* */
|
||||
/************************************************/
|
||||
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace XCharts
|
||||
{
|
||||
internal static class ListPool<T>
|
||||
{
|
||||
private static readonly ObjectPool<List<T>> s_ListPool = new ObjectPool<List<T>>(OnGet, OnClear);
|
||||
static void OnGet(List<T> l)
|
||||
{
|
||||
if (l.Capacity < 50)
|
||||
{
|
||||
l.Capacity = 50;
|
||||
}
|
||||
}
|
||||
static void OnClear(List<T> l)
|
||||
{
|
||||
l.Clear();
|
||||
}
|
||||
|
||||
public static List<T> Get()
|
||||
{
|
||||
return s_ListPool.Get();
|
||||
}
|
||||
|
||||
public static void Release(List<T> toRelease)
|
||||
{
|
||||
s_ListPool.Release(toRelease);
|
||||
}
|
||||
|
||||
public static void ClearAll()
|
||||
{
|
||||
s_ListPool.ClearAll();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 02c30457469c746dc96f00f24cb6e1c6
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,61 @@
|
||||
/************************************************/
|
||||
/* */
|
||||
/* Copyright (c) 2018 - 2021 monitor1394 */
|
||||
/* https://github.com/monitor1394 */
|
||||
/* */
|
||||
/************************************************/
|
||||
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Events;
|
||||
|
||||
namespace XCharts
|
||||
{
|
||||
internal class ObjectPool<T> where T : new()
|
||||
{
|
||||
private readonly Stack<T> m_Stack = new Stack<T>();
|
||||
private readonly UnityAction<T> m_ActionOnGet;
|
||||
private readonly UnityAction<T> m_ActionOnRelease;
|
||||
|
||||
public int countAll { get; private set; }
|
||||
public int countActive { get { return countAll - countInactive; } }
|
||||
public int countInactive { get { return m_Stack.Count; } }
|
||||
|
||||
public ObjectPool(UnityAction<T> actionOnGet, UnityAction<T> actionOnRelease)
|
||||
{
|
||||
m_ActionOnGet = actionOnGet;
|
||||
m_ActionOnRelease = actionOnRelease;
|
||||
}
|
||||
|
||||
public T Get()
|
||||
{
|
||||
T element;
|
||||
if (m_Stack.Count == 0)
|
||||
{
|
||||
element = new T();
|
||||
countAll++;
|
||||
}
|
||||
else
|
||||
{
|
||||
element = m_Stack.Pop();
|
||||
}
|
||||
if (m_ActionOnGet != null)
|
||||
m_ActionOnGet(element);
|
||||
return element;
|
||||
}
|
||||
|
||||
public void Release(T element)
|
||||
{
|
||||
if (m_Stack.Count > 0 && ReferenceEquals(m_Stack.Peek(), element))
|
||||
Debug.LogError("Internal error. Trying to destroy object that is already released to pool.");
|
||||
if (m_ActionOnRelease != null)
|
||||
m_ActionOnRelease(element);
|
||||
m_Stack.Push(element);
|
||||
}
|
||||
|
||||
public void ClearAll()
|
||||
{
|
||||
m_Stack.Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 09e67988253cb4f568b82d52b4113797
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,35 @@
|
||||
/************************************************/
|
||||
/* */
|
||||
/* Copyright (c) 2018 - 2021 monitor1394 */
|
||||
/* https://github.com/monitor1394 */
|
||||
/* */
|
||||
/************************************************/
|
||||
|
||||
using UnityEngine;
|
||||
|
||||
namespace XCharts
|
||||
{
|
||||
internal static class SerieDataPool
|
||||
{
|
||||
private static readonly ObjectPool<SerieData> s_ListPool = new ObjectPool<SerieData>(null, OnClear);
|
||||
|
||||
static void OnGet(SerieData serieData)
|
||||
{
|
||||
}
|
||||
|
||||
static void OnClear(SerieData serieData)
|
||||
{
|
||||
serieData.Reset();
|
||||
}
|
||||
|
||||
public static SerieData Get()
|
||||
{
|
||||
return s_ListPool.Get();
|
||||
}
|
||||
|
||||
public static void Release(SerieData toRelease)
|
||||
{
|
||||
s_ListPool.Release(toRelease);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: faf4da15b01d74648bd13f73125e27bd
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,82 @@
|
||||
/************************************************/
|
||||
/* */
|
||||
/* Copyright (c) 2018 - 2021 monitor1394 */
|
||||
/* https://github.com/monitor1394 */
|
||||
/* */
|
||||
/************************************************/
|
||||
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace XCharts
|
||||
{
|
||||
internal static class SerieLabelPool
|
||||
{
|
||||
private static readonly Stack<GameObject> m_Stack = new Stack<GameObject>(200);
|
||||
private static Dictionary<int, bool> m_ReleaseDic = new Dictionary<int, bool>(1000);
|
||||
|
||||
public static GameObject Get(string name, Transform parent, SerieLabel label, Color color,
|
||||
float iconWidth, float iconHeight, ChartTheme theme)
|
||||
{
|
||||
GameObject element;
|
||||
if (m_Stack.Count == 0 || !Application.isPlaying)
|
||||
{
|
||||
element = CreateSerieLabel(name, parent, label, color, iconWidth, iconHeight, theme);
|
||||
}
|
||||
else
|
||||
{
|
||||
element = m_Stack.Pop();
|
||||
if (element == null)
|
||||
{
|
||||
element = CreateSerieLabel(name, parent, label, color, iconWidth, iconHeight, theme);
|
||||
}
|
||||
m_ReleaseDic.Remove(element.GetInstanceID());
|
||||
element.name = name;
|
||||
element.transform.SetParent(parent);
|
||||
element.transform.localEulerAngles = new Vector3(0, 0, label.textStyle.rotate);
|
||||
var text = new ChartText(element);
|
||||
text.SetColor(color);
|
||||
text.SetFontAndSizeAndStyle(label.textStyle, theme.common);
|
||||
ChartHelper.SetActive(element, true);
|
||||
}
|
||||
return element;
|
||||
}
|
||||
|
||||
private static GameObject CreateSerieLabel(string name, Transform parent, SerieLabel label, Color color,
|
||||
float iconWidth, float iconHeight, ChartTheme theme)
|
||||
{
|
||||
var element = ChartHelper.AddSerieLabel(name, parent, label.backgroundWidth, label.backgroundHeight,
|
||||
color, label.textStyle, theme);
|
||||
ChartHelper.AddIcon("Icon", element.transform, iconWidth, iconHeight);
|
||||
return element;
|
||||
}
|
||||
|
||||
public static void Release(GameObject element)
|
||||
{
|
||||
if (element == null) return;
|
||||
ChartHelper.SetActive(element, false);
|
||||
if (!Application.isPlaying) return;
|
||||
if (!m_ReleaseDic.ContainsKey(element.GetInstanceID()))
|
||||
{
|
||||
m_Stack.Push(element);
|
||||
m_ReleaseDic.Add(element.GetInstanceID(), true);
|
||||
}
|
||||
}
|
||||
|
||||
public static void ReleaseAll(Transform parent)
|
||||
{
|
||||
int count = parent.childCount;
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
Release(parent.GetChild(i).gameObject);
|
||||
}
|
||||
}
|
||||
|
||||
public static void ClearAll()
|
||||
{
|
||||
m_Stack.Clear();
|
||||
m_ReleaseDic.Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e960aeb14c09844e3bdcdc4138af0761
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fb2e76e18ed3b4ffd8ad1e65a0710fb4
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,172 @@
|
||||
/************************************************/
|
||||
/* */
|
||||
/* Copyright (c) 2018 - 2021 monitor1394 */
|
||||
/* https://github.com/monitor1394 */
|
||||
/* */
|
||||
/************************************************/
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using UnityEngine;
|
||||
|
||||
namespace XCharts
|
||||
{
|
||||
public static class ChartCached
|
||||
{
|
||||
private const string NUMERIC_FORMATTER_D = "D";
|
||||
private const string NUMERIC_FORMATTER_d = "d";
|
||||
private const string NUMERIC_FORMATTER_X = "X";
|
||||
private const string NUMERIC_FORMATTER_x = "x";
|
||||
private static readonly string s_DefaultAxisY = "axis_y";
|
||||
private static readonly string s_DefaultAxisX = "axis_x";
|
||||
private static CultureInfo ci = new CultureInfo("en-us");// "en-us", "zh-cn", "ar-iq", "de-de"
|
||||
private static Dictionary<Color, string> s_ColorToStr = new Dictionary<Color, string>(100);
|
||||
private static Dictionary<int, string> s_SerieLabelName = new Dictionary<int, string>(1000);
|
||||
private static Dictionary<Color, string> s_ColorDotStr = new Dictionary<Color, string>(100);
|
||||
private static Dictionary<int, string> s_XAxisName = new Dictionary<int, string>();
|
||||
private static Dictionary<int, string> s_YAxisName = new Dictionary<int, string>();
|
||||
private static Dictionary<string, string> s_AxisLabel = new Dictionary<string, string>();
|
||||
|
||||
|
||||
private static Dictionary<float, Dictionary<string, string>> s_NumberToStr = new Dictionary<float, Dictionary<string, string>>();
|
||||
private static Dictionary<int, Dictionary<string, string>> s_PrecisionToStr = new Dictionary<int, Dictionary<string, string>>();
|
||||
|
||||
public static string FloatToStr(float value, string numericFormatter = "F", int precision = 0)
|
||||
{
|
||||
if (precision > 0 && numericFormatter.Length == 1)
|
||||
{
|
||||
if (!s_PrecisionToStr.ContainsKey(precision))
|
||||
{
|
||||
s_PrecisionToStr[precision] = new Dictionary<string, string>();
|
||||
}
|
||||
if (!s_PrecisionToStr[precision].ContainsKey(numericFormatter))
|
||||
{
|
||||
s_PrecisionToStr[precision][numericFormatter] = numericFormatter + precision;
|
||||
}
|
||||
return NumberToStr(value, s_PrecisionToStr[precision][numericFormatter]);
|
||||
}
|
||||
else
|
||||
{
|
||||
return NumberToStr(value, numericFormatter);
|
||||
}
|
||||
}
|
||||
|
||||
public static string NumberToStr(float value, string formatter)
|
||||
{
|
||||
if (!s_NumberToStr.ContainsKey(value))
|
||||
{
|
||||
s_NumberToStr[value] = new Dictionary<string, string>();
|
||||
}
|
||||
if (!s_NumberToStr[value].ContainsKey(formatter))
|
||||
{
|
||||
if (string.IsNullOrEmpty(formatter))
|
||||
{
|
||||
if (value - (int)value == 0)
|
||||
s_NumberToStr[value][formatter] = ((int)value).ToString();
|
||||
else
|
||||
s_NumberToStr[value][formatter] = value.ToString();
|
||||
}
|
||||
else if (formatter.StartsWith(NUMERIC_FORMATTER_D)
|
||||
|| formatter.StartsWith(NUMERIC_FORMATTER_d)
|
||||
|| formatter.StartsWith(NUMERIC_FORMATTER_X)
|
||||
|| formatter.StartsWith(NUMERIC_FORMATTER_x)
|
||||
)
|
||||
{
|
||||
s_NumberToStr[value][formatter] = ((int)value).ToString(formatter, ci);
|
||||
}
|
||||
else
|
||||
{
|
||||
s_NumberToStr[value][formatter] = value.ToString(formatter, ci);
|
||||
}
|
||||
}
|
||||
return s_NumberToStr[value][formatter];
|
||||
}
|
||||
|
||||
public static string IntToStr(int value, string numericFormatter = "")
|
||||
{
|
||||
return NumberToStr(value, numericFormatter);
|
||||
}
|
||||
|
||||
public static string ColorToStr(Color color)
|
||||
{
|
||||
if (s_ColorToStr.ContainsKey(color))
|
||||
{
|
||||
return s_ColorToStr[color];
|
||||
}
|
||||
else
|
||||
{
|
||||
s_ColorToStr[color] = ColorUtility.ToHtmlStringRGBA(color);
|
||||
return s_ColorToStr[color];
|
||||
}
|
||||
}
|
||||
|
||||
public static string ColorToDotStr(Color color)
|
||||
{
|
||||
if (!s_ColorDotStr.ContainsKey(color))
|
||||
{
|
||||
s_ColorDotStr[color] = "<color=#" + ColorToStr(color) + ">● </color>";
|
||||
}
|
||||
return s_ColorDotStr[color];
|
||||
}
|
||||
|
||||
internal static string GetSerieLabelName(string prefix, int i, int j)
|
||||
{
|
||||
int key = i * 10000000 + j;
|
||||
if (s_SerieLabelName.ContainsKey(key))
|
||||
{
|
||||
return s_SerieLabelName[key];
|
||||
}
|
||||
else
|
||||
{
|
||||
string name = prefix + "_" + i + "_" + j;
|
||||
s_SerieLabelName[key] = name;
|
||||
return name;
|
||||
}
|
||||
}
|
||||
|
||||
internal static string GetXAxisName(int axisIndex, int index = -1)
|
||||
{
|
||||
if (index >= 0)
|
||||
{
|
||||
int key = (axisIndex + 1) * 10000 + index;
|
||||
if (!s_XAxisName.ContainsKey(key))
|
||||
{
|
||||
s_XAxisName[key] = axisIndex > 0 ? s_DefaultAxisX + axisIndex + index : s_DefaultAxisX + index;
|
||||
}
|
||||
return s_XAxisName[key];
|
||||
}
|
||||
else if (!s_XAxisName.ContainsKey(axisIndex))
|
||||
{
|
||||
s_XAxisName[axisIndex] = axisIndex > 0 ? s_DefaultAxisX + axisIndex : s_DefaultAxisX;
|
||||
}
|
||||
return s_XAxisName[axisIndex];
|
||||
}
|
||||
|
||||
internal static string GetYAxisName(int axisIndex, int index = -1)
|
||||
{
|
||||
if (index >= 0)
|
||||
{
|
||||
int key = (axisIndex + 1) * 10000 + index;
|
||||
if (!s_YAxisName.ContainsKey(key))
|
||||
{
|
||||
s_YAxisName[key] = axisIndex > 0 ? s_DefaultAxisY + axisIndex + index : s_DefaultAxisY + index;
|
||||
}
|
||||
return s_YAxisName[key];
|
||||
}
|
||||
else if (!s_YAxisName.ContainsKey(axisIndex))
|
||||
{
|
||||
s_YAxisName[axisIndex] = axisIndex > 0 ? s_DefaultAxisY + axisIndex : s_DefaultAxisY;
|
||||
}
|
||||
return s_YAxisName[axisIndex];
|
||||
}
|
||||
|
||||
internal static string GetAxisTooltipLabel(string axisName)
|
||||
{
|
||||
if (!s_AxisLabel.ContainsKey(axisName))
|
||||
{
|
||||
s_AxisLabel[axisName] = axisName + "_label";
|
||||
}
|
||||
return s_AxisLabel[axisName];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 403191b8caeb44430b89d9f3260c4a76
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,18 @@
|
||||
/************************************************/
|
||||
/* */
|
||||
/* Copyright (c) 2018 - 2021 monitor1394 */
|
||||
/* https://github.com/monitor1394 */
|
||||
/* */
|
||||
/************************************************/
|
||||
|
||||
using UnityEngine;
|
||||
|
||||
namespace XCharts
|
||||
{
|
||||
public static class ChartConst
|
||||
{
|
||||
public static readonly Color32 clearColor32 = new Color32(0, 0, 0, 0);
|
||||
public static readonly Color32 greyColor32 = new Color32(128, 128, 128, 255);
|
||||
public static readonly Color clearColor = Color.clear;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e19d8fc0680be46b5ac9babf7dd9fe27
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,122 @@
|
||||
/************************************************/
|
||||
/* */
|
||||
/* Copyright (c) 2018 - 2021 monitor1394 */
|
||||
/* https://github.com/monitor1394 */
|
||||
/* */
|
||||
/************************************************/
|
||||
|
||||
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using XUGL;
|
||||
|
||||
namespace XCharts
|
||||
{
|
||||
public static class ChartDrawer
|
||||
{
|
||||
public static void DrawSymbol(VertexHelper vh, SerieSymbolType type, float symbolSize,
|
||||
float tickness, Vector3 pos, Color32 color, Color32 toColor, float gap, float[] cornerRadius,
|
||||
Color32 backgroundColor, float smoothness)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case SerieSymbolType.None:
|
||||
break;
|
||||
case SerieSymbolType.Circle:
|
||||
if (gap > 0)
|
||||
{
|
||||
UGL.DrawDoughnut(vh, pos, symbolSize, symbolSize + gap, backgroundColor, backgroundColor, color, smoothness);
|
||||
}
|
||||
else
|
||||
{
|
||||
UGL.DrawCricle(vh, pos, symbolSize, color, toColor, smoothness);
|
||||
}
|
||||
break;
|
||||
case SerieSymbolType.EmptyCircle:
|
||||
if (gap > 0)
|
||||
{
|
||||
UGL.DrawCricle(vh, pos, symbolSize + gap, backgroundColor, smoothness);
|
||||
UGL.DrawEmptyCricle(vh, pos, symbolSize, tickness, color, color, backgroundColor, smoothness);
|
||||
}
|
||||
else
|
||||
{
|
||||
UGL.DrawEmptyCricle(vh, pos, symbolSize, tickness, color, color, backgroundColor, smoothness);
|
||||
}
|
||||
break;
|
||||
case SerieSymbolType.Rect:
|
||||
if (gap > 0)
|
||||
{
|
||||
UGL.DrawSquare(vh, pos, symbolSize + gap, backgroundColor);
|
||||
UGL.DrawSquare(vh, pos, symbolSize, color, toColor);
|
||||
}
|
||||
else
|
||||
{
|
||||
UGL.DrawRoundRectangle(vh, pos, symbolSize, symbolSize, color, color, 0, cornerRadius, true);
|
||||
}
|
||||
break;
|
||||
case SerieSymbolType.Triangle:
|
||||
if (gap > 0)
|
||||
{
|
||||
UGL.DrawTriangle(vh, pos, symbolSize + gap, backgroundColor);
|
||||
UGL.DrawTriangle(vh, pos, symbolSize, color, toColor);
|
||||
}
|
||||
else
|
||||
{
|
||||
UGL.DrawTriangle(vh, pos, symbolSize, color, toColor);
|
||||
}
|
||||
break;
|
||||
case SerieSymbolType.Diamond:
|
||||
if (gap > 0)
|
||||
{
|
||||
UGL.DrawDiamond(vh, pos, symbolSize + gap, backgroundColor);
|
||||
UGL.DrawDiamond(vh, pos, symbolSize, color, toColor);
|
||||
}
|
||||
else
|
||||
{
|
||||
UGL.DrawDiamond(vh, pos, symbolSize, color, toColor);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// public static void DrawLineStyle(VertexHelper vh, LineStyle lineStyle,
|
||||
// Vector3 startPos, Vector3 endPos, Color32 color, float themeWidth)
|
||||
// {
|
||||
// var type = lineStyle.type;
|
||||
// var width = lineStyle.GetWidth(themeWidth);
|
||||
// DrawLineStyle(vh, type, width, startPos, endPos, color);
|
||||
// }
|
||||
|
||||
public static void DrawLineStyle(VertexHelper vh, LineStyle lineStyle,
|
||||
Vector3 startPos, Vector3 endPos, Color32 color, float themeWidth, LineStyle.Type themeType)
|
||||
{
|
||||
var type = lineStyle.GetType(themeType);
|
||||
var width = lineStyle.GetWidth(themeWidth);
|
||||
DrawLineStyle(vh, type, width, startPos, endPos, color);
|
||||
}
|
||||
|
||||
public static void DrawLineStyle(VertexHelper vh, LineStyle.Type lineType, float lineWidth,
|
||||
Vector3 startPos, Vector3 endPos, Color32 color)
|
||||
{
|
||||
switch (lineType)
|
||||
{
|
||||
case LineStyle.Type.Dashed:
|
||||
UGL.DrawDashLine(vh, startPos, endPos, lineWidth, color);
|
||||
break;
|
||||
case LineStyle.Type.Dotted:
|
||||
UGL.DrawDotLine(vh, startPos, endPos, lineWidth, color);
|
||||
break;
|
||||
case LineStyle.Type.Solid:
|
||||
UGL.DrawLine(vh, startPos, endPos, lineWidth, color);
|
||||
break;
|
||||
case LineStyle.Type.DashDot:
|
||||
UGL.DrawDashDotLine(vh, startPos, endPos, lineWidth, color);
|
||||
break;
|
||||
case LineStyle.Type.DashDotDot:
|
||||
UGL.DrawDashDotDotLine(vh, startPos, endPos, lineWidth, color);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 712f08d71f1bf4ab6a1785526bcd5c30
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 47cfa7bd879be4069bd187e46346d73d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in new issue
Block a user