
代码需要进一步整理优化,暂时就这样吧
tool
extends Control
class_name RadarChart
const PI_OVER_2 = PI / 2
export var property_data: Dictionary = {
s = 0.0, d = 2.0, k = 4.0, l = 6.0, a = 8.0, b = 10.0
} setget update_property_data
var edge_number: int = 6 #边数
var radar_layer_count: int = 5 #setget set_radar_layer_count #雷达图层数
var background_color: Color = Color("a6a6a6")
var outline_color: Color = Color(0, 0.43, 0.84, 0.7)
var line_width: float = 3 #线条粗细
var max_value:int = 10 #最大刻度
var point_color:Color = Color.gold
var line_color:Color = Color.white
var radar_layer_points: Array #雷达图每层的位置点集
var origin: Vector2 = Vector2.ZERO #雷达图圆点
var radius: float = 10.0 #雷达图半径
func _init() -> void:
if not is_connected("resized", self, "_on_RadarChart_resized"):
connect("resized", self, "_on_RadarChart_resized")
yield(self, "draw")
set_size(Vector2(300, 300))
func _draw():
origin = Vector2(rect_size.x / 2, rect_size.y / 2)
radius = origin.y if rect_size.x > rect_size.y else origin.x
draw_circle_custom(origin, radius, Color(0.5, 0.5, 0.5, 1)) #替代draw_circle不光滑
_draw_radial_line() #绘制径向辐射线
_draw_radar_layer_polyline() #绘制雷达图每层多边形
_draw_data_polygon() #绘制数值多边形
#自定义画圆
func draw_circle_custom(origin, radius, color, count = 45):
var p = PoolVector2Array()
for i in count:
p.append(get_position_of_index(i, radius, origin, count))
draw_colored_polygon(p, color, [], null, null, true)
##绘制从圆点辐射的径向线
func _draw_radial_line():
for i in edge_number + 1:
var point = get_position_of_index(i, radius - line_width)
draw_line(origin, point, background_color, line_width - 0.5, true)
##绘制雷达图每层的多边形线段
func _draw_radar_layer_polyline():
var property_data_key = property_data.keys()
if radar_layer_points.size() != radar_layer_count + 1:
radar_layer_points.resize(radar_layer_count + 1)
for i in radar_layer_count + 1:
var p_radius = radius / (radar_layer_count) * i
var points = PoolVector2Array()
for j in edge_number + 1:
if i==0:
p_radius = line_width
var point = get_position_of_index(j, p_radius - line_width)
points.push_back(point)
draw_polyline(points, background_color, line_width, true)
radar_layer_points[i] = points
##绘制数据多边形
func _draw_data_polygon():
var poly_points = []
var per_layer_value = float(max_value) / float(radar_layer_count)
for i in property_data.size():
var property_string = property_data.keys()[i]
var property_data_value = property_data[property_string]
# 绘制标签
var direction = (radar_layer_points[1][i] - radar_layer_points[0][i])
draw_string(
get_font("font"),
radar_layer_points.back()[i] + direction.normalized() * 15,
property_string
)
var layer_number = int(property_data_value / per_layer_value)
#超出最大值处理
if layer_number >= radar_layer_count:
var from = radar_layer_points[radar_layer_count][i]
var wight = float(property_data_value - max_value)/float(per_layer_value)
var to = from + wight * direction
poly_points.append(to)
continue
var base = per_layer_value * (layer_number)
var wight = (property_data_value - base) / per_layer_value
var point_from: Vector2 = radar_layer_points[layer_number][i]
var point_to: Vector2 = radar_layer_points[layer_number + 1][i]
var point = lerp(point_from, point_to, wight)
poly_points.append(point)
poly_points.append(poly_points[0]) #首尾闭合
draw_polygon(poly_points, [outline_color]) #绘制数值图多边形
draw_polyline(poly_points,line_color, 3, true) #数值图描边
for i in poly_points.size() - 1:
draw_circle(poly_points[i], 4, point_color) #绘制数值点
func get_position_of_index(
p_index, p_radius = self.radius, p_origin = self.origin, count = self.edge_number
):
var angle = 2.0 * PI / count
var x = p_origin.x + p_radius * cos(angle * p_index - PI_OVER_2)
var y = p_origin.y + p_radius * sin(angle * p_index - PI_OVER_2)
return Vector2(x, y)
func update_property_data(value):
property_data = value
update()
func _on_RadarChart_resized() -> void:
radar_layer_points.clear()
update()
### 编辑器内 修改数据后 重新绘制 ####
func _get_property_list() -> Array:
var pa = []
var sp = (get_script() as Script).get_script_property_list()
for p in sp:
if p.usage == 8192 :
if not p.name in ["radius","radar_layer_points","origin"]:
var pd = p.duplicate()
pd.name = "_"+pd.name
pd.usage = 8199
pa.append(pd)
return pa
func _get(property: String):
if property.begins_with("_"):
return get(property.trim_prefix("_"))
func _set(property: String, value) -> bool:
if property.begins_with("_"):
set(property.trim_prefix("_"),value)
update()
return true
return false
### 编辑器内 修改数据后 重新绘制 ####
代码文件,解压后先放于项目根目录,再移动位置