VML+XML绘制树型图表(Create a Tree Graph by VML+XML)
如今,Flash、Silverlight在网页图表绘制方面打得火热,但VML(Vector Markup Language)却渐渐被人遗忘,本文是一个VML的使用例子,将XML中的数据用树形图表示在页面上
VML(Vector Markup Language) is an application of Extensible Markup Language (XML) 1.0 which defines a format for the encoding of vector information together with additional markup to describe how that information may be displayed and edited.
code is pick from internet, connect me if you are the author, Thanks.
data.xml
<?xml version="1.0" encoding="utf-8"?>
<Company>
<Manager>
<DepartMentA>
<StafferA1 />
<StafferA2 />
<StafferA3 />
</DepartMentA>
<DepartMentB>
<StafferB1 />
<StafferB2 />
<StafferB3 />
</DepartMentB>
<DepartMentC>
<StafferC1 />
<StafferC2 />
<StafferC3 />
</DepartMentC>
</Manager>
</Company>
<?xml version="1.0" encoding="utf-8"?>
<Company>
<Manager>
<DepartMentA>
<StafferA1 />
<StafferA2 />
<StafferA3 />
</DepartMentA>
<DepartMentB>
<StafferB1 />
<StafferB2 />
<StafferB3 />
</DepartMentB>
<DepartMentC>
<StafferC1 />
<StafferC2 />
<StafferC3 />
</DepartMentC>
</Manager>
</Company>
vml.htm
<html xmlns:v="urn:schemas-microsoft-com:vml">
<head>
<META HTTP-EQUIV="MSThemeCompatible" CONTENT="Yes">
<style type="text/css">
v\:*{
behavior:url(#default#VML);
}
v\:RoundRect{
text-align:center;
position:relative;
}
v\:TextBox{
vertical-align:middle;
font-size:13px;
}
</style>
<script type="text/javascript">
function $(id){
return document.getElementById(id);
}
function Point2D(x,y){
this.x = x;
this.y = y;
}
function Xml2Vml(xmlFile){
this.XML = new ActiveXObject("MSXML2.DOMDocument.5.0");
this.XML.async=false;
this.XML.load(xmlFile);
this.SpanX = 10;
this.SpanY = 25;
this.ItemWidth = 100;
this.ItemHeight = 25;
this.VmlRoot = document.createElement('<v:group coordsize="1000,1000" id="vml" style="width:1000px;height:1000px;">');
}
Xml2Vml.prototype.RecursiveParse = function(rootNode,offset){
var allChild = rootNode.childNodes;
var xOffset = offset.x;
var yOffset = offset.y;
if(allChild.length==0){
rootNode.setAttribute("LeftX",xOffset);
rootNode.setAttribute("RightX",xOffset+this.ItemWidth);
xOffset += this.SpanX + this.ItemWidth;
}else{
for(var i=0;i<allChild.length;i++){
var w = this.RecursiveParse(allChild[i],new Point2D(xOffset,yOffset+2*this.SpanY+this.ItemHeight));
xOffset += this.SpanX + w;
}
rootNode.setAttribute("LeftX",(parseInt(allChild[0].getAttribute("LeftX")) + parseInt(allChild[0].getAttribute("RightX")))/2);
rootNode.setAttribute("RightX",(parseInt(allChild[allChild.length-1].getAttribute("LeftX")) + parseInt(allChild[allChild.length-1].getAttribute("RightX")))/2);
}
rootNode.setAttribute("PosY",yOffset);
return xOffset-offset.x-this.SpanX;
}
Xml2Vml.prototype.ParseXml = function(){
this.RecursiveParse(this.XML.documentElement,new Point2D(0,0));
}
Xml2Vml.prototype.RecursiveRender = function(xmlNode){
var allChild = xmlNode.childNodes;
var xl = xmlNode.getAttribute("LeftX");
var xr = xmlNode.getAttribute("RightX");
var x = (parseInt(xl)+parseInt(xr))/2;
var y = xmlNode.getAttribute("PosY");
var str = xmlNode.tagName;
if(xmlNode!=this.XML.documentElement) this.VmlRoot.appendChild(document.createElement('<v:line from="'+x+','+y+'" to="'+x+','+(parseInt(y)+this.SpanY)+'" />'));
y=parseInt(y)+this.SpanY;
var RoundRect = document.createElement('<v:RoundRect style="width:'+this.ItemWidth+'px;height:'+this.ItemHeight+'px;left:'+(x-this.ItemWidth/2)+'px;top:'+y+'px" align="center">')
RoundRect.appendChild(document.createElement('<v:shadow on="True" type="single" color="#b3b3b3" offset="5px,5px"/>'));
var TextBox = document.createElement('<v:TextBox />');
TextBox.innerHTML = str;
RoundRect.appendChild(TextBox);
this.VmlRoot.appendChild(RoundRect);
if(allChild.length>0){
y += this.ItemHeight+this.SpanY;
this.VmlRoot.appendChild(document.createElement('<v:line from="'+x+','+(y-this.SpanY)+'" to="'+x+','+y+'" />'));
xl = (parseInt(allChild[0].getAttribute("LeftX")) + parseInt(allChild[0].getAttribute("RightX")))/2;
xr = (parseInt(allChild[allChild.length-1].getAttribute("LeftX")) + parseInt(allChild[allChild.length-1].getAttribute("RightX")))/2;
this.VmlRoot.appendChild(document.createElement('<v:line from="'+xl+','+y+'" to="'+xr+','+y+'" />'));
for(var i=0;i<allChild.length;i++) this.RecursiveRender(allChild[i]);
}
}
Xml2Vml.prototype.RenderVml = function(){
this.RecursiveRender(this.XML.documentElement);
}
</script>
</head>
<body>
<center>
<div id="div" style="WIDTH: 1000px; HEIGHT: 1000px"></div>
</center>
<script type="text/javascript">
var Ins = new Xml2Vml("data.xml");
Ins.ParseXml();
Ins.RenderVml();
$("div").appendChild(Ins.VmlRoot);
</script>
</body>
</html>
<html xmlns:v="urn:schemas-microsoft-com:vml">
<head>
<META HTTP-EQUIV="MSThemeCompatible" CONTENT="Yes">
<style type="text/css">
v\:*{
behavior:url(#default#VML);
}
v\:RoundRect{
text-align:center;
position:relative;
}
v\:TextBox{
vertical-align:middle;
font-size:13px;
}
</style>
<script type="text/javascript">
function $(id){
return document.getElementById(id);
}
function Point2D(x,y){
this.x = x;
this.y = y;
}
function Xml2Vml(xmlFile){
this.XML = new ActiveXObject("MSXML2.DOMDocument.5.0");
this.XML.async=false;
this.XML.load(xmlFile);
this.SpanX = 10;
this.SpanY = 25;
this.ItemWidth = 100;
this.ItemHeight = 25;
this.VmlRoot = document.createElement('<v:group coordsize="1000,1000" id="vml" style="width:1000px;height:1000px;">');
}
Xml2Vml.prototype.RecursiveParse = function(rootNode,offset){
var allChild = rootNode.childNodes;
var xOffset = offset.x;
var yOffset = offset.y;
if(allChild.length==0){
rootNode.setAttribute("LeftX",xOffset);
rootNode.setAttribute("RightX",xOffset+this.ItemWidth);
xOffset += this.SpanX + this.ItemWidth;
}else{
for(var i=0;i<allChild.length;i++){
var w = this.RecursiveParse(allChild[i],new Point2D(xOffset,yOffset+2*this.SpanY+this.ItemHeight));
xOffset += this.SpanX + w;
}
rootNode.setAttribute("LeftX",(parseInt(allChild[0].getAttribute("LeftX")) + parseInt(allChild[0].getAttribute("RightX")))/2);
rootNode.setAttribute("RightX",(parseInt(allChild[allChild.length-1].getAttribute("LeftX")) + parseInt(allChild[allChild.length-1].getAttribute("RightX")))/2);
}
rootNode.setAttribute("PosY",yOffset);
return xOffset-offset.x-this.SpanX;
}
Xml2Vml.prototype.ParseXml = function(){
this.RecursiveParse(this.XML.documentElement,new Point2D(0,0));
}
Xml2Vml.prototype.RecursiveRender = function(xmlNode){
var allChild = xmlNode.childNodes;
var xl = xmlNode.getAttribute("LeftX");
var xr = xmlNode.getAttribute("RightX");
var x = (parseInt(xl)+parseInt(xr))/2;
var y = xmlNode.getAttribute("PosY");
var str = xmlNode.tagName;
if(xmlNode!=this.XML.documentElement) this.VmlRoot.appendChild(document.createElement('<v:line from="'+x+','+y+'" to="'+x+','+(parseInt(y)+this.SpanY)+'" />'));
y=parseInt(y)+this.SpanY;
var RoundRect = document.createElement('<v:RoundRect style="width:'+this.ItemWidth+'px;height:'+this.ItemHeight+'px;left:'+(x-this.ItemWidth/2)+'px;top:'+y+'px" align="center">')
RoundRect.appendChild(document.createElement('<v:shadow on="True" type="single" color="#b3b3b3" offset="5px,5px"/>'));
var TextBox = document.createElement('<v:TextBox />');
TextBox.innerHTML = str;
RoundRect.appendChild(TextBox);
this.VmlRoot.appendChild(RoundRect);
if(allChild.length>0){
y += this.ItemHeight+this.SpanY;
this.VmlRoot.appendChild(document.createElement('<v:line from="'+x+','+(y-this.SpanY)+'" to="'+x+','+y+'" />'));
xl = (parseInt(allChild[0].getAttribute("LeftX")) + parseInt(allChild[0].getAttribute("RightX")))/2;
xr = (parseInt(allChild[allChild.length-1].getAttribute("LeftX")) + parseInt(allChild[allChild.length-1].getAttribute("RightX")))/2;
this.VmlRoot.appendChild(document.createElement('<v:line from="'+xl+','+y+'" to="'+xr+','+y+'" />'));
for(var i=0;i<allChild.length;i++) this.RecursiveRender(allChild[i]);
}
}
Xml2Vml.prototype.RenderVml = function(){
this.RecursiveRender(this.XML.documentElement);
}
</script>
</head>
<body>
<center>
<div id="div" style="WIDTH: 1000px; HEIGHT: 1000px"></div>
</center>
<script type="text/javascript">
var Ins = new Xml2Vml("data.xml");
Ins.ParseXml();
Ins.RenderVml();
$("div").appendChild(Ins.VmlRoot);
</script>
</body>
</html>