重用ADOBE报表图形
来源:互联网 发布:考研网络课程哪家好 编辑:程序博客网 时间:2024/05/21 23:22
下面通过一个实例了解一下SVG重用的过程。报表是我们经常需要用到的图形元素,首先我们从ADOBE SVG站点上得到了一个SVG图表的例子,这是用Adobe Illustrator 9.0画的DEMO,做的非常漂亮,我们的目的是希望重用其中的报表图形。
大致思路如下,分析其中的SVG图形,样式以及JAVASCRIPT代码,并分离出我们使用的主要接口,然后通过这些接口,将自己的数据显示出来。
通过分析,确定该例子包括:
1,一个饼图,鼠标在上面移动可以显示该部分的数据和比例
2,一个柱状图,鼠标移动可以显示高度坐标
3,背景和标题
我们的工作流程如下:
1,确定接口,为简单起见,我们仅仅使用四个接口,剩下的操作对我们来说是透明的,并不需要关心他们的具体内容
Initialize 初始化图形,为避免歧义,将原来的函数改名为InitialCharts
SetTitle 设置标题
AddChartValue 添加数值
ClearChart 将图形数值清除
2,将代码和SVG元素分离,将所有的样式和CSS定义与SVG放在一起,这样在装载SVG时就可以不丢失原有的样式了。文件分别保存为Reusablecharts.js和Reusablecharts.svg
3,创建myCharts.svg, 并装载Reusablecharts.js和Reusablecharts.svg图形到该文档。这些在以前的例子中都演示过,就不详细介绍了。
4,确定我们要显示的数据源,这里可以简单的编几个数据,也可以复杂一点,从网上或数据库中取得数据。这里还是使用我的BLOG RSS
5,显示报表
使用AddChartValue将XMLHTTPREQUEST取得RSS数据加入报表
对Reusablecharts.js中代码做一些必要的改动:
1,将原来初始化函数中的SVGDocument移动到新的SVG初始化函数中
2,由于动态加载SVG时,SVGDocument进行了优化,空的(例如只有回车符)TEXT节点被优化为无子节点的TEXT节点,例如
<text id="XPos" x="0" y="10">
</text>成为<text id="XPos" x="0" y="10"/>
所以代码在静态SVG时可以通过,而动态加载时有问题,例如在原代码中的
NewItem = SVGDocument.createTextNode(Value + Percent)
SVGDocument.getElementById("labelamount").replaceChild(NewItem, SVGDocument.getElementById("labelamount").getFirstChild())
就会报“无效对象”错误。
所以改为
if(SVGDocument.getElementById("labelamount").hasChildNodes() == true)
SVGDocument.getElementById("labelamount").getFirstChild().setData( Value + Percent);
else
{
NewItem = SVGDocument.createTextNode(Value + Percent)
SVGDocument.getElementById("labelamount").appendChild(NewItem);
}
这样的地方有几处。
我们一共添加了3个变量,7个函数,修改了几个函数后,就可以使用了。如果想去掉其中背景和辅助图形,只保留报表图形也很简单。
最后的代码如下:
MyCharts.svg:
<svg onload="myInit(evt)" width="100%" height="100%">
<title>SVG REPORT REUSE DEMO</title>
<script xlink:href="ReusableCharts.js"/>
<script type="text/javascript">
<![CDATA[
var svgns = "http://www.w3.org/2000/svg";
var dataUrl = "http://blog.csdn.net/firefight/Rss.aspx";
//var svgUrl = "http://localhost/svg/ReusableCharts.svg";
var svgUrl = "http://bbs.xml.org.cn/UploadFile/20068141358690824.txt";
function myInit(evt)
...{
SVGDocument = evt.getTarget().getOwnerDocument();
//Get reusable SVG charts
getSvgCharts();
//Set charts entry points
InitialCharts();
//Get data from blog RSS
getChartData();
//Refresh data every 10 seconds
setTimeout("getChartData()",10000);
}
function getDataByXmlHttp(url)
...{
var xmlhttp;
var error;
var s = null;
//Create XMLHTTP object
eval('try {xmlhttp = new ActiveXObject("Microsoft.XMLHTTP"); } catch (e) {xmlhttp = null;error=e;}');
if(null != xmlhttp)
...{
xmlhttp.Open("GET", url, false);
xmlhttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
xmlhttp.Send();
s = xmlhttp.responseText;
}
return s;
}
function getSvgCharts()
...{
var s = getDataByXmlHttp(svgUrl);
//alert(s);
//Include into local svg document
var newNode = parseXML(s, SVGDocument);
//alert(printNode(newNode));
var svgElem = SVGDocument.getElementById("newRoot");
svgElem.appendChild(newNode);
//svgElem = SVGDocument.getElementById("labelamount");
//alert(printNode(svgElem));
}
function getChartData()
...{
var s = getDataByXmlHttp(dataUrl);
//alert(s);
var xml_dom = new ActiveXObject("MSXML2.DOMDocument");
//alert(xmlhttp.responseText);
xml_dom.loadXML(s);
drawText(xml_dom);
}
function drawText(xml)
...{
//Remove all
ClearChart();
//Set char title
SetTitle("My Blog Comments Statistic");
//Get data
var nodes = xml.selectNodes("/rss/channel/item");
var count = 0;
while(nodes[count]!=null)
...{
//Get artical and comment time values from my blog RSS
var title = nodes[count].getElementsByTagName("title");
var commentTimes = nodes[count].getElementsByTagName("slash:comments");
var times = Number( commentTimes[0].text )*10 + 5;
//Add data to chart
AddChartValue(times, title[0].text ,false);
count++;
}
//Update date time
yy_datetime();
}
function setTextNodeValue(id, value)
...{
if(SVGDocument.getElementById( id ).hasChildNodes() == true)
SVGDocument.getElementById( id ).getFirstChild().setData( value );
else
...{
NewItem = SVGDocument.createTextNode( value )
SVGDocument.getElementById( id ).appendChild(NewItem);
}
}
function yy_datetime()
...{
var datetime,temp,date,time;
datetime = new Date().toLocaleString();
temp = datetime.lastIndexOf(" ");
date = datetime.substring(0,temp);
time = datetime.substring(temp+1,datetime.length);
setTextNodeValue("updateTime", "Update time: " + date + " " + time);
}
// ]]></script>
<!-- Fix svg item place here -->
<svg id="skeleton" x="50" y="50">
<text id="updateTime" x="300" y="480"/>
</svg>
<!-- Dynamic svg item place here -->
<svg id="newRoot"/>
</svg>
ReusableCharts.js:
"#C2A00E",
"#71A214",
"#3399CC",
"#CC99FF",
"#FF9999",
"#00CC99",
"#C2CC0E",
"#71CC14",
"#CC68CC",
"#66FFCC")
ActiveSegment = "Pie"
CurrentColor = 0;
SVGDocument = null
BarChartHeight = 150
BarChartWidth = 250
PieChartSize = 140
MoveDistance = 40
Values = new Array()
Names = new Array()
PieElements = new Array()
BarElements = new Array()
BarTexts = new Array()
DeleteList = new Array()
PieTotalSize = 0;
BarTotalSize = 0;
MaxSize = 0;
AngleFactor = Math.pow(2, .5)
Removed = false
function InitialCharts()
...{
//Get entry port
ParentGroup1 = SVGDocument.getElementById("slices")
Grandparent1 = SVGDocument.getElementById("piechart")
ParentGroup2 = SVGDocument.getElementById("bars")
Grandparent2 = SVGDocument.getElementById("barchart")
}
function ClearChart()
...{
for (var I = 0; I < PieElements.length; I++)
...{
ParentGroup1.removeChild(PieElements[I])
ParentGroup2.removeChild(BarElements[I])
SVGDocument.getElementById("labels").removeChild(Names[I])
}
PieElements = new Array()
BarElements = new Array()
BarTexts = new Array()
Values = new Array()
Names = new Array()
PieTotalSize = 0;
BarTotalSize = 0;
MaxSize = 0;
if (!(Removed))
...{
Grandparent1.removeChild(ParentGroup1)
Grandparent2.removeChild(ParentGroup2)
}
Removed = true
}
function AddChartValue(Value, Name, Repress)
...{
Value = Value * 1
if ((Value <= 0) || (isNaN(Value)))
...{
alert("Negative, textual or null values are not allowed")
return;
}
Color = ColorArray[CurrentColor]
CurrentColor++
if (CurrentColor >= ColorArray.length) CurrentColor = 0
if (!(Removed))
...{
Grandparent1.removeChild(ParentGroup1)
Grandparent2.removeChild(ParentGroup2)
}
DeleteList[DeleteList.length] = false
Values[Values.length] = Value * 1
Names[Names.length] = SVGDocument.createElement("text")
PieElements[PieElements.length] = SVGDocument.createElement("path")
PieElements[PieElements.length - 1].setAttribute("style", "stroke:black;fill:" + Color)
PieElements[PieElements.length - 1].setAttribute("onmouseover", "DisplayInfo('" + Name + "', '" + Value + "')")
PieElements[PieElements.length - 1].setAttribute("onmouseout", "DisplayInfo(' ', ' ')")
ParentGroup1.appendChild(PieElements[PieElements.length - 1])
BarElements[BarElements.length] = SVGDocument.createElement("path")
BarTexts[BarTexts.length] = SVGDocument.createElement("text")
BarElements[BarElements.length - 1].setAttribute("style", "stroke:black;fill:" + Color)
BarElements[BarElements.length - 1].setAttribute("onmouseover", "BarTexts[" + (BarTexts.length - 1) + "].getStyle().setProperty('visibility', 'show')")
BarElements[BarElements.length - 1].setAttribute("onmouseout", "BarTexts[" + (BarTexts.length - 1) + "].getStyle().setProperty('visibility', 'hidden')")
ParentGroup2.appendChild(BarElements[BarElements.length - 1])
BarTexts[BarTexts.length - 1].setAttribute("style", "text-anchor:end;font-weight:bold;font-size:13;visibility:hidden")
BarTexts[BarTexts.length - 1].setAttribute("x", "188")
BarTexts[BarTexts.length - 1].appendChild(SVGDocument.createTextNode(Value + " -"))
SVGDocument.getElementById("barsidetext").appendChild(BarTexts[BarTexts.length - 1])
Names[Names.length - 1].appendChild(SVGDocument.createTextNode(Name + ""))
Names[Names.length - 1].setAttribute("transform", "rotate(45)")
SVGDocument.getElementById("labels").appendChild(Names[Names.length - 1])
Refresh()
if (Repress)
Removed = true
else
...{
Removed = false
Grandparent1.appendChild(ParentGroup1)
Grandparent2.appendChild(ParentGroup2)
}
}
function Refresh()
...{
PieTotalSize = 0
BarTotalSize = 0
MaxSize = 0
for (var I = 0; I < Values.length; I++)
...{
PieTotalSize += Values[I]
BarTotalSize++
if (Values[I] > MaxSize)
MaxSize = Values[I]
}
PieStart = 0
BarStart = 0
if (PieTotalSize > 0)
for (var I = 0; I < Values.length; I++)
...{
PieStart = DrawPieSegment(PieStart, Values[I] / PieTotalSize, PieElements[I], I)
BarStart = DrawBarSegment(BarStart, Values[I] / MaxSize, BarElements[I], BarTexts[I], Names[I])
}
SVGDocument.getElementById("max").replaceChild(SVGDocument.createTextNode(MaxSize + ""), SVGDocument.getElementById("max").getFirstChild())
SVGDocument.getElementById("min").replaceChild(SVGDocument.createTextNode("0"), SVGDocument.getElementById("min").getFirstChild())
}
function DeleteSegment()
...{
if (ActiveSegment == "Pie")
...{
NewValues = new Array()
NewNames = new Array()
NewPieElements = new Array()
NewBarElements = new Array()
NewBarTexts = new Array()
NewDeleteList = new Array()
SomethingDeleted = false
CurrentCopySpot = 0
for (var I = 0; I < PieElements.length; I++)
...{
if (!(DeleteList[I]))
...{
NewValues[CurrentCopySpot] = Values[I]
NewNames[CurrentCopySpot] = Names[I]
NewPieElements[CurrentCopySpot] = PieElements[I]
NewBarElements[CurrentCopySpot] = BarElements[I]
NewBarTexts[CurrentCopySpot] = BarTexts[I]
NewDeleteList[CurrentCopySpot] = DeleteList[I]
NewBarElements[CurrentCopySpot].setAttribute("onmouseover", "BarTexts[" + CurrentCopySpot + "].getStyle().setProperty('visibility', 'show')")
NewBarElements[CurrentCopySpot].setAttribute("onmouseout", "BarTexts[" + CurrentCopySpot + "].getStyle().setProperty('visibility', 'hidden')")
CurrentCopySpot++
}
else
...{
SomethingDeleted = true
PieElements[I].getParentNode().removeChild(PieElements[I])
BarElements[I].getParentNode().removeChild(BarElements[I])
BarTexts[I].getParentNode().removeChild(BarTexts[I])
Names[I].getParentNode().removeChild(Names[I])
}
}
if (SomethingDeleted)
...{
Values = NewValues
Names = NewNames
PieElements = NewPieElements
BarElements = NewBarElements
BarTexts = NewBarTexts
DeleteList = NewDeleteList
Refresh()
}
else
alert("To delete segments, click on the segments to be deleted to pull them out, then click on the Delete button")
}
else
...{
NewValues = new Array()
NewNames = new Array()
NewPieElements = new Array()
NewBarElements = new Array()
NewBarTexts = new Array()
NewDeleteList = new Array()
SomethingDeleted = false
CurrentCopySpot = 0
for (var I = 0; I < PieElements.length - 1; I++)
...{
NewValues[I] = Values[I]
NewNames[I] = Names[I]
NewPieElements[I] = PieElements[I]
NewBarElements[I] = BarElements[I]
NewBarTexts[I] = BarTexts[I]
NewDeleteList[I] = DeleteList[I]
NewBarElements[I].setAttribute("onmouseover", "BarTexts[" + CurrentCopySpot + "].getStyle().setProperty('visibility', 'show')")
NewBarElements[I].setAttribute("onmouseout", "BarTexts[" + CurrentCopySpot + "].getStyle().setProperty('visibility', 'hidden')")
CurrentCopySpot++
}
if (PieElements.length > 0)
...{
SomethingDeleted = true
PieElements[PieElements.length - 1].getParentNode().removeChild(PieElements[PieElements.length - 1])
BarElements[PieElements.length - 1].getParentNode().removeChild(BarElements[PieElements.length - 1])
BarTexts[PieElements.length - 1].getParentNode().removeChild(BarTexts[PieElements.length - 1])
Names[PieElements.length - 1].getParentNode().removeChild(Names[PieElements.length - 1])
}
if (SomethingDeleted)
...{
Values = NewValues
Names = NewNames
PieElements = NewPieElements
BarElements = NewBarElements
BarTexts = NewBarTexts
DeleteList = NewDeleteList
Refresh()
}
}
}
parent.deleteOuties = DeleteSegment
function DrawBarSegment(Start, Height, Element, Text, Label)
...{
XOffset3D = 10
YOffset3D = 5
PathData = "M" + (Start + (BarChartWidth / BarTotalSize)) + ",0"
PathData = PathData + "h" + (BarChartWidth / BarTotalSize * -1)
PathData = PathData + "v" + (Height * BarChartHeight * -1)
PathData = PathData + "l" + XOffset3D + ",-" + YOffset3D
PathData = PathData + "h" + (BarChartWidth / BarTotalSize)
PathData = PathData + "v" + (Height * BarChartHeight)
PathData = PathData + "l-" + XOffset3D + "," + YOffset3D
PathData = PathData + "v" + (Height * BarChartHeight * -1)
PathData = PathData + "h" + (BarChartWidth / BarTotalSize * -1)
PathData = PathData + "h" + (BarChartWidth / BarTotalSize)
PathData = PathData + "l" + XOffset3D + ",-" + YOffset3D
PathData = PathData + "l-" + XOffset3D + "," + YOffset3D
Element.setAttribute("d", PathData)
Label.setAttribute("x", Start / AngleFactor)
Label.setAttribute("y", Start * -1 / AngleFactor)
Text.setAttribute("y", (275 - BarChartHeight * Height))
return Start + BarChartWidth / BarTotalSize
}
function DrawPieSegment(Start, Size, Element, ID)
...{
PathData = "M0,0L"
PathData = PathData + PieChartSize * Math.sin(Start * Math.PI * 2) + "," + PieChartSize * Math.cos(Start * Math.PI * 2)
if (Size >= .5)
PathData = PathData + "A" + PieChartSize + " " + PieChartSize + " 1 1 0 " + PieChartSize * Math.sin((Start + Size) * Math.PI * 2) + "," + PieChartSize * Math.cos((Start + Size) * Math.PI * 2)
else
PathData = PathData + "A" + PieChartSize + " " + PieChartSize + " 0 0 0 " + PieChartSize * Math.sin((Start + Size) * Math.PI * 2) + "," + PieChartSize * Math.cos((Start + Size) * Math.PI * 2)
PathData = PathData + "z"
Element.setAttribute("d", PathData)
if (Start > 0)
Element.setAttribute("onclick", "MoveSegment(evt, " + (Start + Size / 2) + ", true, " + ID + ")")
else
...{
DeleteList[ID] = true;
Angle = Start + Size / 2
X = MoveDistance * Math.sin(Angle * 2 * Math.PI)
Y = MoveDistance * Math.cos(Angle * 2 * Math.PI)
Element.setAttribute("transform", "translate(" + X + "," + Y + ")")
Element.setAttribute("onclick", "MoveSegment(evt, " + ((Start + Size / 2) * -1) + ", false, " + ID + ")")
}
return Start + Size
}
function MoveSegment(MouseEvent, Angle, CanBeDeleted, ID)
...{
Element = MouseEvent.getTarget()
if (Angle < 0)
...{
X = 0
Y = 0
}
else
...{
X = MoveDistance * Math.sin(Angle * 2 * Math.PI)
Y = MoveDistance * Math.cos(Angle * 2 * Math.PI)
}
DeleteList[ID] = CanBeDeleted
Element.setAttribute("transform", "translate(" + X + "," + Y + ")")
Element.setAttribute("onclick", "MoveSegment(evt, " + (Angle * -1) + ", " + (!CanBeDeleted) + ", " + ID + ")")
}
function DisplayInfo(Text, Value)
...{
if (Text != " ")
Percent = " (" + Math.round(Value / PieTotalSize * 10000) / 100 + "%)"
else
Percent = ""
if(SVGDocument.getElementById("labelamount").hasChildNodes() == true)
SVGDocument.getElementById("labelamount").getFirstChild().setData( Value + Percent);
else
...{
NewItem = SVGDocument.createTextNode(Value + Percent)
SVGDocument.getElementById("labelamount").appendChild(NewItem);
}
if(SVGDocument.getElementById("labelitem").hasChildNodes() == true)
SVGDocument.getElementById("labelitem").getFirstChild().setData(Text + "");
else
...{
NewItem = SVGDocument.createTextNode(Text + "")
SVGDocument.getElementById("labelitem").appendChild(NewItem);
}
if (Text + Value == " ")
s = " ";
else
s = ":";
if(SVGDocument.getElementById("labelcolon").hasChildNodes() == true)
SVGDocument.getElementById("labelcolon").getFirstChild().setData( s );
else
...{
NewItem = SVGDocument.createTextNode( s )
SVGDocument.getElementById("labelcolon").appendChild(NewItem);
}
//Original code has some problems
/**//*NewItem = SVGDocument.createTextNode(Value + Percent)
SVGDocument.getElementById("labelamount").replaceChild(NewItem, SVGDocument.getElementById("labelamount").getFirstChild())
NewItem = SVGDocument.createTextNode(Text + "")
SVGDocument.getElementById("labelitem").replaceChild(NewItem, SVGDocument.getElementById("labelitem").getFirstChild())
if (Text + Value == " ")
NewItem = SVGDocument.createTextNode(" ")
else
NewItem = SVGDocument.createTextNode(":")
SVGDocument.getElementById("labelcolon").replaceChild(NewItem, SVGDocument.getElementById("labelcolon").getFirstChild())*/
}
function SetTitle(Text)
...{
if(SVGDocument.getElementById("title").hasChildNodes() == true)
SVGDocument.getElementById("title").getFirstChild().setData( Text + "" );
else
...{
NewItem = SVGDocument.createTextNode( Text + "" )
SVGDocument.getElementById("title").appendChild(NewItem);
}
//Original code has some problems
/**//*NewItem = SVGDocument.createTextNode(Text + "")
SVGDocument.getElementById("title").replaceChild(NewItem, SVGDocument.getElementById("title").getFirstChild())
*/
}
function SetAxis(Text)
...{
NewItem = SVGDocument.createTextNode(Text + "")
SVGDocument.getElementById("axis").replaceChild(NewItem, SVGDocument.getElementById("axis").getFirstChild())
NewItem = SVGDocument.createTextNode(Text + "")
SVGDocument.getElementById("subtitle").replaceChild(NewItem, SVGDocument.getElementById("subtitle").getFirstChild())
}
function ShowPie()
...{
ActiveSegment = "Pie"
SVGDocument.getElementById("showpierect").getStyle().setProperty("fill", "blue");
SVGDocument.getElementById("showbarrect").getStyle().setProperty("fill", "#FC8D4F");
SVGDocument.getElementById("barchart").getStyle().setProperty("visibility", "hidden");
SVGDocument.getElementById("subtitle").getStyle().setProperty("visibility", "show");
SVGDocument.getElementById("piechart").getStyle().setProperty("visibility", "show");
SVGDocument.getElementById("pieitemlabel").getStyle().setProperty("visibility", "show");
SVGDocument.getElementById("barsidetext").getStyle().setProperty("visibility", "hidden");
}
function ShowBar()
...{
ActiveSegment = "Bar"
SVGDocument.getElementById("showpierect").getStyle().setProperty("fill", "#FC8D4F");
SVGDocument.getElementById("showbarrect").getStyle().setProperty("fill", "blue");
SVGDocument.getElementById("barchart").getStyle().setProperty("visibility", "show");
SVGDocument.getElementById("subtitle").getStyle().setProperty("visibility", "hidden");
SVGDocument.getElementById("piechart").getStyle().setProperty("visibility", "hidden");
SVGDocument.getElementById("pieitemlabel").getStyle().setProperty("visibility", "hidden");
SVGDocument.getElementById("barsidetext").getStyle().setProperty("visibility", "show");
}
parent.clearChart = ClearChart
parent.addChartValue = AddChartValue
parent.setTitle = SetTitle
parent.setAxis = SetAxis
ReusableCharts.svg放在http://bbs.xml.org.cn/UploadFile/20068141358690824.txt
效果如下:
是不是比我自己画的柱状图好看多了,而且功能强大,更重要的是并没有编写多少代码。而且可以供更多人使用。
从这个例子可以看出,在拿到一个SVG文档后,重用其中我们感兴趣的部分是比较简单的。
在该例子中,可重用的代码中全部采用根据ID进行定位的方法(getElementById),为重用代码提供了方便和可能。
为避免重用部分的ID与用户的ID冲突,以及今后嵌套包含时判断是否已经引入该部分图形,所有的可重用部分的ID应当有自己的命名空间,以保证ID的唯一性。
- 重用ADOBE报表图形
- 图形报表
- [修改]js图形报表
- [修改]js图形报表
- 简单图形报表
- JFreeChart图形报表实例
- 话说图形报表
- flex图形报表
- 报表 统计(图形)
- jfreechart图形报表
- 各种图形报表
- js图形报表
- 图形报表组件
- highCharts图形报表神器
- amcharts图形报表
- 图形报表,HighCharts
- FusionCharts绘制图形报表
- JSChart_页面图形报表
- 什么是module 以及如何写一个module
- GDIPLUS
- 世界编程语言排名:Ruby崛起,狂升15位
- 黑色星期一颠覆“百度神话” 故事还能讲多久?
- 北京特色小店
- 重用ADOBE报表图形
- 商业地产管理软件
- Spring中的getBean
- 测试速度
- PC市场排位继续变化:惠普PK戴尔
- Cannot find message resources under key org.apache.struts.action.MESSAGE的错误
- 动网论坛权限提升漏洞
- XML——连接SQL和Web程序的桥梁
- System.map文件的作用