mirror of
https://github.com/XCharts-Team/XCharts.git
synced 2026-05-28 20:28:46 +00:00
增加LabelStyle的showCondition,showFilter,showThreshold可控制label显示和隐藏
This commit is contained in:
@@ -81,6 +81,7 @@ slug: /changelog
|
|||||||
|
|
||||||
## master
|
## master
|
||||||
|
|
||||||
|
* (2026.05.22) 增加`LabelStyle`的`showCondition`,`showFilter`,`showThreshold`可控制`label`显示和隐藏
|
||||||
* (2026.05.22) 增加`LabelStyle`的`minGap`可避免`label`过于密集
|
* (2026.05.22) 增加`LabelStyle`的`minGap`可避免`label`过于密集
|
||||||
* (2026.05.17) 修复`DataZoom`点击时指示区域不准的问题
|
* (2026.05.17) 修复`DataZoom`点击时指示区域不准的问题
|
||||||
* (2026.05.17) 增加`Legend`的`Width`和`Height`可设置固定宽高
|
* (2026.05.17) 增加`Legend`的`Width`和`Height`可设置固定宽高
|
||||||
|
|||||||
@@ -113,6 +113,15 @@ namespace XCharts.Editor
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void PropertyFlagsField(SerializedProperty prop, string relativePropName, System.Type enumType)
|
||||||
|
{
|
||||||
|
if (IngorePropertys.Contains(relativePropName)) return;
|
||||||
|
if (!ChartEditorHelper.PropertyFlagsField(ref m_DrawRect, m_Heights, m_KeyName, prop, relativePropName, enumType))
|
||||||
|
{
|
||||||
|
Debug.LogError("PropertyFlagsField ERROR:" + prop.displayName + ", " + relativePropName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected void PropertyFieldLimitMin(SerializedProperty prop, string relativePropName, float minValue)
|
protected void PropertyFieldLimitMin(SerializedProperty prop, string relativePropName, float minValue)
|
||||||
{
|
{
|
||||||
if (IngorePropertys.Contains(relativePropName)) return;
|
if (IngorePropertys.Contains(relativePropName)) return;
|
||||||
|
|||||||
@@ -26,7 +26,10 @@ namespace XCharts.Editor
|
|||||||
PropertyField(prop, "m_Height");
|
PropertyField(prop, "m_Height");
|
||||||
PropertyField(prop, "m_FixedX");
|
PropertyField(prop, "m_FixedX");
|
||||||
PropertyField(prop, "m_FixedY");
|
PropertyField(prop, "m_FixedY");
|
||||||
PropertyField(prop, "m_MinGap");
|
PropertyField(prop, "m_ShowCondition");
|
||||||
|
PropertyField(prop, "m_ShowFilter");
|
||||||
|
PropertyField(prop, "m_ShowThreshold");
|
||||||
|
PropertyField(prop, "m_ShowMinGap");
|
||||||
PropertyField(prop, "m_Icon");
|
PropertyField(prop, "m_Icon");
|
||||||
PropertyField(prop, "m_Background");
|
PropertyField(prop, "m_Background");
|
||||||
PropertyField(prop, "m_TextStyle");
|
PropertyField(prop, "m_TextStyle");
|
||||||
|
|||||||
@@ -507,6 +507,28 @@ namespace XCharts.Editor
|
|||||||
{
|
{
|
||||||
return PropertyField(ref drawRect, heights, key, parentProp.FindPropertyRelative(relativeName));
|
return PropertyField(ref drawRect, heights, key, parentProp.FindPropertyRelative(relativeName));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static bool PropertyFlagsField(ref Rect drawRect, Dictionary<string, float> heights, string key,
|
||||||
|
SerializedProperty parentProp, string relativeName, System.Type enumType)
|
||||||
|
{
|
||||||
|
return PropertyFlagsField(ref drawRect, heights, key, parentProp.FindPropertyRelative(relativeName), enumType);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool PropertyFlagsField(ref Rect drawRect, Dictionary<string, float> heights, string key,
|
||||||
|
SerializedProperty prop, System.Type enumType)
|
||||||
|
{
|
||||||
|
if (prop == null) return false;
|
||||||
|
var label = GetContent(prop.displayName);
|
||||||
|
var enumValue = (System.Enum)System.Enum.ToObject(enumType, prop.intValue);
|
||||||
|
EditorGUI.BeginChangeCheck();
|
||||||
|
var newValue = EditorGUI.EnumFlagsField(drawRect, label, enumValue);
|
||||||
|
if (EditorGUI.EndChangeCheck())
|
||||||
|
prop.intValue = (int)(object)newValue;
|
||||||
|
var hig = EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing;
|
||||||
|
drawRect.y += hig;
|
||||||
|
heights[key] += hig;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
public static bool PropertyFieldWithMinValue(ref Rect drawRect, Dictionary<string, float> heights, string key,
|
public static bool PropertyFieldWithMinValue(ref Rect drawRect, Dictionary<string, float> heights, string key,
|
||||||
SerializedProperty parentProp, string relativeName, float minValue)
|
SerializedProperty parentProp, string relativeName, float minValue)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -68,6 +68,50 @@ namespace XCharts.Runtime
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
End
|
End
|
||||||
}
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// The value-based condition for showing label. Controls visibility based on threshold comparison.
|
||||||
|
/// ||标签基于值的显示条件,通过与阈值比较来控制标签的显示。
|
||||||
|
/// </summary>
|
||||||
|
public enum ShowCondition
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Always show label.
|
||||||
|
/// ||总是显示标签。
|
||||||
|
/// </summary>
|
||||||
|
Always,
|
||||||
|
/// <summary>
|
||||||
|
/// Show label when value is greater than showThreshold.
|
||||||
|
/// ||大于showThreshold才显示标签。
|
||||||
|
/// </summary>
|
||||||
|
GreaterThan,
|
||||||
|
/// <summary>
|
||||||
|
/// Show label when value is less than showThreshold.
|
||||||
|
/// ||小于showThreshold才显示标签。
|
||||||
|
/// </summary>
|
||||||
|
LessThan,
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// The data-pattern-based filter for showing label. Controls visibility based on data topology.
|
||||||
|
/// ||标签基于数据形态的显示筛选,通过数据的拓扑特征(波峰/波谷)来控制标签的显示。
|
||||||
|
/// </summary>
|
||||||
|
public enum ShowFilter
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// All data points show label.
|
||||||
|
/// ||所有数据点都显示标签。
|
||||||
|
/// </summary>
|
||||||
|
All,
|
||||||
|
/// <summary>
|
||||||
|
/// Show label when value is at a peak.
|
||||||
|
/// ||波峰才显示标签。
|
||||||
|
/// </summary>
|
||||||
|
Peak,
|
||||||
|
/// <summary>
|
||||||
|
/// Show label when value is at a valley.
|
||||||
|
/// ||波谷才显示标签。
|
||||||
|
/// </summary>
|
||||||
|
Valley
|
||||||
|
}
|
||||||
|
|
||||||
[SerializeField] protected bool m_Show = true;
|
[SerializeField] protected bool m_Show = true;
|
||||||
[SerializeField] Position m_Position = Position.Default;
|
[SerializeField] Position m_Position = Position.Default;
|
||||||
@@ -82,7 +126,10 @@ namespace XCharts.Runtime
|
|||||||
[SerializeField] protected float m_Height = 0;
|
[SerializeField] protected float m_Height = 0;
|
||||||
[SerializeField][Since("v3.15.0")] protected float m_FixedX = 0;
|
[SerializeField][Since("v3.15.0")] protected float m_FixedX = 0;
|
||||||
[SerializeField][Since("v3.15.0")] protected float m_FixedY = 0;
|
[SerializeField][Since("v3.15.0")] protected float m_FixedY = 0;
|
||||||
[SerializeField][Since("v3.16.0")] protected float m_MinGap = 0;
|
[SerializeField][Since("v3.16.0")] protected ShowCondition m_ShowCondition = ShowCondition.Always;
|
||||||
|
[SerializeField][Since("v3.16.0")] protected ShowFilter m_ShowFilter = ShowFilter.All;
|
||||||
|
[SerializeField][Since("v3.16.0")] protected double m_ShowThreshold = 0;
|
||||||
|
[SerializeField][Since("v3.16.0")] protected float m_ShowMinGap = 0;
|
||||||
|
|
||||||
[SerializeField] protected IconStyle m_Icon = new IconStyle();
|
[SerializeField] protected IconStyle m_Icon = new IconStyle();
|
||||||
[SerializeField] protected ImageStyle m_Background = new ImageStyle();
|
[SerializeField] protected ImageStyle m_Background = new ImageStyle();
|
||||||
@@ -101,6 +148,9 @@ namespace XCharts.Runtime
|
|||||||
m_Height = 0;
|
m_Height = 0;
|
||||||
m_NumericFormatter = "";
|
m_NumericFormatter = "";
|
||||||
m_AutoOffset = false;
|
m_AutoOffset = false;
|
||||||
|
m_ShowCondition = ShowCondition.Always;
|
||||||
|
m_ShowFilter = ShowFilter.All;
|
||||||
|
m_ShowThreshold = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -309,14 +359,45 @@ namespace XCharts.Runtime
|
|||||||
set { if (PropertyUtil.SetStruct(ref m_FixedY, value)) SetComponentDirty(); }
|
set { if (PropertyUtil.SetStruct(ref m_FixedY, value)) SetComponentDirty(); }
|
||||||
}
|
}
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
/// The value-based show condition of label. Default is ShowCondition.Always.
|
||||||
|
/// When set to GreaterThan or LessThan, the label is shown only when the value satisfies the threshold.
|
||||||
|
/// ||标签基于值的显示条件。默认为ShowCondition.Always,总是显示。
|
||||||
|
/// 设为GreaterThan或LessThan时,只有满足showThreshold阈值条件的数据点才显示标签。
|
||||||
|
/// </summary>
|
||||||
|
public ShowCondition showCondition
|
||||||
|
{
|
||||||
|
get { return m_ShowCondition; }
|
||||||
|
set { if (PropertyUtil.SetStruct(ref m_ShowCondition, value)) SetComponentDirty(); }
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// The data-pattern-based show filter of label. Default is ShowFilter.All.
|
||||||
|
/// When set to Peak or Valley, the label is shown only at local maximum or minimum data points.
|
||||||
|
/// ||标签基于数据形态的显示筛选。默认为ShowFilter.All,所有数据点都显示。
|
||||||
|
/// 设为Peak或Valley时,只在局部波峰或波谷的数据点显示标签。
|
||||||
|
/// </summary>
|
||||||
|
public ShowFilter showFilter
|
||||||
|
{
|
||||||
|
get { return m_ShowFilter; }
|
||||||
|
set { if (PropertyUtil.SetStruct(ref m_ShowFilter, value)) SetComponentDirty(); }
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// The threshold for showCondition. When showCondition is GreaterThan or LessThan, only values that satisfy the comparison will show label. Default is 0.
|
||||||
|
/// ||showCondition的阈值。当showCondition为GreaterThan或LessThan时生效,只有满足比较条件的值才显示标签。默认值为0。
|
||||||
|
/// </summary>
|
||||||
|
public double showThreshold
|
||||||
|
{
|
||||||
|
get { return m_ShowThreshold; }
|
||||||
|
set { if (PropertyUtil.SetStruct(ref m_ShowThreshold, value)) SetComponentDirty(); }
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
/// the gap between label and the previous label. When the distance to the previous label is less than this value,
|
/// the gap between label and the previous label. When the distance to the previous label is less than this value,
|
||||||
/// the label with smaller y value will be hidden. Default is 0, which means this function is turned off.
|
/// the label with smaller y value will be hidden. Default is 0, which means this function is turned off.
|
||||||
/// 和上一个标签的最小间距。当和上一个标签的距离小于该值时,隐藏对应y值较小的标签。默认为0不开启该功能。
|
/// 和上一个标签的最小间距。当和上一个标签的距离小于该值时,隐藏对应y值较小的标签。默认为0不开启该功能。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public float minGap
|
public float showMinGap
|
||||||
{
|
{
|
||||||
get { return m_MinGap; }
|
get { return m_ShowMinGap; }
|
||||||
set { if (PropertyUtil.SetStruct(ref m_MinGap, value)) SetComponentDirty(); }
|
set { if (PropertyUtil.SetStruct(ref m_ShowMinGap, value)) SetComponentDirty(); }
|
||||||
}
|
}
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// the sytle of background.
|
/// the sytle of background.
|
||||||
|
|||||||
@@ -546,6 +546,7 @@ namespace XCharts.Runtime
|
|||||||
currLabel, color, chart);
|
currLabel, color, chart);
|
||||||
var offset = GetSerieDataLabelOffset(serieData, currLabel);
|
var offset = GetSerieDataLabelOffset(serieData, currLabel);
|
||||||
var active = currLabel.show && !isIgnore && !serie.IsMinShowLabelValue(value);
|
var active = currLabel.show && !isIgnore && !serie.IsMinShowLabelValue(value);
|
||||||
|
if (active) active = CheckLabelVisible(currLabel, serieData.index, value, i);
|
||||||
if (active)
|
if (active)
|
||||||
{
|
{
|
||||||
anyLabelActive = true;
|
anyLabelActive = true;
|
||||||
@@ -577,10 +578,11 @@ namespace XCharts.Runtime
|
|||||||
currLabel, color, chart);
|
currLabel, color, chart);
|
||||||
var labelPos = UpdateLabelPosition(serieData, currLabel);
|
var labelPos = UpdateLabelPosition(serieData, currLabel);
|
||||||
var active = currLabel.show && !isIgnore && !serie.IsMinShowLabelValue(value);
|
var active = currLabel.show && !isIgnore && !serie.IsMinShowLabelValue(value);
|
||||||
if (active && currLabel.minGap > 0 && lastActiveLabelSerieData != null)
|
if (active) active = CheckLabelVisible(currLabel, serieData.index, value, defaultDimension);
|
||||||
|
if (active && currLabel.showMinGap > 0 && lastActiveLabelSerieData != null)
|
||||||
{
|
{
|
||||||
var dist = Mathf.Abs(labelPos.x - lastActiveLabelPos.x);
|
var dist = Mathf.Abs(labelPos.x - lastActiveLabelPos.x);
|
||||||
if (dist < currLabel.minGap)
|
if (dist < currLabel.showMinGap)
|
||||||
{
|
{
|
||||||
var currValue = serieData.GetData(1);
|
var currValue = serieData.GetData(1);
|
||||||
if (Math.Abs(currValue) >= Math.Abs(lastActiveLabelValue))
|
if (Math.Abs(currValue) >= Math.Abs(lastActiveLabelValue))
|
||||||
@@ -641,6 +643,66 @@ namespace XCharts.Runtime
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private bool CheckLabelVisible(LabelStyle label, int dataIndex, double value, int dimension)
|
||||||
|
{
|
||||||
|
// showCondition: 基于阈值的条件检查(AND showFilter)
|
||||||
|
bool conditionResult;
|
||||||
|
switch (label.showCondition)
|
||||||
|
{
|
||||||
|
case LabelStyle.ShowCondition.GreaterThan:
|
||||||
|
conditionResult = value > label.showThreshold;
|
||||||
|
break;
|
||||||
|
case LabelStyle.ShowCondition.LessThan:
|
||||||
|
conditionResult = value < label.showThreshold;
|
||||||
|
break;
|
||||||
|
default: // Always
|
||||||
|
conditionResult = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!conditionResult)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// showFilter: 基于数据形态的过滤检查
|
||||||
|
switch (label.showFilter)
|
||||||
|
{
|
||||||
|
case LabelStyle.ShowFilter.Peak:
|
||||||
|
{
|
||||||
|
bool isPeak = true;
|
||||||
|
bool hasNeighbor = false;
|
||||||
|
if (dataIndex > 0)
|
||||||
|
{
|
||||||
|
hasNeighbor = true;
|
||||||
|
isPeak &= value > serie.data[dataIndex - 1].GetData(dimension);
|
||||||
|
}
|
||||||
|
if (dataIndex < serie.dataCount - 1)
|
||||||
|
{
|
||||||
|
hasNeighbor = true;
|
||||||
|
isPeak &= value > serie.data[dataIndex + 1].GetData(dimension);
|
||||||
|
}
|
||||||
|
return isPeak && hasNeighbor;
|
||||||
|
}
|
||||||
|
case LabelStyle.ShowFilter.Valley:
|
||||||
|
{
|
||||||
|
bool isValley = true;
|
||||||
|
bool hasNeighbor = false;
|
||||||
|
if (dataIndex > 0)
|
||||||
|
{
|
||||||
|
hasNeighbor = true;
|
||||||
|
isValley &= value < serie.data[dataIndex - 1].GetData(dimension);
|
||||||
|
}
|
||||||
|
if (dataIndex < serie.dataCount - 1)
|
||||||
|
{
|
||||||
|
hasNeighbor = true;
|
||||||
|
isValley &= value < serie.data[dataIndex + 1].GetData(dimension);
|
||||||
|
}
|
||||||
|
return isValley && hasNeighbor;
|
||||||
|
}
|
||||||
|
default: // All
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public virtual void RefreshEndLabelInternal()
|
public virtual void RefreshEndLabelInternal()
|
||||||
{
|
{
|
||||||
if (m_EndLabel == null)
|
if (m_EndLabel == null)
|
||||||
|
|||||||
Reference in New Issue
Block a user