![]()
原理是利用字典获得坐标位置,一二三层是横向显示,关键控制好X坐标,第四层竖向显示,关键控制好Y坐标
数据方面:员工之间是通过manager=id来做关联的.
1.绘制单元格,图片等信息
2.绘制线条
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.UI; using System.Web.UI.WebControls; using System.Data; using System.Drawing; using System.Drawing.Drawing2D; using System.IO; namespace Orgchart { public partial class Orgchart : System.Web.UI.Page { Dictionary<int, ImageUnit> NodeDic = new Dictionary<int, ImageUnit>(); //绘制单元集合字典 List<Staff> list1 = null, list2 = null, list3 = null, list4 = null; int unitWidth = 150; int startX = 250; protected void Page_Load(object sender, EventArgs e) { if (!IsPostBack) { list1 = new List<Staff>(); list1.Add(new Staff(1, 0, "董事会", "总裁", "keller1", "77391929@qq.com", DateTime.Now, DateTime.Now, DateTime.Now, "xi.jpg")); list2 = new List<Staff>(); list2.Add(new Staff(11, 1, "人事部", "人事部主管", "keller11", "77391929@qq.com", DateTime.Now, DateTime.Now, DateTime.Now, "xi.jpg")); list2.Add(new Staff(12, 1, "开发部", "开发部主管", "keller12", "77391929@qq.com", DateTime.Now, DateTime.Now, DateTime.Now, "xi.jpg")); list2.Add(new Staff(13, 1, "市场部", "市场部主管", "keller13", "77391929@qq.com", DateTime.Now, DateTime.Now, DateTime.Now, "xi.jpg")); list3 = new List<Staff>(); list3.Add(new Staff(121, 12, "开发部", "开发经理1", "keller121", "77391929@qq.com", DateTime.Now, DateTime.Now, DateTime.Now, "xi.jpg")); list3.Add(new Staff(122, 12, "开发部", "开发经理2", "keller122", "77391929@qq.com", DateTime.Now, DateTime.Now, DateTime.Now, "xi.jpg")); list3.Add(new Staff(123, 12, "开发部", "开发经理3", "keller123", "77391929@qq.com", DateTime.Now, DateTime.Now, DateTime.Now, "xi.jpg")); list4 = new List<Staff>(); list4.Add(new Staff(1211, 121, "开发部", " 程序员1题目要长字体会变小试试 ", "keller1211", "77391929@qq.com", DateTime.Now, DateTime.Now, DateTime.Now, "xi.jpg")); list4.Add(new Staff(1212, 121, "开发部", "程序员2", "keller1212", "77391929@qq.com", DateTime.Now, DateTime.Now, DateTime.Now, "xi.jpg")); Graphics g = null; Bitmap img = null; InitStaff(); int Mapheight = GetMaxYFromDic() + 150; //画布高度 int MapWidth = GetMaxXFromDic() + 180; //画布宽度 img = new Bitmap(MapWidth, Mapheight);//生成图像的实例 g = Graphics.FromImage(img);//从Img对象生成新的Graphics对象 g.Clear(Color.White);//填充背景色:白色 if (list1 != null) { DrawLineTag(g, 0); DrawLayer(g, list1, true); } if (list2 != null) { DrawLineTag(g, 1); DrawLayer(g, list2, false); } if (list3 != null) { DrawLineTag(g, 2); DrawLayer3(g, list3, false); } if (list4 != null) { DrawLineTag(g, 3); DrawLayer4(g, list4, false); } MemoryStream ms = null; ms = new MemoryStream();//生成内存流对象 System.Drawing.Imaging.EncoderParameters ps = new System.Drawing.Imaging.EncoderParameters(1); System.Drawing.Imaging.EncoderParameter p1 = new System.Drawing.Imaging.EncoderParameter(System.Drawing.Imaging.Encoder.Quality, 100L); ps.Param[0] = p1; img.Save(ms, GetEncoder(System.Drawing.Imaging.ImageFormat.Jpeg), ps); Response.ClearContent();//更改http ContentType Response.ContentType = "image/Gif"; Response.BinaryWrite(ms.ToArray());//将整个二进制流的内容写入字节数组 */ //回收资源 g.Dispose(); img.Dispose(); Response.End(); } } public void InitStaff() { ImageUnit iu = null; int count = 0; int leftBrotherMaxX = 0; int leftBrotherCount = 0; if (list1 != null) { count = 0; iu = new ImageUnit(); for (int i = 0; i < list1.Count; i++) { Staff obj = list1[i]; iu.staff = obj; iu.x = startX + count * 200; iu.y = 5; NodeDic.Add(obj.id, iu); iu = new ImageUnit(); count++; } } if (list2 != null) { count = 0; iu = new ImageUnit(); foreach (Staff item in list2) { iu.staff = item; iu.x = NodeDic[item.manager].x + 180;//父节点X iu.y = 185; leftBrotherCount = FindBrotherLeft(item.manager, list2, out leftBrotherMaxX); if (leftBrotherCount > 0) { iu.x = leftBrotherMaxX + (unitWidth + 30); MoveRightNodes(item.manager, list1); MoveRightNodes2(iu.x, list2); } else { if (iu.staff.manager == item.manager)//第二层对齐方式 { iu.x = iu.x - 180; } } NodeDic.Add(item.id, iu); iu = new ImageUnit(); count++; } } if (list3 != null) { count = 0; iu = new ImageUnit(); foreach (Staff item in list3) { iu.staff = item; iu.y = 365; iu.x = NodeDic[item.manager].x; //父节点X leftBrotherCount = FindBrotherLeft(item.manager, list3, out leftBrotherMaxX); if (leftBrotherCount > 0) { iu.x = leftBrotherMaxX + (unitWidth + 30); MoveRightNodes(NodeDic[item.manager].staff.manager, list1); MoveRightNodes(item.manager, list2); MoveRightNodes2(iu.x, list3); } NodeDic.Add(item.id, iu); iu = new ImageUnit(); count++; } } if (list4 != null) { count = 0; iu = new ImageUnit(); foreach (Staff item in list4) { iu.staff = item; iu.y = 545; iu.x = NodeDic[item.manager].x - 15; //父节点X leftBrotherCount = FindBrotherLeft(item.manager, list4); if (leftBrotherCount > 0) { leftBrotherCount = leftBrotherCount + 1; iu.y = 545 + (leftBrotherCount - 1) * 180; } NodeDic.Add(item.id, iu); iu = new ImageUnit(); count++; } } } #region left right //寻找左边兄弟 public int FindBrotherLeft(int parentId, List<Staff> list, out int leftBrotherMaxX) { int count = 0; leftBrotherMaxX = 0; foreach (Staff obj in list) { //ContainsKey是否包含指定的键 if (obj.manager == parentId && NodeDic.ContainsKey(obj.id)) { count++; if (NodeDic[obj.id].x > leftBrotherMaxX) { leftBrotherMaxX = NodeDic[obj.id].x; } } } return count; } //寻找己赋坐标兄弟 public int FindBrotherLeft(int parentId, List<Staff> list) { int count = 0; foreach (Staff obj in list) { //ContainsKey是否包含指定的键 if (obj.manager == parentId && NodeDic.ContainsKey(obj.id)) { count++; } } return count; } //移动指定x 右边的节点 半个unit宽度 public void MoveRightNodes(int parentId, List<Staff> list) { foreach (Staff obj in list) { if (obj.id == parentId) { NodeDic[obj.id].x += (unitWidth + 30) / 2; } else { if (NodeDic[obj.id].x > NodeDic[parentId].x) { NodeDic[obj.id].x += (unitWidth + 30); } } } } //移动指定x 右边的节点 半个unit宽度 public void MoveRightNodes(int parentId, List<Staff> listParent, List<Staff> listCurrent) { foreach (Staff obj in listParent) { if (obj.id == parentId) NodeDic[obj.id].x += (unitWidth + 30) / 2; else if (NodeDic[obj.id].x > NodeDic[parentId].x) { NodeDic[obj.id].x += (unitWidth + 30); foreach (Staff _obj in listCurrent) { if (_obj.manager == obj.id) { if (NodeDic.ContainsKey(obj.id)) NodeDic[obj.id].x += (unitWidth + 30); } } } } } //移动指定x 右边的节点 半个unit宽度 public void MoveRightNodes2(int x, List<Staff> list) { foreach (Staff obj in list) { if (NodeDic.ContainsKey(obj.id) && NodeDic[obj.id].x >= x) NodeDic[obj.id].x += (unitWidth + 30); } } #endregion #region 绘制线条 public void DrawLayer(Graphics g, List<Staff> list, bool isFirst) { int MinChildX = 0, MaxChildX = 0; SolidBrush sb = new SolidBrush(Color.Black); Pen p = new Pen(sb); foreach (Staff obj in list) { if (GetChildCount(obj.id) > 0) { MinChildX = GetMinXFromDicByParentID(obj.id, NodeDic); //获取子结点中最小x MaxChildX = GetMaxXFromDicByParentID(obj.id, NodeDic);//获取子结点中最大x g.DrawLine(p, MinChildX + unitWidth / 2, NodeDic[obj.id].y + 180 - 15, MaxChildX + 75, NodeDic[obj.id].y + 180 - 15); //画子横线 g.DrawLine(p, NodeDic[obj.id].x + unitWidth / 2, NodeDic[obj.id].y + 150, NodeDic[obj.id].x + unitWidth / 2, NodeDic[obj.id].y + 165); //画子竖线 } DrawUnit123(g, obj, isFirst); //画结点 } } public void DrawLayer3(Graphics g, List<Staff> list, bool isFirst) { int MaxChildY = 0; SolidBrush sb = new SolidBrush(Color.Black); Pen p = new Pen(sb); p.Width = 1; p.Color = Color.Black; foreach (Staff obj in list) { if (GetChildCount(obj.id) > 0) { MaxChildY = GetMaxYFromDicByParentID(obj.id); g.DrawLine(p, NodeDic[obj.id].x + unitWidth - 3, NodeDic[obj.id].y + 60, NodeDic[obj.id].x + unitWidth - 3, MaxChildY + 20); //NodeDic[obj.ID].y + 165); //画子竖线 } DrawUnit123(g, obj, isFirst); //画结点 } } public void DrawLayer4(Graphics g, List<Staff> list, bool isFirst) { int MaxChildY = 0; SolidBrush sb = new SolidBrush(Color.Black); Pen p = new Pen(sb); p.Width = 1; foreach (Staff obj in list) { if (GetChildCount(obj.id) > 0) { MaxChildY = GetMaxYFromDicByParentID(obj.id); } DrawUnit4(g, obj, isFirst); //画结点 } } #endregion #region 绘图处理 private static System.Drawing.Imaging.ImageCodecInfo GetEncoder(System.Drawing.Imaging.ImageFormat format) { System.Drawing.Imaging.ImageCodecInfo[] codecs = System.Drawing.Imaging.ImageCodecInfo.GetImageDecoders(); foreach (System.Drawing.Imaging.ImageCodecInfo codec in codecs) { if (codec.FormatID == format.Guid) { return codec; } } return null; } //图片缩放--变窄 public System.Drawing.Image NarrowImage(System.Drawing.Image img, int x, int y) { return new Bitmap(img, x, y); } //获取子结点个数 public int GetChildCount(int parentId) { int Count = 0; foreach (int ID in NodeDic.Keys) { if (NodeDic[ID].staff.manager == parentId) Count++; } return Count; } //获取字典指定父级的子结点的最小横坐标 public int GetMinXFromDicByParentID(int parentId, Dictionary<int, ImageUnit> Dic) { int MinValue = 1000000; foreach (int ID in Dic.Keys) { if (Dic[ID].staff.manager == parentId) { if (Dic[ID].x < MinValue) MinValue = Dic[ID].x; } } if (MinValue == 1000000) MinValue = 0; return MinValue; } //获取字典指定父级的子结点的最大横坐标 public int GetMaxXFromDicByParentID(int parentId, Dictionary<int, ImageUnit> Dic) { int MaxValue = 0; foreach (int ID in Dic.Keys) { if (Dic[ID].staff.manager == parentId) { if (Dic[ID].x > MaxValue) MaxValue = Dic[ID].x; } } return MaxValue; } //获取字典指定父级的子结点的最大横坐标 public int GetMaxXFromDic() { int MaxValue = 0; foreach (int ID in NodeDic.Keys) { if (NodeDic[ID].x > MaxValue) MaxValue = NodeDic[ID].x; } return MaxValue; } //获取字典指定父级的子结点的最大纵坐标 public int GetMaxYFromDicByParentID(int parentId) { int MaxValue = 0; foreach (int ID in NodeDic.Keys) { if (NodeDic[ID].staff.manager == parentId) { if (NodeDic[ID].y > MaxValue) MaxValue = NodeDic[ID].y; } } return MaxValue; } //获得字典指定父级的子结点的最大纵坐标 public int GetMaxYFromDic() { int MaxValue = 0; foreach (int ID in NodeDic.Keys) { if (NodeDic[ID].y > MaxValue) MaxValue = NodeDic[ID].y; } return MaxValue; } #endregion #region 绘制单元 // 绘制员工单元 1 2 3 public void DrawUnit123(Graphics g, Staff obj, bool isFirst) { int x, y; x = NodeDic[obj.id].x; y = NodeDic[obj.id].y; SolidBrush sb = new SolidBrush(Color.FromArgb(39, 57, 153)); Font f = new Font("", 9, FontStyle.Regular); //定义字体 Rectangle r = new Rectangle(x, y, unitWidth, 70); //绘制矩形 g.FillRectangle(sb, r);//填充矩形 sb.Color = Color.White;//笔刷颜色 //部门 int StringStartX = (unitWidth - Convert.ToInt32(g.MeasureString(obj.department, f).Width)) / 2; g.DrawString(obj.department, f, sb, x + StringStartX, y + 3, StringFormat.GenericTypographic); //部门 //处理职位过长的状况 if (obj.position == null) { obj.position = ""; } else { if (g.MeasureString(obj.position, f).Width > unitWidth) { float FontSize = 9; while (g.MeasureString(obj.position, f).Width > unitWidth) { FontSize--; f = new Font("", FontSize, FontStyle.Regular); y++; } f = new Font("", FontSize + 1, FontStyle.Regular); } StringStartX = (unitWidth - Convert.ToInt32(g.MeasureString(obj.position, f).Width)) / 2; //g.DrawString(currentPositionName.ToUpper(), f, sb, x + StringStartX, y + 18); g.DrawString(obj.position, f, sb, x + StringStartX, y + 18); } //处理职位过长的状况 //姓名 f = new Font("", 9, FontStyle.Regular); StringStartX = (unitWidth - Convert.ToInt32(g.MeasureString(obj.name, f).Width)) / 2; g.DrawString(obj.name, f, sb, x + StringStartX, y + 33); //姓名 //邮箱 if (obj.email.Contains("@")) { obj.email = obj.email.Substring(0, obj.email.IndexOf('@')); } else obj.email = obj.email; StringStartX = (unitWidth - Convert.ToInt32(g.MeasureString(obj.email, f).Width)) / 2; g.DrawString(obj.email, f, sb, x + StringStartX, y + 48); //邮箱 sb.Color = Color.Black; g.DrawString(FormatDate(obj.joinCompany), f, sb, x + 5, y + 75); g.DrawString(FormatDate(obj.joinMarketing), f, sb, x + 5, y + 95); g.DrawString(FormatDate(obj.joinCurrentPosition), f, sb, x + 5, y + 115); if (!isFirst) { Pen p = new Pen(sb); g.DrawLine(p, x + unitWidth / 2, y, x + unitWidth / 2, y - 15); } if (obj.imgPath != null) { string path = Server.MapPath(obj.imgPath); System.Drawing.Image img = System.Drawing.Image.FromFile(path); img = NarrowImage(img, 45, 50); g.DrawImage(img, x + 53, y + 75); } } // 绘制第四层员工单元 public void DrawUnit4(Graphics g, Staff obj, bool isFirst) { int x, y; x = NodeDic[obj.id].x; y = NodeDic[obj.id].y; SolidBrush sb = new SolidBrush(Color.FromArgb(39, 57, 153)); Font f = new Font("", 9, FontStyle.Regular); //定义字体 Rectangle r = new Rectangle(x, y, unitWidth, 70); //绘制矩形 g.FillRectangle(sb, r);//填充矩形 sb.Color = Color.White;//笔刷颜色 //部门 int StringStartX = (unitWidth - Convert.ToInt32(g.MeasureString(obj.department, f).Width)) / 2; g.DrawString(obj.department, f, sb, x + StringStartX, y + 3, StringFormat.GenericTypographic); //部门 //处理职位过长的状况 if (obj.position == null) { obj.position = ""; } else { if (g.MeasureString(obj.position, f).Width > unitWidth) { float FontSize = 9; while (g.MeasureString(obj.position, f).Width > unitWidth) { FontSize--; f = new Font("", FontSize, FontStyle.Regular); y++; } f = new Font("", FontSize + 1, FontStyle.Regular); } StringStartX = (unitWidth - Convert.ToInt32(g.MeasureString(obj.position, f).Width)) / 2; //g.DrawString(currentPositionName.ToUpper(), f, sb, x + StringStartX, y + 18); g.DrawString(obj.position, f, sb, x + StringStartX, y + 18); } //处理职位过长的状况 //姓名 f = new Font("", 9, FontStyle.Regular); StringStartX = (unitWidth - Convert.ToInt32(g.MeasureString(obj.name, f).Width)) / 2; g.DrawString(obj.name, f, sb, x + StringStartX, y + 33); //姓名 //邮箱 if (obj.email.Contains("@")) { obj.email = obj.email.Substring(0, obj.email.IndexOf('@')); } else obj.email = obj.email; StringStartX = (unitWidth - Convert.ToInt32(g.MeasureString(obj.email, f).Width)) / 2; g.DrawString(obj.email, f, sb, x + StringStartX, y + 48); //邮箱 sb.Color = Color.Black; g.DrawString(FormatDate(obj.joinCompany), f, sb, x + 5, y + 75); g.DrawString(FormatDate(obj.joinMarketing), f, sb, x + 5, y + 95); g.DrawString(FormatDate(obj.joinCurrentPosition), f, sb, x + 5, y + 115); if (!isFirst) { Pen p = new Pen(sb); p.Width = 1; p.Color = Color.Black; if (NodeDic[obj.id].toRight == true) g.DrawLine(p, x + unitWidth, y + 20, x + unitWidth + 13, y + 20); else g.DrawLine(p, x, y + 20, x - 15, y + 20); } if (obj.imgPath != null) { string path = Server.MapPath(obj.imgPath); System.Drawing.Image img = System.Drawing.Image.FromFile(path); img = NarrowImage(img, 45, 50); g.DrawImage(img, x + 53, y + 75); } } #endregion //时间转换 public string FormatDate(DateTime? dt) { if (dt == null) return "000-00"; else { string MM = ""; if (dt.Value.Month == 1) MM = "Jan"; else if (dt.Value.Month == 2) MM = "Feb"; else if (dt.Value.Month == 3) MM = "Mar"; else if (dt.Value.Month == 4) MM = "Apr"; else if (dt.Value.Month == 5) MM = "May"; else if (dt.Value.Month == 6) MM = "Jun"; else if (dt.Value.Month == 7) MM = "Jul"; else if (dt.Value.Month == 8) MM = "Aug"; else if (dt.Value.Month == 9) MM = "Sep"; else if (dt.Value.Month == 10) MM = "Oct"; else if (dt.Value.Month == 11) MM = "Nov"; else if (dt.Value.Month == 12) MM = "Dec"; return MM + "-" + dt.Value.Year.ToString().Substring(2, 2); } } //业务相关的:记录员工的加入公司时间,市场部的时间,当前职位时间 public void DrawLineTag(Graphics g, int layth) { SolidBrush sb = new SolidBrush(Color.Black);//生成笔刷类的实例 Font f = new Font("", 10, FontStyle.Regular); g.DrawString("joinCompany:", f, sb, 5, 75 + layth * 180); g.DrawString("joinMarketing:", f, sb, 5, 95 + layth * 180); g.DrawString("joinCurrentPosition:", f, sb, 5, 115 + layth * 180); } } public class ImageUnit { // x,y坐标 public int x; public int y; public bool toRight = true; public Staff staff; public ImageUnit() { } public ImageUnit(int x, int y, Staff staff) { this.x = x; this.y = y; this.staff = staff; } } public class Staff { public int id{ get; set; }//员工编号 public int manager { get; set; }//经理--对应员工编号 public string department { get; set; }//部门 public string position { get; set; }//职位 public string name { get; set; }//员工姓名 public string email { get; set; }//员工邮箱 public DateTime joinCompany { get; set; }//加入公司时间 public DateTime joinMarketing { get; set; }//加入市场部时间 public DateTime joinCurrentPosition { get; set; }//加入当前职位时间 public string imgPath { get; set; }//图片URL public Staff() { } public Staff(int _id, int _manager, string _department, string _position, string _name, string _email, DateTime _joinCompany, DateTime _joinMarketing, DateTime _joinCurrentPosition, string _imgPath) { id = _id; manager = _manager; department = _department; position = _position; name = _name; email = _email; joinCompany = _joinCompany; joinMarketing = _joinMarketing; joinCurrentPosition = _joinCurrentPosition; imgPath = _imgPath; } } }