簡體   English   中英

如何圍繞圓圈定位標簽?

[英]How to position labels around circle?

我正在試圖弄清楚如何計算圓周圍的文字標簽的位置。 這比你第一次閱讀時想象的要復雜得多。

我得到了基礎知識:

X = ptCenter.X + (dRadius * Math.Cos(dAngle * Math.PI / 180.0))
Y = ptCenter.Y + (dRadius * Math.Sin(dAngle * Math.PI / 180.0))

那么,這將給出我在圓角dAngle與半徑dRadius的關鍵點。 當然,DrawText(任何種類,但我特別使用DrawingContext.DrawText,如果這對你的答案有任何不同)繪制時給定的點作為文本的左上角。

問題是,這不是繪制文本的正確位置。 以下是該問題的說明:

https://support.office.com/en-us/article/Present-your-data-in-a-radar-chart-16e20279-eed4-43c2-9bf5-29ff9b10601d

Jan水平居中於點2月從左下角繪制,而Mar似乎是水平中間的那種4月垂直居中等等。

標簽不是以統一的方式定位在點周圍。 它取決於你繪制的角度。

我需要繪制的標簽數量可能會有所不同,因此硬編碼軟糖因素已經出來了。 我需要繪制的角度也可以變化,因此也沒有任何軟糖因素。 所有這一切都必須在飛行中計算。

看起來好像0,90,180,270是特殊情況,而其他似乎是在點周圍垂直半中心,但根據你所談論的圓圈的哪一邊向右或向左繪制?

我在這里走在正確的軌道上嗎? 或者是否有“已知”算法?

謝謝。

你是對的,問題並不像它看起來那么簡單。 用鉛筆和紙坐下后,我認為問題可以解決為更簡單的步驟:

在此輸入圖像描述

  1. 確定圓的尺寸和所需的邊距(在圖像上:藍色虛線圓圈)。
  2. 確定標簽文本的大小(在圖像上:標簽周圍的黑框)。
  3. 確定應該觸摸藍色虛線圓圈的(黑色)標簽文本框架上的點。 對於每個維度(X,Y)分別:
    • 如果文本標簽的中心點在距離軸標簽大小的一半之內(在圖像上:在橙色雙線內 - 請參見圓圈上方的標簽),那么您的點位於標簽文本框架的邊緣
    • 否則,該點位於標簽文本框的角落
  4. 從圓圈中間“移動”標簽,使其黑色框架在步驟3中確定的點處觸及藍色虛線。 (在圖像上:從圓心到標簽中心的紅線)
  5. 根據接觸圓的點,確定標簽的左上角,並在結果位置繪制標簽。

對不起,這里沒有公式,我需要更多時間來撰寫它們。 但是我想告訴你,這里的定位標簽不僅僅需要在兩行代碼中對sin()cos()進行簡單的評估。

您需要的是要在您計算的點上定位的文本中心。 因此,您需要在X方向上移動半個寬度,在Y方向上移動半個高度。這會將標簽定位在圓圈“內部”。 像這樣:

public class CircleText : FrameworkElement {
    public string[] Labels
    {
        get { return (string[])GetValue(LabelsProperty); }
        set { SetValue(LabelsProperty, value); }
    }

    public static readonly DependencyProperty LabelsProperty =
        DependencyProperty.Register("Labels", typeof(string[]), typeof(CircleText), new PropertyMetadata(null, OnLabelsChanged));

    private static void OnLabelsChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) {
        ((CircleText) d).InvalidateVisual();
    }

    protected override void OnRender(DrawingContext drawingContext) {
        if (Labels == null || Labels.Length == 0)
            return;
        var centerX = this.ActualWidth / 2;
        var centerY = this.ActualHeight / 2;
        var rad = Math.Min(this.ActualWidth / 2, this.ActualHeight / 2);
        for (int i = 0; i < Labels.Length; i++) {
            var angle = 360 / (Labels.Length) * i;
            var x = centerX + rad * Math.Cos(angle * Math.PI / 180.0);
            var y = centerY + rad * Math.Sin(angle * Math.PI / 180.0);
            FormattedText text = new FormattedText(
                Labels[i],
                CultureInfo.GetCultureInfo("en-us"),
                FlowDirection.LeftToRight,
                new Typeface("Verdana"),
                12,
                Brushes.Black);
            x -= text.Width / 2;
            y -= text.Height / 2;
            drawingContext.DrawText(text, new Point(x, y));
        }

    }
}

如果要在點上繪制線條,並且希望標簽位於這些線條之外 - 則需要根據已計算的cos和sin值移動標簽。 這會將標簽定位在“外部”,如下所示:

protected override void OnRender(DrawingContext drawingContext) {
        if (Labels == null || Labels.Length == 0)
            return;
        var centerX = this.ActualWidth / 2;
        var centerY = this.ActualHeight / 2;
        var rad = Math.Min(this.ActualWidth / 2, this.ActualHeight / 2);
        for (int i = 0; i < Labels.Length; i++) {
            var angle = 360 / (Labels.Length) * i;
            var xshift = Math.Cos(angle * Math.PI / 180.0);
            var yshift = Math.Sin(angle * Math.PI / 180.0);
            var x = centerX + rad * xshift;
            var y = centerY + rad * yshift;
            drawingContext.DrawLine(new Pen(Brushes.Black, 1), new Point(centerX, centerY), new Point(x,y));
            FormattedText text = new FormattedText(
                Labels[i],
                CultureInfo.GetCultureInfo("en-us"),
                FlowDirection.LeftToRight,
                new Typeface("Verdana"),
                12,
                Brushes.Black);
            x -= (1 - xshift) * text.Width / 2;
            y -= (1 - yshift) * text.Height / 2;                
            drawingContext.DrawText(text, new Point(x, y));
        }            
    }

當然,上述適用於任何數量的標簽。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM