I have created a custom control to show a graph with Axis labels and tickmarks. The Tickmarks and numbers are generated automatically and have absolute values set with percentages, so that they should be in line with the markings. The layout code looks like this:
style.flexGrow = 0;
style.paddingRight = 10;
plotTitle = new Label("Plot Title") { name = "PlotTitel" };
plotTitle.style.unityTextAlign = TextAnchor.MiddleCenter;
plotTitle.style.unityFontStyleAndWeight = FontStyle.Bold;
plotTitle.style.fontSize = 19;
Add(plotTitle);
plotArea = new VisualElement() { name = "PlotArea" };
plotArea.style.flexDirection = FlexDirection.Row;
plotArea.style.flexGrow = 1;
Add(plotArea);
yArea = new VisualElement() { name = "YArea" };
yArea.style.width = 55;
plotArea.Add(yArea);
yLabels = new VisualElement() { name = "YLabels" };
yLabels.style.flexGrow = 1;
yLabels.style.flexDirection = FlexDirection.Row;
yArea.Add(yLabels);
VisualElement corner = new VisualElement() { name = "Corner" };
corner.style.height = 35;
yArea.Add(corner);
yAxisLabel = new Label("Y Axis") { name = "YAxisLabel" };
yAxisLabel.style.width = 20;
yAxisLabel.style.unityTextAlign = TextAnchor.MiddleCenter;
yAxisLabel.transform.rotation = Quaternion.Euler(0, 0, -90);
yLabels.Add(yAxisLabel);
yTicks = new VisualElement() { name = "YTicks" };
yTicks.style.width = 30;
yTicks.style.justifyContent = Justify.SpaceBetween;
yLabels.Add(yTicks);
yTickMarks = new VisualElement() { name = "YTickMarks" };
yTickMarks.style.width = 5;
yLabels.Add(yTickMarks);
plotContainer = new VisualElement() { name = "PlotContainer" };
plotContainer.style.flexGrow = 1;
plotArea.Add(plotContainer);
visualizerPlot = new VisualElement() { name = "VisualizerPlot" };
visualizerPlot.style.flexGrow = 1;
visualizerPlot.style.borderTopWidth = 2;
visualizerPlot.style.borderRightWidth = 2;
visualizerPlot.style.borderBottomWidth = 2;
visualizerPlot.style.borderLeftWidth = 2;
visualizerPlot.AddToClassList("boarderColor");
plotContainer.Add(visualizerPlot);
xArea = new VisualElement() { name = "XArea" };
xArea.style.height = 35;
plotContainer.Add(xArea);
xTickMarks = new VisualElement() { name = "XTickMarks" };
xTickMarks.style.flexDirection = FlexDirection.Row;
xTickMarks.style.height = 5;
xArea.Add(xTickMarks);
xTicks = new VisualElement() { name = "XTicks" };
xTicks.style.flexDirection = FlexDirection.Row;
xTicks.style.justifyContent = Justify.SpaceBetween;
xTicks.style.height = 10;
xArea.Add(xTicks);
xAxisLabel = new Label("X Axis") { name = "XAxisLabel" };
xAxisLabel.style.unityTextAlign = TextAnchor.MiddleCenter;
xAxisLabel.style.height = 20;
xAxisLabel.style.marginTop = 0;
xAxisLabel.style.marginBottom = 0;
xAxisLabel.style.paddingTop = 0;
xAxisLabel.style.paddingBottom = 0;
xArea.Add(xAxisLabel);
RegisterCallback<GeometryChangedEvent>(OnGeometryChanged);
}
public void SetUpControl(PlotVisualizerBase plotVisualizer)
{
plotTitle.text = plotVisualizer.title;
xAxisLabel.text = plotVisualizer.xAxis;
yAxisLabel.text = plotVisualizer.yAxis;
m_xTicksCount = plotVisualizer.numTicksX;
m_minX = plotVisualizer.xAxisInterval.x;
m_maxX = plotVisualizer.xAxisInterval.y;
m_yTicksCount = plotVisualizer.numTicksY;
m_minY = plotVisualizer.yAxisInterval.x;
m_maxY = plotVisualizer.yAxisInterval.y;
visualizerPlot.style.backgroundImage = new StyleBackground(Background.FromRenderTexture(plotVisualizer.plotTexture));
CreatePlotGrid();
CreateXTicks();
CreateYTicks();
}
private void CreateXTicks()
{
xTicks.Clear();
for (int i = 0; i <= m_xTicksCount; i++)
{
Label tick = new Label() { name = "tick" };
tick.text = (m_minX + i * (m_maxX - minX) / m_xTicksCount).ToString("F2");
tick.style.position = Position.Absolute;
float xPos = (i / (float)m_xTicksCount) * 100f;
tick.style.left = Length.Percent(xPos);
tick.style.translate = new Translate(Length.Percent(-50), 0, 0);
tick.style.fontSize = 10;
xTicks.Add(tick);
}
}
private void CreateYTicks()
{
yTicks.Clear();
for (int i = 0; i <= m_yTicksCount; i++)
{
Label tick = new Label() { name = "tick" };
tick.text = (m_maxY - i * (m_maxY - m_minY) / m_yTicksCount).ToString("F2");
tick.style.position = Position.Absolute;
float yPos = (i / (float)m_yTicksCount) * 100f;
tick.style.top = Length.Percent(yPos);
tick.style.width = new Length(30);
tick.style.translate = new Translate(0, Length.Percent(-50), 0);
tick.style.unityTextAlign = TextAnchor.MiddleRight;
tick.style.fontSize = 10;
yTicks.Add(tick);
}
}
private void CreatePlotGrid()
{
visualizerPlot.Clear();
for (int i = 0; i < m_yTicksCount; i++)
{
VisualElement rowElement = new VisualElement();
rowElement.style.flexDirection = FlexDirection.Row;
rowElement.style.flexGrow = 1;
if (i < m_yTicksCount - 1)
{
rowElement.style.borderBottomWidth = 1;
rowElement.AddToClassList("boarderColor");
}
for (int j = 0; j < m_xTicksCount; j++)
{
VisualElement gridElement = new VisualElement();
gridElement.style.flexGrow = 1;
if (j < m_xTicksCount - 1)
{
gridElement.style.borderRightWidth = 1;
gridElement.AddToClassList("boarderColor");
}
rowElement.Add(gridElement);
}
visualizerPlot.Add(rowElement);
}
}
private void OnGeometryChanged(GeometryChangedEvent evt)
{
visualizerPlot.style.height = visualizerPlot.resolvedStyle.width;
}
So if i use this control in an editor it looks good and the numbers are next to the lines for the graph.
But if i use it for a runtime UI the absolute values of the numbers behave different and they are not in line any more, even tho the values are in percentage and the same when i look with the debugger.
In the Inspector
In my Runtime UI
Pannelsettings
Unity Version 2023.2.20f1
Thanks in Advance
Sascha