UE实现UMG数据雷达图

需要用UE做一个这样的功能,找了一圈,发现有饼图,环形图,要么就是说需要插件。

读了UE5实现UMG饼图控件_ue 图表插件-CSDN博客这篇文章,发现,其实数据雷达图好像更简单。因为饼图是需要画圆,而雷达图就只是三角形。

雷达图表示数据的长度变化了,怎么确定点的位置是个问题。这个长度,其实就是半径长度。

代码如下:

头文件

 1 // Fill out your copyright notice in the Description page of Project Settings.
 2 
 3 #pragma once
 4 
 5 #include "CoreMinimal.h"
 6 #include "Blueprint/UserWidget.h"
 7 #include "PieUserWidget.generated.h"
 8 
 9 /**
10  * 
11  */
12 UCLASS(BlueprintType, Blueprintable)
13 class Test_API UPieUserWidget : public UUserWidget
14 {
15     GENERATED_BODY()
16 protected:
17     virtual int32 NativePaint(const FPaintArgs& Args, const FGeometry& AllottedGeometry, const FSlateRect& MyCullingRect, FSlateWindowElementList& OutDrawElements, int32 LayerId, const FWidgetStyle& InWidgetStyle, bool bParentEnabled) const override;
18 
19 public:
20     UPROPERTY(EditAnywhere,BlueprintReadWrite)
21     float OuterR;
22     UPROPERTY(EditAnywhere,BlueprintReadWrite,meta=(ClampMin = 0, ClampMax = 360))
23     TArray<float> Angles;
24     UPROPERTY(EditAnywhere,BlueprintReadWrite)
25     TArray<FColor> Colors;
26     UPROPERTY(EditAnywhere,BlueprintReadWrite,meta=(ClampMin = 0, ClampMax = 360))
27     TArray<float> InnerRArray;
28     
29     UFUNCTION(BlueprintCallable)
30     void SetValues(const TArray<float>& InValues, const TArray<FColor>& InColors);
31     UFUNCTION(BlueprintCallable)
32     void SetPointsRArray(const TArray<float>& InValues);
33 
34 private:
35     void DrawPart(FSlateWindowElementList& OutDrawElement,
36         const FGeometry& AllottedGeometry,
37         int LayerId, float R,
38         int32 InBeginAngle, int32 InEndAngle,
39         const FColor& InColor,
40         float StartR,
41         float EndR) const;
42 
43     FColor GetCircleColor(int32 index) const;
44     float GetPointsR(int32 index) const;
45 };
View Code

cpp

  1 // Fill out your copyright notice in the Description page of Project Settings.
  2 
  3 
  4 #include "UI/Common/PieUserWidget.h"
  5 
  6 #include "VectorTypes.h"
  7 #include "EnvironmentQuery/EnvQueryTypes.h"
  8 
  9 int32 UPieUserWidget::NativePaint(const FPaintArgs& Args,
 10                                   const FGeometry& AllottedGeometry,
 11                                   const FSlateRect& MyCullingRect,
 12                                   FSlateWindowElementList& OutDrawElements,
 13                                   int32 LayerId,
 14                                   const FWidgetStyle& InWidgetStyle,
 15                                   bool bParentEnabled) const
 16 {
 17     float StartAngle = 0.f;
 18     float EndAngle = 0.f;
 19     FColor CircleColor;
 20     float StartR = 0.f;
 21     float EndR = 0.f;
 22 
 23     for(int i = 0; i<Angles.Num() - 1; i++)
 24     {
 25         StartAngle += Angles[i];
 26         EndAngle = StartAngle + Angles[i+1];
 27         StartR = GetPointsR(i);
 28         EndR = GetPointsR(i+1);
 29         if(StartR != EndR)
 30             CircleColor = GetCircleColor(i);
 31         CircleColor = GetCircleColor(i);
 32         DrawPart(OutDrawElements,
 33             AllottedGeometry,
 34             LayerId,
 35             OuterR,
 36             StartAngle,
 37             EndAngle,
 38             CircleColor,
 39             StartR,
 40             EndR
 41             );
 42     }
 43     return LayerId++;
 44 }
 45 
 46 void UPieUserWidget::DrawPart(FSlateWindowElementList& OutDrawElement,
 47         const FGeometry& AllottedGeometry,
 48         int LayerId, float R,
 49         int32 InBeginAngle, int32 InEndAngle,
 50         const FColor& InColor,
 51         float StartR,
 52         float EndR) const
 53 {
 54     if(InBeginAngle >= InEndAngle) return;
 55 
 56     TArray<FSlateVertex> VertexArray;
 57     TArray<SlateIndex> VertexIndex;
 58     
 59     FSlateVertex BeginVertex;
 60     FSlateVertex EndVertex;
 61     FSlateVertex CenterVertex;
 62 
 63     BeginVertex.Color = InColor;
 64     EndVertex.Color = InColor;
 65     CenterVertex.Color = InColor;
 66 
 67     FVector2D BeginPosition;
 68     FVector2D EndPosition;
 69 
 70     FVector2D CenterPosition = FVector2D(R,R);
 71     BeginPosition = FVector2D(
 72         CenterPosition.X + StartR * FMath::Cos(FMath::DegreesToRadians(InBeginAngle - 90)),
 73         CenterPosition.Y + StartR * FMath::Sin(FMath::DegreesToRadians(InBeginAngle - 90))
 74         );
 75     EndPosition = FVector2D(
 76         CenterPosition.X + EndR * FMath::Cos(FMath::DegreesToRadians(InEndAngle - 90)),
 77         CenterPosition.Y + EndR * FMath::Sin(FMath::DegreesToRadians(InEndAngle - 90))
 78         );
 79     const FSlateRenderTransform& SlateRenderTransform = AllottedGeometry.ToPaintGeometry().GetAccumulatedRenderTransform();
 80     BeginPosition = SlateRenderTransform.TransformPoint(BeginPosition);
 81     EndPosition = SlateRenderTransform.TransformPoint(EndPosition);
 82     CenterPosition = SlateRenderTransform.TransformPoint(CenterPosition);
 83         
 84     BeginVertex.Position = BeginPosition;
 85     EndVertex.Position = EndPosition;
 86     CenterVertex.Position = CenterPosition;
 87 
 88     int32 BeginVertexIndex = VertexArray.Add(BeginVertex);
 89     int32 EndVertexIndex = VertexArray.Add(EndVertex);
 90     int32 CenterVertexIndex = VertexArray.Add(CenterVertex);
 91     VertexIndex.Add(CenterVertexIndex);
 92     VertexIndex.Add(BeginVertexIndex);
 93     VertexIndex.Add(EndVertexIndex);
 94     /**
 95     for(int32 Angle = InBeginAngle - 90; Angle < InEndAngle - 90; Angle++)
 96     {
 97         FVector2D CenterPosition = FVector2D(R,R);
 98         BeginPosition = FVector2D(
 99             CenterPosition.X + R * FMath::Cos(FMath::DegreesToRadians(Angle)),
100             CenterPosition.Y + R * FMath::Sin(FMath::DegreesToRadians(Angle))
101             );
102         EndPosition = FVector2D(
103             CenterPosition.X + R * FMath::Cos(FMath::DegreesToRadians(Angle + 1)),
104             CenterPosition.Y + R * FMath::Sin(FMath::DegreesToRadians(Angle + 1))
105             );
106         const FSlateRenderTransform& SlateRenderTransform = AllottedGeometry.ToPaintGeometry().GetAccumulatedRenderTransform();
107         BeginPosition = SlateRenderTransform.TransformPoint(BeginPosition);
108         EndPosition = SlateRenderTransform.TransformPoint(EndPosition);
109         CenterPosition = SlateRenderTransform.TransformPoint(CenterPosition);
110         
111         BeginVertex.Position = BeginPosition;
112         EndVertex.Position = EndPosition;
113         CenterVertex.Position = CenterPosition;
114 
115         int32 BeginVertexIndex = VertexArray.Add(BeginVertex);
116         int32 EndVertexIndex = VertexArray.Add(EndVertex);
117         int32 CenterVertexIndex = VertexArray.Add(CenterVertex);
118         VertexIndex.Add(CenterVertexIndex);
119         VertexIndex.Add(BeginVertexIndex);
120         VertexIndex.Add(EndVertexIndex);
121     }
122     **/
123     const FSlateBrush* Brush = FCoreStyle::Get().GetBrush("PIECHART");
124     const FSlateResourceHandle Handle = FSlateApplication::Get().GetRenderer()->GetResourceHandle(*Brush);
125     FSlateDrawElement::MakeCustomVerts(OutDrawElement,LayerId,Handle,VertexArray,VertexIndex,nullptr,0,0);
126 }
127 void UPieUserWidget::SetValues(const TArray<float>& InValues, const TArray<FColor>& InColors)
128 {
129     Colors = InColors;
130     float Sum = 0.f;
131     for(int i = 0; i<InValues.Num(); i++)
132     {
133         Sum += InValues[i];
134     }
135     Angles.Empty();
136     Angles.Add(0.f);
137     for(int i = 0; i<InValues.Num(); i++)
138     {
139         Angles.Add(InValues[i] / Sum * 360.f);
140     }
141 }
142 
143 FColor UPieUserWidget::GetCircleColor(int32 index) const
144 {
145     if(Colors.IsValidIndex(index))
146     {
147         return FColor(Colors[index].R, Colors[index].G, Colors[index].B) ; //Colors[index];
148     }
149     return FColor::Red;
150 }
151 void UPieUserWidget::SetPointsRArray(const TArray<float>& InValues)
152 {
153     InnerRArray = InValues;
154 }
155 float UPieUserWidget::GetPointsR(int32 index) const
156 {
157     if(InnerRArray.IsValidIndex(index))
158     {
159         return InnerRArray[index];
160     }
161     if(InnerRArray.IsValidIndex(0) )
162     {
163         return InnerRArray[0];
164     }
165     return OuterR;
166 }
View Code

代码写好编译后,不知怎么回事,直接继承的子类蓝图没有designer和Graph,也不能在其他UMG内添加。

想了个绕圈的方法,就是先创建继承UserWidget的蓝图子类,然后在Class Setting内修改ParentClass为PieUserWidget。然后需要删除的CanvasPanel。

子类蓝图添加

 变量值为:

 

 效果图:

 

 这个还是可以继续改进的

posted on 2025-03-05 17:16  Ming明、  阅读(98)  评论(0)    收藏  举报