前段时间因项目需要实现一个能直观的表达出商品流向的功能。当初考虑了,SVG和VML以及生成图片来显示,因为系统一般在IE下使用,最后采用了VML实现,下面是实现后的几张贴图。
由于时间比较仓促只实现了基本功能没有细化,看起来比较粗糙。
下面主要简述下实现的思路及主要代码,废话不多说代码贴上。
线及长方形的显示主要是由几个DTO来描述:
//矩形DTO public class RectangleDTO { private double left;//矩形图左起点 private double top;//矩形图顶点 private double width;//矩形宽度 private String enterpriseName;//图形名称 private String rectangleColor;//矩形底色 private String characterColor;//字体颜色 private double lineX;//从矩形图引出线的X坐标 private double lineY;//从矩形图引出线的Y坐标 public double getLeft() { return left; } public void setLeft(double left) { this.left = left; } public double getTop() { return top; } public void setTop(double top) { this.top = top; } public double getWidth() { return width; } public void setWidth(double width) { this.width = width; } public String getEnterpriseName() { return enterpriseName; } public void setEnterpriseName(String enterpriseName) { this.enterpriseName = enterpriseName; } public String getRectangleColor() { return rectangleColor; } public void setRectangleColor(String rectangleColor) { this.rectangleColor = rectangleColor; } public String getCharacterColor() { return characterColor; } public void setCharacterColor(String characterColor) { this.characterColor = characterColor; } public double getLineX() { return lineX; } public void setLineX(double lineX) { this.lineX = lineX; } public double getLineY() { return lineY; } public void setLineY(double lineY) { this.lineY = lineY; } } //细化下矩形的点,为线的起始点做准备 public class RectangleAllDTO extends RectangleDTO{ private double leftX;//矩形框左中点X坐标 private double leftY;//矩形框左中点Y坐标 private double rightX;//矩形框右中点X坐标 private double rightY;//矩形框右中点Y坐标 public double getLeftX() { return leftX; } public void setLeftX(double leftX) { this.leftX = leftX; } public double getLeftY() { return leftY; } public void setLeftY(double leftY) { this.leftY = leftY; } public double getRightX() { return rightX; } public void setRightX(double rightX) { this.rightX = rightX; } public double getRightY() { return rightY; } public void setRightY(double rightY) { this.rightY = rightY; } } //连线的DTO public class LineDTO { private double startX;//起点X坐标 private double startY;//起点Y坐标 private double endX;//终点X坐标 private double endY;//终点Y坐标 private double controlX;//为绘曲线的控制点X坐标 private double controlY;//为绘曲线的控制点Y坐标 private double contentLeft;//内容文字左起点 private double contentTop;//内容文字顶点 private String content;//内容文字 private double contentWidth;//文字宽度 private double contentHeight;//文字高度 private String lineColor;//曲线颜色 private List contentList = new ArrayList();//文字内容列表 public void addContent(LineContentDTO object){ this.contentList.add(object); } public double getStartX() { return startX; } public void setStartX(double startX) { this.startX = startX; } public double getStartY() { return startY; } public void setStartY(double startY) { this.startY = startY; } public double getEndX() { return endX; } public void setEndX(double endX) { this.endX = endX; } public double getEndY() { return endY; } public void setEndY(double endY) { this.endY = endY; } public double getControlX() { return controlX; } public void setControlX(double controlX) { this.controlX = controlX; } public double getControlY() { return controlY; } public void setControlY(double controlY) { this.controlY = controlY; } public double getContentLeft() { return contentLeft; } public void setContentLeft(double contentLeft) { this.contentLeft = contentLeft; } public double getContentTop() { return contentTop; } public void setContentTop(double contentTop) { this.contentTop = contentTop; } public String getContent() { return content; } public void setContent(String content) { this.content = content; } public double getContentWidth() { return contentWidth; } public void setContentWidth(double contentWidth) { this.contentWidth = contentWidth; } public String getLineColor() { return lineColor; } public void setLineColor(String lineColor) { this.lineColor = lineColor; } public List getContentList() { return contentList; } public void setContentList(List contentList) { this.contentList = contentList; } public double getContentHeight() { return contentHeight; } public void setContentHeight(double contentHeight) { this.contentHeight = contentHeight; } } //线上文字的DTO public class LineContentDTO { private double left;//文字内容左起点 private double top; //文字内容顶点 private double width;//文字内容在页面上所占宽度 private String content;//文字具体内容 public double getLeft() { return left; } public void setLeft(double left) { this.left = left; } public double getTop() { return top; } public void setTop(double top) { this.top = top; } public double getWidth() { return width; } public void setWidth(double width) { this.width = width; } public String getContent() { return content; } public void setContent(String content) { this.content = content; } }
页面先生成矩形然后在生成连线,矩形的位置和连线的起始点根据自己的业务需求计算出来,这里就不在叙述。页面显示主要代码:
<div id="Graph_layer" style="position:absolute;z-index:1; left: 30px; top: 0px;"> <#list rectangleList as rectangle> <v:RoundRect id="_x0000_s00201" style="position:absolute;left:${rectangle.left?string('#.##')}px;top:${rectangle.top?string('#.##')}px;width:${rectangle.width?string('#.##')}px;height:20px;z-index:1" fillcolor="${rectangle.rectangleColor}" strokeweight="1px" strokecolor="#5E80A4" arcsize="0.1"> <v:shadow on="T" type="single" color="#b3b3b3" offset="3px,3px"/> </v:RoundRect> <v:shape inset="0px,0px,0px,0px" id="_x0000_s1025" style="position:absolute;left:${rectangle.left?string('#.##')}px;top:${rectangle.top?string('#.##')}px;width:${rectangle.width?string('#.##')}px;height:30px;z-index:1;text-align:center"> <v:textbox><!-- <a οnclick="forward('${rectangle.url}')" href="#" title="点击查看详细信息">--><span class="nameStyle" style="color:${rectangle.characterColor}">${rectangle.enterpriseName}</span></a></v:textbox> </v:shape> </#list> <#list lineList as line> <v:rect id="_x0000_s1044" style="position:absolute;left:${(line.startX-3)?string('#.##')}px;top:${(line.startY-3)?string('#.##')}px;width:6px;height:6px;z-index:1" filled="f" strokecolor="#436589"></v:rect> <v:rect id="_x0000_s1044" style="position:absolute;left:${(line.endX-3)?string('#.##')}px;top:${(line.endY-3)?string('#.##')}px;width:6px;height:6px;z-index:1" filled="f" strokecolor="#436589"></v:rect> <v:curve style="position:absolute;left:0px;top:0px;z-index:1" from="${line.startX?string('#.##')}px,${line.startY?string('#.##')}px" to="${line.endX?string('#.##')}px,${line.endY?string('#.##')}px" filled="f" control1="${line.controlX?string('#.##')}px,${line.controlY?string('#.##')}px" οnclick="javascript:controlCase(this)" strokecolor="${line.lineColor}" strokeweight="1.0px"> <v:stroke opacity="1" startarrow="none" endarrow="block" endarrowwidth="medium" endarrowlength="long"/> </v:curve> <v:rect id="_x0000_s1040" style="position:absolute;left:${line.contentLeft?string('#.##')}px;top:${line.contentTop?string('#.##')}px;width:${line.contentWidth?string('#.##')}px;height:${line.contentHeight?string('#.##')}px;z-index:1" fillcolor="#FFFFFF" stroked="f"> <v:fill type="frame" opacity="0.0"/> </v:rect> <v:shape inset="0px,0px,0px,0px" id="_x0000_s1025" style="position:absolute;left:${line.contentLeft?string('#.##')}px;top:${line.contentTop?string('#.##')}px;width:${line.contentWidth?string('#.##')}px;height:${line.contentHeight?string('#.##')}px;z-index:1;text-align:left"> <v:textbox inset="0px,0px,0px,0px"><span class="lineContentStyle">${line.content}</span></v:textbox> </v:shape> </#list> </div>
上面的是生成图形主要VML代码。在实现的过程中主要是参考了两个教程,下面也贴出来,喜欢的朋友拿去研究研究。
PS:在实现的过程中想把显示的数字放置到线的中点处,探究发现VML中的曲线是贝塞尔曲线,关于更多的贝塞尔曲线可以参考维基百科。
相关资源:敏捷开发V1.0.pptx