実現したいこと
タイトルの通りですが、通常はY軸の左右どちらかに出る軸ラベルを軸の真上に描きたい。
発生している問題・分からないこと
複数のY軸が存在している場合にその座標の取り方がわからない。
具体的な描画の仕方も。
該当のソースコード
特になし
試したこと・調べたこと
- teratailやGoogle等で検索した
- ソースコードを自分なりに変更した
- 知人に聞いた
- その他
上記の詳細・結果
生成AI(chatGPTやgemini)に訊いても、やたらと存在しないAPIを使ったり、変な位置に表示したり、何も表示できなかったりで解決できなかった。
どうも、Y軸の真上はY軸の担当描画エリア外らしく、工夫が必要らしい、というところまではわかりました。
補足
特になし
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
回答1件
0
通常はY軸の左右どちらかに出る軸ラベルを軸の真上に描きたい。
ラベルを目盛りに重ねるって意味ですよね?見にくくないですか?(余計なお世話か^^;
Custom Axisを作れば、どうとでも描画できそうです。
ScottPlot5 WinForms Demo
ScottPlot5 WinForms Demo/Demos/CustomAxis.cs at main · ScottPlot/ScottPlot
ただ実際どうやるかは、既存実装を参考にしながら試行錯誤が必要そうです。
YAxisBase.cs at main · ScottPlot/ScottPlot
AxisBase.cs at main · ScottPlot/ScottPlot
FloatingAxisでよければリフレクションでごまかせましたが、残念ながら端に寄せるとはみ出た部分が消えますorz
cs
1using System.Reflection; 2using ScottPlot; 3using ScottPlot.AxisPanels; 4using ScottPlot.Plottables; 5using ScottPlot.WinForms; 6 7namespace Qa3g98l2vj841kv; 8 9public partial class Form1 : Form 10{ 11 public Form1() 12 { 13 InitializeComponent(); 14 15 var formsPlot1 = new FormsPlot { Dock = DockStyle.Fill, Parent = this, }; 16 17 // カスタムAxesに入れ替える 18 formsPlot1.Plot.Axes.Remove(formsPlot1.Plot.Axes.Left); 19 formsPlot1.Plot.Axes.AddLeftAxis(new CenterTickLabelYAxis(Edge.Left)); 20 21 var sig1 = formsPlot1.Plot.Add.Signal(Generate.Sin(mult: 0.01)); 22 sig1.Axes.YAxis = formsPlot1.Plot.Axes.Left; 23 formsPlot1.Plot.Axes.Left.Label.Text = "Left Axis"; 24 formsPlot1.Plot.Axes.Left.Label.ForeColor = sig1.Color; 25 26 27 formsPlot1.Plot.Axes.Remove(formsPlot1.Plot.Axes.Right); 28 formsPlot1.Plot.Axes.AddRightAxis(new CenterTickLabelYAxis(Edge.Right)); 29 30 var sig2 = formsPlot1.Plot.Add.Signal(Generate.Cos(mult: 100)); 31 sig2.Axes.YAxis = formsPlot1.Plot.Axes.Right; 32 formsPlot1.Plot.Axes.Right.Label.Text = "Right Axis"; 33 formsPlot1.Plot.Axes.Right.Label.ForeColor = sig2.Color; 34 35 36 // FloatingAxisでよければリフレクションでごまかせるが... 37 var floatingY = new FloatingAxis(formsPlot1.Plot.Axes.Left) 38 { 39 // 残念ながら端に寄せるとはみ出た部分が消えるorz 40 //Position = 0, 41 }; 42 formsPlot1.Plot.Add.Plottable(floatingY); 43 44 var labelStyle = (LabelStyle)floatingY.GetType() 45 .GetProperty("TickLabelStyle", BindingFlags.NonPublic | BindingFlags.Instance)! 46 .GetValue(floatingY)!; 47 labelStyle.Alignment = Alignment.MiddleCenter; 48 } 49} 50 51// カスタムAxes(Y軸専用) 52internal class CenterTickLabelYAxis : YAxisBase 53{ 54 public override Edge Edge { get; } 55 56 public CenterTickLabelYAxis(Edge edge) 57 { 58 if (edge != Edge.Left && edge != Edge.Right) throw new InvalidOperationException(); 59 60 Edge = edge; 61 TickGenerator = new ScottPlot.TickGenerators.NumericAutomatic(); 62 LabelRotation = edge == Edge.Left ? -90 : 90; 63 } 64 65 public override float Measure(Paint paint) 66 { 67 if (!IsVisible) return 0; 68 if (!Range.HasBeenSet) return SizeWhenNoData; 69 70 float maxTickLabelWidth = TickGenerator.Ticks.Length > 0 71 ? TickGenerator.Ticks.Select(x => TickLabelStyle.Measure(x.Label, paint).Width).Max() 72 : 0; 73 74 // 軸上にラベルを表示するのでPaddingBetweenTickAndAxisLabelsは不要 75 //float axisLabelHeight = string.IsNullOrEmpty(LabelStyle.Text) && LabelStyle.Image is null 76 // ? EmptyLabelPadding.Horizontal 77 // : LabelStyle.Measure(LabelText, paint).Height 78 // + PaddingBetweenTickAndAxisLabels.Horizontal 79 // + PaddingOutsideAxisLabels.Horizontal; 80 float axisLabelHeight = string.IsNullOrEmpty(LabelStyle.Text) && LabelStyle.Image is null 81 ? EmptyLabelPadding.Horizontal 82 : LabelStyle.Measure(LabelText, paint).Height 83 //+ PaddingBetweenTickAndAxisLabels.Horizontal 84 + PaddingOutsideAxisLabels.Horizontal; 85 86 // ラベルが軸の反対側に半分出るので1/2 87 //return maxTickLabelWidth + axisLabelHeight; 88 return maxTickLabelWidth / 2 + axisLabelHeight; 89 } 90 91 public override void Render(RenderPack rp, float size, float offset) 92 { 93 if (!IsVisible) return; 94 95 PixelRect panelRect = GetPanelRect(rp.DataRect, size, offset, rp.Paint); 96 float x = Edge == Edge.Left 97 ? panelRect.Left + PaddingOutsideAxisLabels.Horizontal 98 : panelRect.Right - PaddingOutsideAxisLabels.Horizontal; 99 Pixel labelPoint = new(x, rp.DataRect.VerticalCenter); 100 101 LabelAlignment = Alignment.UpperCenter; 102 LabelStyle.Render(rp.Canvas, labelPoint, rp.Paint); 103 104 //DrawTicks(rp, TickLabelStyle, panelRect, TickGenerator.Ticks, this, MajorTickStyle, MinorTickStyle); 105 DrawTicks2(rp, TickLabelStyle, panelRect, TickGenerator.Ticks, this, MajorTickStyle, MinorTickStyle); 106 107 DrawFrame(rp, panelRect, Edge, FrameLineStyle); 108 } 109 110 private static void DrawTicks2(RenderPack rp, LabelStyle label, PixelRect panelRect, IEnumerable<Tick> ticks, IAxis axis, TickMarkStyle majorStyle, TickMarkStyle minorStyle) 111 { 112 Paint paint = rp.Paint; 113 114 foreach (Tick tick in ticks) 115 { 116 paint.Color = tick.IsMajor ? majorStyle.Color : minorStyle.Color; 117 paint.StrokeWidth = tick.IsMajor ? majorStyle.Width : minorStyle.Width; 118 paint.IsAntialias = tick.IsMajor ? majorStyle.AntiAlias : minorStyle.AntiAlias; 119 float tickLength = tick.IsMajor ? majorStyle.Length : minorStyle.Length; 120 float yPx = axis.GetPixel(tick.Position, panelRect); 121 float x = axis.Edge == Edge.Left ? panelRect.Right : panelRect.Left; 122 //float xEdge = axis.Edge == Edge.Left ? x - tickLength : x + tickLength; 123 124 // 左右にtickLength分の線を引く 125 //PixelLine pxLine = new(x, yPx, xEdge, yPx); 126 PixelLine pxLine = new(x - tickLength, yPx, x + tickLength, yPx); 127 128 var lineStyle = tick.IsMajor ? majorStyle : minorStyle; 129 lineStyle.Render(rp.Canvas, paint, pxLine); 130 131 if (string.IsNullOrWhiteSpace(tick.Label) || !label.IsVisible) continue; 132 label.Text = tick.Label; 133 //float pxDistanceFromTick = 5; 134 //float pxDistanceFromEdge = tickLength + pxDistanceFromTick; 135 136 // 軸に重ねるので余計なオフセット計算なし 137 //float xPx = axis.Edge == Edge.Left ? x - pxDistanceFromEdge : x + pxDistanceFromEdge; 138 float xPx = x; 139 140 Pixel px = new(xPx, yPx); 141 if (label.Rotation == 0) 142 { 143 // 何も気にせずMiddleCenterに描く 144 //label.Alignment = axis.Edge == Edge.Left ? Alignment.MiddleRight : Alignment.MiddleLeft; 145 label.Alignment = Alignment.MiddleCenter; 146 } 147 label.Render(rp.Canvas, px, paint); 148 } 149 } 150}
投稿2026/01/30 12:03
総合スコア10225
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
