파이차트

Eden·2022년 12월 12일
0

기본적으로 제공하는 Chart 컨트롤을 사용할때 차트의 배경과 텍스트 정보에 대한 컨트롤 어려워 직접만들어 보았다.
wpf에는 호(arc)를 그리는 기능이 없어 직접 그렸던 경험을 토대로 만들었다. 다른 부분은 연속적으로 점 크기의 라인을 찍어 호를 나타내는 로직에서 속도상의 문제(라인을 연속적으로 그리게 되면 라인의 두께가 클때 구분 영역에서의 경계 표현이 제대로 되지 않았으며 두께 값을 줄이면 그려야할 라인의 수가 많아지고 속도 문제가 발생)로 폴리곤(로직적으로 (Angle + 1)각형의 도형)을 이용해 파이차트를 나타내었다.

public void DrawARCGraduation_Center(Canvas Canvas, int StartAngle, int Range, Brush color) // Canvas : xaml에서 도형을 그릴 Canvas,  StartAngle : 파이차트 한 영역이 시작되는 angle 값, Range : 파이차트의 크기를 결정하는 angel 범위, color : 해당 파이차트의 색
        {
            int InitAngle_ = StartAngle;
            Polygon polygon = new Polygon()
            {
                Stroke = color, // 라인 색
                StrokeThickness = 0.2, // 두께 값을 크게 하면 파이차트간 경계에 어색함이 생길 수 있음
                Fill = color,  // 도형 내부색
            };

            polygon.Points.Add(new Point() { X = Canvas.ActualWidth/2 - 10 , Y = Canvas.ActualWidth/2 - 10  }); // 중심점 , Canvas의 넓이값의 반  - 10 은 원이 canvas에 꽉차지 않도록 SetLeft, SetTop으로 10만큼 이동하여 Canvas 중심에 위치시킴
            for (int i = 0; i <= Range; i++) // 삼각함수를 이용해 Range 만큼 점 추가
            {
                if(i == Range)
                {
					polygon.Points.Add(new Point() { X = Canvas.ActualWidth / 2 - 10 - Math.Sin((double)InitAngle_ / 180 * Math.PI) * (-(Canvas.ActualWidth / 2 - 10)), Y = Canvas.ActualWidth / 2 - 10 + Math.Cos((double)InitAngle_ / 180 * Math.PI) * (-(Canvas.ActualWidth / 2 - 10)) });
                }
                else if (i < 360)
                {
					polygon.Points.Add(new Point() { X = Canvas.ActualWidth/2 - 10 - Math.Sin((double)InitAngle_ / 180 * Math.PI) * (-(Canvas.ActualWidth/2 - 10)), Y = Canvas.ActualWidth / 2 - 10 + Math.Cos((double)InitAngle_ / 180 * Math.PI) * (-(Canvas.ActualWidth/2 - 10)) });
                    InitAngle_++;
                }

            }
            polygon.Opacity = 0.75; // 도형의 투명도 설정
            Canvas.Children.Add(polygon);
            Canvas.SetLeft(polygon, 10); // 도형 중심 맞추기
            Canvas.SetTop(polygon, 10); // 도형 중심 맞추기

            if (Range / 3.6 > 5) // 파이차트 특정 퍼센트 이상의 차트에 대해서 퍼센트를 표시하도록 하는 부분, 5는 퍼센트에 해당   
            {
                TextBlock textBlock = new TextBlock();
                textBlock.FontSize = 13;
                textBlock.FontWeight = FontWeight.FromOpenTypeWeight(500);
                textBlock.TextAlignment = TextAlignment.Left;
                textBlock.HorizontalAlignment = HorizontalAlignment.Left;
                textBlock.VerticalAlignment = VerticalAlignment.Top;

###                 textBlock.Text = Math.Round(Range / 3.6, 1).ToString() + "%";

				// 텍스트가 원하는 위치(중심)에 정확히 오도록 텍스트의 넓이 값을 구하는 부분
                var formattedText = new FormattedText(textBlock.Text, CultureInfo.CurrentCulture, FlowDirection.LeftToRight, new Typeface(textBlock.FontFamily, textBlock.FontStyle, textBlock.FontWeight, textBlock.FontStretch), textBlock.FontSize, Brushes.Black, new NumberSubstitution()); 
                
                double TextWidth = formattedText.Width;
                textBlock.Foreground = new SolidColorBrush(Color.FromRgb(255, 255, 255));
                textBlock.Margin = new Thickness(0, 0, 0, 0);
                //textBlock.RenderTransform = new RotateTransform(30, TextWidth / 2, 100 + textBlock.FontSize * 0.5);
                textBlock.RenderTransform = new RotateTransform((StartAngle + StartAngle + Range) / 2, TextWidth / 2, 75 + textBlock.FontSize * 0.5); // y 기준 100 아래로 이동 -20
                Canvas.Children.Add(textBlock);
                Canvas.SetLeft(textBlock, 10 + Canvas.ActualWidth/2 - 10 - TextWidth / 2); // 텍스트 중앙에 위치하도록
                Canvas.SetTop(textBlock, 25 - textBlock.FontSize * 0.5); //기준값 10 RotateTransform -20 에 해당하는 값 + 20
            }
        }

profile
주섬주섬..

0개의 댓글