C# 使用GDI绘制雷达图
程序员文章站
2023-11-14 09:40:04
最近项目要用C#实现画一个雷达图,搜了搜网上竟然找不到C#画雷达图的解决方案,那么自己实现一个吧 实现效果如下图: 代码如下: 1 public static class RadarDemo 2 { 3 static float mW = 1200; 4 static float mH = 1200 ......
最近项目要用c#实现画一个雷达图,搜了搜网上竟然找不到c#画雷达图的解决方案,那么自己实现一个吧
实现效果如下图:
代码如下:
1 public static class radardemo 2 { 3 static float mw = 1200; 4 static float mh = 1200; 5 static dictionary<string, float> mdata = new dictionary<string, float> 6 { 7 //{ "速度",77}, 8 { "力量", 72}, 9 { "防守", 110}, 10 { "射门", 50}, 11 { "传球", 80}, 12 { "耐力", 60 } 13 };//维度数据 14 static float mcount = mdata.count; //边数 15 static float mcenter = mw * 0.5f; //中心点 16 static float mradius = mcenter - 100; //半径(减去的值用于给绘制的文本留空间) 17 static double mangle = (math.pi * 2) / mcount; //角度 18 static graphics graphics = null; 19 static int mpointradius = 5; // 各个维度分值圆点的半径 20 static int textfontsize = 18; //顶点文字大小 px 21 const string textfontfamily = "microsoft yahei"; //顶点字体 22 static color linecolor = color.green; 23 static color fillcolor = color.fromargb(128, 255, 0, 0); 24 static color fontcolor = color.black; 25 26 public static void show() 27 { 28 bitmap img = new bitmap((int)mw, (int)mh); 29 graphics = graphics.fromimage(img); 30 graphics.clear(color.white); 31 img.save($"{appdomain.currentdomain.basedirectory}radar/0.png", imageformat.png); 32 drawpolygon(graphics); 33 img.save($"{appdomain.currentdomain.basedirectory}radar/1.png", imageformat.png); 34 drawlines(graphics); 35 img.save($"{appdomain.currentdomain.basedirectory}radar/2.png", imageformat.png); 36 drawtext(graphics); 37 img.save($"{appdomain.currentdomain.basedirectory}radar/3.png", imageformat.png); 38 drawregion(graphics); 39 img.save($"{appdomain.currentdomain.basedirectory}radar/4.png", imageformat.png); 40 drawcircle(graphics); 41 img.save($"{appdomain.currentdomain.basedirectory}radar/5.png", imageformat.png); 42 img.dispose(); 43 graphics.dispose(); 44 45 } 46 47 48 // 绘制多边形边 49 private static void drawpolygon(graphics ctx) 50 { 51 var r = mradius / mcount; //单位半径 52 pen pen = new pen(linecolor); 53 //画6个圈 54 for (var i = 0; i < mcount; i++) 55 { 56 var points = new list<pointf>(); 57 var currr = r * (i + 1); //当前半径 58 //画6条边 59 for (var j = 0; j < mcount; j++) 60 { 61 var x = (float)(mcenter + currr * math.cos(mangle * j)); 62 var y = (float)(mcenter + currr * math.sin(mangle * j)); 63 points.add(new pointf { x = x, y = y }); 64 } 65 ctx.drawpolygon(pen, points.toarray()); 66 //break; 67 } 68 69 ctx.save(); 70 } 71 72 //顶点连线 73 private static void drawlines(graphics ctx) 74 { 75 for (var i = 0; i < mcount; i++) 76 { 77 var x = (float)(mcenter + mradius * math.cos(mangle * i)); 78 var y = (float)(mcenter + mradius * math.sin(mangle * i)); 79 ctx.drawline(new pen(linecolor), new pointf { x = mcenter, y = mcenter }, new pointf { x = x, y = y }); 80 //break; 81 } 82 ctx.save(); 83 } 84 85 //绘制文本 86 private static void drawtext(graphics ctx) 87 { 88 var fontsize = textfontsize;//mcenter / 12; 89 font font = new font(textfontfamily, fontsize, fontstyle.regular); 90 91 int i = 0; 92 foreach (var item in mdata) 93 { 94 var x = (float)(mcenter + mradius * math.cos(mangle * i)); 95 var y = (float)(mcenter + mradius * math.sin(mangle * i) - fontsize); 96 97 if (mangle * i > 0 && mangle * i <= math.pi / 2) 98 { 99 ctx.drawstring(item.key, font, new solidbrush(fontcolor), x - ctx.measurestring(item.key, font).width * 0.5f, y + fontsize/* y + fontsize*/); 100 } 101 else if (mangle * i > math.pi / 2 && mangle * i <= math.pi) 102 { 103 ctx.drawstring(item.key, font, new solidbrush(fontcolor), x - ctx.measurestring(item.key, font).width, y /*y + fontsize*/); 104 } 105 else if (mangle * i > math.pi && mangle * i <= math.pi * 3 / 2) 106 { 107 ctx.drawstring(item.key, font, new solidbrush(fontcolor), x - ctx.measurestring(item.key, font).width, y); 108 } 109 else if (mangle * i > math.pi * 3 / 2) 110 { 111 ctx.drawstring(item.key, font, new solidbrush(fontcolor), x - ctx.measurestring(item.key, font).width * 0.5f, y - fontsize * 0.5f); 112 } 113 else 114 { 115 ctx.drawstring(item.key, font, new solidbrush(fontcolor), x, y /* y + fontsize*/); 116 } 117 i++; 118 } 119 ctx.save(); 120 } 121 122 //绘制数据区域 123 private static void drawregion(graphics ctx) 124 { 125 int i = 0; 126 list<pointf> points = new list<pointf>(); 127 foreach (var item in mdata) 128 { 129 var x = (float)(mcenter + mradius * math.cos(mangle * i) * item.value / 100); 130 var y = (float)(mcenter + mradius * math.sin(mangle * i) * item.value / 100); 131 132 points.add(new pointf { x = x, y = y }); 133 134 //ctx.drawarc(new pen(linecolor), x, y, r, r, 0, (float)math.pi * 2); 135 i++; 136 } 137 138 139 //graphicspath path = new graphicspath(); 140 //path.addlines(points.toarray()); 141 142 ctx.fillpolygon(new solidbrush(fillcolor), points.toarray()); 143 144 ctx.save(); 145 } 146 147 //画点 148 private static void drawcircle(graphics ctx) 149 { 150 //var r = mcenter / 18; 151 var r = mpointradius; 152 153 int i = 0; 154 foreach (var item in mdata) 155 { 156 var x = (float)(mcenter + mradius * math.cos(mangle * i) * item.value / 100); 157 var y = (float)(mcenter + mradius * math.sin(mangle * i) * item.value / 100); 158 ctx.fillpie(new solidbrush(fillcolor), x - r, y - r, r * 2, r * 2, 0, 360); 159 //ctx.drawarc(new pen(linecolor), x, y, r, r, 0, (float)math.pi * 2); 160 i++; 161 } 162 ctx.save(); 163 } 164 165 }
把这个类粘贴到你的项目中,执行radardemo.show();就会在你的根目录里生成雷达图了,为了方便理解怎么画出来的,我把画每一个步骤时的图片都保存下来了。可以自行运行查看