增加TextLimit组件可以设置AxisLabel的文本自适应

This commit is contained in:
monitor1394
2020-01-26 22:34:57 +08:00
parent 8043b116a2
commit 616d63a4de
11 changed files with 252 additions and 8 deletions

View File

@@ -1,6 +1,7 @@
# 更新日志
* (2020.01.26) 增加`TextLimit`组件可以设置`AxisLabel`的文本自适应
* (2020.01.20) 优化`Tooltip`设置`itemFormatter`时显示系列颜色
* (2020.01.20) 增加`Radar`雷达图在`inspector`配置`areaStyle`的支持
* (2020.01.15) 发布`v1.2.0`版本

View File

@@ -42,6 +42,7 @@
* [SerieData 数据项](#SerieData)
* [SerieLabel 图形上的文本标签](#SerieLabel)
* [SerieSymbol 图形标记](#SerieSymbol)
* [TextLimit 文本自适应](#TextLimit)
* [TextStyle 文本样式](#TextStyle)
## `Theme`
@@ -155,6 +156,13 @@
* `min`:指示器的最小值,默认为 0 无限制。
* `textStyle`:文本样式 [TextStyle](#TextStyle)。
## `TextLimit`
* `enable`:是否启用文本自适应。默认为`true`
* `maxWidth`:设定最大宽度。默认为`0`表示自动获取,否则表示自定义。当文本的宽度大于该值进行裁剪。
* `gap`:两边留白像素距离。默认为`10`
* `suffix` 长度超出被裁剪后附加的后缀。默认为`...`
## `TextStyle`
* `rotate`:旋转。
@@ -632,6 +640,7 @@
* `fontStyle`:文字字体的风格。
* `formatter`:图例内容字符串模版格式器。支持用 \n 换行。模板变量为图例名称 {value},支持{value:f0}{value:f1}{value:f2}。
* `forceENotation`是否强制使用科学计数法格式化显示数值。默认为false当小数精度大于3时才采用科学计数法。
* `textLimit`:文本自适应 [TextLimit](#TextLimit)。只在类目轴中有效。
## `AxisLine`

View File

@@ -30,6 +30,7 @@ namespace XCharts
SerializedProperty m_FontSize = prop.FindPropertyRelative("m_FontSize");
SerializedProperty m_FontStyle = prop.FindPropertyRelative("m_FontStyle");
SerializedProperty m_ForceENotation = prop.FindPropertyRelative("m_ForceENotation");
SerializedProperty m_TextLimit = prop.FindPropertyRelative("m_TextLimit");
ChartEditorHelper.MakeFoldout(ref drawRect, ref m_AxisLabelToggle, prop, "Axis Label", show, false);
drawRect.y += EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing;
@@ -54,6 +55,8 @@ namespace XCharts
drawRect.y += EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing;
EditorGUI.PropertyField(drawRect, m_ForceENotation);
drawRect.y += EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing;
EditorGUI.PropertyField(drawRect, m_TextLimit);
drawRect.y += EditorGUI.GetPropertyHeight(m_TextLimit);
--EditorGUI.indentLevel;
}
}
@@ -63,7 +66,8 @@ namespace XCharts
float height = 0;
if (ChartEditorHelper.IsToggle(m_AxisLabelToggle, prop))
{
height += 9 * EditorGUIUtility.singleLineHeight + 10 * EditorGUIUtility.standardVerticalSpacing;
height += 10 * EditorGUIUtility.singleLineHeight + 9 * EditorGUIUtility.standardVerticalSpacing;
height += EditorGUI.GetPropertyHeight(prop.FindPropertyRelative("m_TextLimit"));
}
return height;
}

View File

@@ -0,0 +1,53 @@
/******************************************/
/* */
/* Copyright (c) 2018 monitor1394 */
/* https://github.com/monitor1394 */
/* */
/******************************************/
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
namespace XCharts
{
[CustomPropertyDrawer(typeof(TextLimit), true)]
public class TextLimitDrawer : PropertyDrawer
{
private Dictionary<string, bool> m_TextLimitToggle = new Dictionary<string, bool>();
public override void OnGUI(Rect pos, SerializedProperty prop, GUIContent label)
{
Rect drawRect = pos;
drawRect.height = EditorGUIUtility.singleLineHeight;
SerializedProperty m_Enable = prop.FindPropertyRelative("m_Enable");
SerializedProperty m_MaxWidth = prop.FindPropertyRelative("m_MaxWidth");
SerializedProperty m_Gap = prop.FindPropertyRelative("m_Gap");
SerializedProperty m_LimitSuffix = prop.FindPropertyRelative("m_Suffix");
ChartEditorHelper.MakeFoldout(ref drawRect, ref m_TextLimitToggle, prop, "Text Limit", m_Enable, false);
drawRect.y += EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing;
if (ChartEditorHelper.IsToggle(m_TextLimitToggle, prop))
{
++EditorGUI.indentLevel;
EditorGUI.PropertyField(drawRect, m_MaxWidth);
drawRect.y += EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing;
EditorGUI.PropertyField(drawRect, m_Gap);
drawRect.y += EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing;
EditorGUI.PropertyField(drawRect, m_LimitSuffix);
drawRect.y += EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing;
--EditorGUI.indentLevel;
}
}
public override float GetPropertyHeight(SerializedProperty prop, GUIContent label)
{
float height = 0;
if (ChartEditorHelper.IsToggle(m_TextLimitToggle, prop))
{
height += 3 * EditorGUIUtility.singleLineHeight + 2 * EditorGUIUtility.standardVerticalSpacing;
}
return height;
}
}
}

View File

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

View File

@@ -918,6 +918,7 @@ namespace XCharts
"x1","x2","x3","x4","x5"
}
};
axis.axisLabel.textLimit.enable = true;
return axis;
}
}
@@ -968,6 +969,7 @@ namespace XCharts
m_BoundaryGap = false,
m_Data = new List<string>(5),
};
axis.axisLabel.textLimit.enable = false;
return axis;
}
}

View File

@@ -7,6 +7,7 @@
using System;
using UnityEngine;
using UnityEngine.UI;
namespace XCharts
{
@@ -27,7 +28,7 @@ namespace XCharts
[SerializeField] private int m_FontSize;
[SerializeField] private FontStyle m_FontStyle;
[SerializeField] private bool m_ForceENotation = false;
[SerializeField] private TextLimit m_TextLimit = new TextLimit();
/// <summary>
/// Set this to false to prevent the axis label from appearing.
@@ -78,6 +79,10 @@ namespace XCharts
/// 是否强制使用科学计数法格式化显示数值。默认为false当小数精度大于3时才采用科学计数法。
/// </summary>
public bool forceENotation { get { return m_ForceENotation; } set { m_ForceENotation = value; } }
/// <summary>
/// 文本限制。
/// </summary>
public TextLimit textLimit { get { return m_TextLimit; } }
public static AxisLabel defaultAxisLabel
{
@@ -107,6 +112,7 @@ namespace XCharts
m_FontSize = other.fontSize;
m_FontStyle = other.fontStyle;
m_Formatter = other.formatter;
m_TextLimit.Copy(other.textLimit);
}
public override bool Equals(object obj)
@@ -125,7 +131,8 @@ namespace XCharts
m_FontSize == other.fontSize &&
m_FontStyle == other.fontStyle &&
m_ForceENotation == other.forceENotation &&
m_Formatter == other.formatter;
m_Formatter.Equals(other.formatter) &&
m_TextLimit.Equals(other.textLimit);
}
public override int GetHashCode()
@@ -133,16 +140,24 @@ namespace XCharts
return base.GetHashCode();
}
public void SetRelatedText(Text txt, float labelWidth)
{
m_TextLimit.SetRelatedText(txt,labelWidth);
}
public string GetFormatterContent(string category)
{
if (string.IsNullOrEmpty(category)) return category;
if (string.IsNullOrEmpty(m_Formatter))
return category;
{
return m_TextLimit.GetLimitContent(category);
}
else
{
var content = m_Formatter.Replace("{value}", category);
content = content.Replace("\\n", "\n");
content = content.Replace("<br/>", "\n");
return content;
return m_TextLimit.GetLimitContent(content);
}
}

View File

@@ -0,0 +1,136 @@
/******************************************/
/* */
/* Copyright (c) 2018 monitor1394 */
/* https://github.com/monitor1394 */
/* */
/******************************************/
using System;
using UnityEngine;
using UnityEngine.UI;
namespace XCharts
{
/// <summary>
/// 文本字符限制和自适应。当文本长度超过设定的长度时进行裁剪,并将后缀附加在最后。
/// 只在类目轴中有效。
/// </summary>
[Serializable]
public class TextLimit : SubComponent
{
[SerializeField] private bool m_Enable = true;
[SerializeField] private float m_MaxWidth = 0;
[SerializeField] private float m_Gap = 10;
[SerializeField] private string m_Suffix = "...";
/// <summary>
/// 是否启用文本自适应。默认为true。
/// </summary>
public bool enable { get { return m_Enable; } set { m_Enable = value; } }
/// <summary>
/// 设定最大宽度。默认为0表示自动获取否则表示自定义。当文本的宽度大于该值进行裁剪。
/// </summary>
public float maxWidth { get { return m_MaxWidth; } set { m_MaxWidth = value; } }
/// <summary>
/// 两边留白像素距离。默认为10
/// </summary>
public float gap { get { return m_Gap; } set { m_Gap = value; } }
/// <summary>
/// 长度超出时的后缀。
/// </summary>
public string suffix { get { return m_Suffix; } set { m_Suffix = value; } }
private Text m_RelatedText;
private TextGenerationSettings m_RelatedTextSettings;
private float m_RelatedTextWidth = 0;
public void Copy(TextLimit other)
{
m_Enable = other.enable;
m_Gap = other.gap;
m_Suffix = other.suffix;
m_MaxWidth = other.maxWidth;
}
public override bool Equals(object obj)
{
if (obj == null || GetType() != obj.GetType())
{
return false;
}
var other = (TextLimit)obj;
return m_Enable == other.enable &&
m_MaxWidth == other.maxWidth &&
m_Gap == other.gap &&
m_Suffix.Equals(other.suffix);
}
public override int GetHashCode()
{
return base.GetHashCode();
}
public void SetRelatedText(Text txt, float labelWidth)
{
m_RelatedText = txt;
m_RelatedTextSettings = txt.GetGenerationSettings(Vector2.zero);
m_RelatedTextWidth = labelWidth;
}
public string GetLimitContent(string content)
{
float checkWidth = m_MaxWidth > 0 ? m_MaxWidth : m_RelatedTextWidth;
if (m_RelatedText == null || checkWidth <= 0) return content;
else
{
if (m_Enable)
{
float len = m_RelatedText.cachedTextGenerator.GetPreferredWidth(content, m_RelatedTextSettings);
float suffixLen = m_RelatedText.cachedTextGenerator.GetPreferredWidth(suffix, m_RelatedTextSettings);
if (len > checkWidth - m_Gap * 2 - suffixLen)
{
return content.Substring(0, GetAdaptLength(content, suffixLen)) + suffix;
}
else
{
return content;
}
}
else
{
return content;
}
}
}
private int GetAdaptLength(string content, float suffixLen)
{
int start = 0;
int middle = content.Length / 2;
int end = content.Length;
float checkWidth = m_MaxWidth > 0 ? m_MaxWidth : m_RelatedTextWidth;
float limit = checkWidth - m_Gap * 2 - suffixLen;
if (limit < 0) return 0;
float len = 0;
while (len != limit && middle != start)
{
len = m_RelatedText.cachedTextGenerator.GetPreferredWidth(content.Substring(0, middle), m_RelatedTextSettings);
if (len < limit)
{
start = middle;
}
else if (len > limit)
{
end = middle;
}
else
{
break;
}
middle = (start + end) / 2;
}
return middle;
}
}
}

View File

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

View File

@@ -487,8 +487,9 @@ namespace XCharts
Vector2.zero, new Vector2(1, 0.5f), new Vector2(m_Grid.left, 20),
yAxis.axisLabel.fontSize, yAxis.axisLabel.rotate, yAxis.axisLabel.fontStyle);
}
float labelWidth = yAxis.GetScaleWidth(coordinateHeight, i, m_DataZoom);
float labelWidth = yAxis.GetScaleWidth(coordinateHeight, i, m_DataZoom);
if (i == 0) yAxis.axisLabel.SetRelatedText(txt, labelWidth);
txt.transform.localPosition = GetLabelYPosition(totalWidth + (yAxis.boundaryGap ? labelWidth / 2 : 0), i, yAxisIndex, yAxis);
var isPercentStack = m_Series.IsPercentStack(SerieType.Bar);
@@ -582,12 +583,13 @@ namespace XCharts
m_ThemeInfo.font, labelColor, TextAnchor.MiddleCenter, new Vector2(0, 1),
new Vector2(0, 1), new Vector2(1, 0.5f), new Vector2(labelWidth, 20),
xAxis.axisLabel.fontSize, xAxis.axisLabel.rotate, xAxis.axisLabel.fontStyle);
if (i == 0) xAxis.axisLabel.SetRelatedText(txt, labelWidth);
txt.transform.localPosition = GetLabelXPosition(totalWidth + (xAxis.boundaryGap ? labelWidth : labelWidth / 2),
i, xAxisIndex, xAxis);
totalWidth += labelWidth;
var isPercentStack = m_Series.IsPercentStack(SerieType.Bar);
txt.text = xAxis.GetLabelName(coordinateWidth, i, xAxis.runtimeMinValue, xAxis.runtimeMaxValue, m_DataZoom, isPercentStack);
txt.text = xAxis.GetLabelName(coordinateWidth, i, xAxis.runtimeMinValue, xAxis.runtimeMaxValue, m_DataZoom,
isPercentStack);
txt.gameObject.SetActive(xAxis.show &&
(xAxis.axisLabel.interval == 0 || i % (xAxis.axisLabel.interval + 1) == 0));
xAxis.axisLabelTextList.Add(txt);

Binary file not shown.

After

Width:  |  Height:  |  Size: 95 KiB