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 };
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 }
代码写好编译后,不知怎么回事,直接继承的子类蓝图没有designer和Graph,也不能在其他UMG内添加。
想了个绕圈的方法,就是先创建继承UserWidget的蓝图子类,然后在Class Setting内修改ParentClass为PieUserWidget。然后需要删除的CanvasPanel。
子类蓝图添加

变量值为:

效果图:

这个还是可以继续改进的
浙公网安备 33010602011771号