饼状图
- 使用UE绘制前提
- 完整的创建过程
- 1
- 2
- 3
- 4
- 5
- 6
- 6
- 7
- 8
- 附录代码
- .h代码
- .c代码
使用UE绘制前提
EPIC Game使用的版本是Unreal Engine 5.0.3。
没有使用其他额外的插件,使用的是C++和Ui共同绘制。
C++编译器使用的是VS2019。
完整的创建过程
1
首先在UE中随意一种项目的白色。默认为C++,名称注意使用英文
2
3
4
之后就直接跳进VS2019中去了。然后将附录中的代码整上去。先保存后编译。一定要先保存后编译
上面的报错全都无伤大雅,真正的检查是在Live Coding 中。
但是如果有其他的报错还是要研究分析一下,比如中英文错了等等。不再多提。
5
完成VS2019中的编码后使用的检测系统如下图所示,快捷键是Ctrl + Alt + F11。
如果Live Coding中显示Successfully,那么就成功了
6
在进入到UE中新建一个UI控件
6
7
控件蓝图中放入画布画板,再将你自己命名的用户控件放入其中
8
在右上角点击转移到图表中去,然后连线如下
运行后如下
也可以进行更改,让他显示两个饼图
颜色大小都可以自定义来实现。
附录代码
.h代码
.h文件代码如下
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include <fstream>
#include "CoreMinimal.h"
#include "Blueprint/UserWidget.h"
#include "PieWidget.generated.h"
/**
*
*/
UCLASS()
class ECHART1_API UPieWidget : public UUserWidget
{
GENERATED_BODY()
public:
UFUNCTION(BlueprintCallable)
void SetValues(TArray<float> InValues);
UFUNCTION(BlueprintCallable)
void SetColor(TArray<FLinearColor> InColors);
protected:
virtual int32 NativePaint(
const FPaintArgs& Args,
const FGeometry& AllottedGeometry,
const FSlateRect& MyCullingRect, FSlateWindowElementList& OutDrawElements, int32 LayerId,
const FWidgetStyle& InWidgetStyle,
bool bParentEnabled) const;
private:
//私有的绘制扇形所需元素从上到下依次是
//绘制所需元素,绘制所需几何,所需元素,圆心所在,半径,圆心开始角度,结束角度,颜色
void DrawFan(
FSlateWindowElementList& OutDrawElements,
const FGeometry& AllottedGeometry,
int32 Layer,
const FVector2D& CenterPosition,
float Radius,
int32 BeginAngle,
int32 EndAngle,
FColor Color
)const;
TArray<int32> Angles;
TArray<FLinearColor> Colors;
FColor GetColorByIndex(int32 InIndex)const;
};
.c代码
.c文件如下
#include "PieWidget.h"
void UPieWidget::SetValues(TArray<float> InValues)
{
if (InValues.Num() < 1)
return;
Angles.Empty();
Angles.Add(0);
//求取数据的总值
float Total = 0;
for (int32 Index = 0; Index < InValues.Num(); Index++)
{
Total += InValues[Index];
}
//求取每个值占总值的多少,化成度数
float CurrentTotal = 0;
for (int32 Index = 0; Index < InValues.Num(); Index++)
{
CurrentTotal += InValues[Index];
int32 Angle = (int32)((CurrentTotal / Total) * 360);
Angles.Add(Angle);
}
}
void UPieWidget::SetColor(TArray<FLinearColor> InColors)
{
Colors = InColors;
}
int32 UPieWidget::NativePaint(
const FPaintArgs& Args,
const FGeometry& AllottedGeometry,
const FSlateRect& MyCullingRect, FSlateWindowElementList& OutDrawElements, int32 LayerId,
const FWidgetStyle& InWidgetStyle,
bool bParentEnabled) const
{
//绘制饼状图
for (int32 Index = 0; Index < Angles.Num() - 1; Index++)
{
int32 BegingAngle = Angles[Index];
int32 EndAngle = Angles[Index + 1];
DrawFan(OutDrawElements, AllottedGeometry, LayerId, FVector2D(300.f, 300.f), 250.f, BegingAngle, EndAngle, GetColorByIndex(Index));
}
return LayerId++;
}
void UPieWidget::DrawFan(
FSlateWindowElementList& OutDrawElements,
const FGeometry& AllottedGeometry,
int32 Layer,
const FVector2D& CenterPosition,
float Radius,
int32 BeginAngle,
int32 EndAngle,
FColor Color) const
{
//绘制扇形
if (EndAngle <= BeginAngle)//如果结束角度小于等于开始角度,不用绘制
return;
if (Radius <= 0.f)//半径很小也不绘制
return;
//定义顶点数组
TArray<FSlateVertex> SlateVertexArray;
//定义索引数组
TArray<SlateIndex> SlateIndexArray;
//画三角
for (int32 CurrentAngle = BeginAngle; CurrentAngle < EndAngle; CurrentAngle++)
{
FSlateVertex CurrentSlateVertex;//当前顶点
FSlateVertex NextSlateVertex;//下一个顶点
FSlateVertex CenterSlateVertex;//中心点
//将当前顶点的一维转换为二维
FVector2D CurrentSlateVertextPositon = FVector2D(
CenterPosition.X + Radius * FMath::Cos(FMath::DegreesToRadians(CurrentAngle)),
CenterPosition.Y + Radius * FMath::Sin(FMath::DegreesToRadians(CurrentAngle))
);
//将下一个顶点的一维转换为二维
FVector2D NextSlateVertextPositon = FVector2D(
CenterPosition.X + Radius * FMath::Cos(FMath::DegreesToRadians(CurrentAngle + 1)),
CenterPosition.Y + Radius * FMath::Sin(FMath::DegreesToRadians(CurrentAngle + 1))
);
//位置赋给三个顶点
CurrentSlateVertex.Position = (FVector2f)AllottedGeometry.ToPaintGeometry().GetAccumulatedRenderTransform().TransformPoint(CurrentSlateVertextPositon);
NextSlateVertex.Position = (FVector2f)AllottedGeometry.ToPaintGeometry().GetAccumulatedRenderTransform().TransformPoint(NextSlateVertextPositon);
CenterSlateVertex.Position = (FVector2f)AllottedGeometry.ToPaintGeometry().GetAccumulatedRenderTransform().TransformPoint(CenterPosition);
CurrentSlateVertex.Color = Color;
NextSlateVertex.Color = Color;
CenterSlateVertex.Color = Color;
//把三个坐标放入到数组中
int32 IndexOfCurrentSlateVertex = SlateVertexArray.Add(CurrentSlateVertex);
int32 IndexOfNextSlateVertex = SlateVertexArray.Add(NextSlateVertex);
int32 IndexOfCenterSlateVertex = SlateVertexArray.Add(CenterSlateVertex);
//把索引值放入到索引数组中
SlateIndexArray.Add(IndexOfCurrentSlateVertex);
SlateIndexArray.Add(IndexOfCenterSlateVertex);
SlateIndexArray.Add(IndexOfNextSlateVertex);
}
//顶点的UV
for (FSlateVertex& TempSlateVertex : SlateVertexArray)
{
TempSlateVertex.TexCoords[0] = 0.0f;
TempSlateVertex.TexCoords[1] = 0.0f;
TempSlateVertex.TexCoords[2] = 0.0f;
TempSlateVertex.TexCoords[3] = 0.0f;
}
//绘制
const FSlateBrush* SlateBrush = FCoreStyle::Get().GetBrush("ColorSpectrum.Spectrum");
FSlateResourceHandle SlateResourceHandle = FSlateApplication::Get().GetRenderer()->GetResourceHandle(*SlateBrush);
FSlateDrawElement::MakeCustomVerts(
OutDrawElements,
Layer,
SlateResourceHandle,
SlateVertexArray,
SlateIndexArray,
nullptr, 0, 0
);
}
FColor UPieWidget::GetColorByIndex(int32 InIndex) const
{
if (Colors.Num() < 1)
return FColor::White;
return Colors[InIndex % Colors.Num()].ToFColor(true);
}