Use VML to create a full Statistical Chart (pie chart) [from csdn]

Source: Internet
Author: User
Abstract:

VML is a vector graphics implementation embedded in Microsoft IE 5.0 and later versions. Although Ms also advocates the use of SVG in the future, it serves as an embedded markup language for IE, in some cases, applications are more convenient. This article describes the creation process of a statistical pie chart to show the Web charm of VML.ArticleBy implementing a javascript class, you can see the entire pie chart creation process.

Since its publication, Vector Markup Language (VML) seems to be in an unknown state. Till now, the situation has not changed. In fact, if you are careful, you can find that many Ms products are still built-in on the web. The most typical example is the custom image of office, which stores word or PPT documents as HTML, if a custom image is used in the document, you can see that those images are expressed using VML. Another typical application is the tool for exporting Visio to the Web.

Some time ago, James gave an example of using ASP to generate a Statistical Chart in csdn. I also readCodeAnd asked him for some questions. James's color was very good. Unfortunately, I didn't have that skill, so I used random color in code implementation, the overall interface may look a little bad.

A typical statistical chart is a pie chart, bar chart, and curve chart. This article focuses on the pie production process. The article uses JavaScript to implement a class. If the related JavaScript object-oriented is not particularly familiar, for more information, see my other articles "Object-Oriented JavaScript programming" and "on Object-Oriented JavaScript programming".

For the moment, we do not consider how to implement it. Let's first look at the final use of the code.

Objpie = new vmlpie ("600px", "450px", "demographic Chart"); // initialize width, height, title
Objpie. borderwidth = 3; // chart border
Objpie. bordercolor = "blue"; // chart border color
Objpie. width = "800px"; // defines the chart width.
Objpie. Height = "600px"; // defines the chart height.
Objpie. backgroundcolor = "# ffffff"; // defines the background color.
Objpie. Shadow = true; // whether shadow is required. Set true to false to avoid shadow.
// Add chart data
// The Order is name, value, and description.
Objpie. adddata ("Beijing", 50, "Beijing population ");
Objpie. adddata ("Shanghai", 52, "fixed population in Shanghai ");
Objpie. adddata ("Tianjin", 30, "population outside Tianjin ");
Objpie. adddata ("Xi'an", 58, "Xi'an Urban Population ");
Objpie. adddata ("Wuhan", 30, "Wuhan's field population ");
Objpie. adddata ("Chongqing", 58, "Chongqing urban population ");
Result. innerhtml = objpie. Draw (); // generate VML data

This code is the final call. I encapsulated a javascript class of vmlpie, and the focus of this article is to describe the specific implementation process of the class in detail, in addition, to use VML, you must make the following statement.

1. namespace Declaration for HTML tags

<HTML xmlns: V = "urn: Schemas-Microsoft-com: VML" xmlns: O = "urn: Schemas-Microsoft-com: Office: office">

2. Style Declaration between

<Style>
V \: * {behavior: URL (# default # VML )}
O \: * {behavior: URL (# default # VML )}
. Shape {behavior: URL (# default # VML )}
</Style>
After completing the above work, the code can be complete.

Now we are going to talk about the implementation of vmlpie. First, I will give a simple description of the implemented functions.

// vmlpic main function, which allows you to create a vmlpie instance
function vmlpie (pwidth, pheight, pcaption, pcontainer) {}< br> // start drawing, draw the image to the specified container
vmlpie. prototype. draw = function () {}< br> // each block of the pie chart
vmlpie. prototype. createpie = function () {}< br> // interface function:
// zoom in or out the image
// parameter description:
// ivalue: A multiple of magnification or reduction. 1 is the size of the source image, 0.5 is the size of the source image, 2 is the size of the source image
// twice, and so on
vmlpie. prototype. zoom = function (ivalue) {}< br> // interface function:
// Add pie chart data
// parameter description:
// sname: DATA tag name
// svalue: data value
// stooltiptext: data description
vmlpie. prototype. adddata = function (sname, svalue, stooltiptext) {}< br> // interface function:
// clear all data
vmlpie. prototype. clear = function () {}< br> // The following four functions are extended and provide VML interaction
function hoverpie (EL) {}< br> function restorepie (EL) {}< br> function legendmouseoverevent () {}< br> function legendmouseoutevent () {}

After reading the descriptions of these functions, I think the readers have a general idea about the structure of the entire class. However, there may not be a clear idea about VML creation, next, I will introduce several VML elements. I will just give a general introduction to some usage details, which will be detailed in the American Leopard's "VML Chinese tutorial, if you are interested, refer to the reference.

1. V: Group

As a container for other VML elements, its coordsize attribute defines its coordinate size. The positions of the internal elements are only relative to the coordsize defined by the group element. Assume that coordsize is defined, it defines the canvas of 21600*21600. If there is a V: shape or other elements inside, shape. style. left = "2160px". The actual position is only at the 1/10 width of the V: group.

2. V: rect

Defines a rectangle element. fillcolor indicates the filled background color, stokecolor indicates the border color, and strokeweight indicates the Border width.

3. V: Shape

The default shape element provided by VML can define any shape by defining the path. For the usage of the path, refer to W3C documentation.

4. V: Fill

As a child element of shape, it is used to set the background Effect of shape. The fill method is set through type. The usage is as follows:

1) solid: solid fill, set fill color through color

2) gradient: linear gradient. In this case, the color and color2 parameters are required to set the start color and end color of the gradient. In angle, the gradient direction is set.

3) gradientradial: the gradient of the center. Other methods are similar to gradient.

4) Tile: uses image tile and SRC to set the image

5) pattern: use an image as a stamp filling mode.

6) frame: use images to attract gods

In addition, Opacity is used to set transparency.

5. V: Shadow

To set whether the shape needs shadow, the following parameters are used:

On: sets whether to enable shadow.

Color: shadow color

Offset: Shadow Deviation

6. V: textbox

Define the text area of a shape

These elements need to be used in vmlpie production, so I made a brief introduction. For details, refer to Leopard's "VML Chinese tutorial". in addition, the Vector Markup Language (VML) SDK document in msdn is a good reference. W3C note is abstract and is also a very important reference for some in-depth development.

After completing a series of preparations, we should start to introduce how to draw pie. First, let's take a look at the following one to clearly describe the element structure of vmlpie.

To clearly display the text structure of VML, I use the XML format as follows.




VML pie chart










Chongqing (50)



after completing the basic idea of plotting, the rest is to gradually complete the creation process through DOM. For the sake of simplicity, we will analyze the function installation step by step.

1. vmlpie

This. Container = pcontainer;
This. width = pwidth | "400px ";
This. Height = pheight | "250px ";
This. Caption = pcaption | "VML Chart ";
This. backgroundcolor = "";
This. Shadow = false;
This. borderwidth = 0;
This. bordercolor = NULL;
This. All = new array ();
This. ID = Document. uniqueid;
This. randcolor = function (){
Return "RGB (" + parseint (math. random () * 255) + "," + parseint (math. random () * 255) + "," + parseint (math. random () * 255) + ")";
}
This. vmlobject = NULL;
This. legendobject = NULL;

This function just initializes some variables and declares some attributes that can be used by the class. The randcolor function is used to generate random colors. As mentioned above, random colors are used for the color of each block in a pie chart, one problem is that sometimes the two colors are very similar. I would be grateful if I could provide several basic color lists.

2. vmlpie. Prototype. adddata

Add chart data. Here I use prototype lagging loading. If you think this is not clear enough, you can change it to a built-in form like this. randcolor.

The implementation code is as follows:

Vmlpie. Prototype. adddata = function (sname, svalue, stooltiptext ){
VaR odata = new object ();
Odata. Name = sname;
Odata. value = svalue;
Odata. tooltiptext = stooltiptext;
VaR icount = this. All. length;
This. All [icount] = odata;
}
Here, an object is used to store each data item and then put it in the array of this. All.

3. vmlpie. Prototype. Draw

The most critical function for the implementation of the entire class, that is, drawing the image step by step in this function and subsequent createpie functions.

// draws an external frame
var o = document. createelement ("V: group");
O. id = This. ID;
O. style. width = This. width;
O. style. height = This. height;
O. coordsize = "21600,21600";
// Add a background layer
var vrect = document. createelement ("V: rect");
vrect. style. width = "21600px"
vrect. style. height = "21600px"
O. appendchild (vrect);
// Add the title
var vcaption = document. createelement ("V: textbox");
vcaption. style. fontsize = "24px";
vcaption. style. height = "24px"
vcaption. presize = "24";
vcaption. style. fontweight = "bold";
vcaption. innerhtml = This. caption;
vcaption. style. textalign = "center";

Vrect. appendchild (vcaption );
// Set the border size
If (this. borderwidth ){
Vrect. strokeweight = This. borderwidth;
}
// Set the border color
If (this. bordercolor ){
Vrect. strokecolor = This. bordercolor;
}
// Set the background color
If (this. backgroundcolor ){
Vrect. fillcolor = This. backgroundcolor;
}
// Set whether a shadow is displayed.
If (this. Shadow ){
VaR vshadow = Document. createelement ("V: Shadow ");
Vshadow. On = "T ";
Vshadow. type = "single ";
Vshadow. color = "graytext ";
Vshadow. offset = "4px, 4px ";
Vrect. appendchild (vshadow );
}
This. vmlobject = O;

After completing the above work, a canvas has been created, and the image outer frame and its title have been created. The most important work is to call createpie to draw each block, and make a legend.
4. vmlpie. Prototype. createpie

Createpie provides a parameter, that is, the container for creating a pie chart. We have created a V: group element through the above Code of draw, which is the container for creating a pie chart.

VaR MX = math. Pow (2, 16) * 360;
// This parameter is the key to drawing.
// AE x y width height startangle endangle
// X y indicates the center of the circle
// Width and height
// The startangle endangle calculation method is as follows:
// 2 ^ 16 * degree
VaR vtotal = 0;
VaR startangle = 0;
VaR endangle = 0;
VaR pieangle = 0;
VaR prepieangle = 0;

// Calculate the sum of data
For (I = 0; I <this. All. length; I ++ ){
Vtotal + = this. All [I]. value;
}
// Create a legend container
// Here, the left, top, or width of the sub-element is for the coordinate system set by the container.
// Example
// If the coordsize of the chart container is set to 21600,21600, the location of the objlengendgroup is relative to the coordinate system.
// There is no direct relationship with the actual image display size
VaR objlegendgroup = Document. createelement ("V: group ");
With (objlegendgroup ){
Style. Left = "17000px ";
Style. Top = "4000px ";
Style. width = "4000px ";
Style. Height = 1400 * This. All. Length + "PX ";
Coordsize = "21600,21600 ";
}
// Fill in the background of the legend and set the shadow.
VaR objlegendrect = Document. createelement ("V: rect ");
Objlegendrect. fillcolor = "# ebf1f9 ";
Objlegendrect. strokeweight = 1;
With (objlegendrect ){
// If it is set to 21600,21600, it means that the group customer zone is fully covered.
Style. width = "21600px ";
Style. Height = "21600px ";
}
// Add a shadow to the legend
VaR vshadow = Document. createelement ("V: Shadow ");
Vshadow. On = "T ";
Vshadow. type = "single ";
Vshadow. color = "graytext ";
Vshadow. offset = "4px, 4px ";
Objlegendrect. appendchild (vshadow );

// Put it in the container of the legend
Objlegendgroup. appendchild (objlegendrect );

This. legendobject = objlegendgroup;
Vgroup. appendchild (objlegendgroup );

At this time, we have drawn the positions of various regions. Through the above code, I have drawn a legendgroup and used it as the display position of the legend. In addition, the main V: group is used as the drawing container of pie. If the shape of pie should be put into a group for the sake of standardization, it will be more convenient in future programming control.

The following code is what I want to talk about, because the code is more critical. In addition to providing the code, I also focus on the role of each statement.

For (I = 0; I <this. All. length; I ++) {// specify the pie chart in sequence.
VaR vpieel = Document. createelement ("V: Shape ");
VaR vpieid = Document. uniqueid;
Vpieel. style. width = "15000px ";
Vpieel. style. Height = "14000px ";
Vpieel. style. Top = "4000px ";
Vpieel. style. Left = "1000px ";
Vpieel. adj = "0, 0 ";
Vpieel. coordsize = "1500,1400 ";
Vpieel. strokecolor = "white ";
Vpieel. ID = vpieid;
Vpieel. style. zindex = 1;
Vpieel. onmouseover = "hoverpie (this )";
Vpieel. onmouseout = "restorepie (this )";
Pieangle = this. All [I]. Value/vtotal;
Startangle + = prepieangle;
Prepieangle = pieangle;
Endangle = pieangle;
Vpieel. Path = "m 750 700 AE 750 700 750 700" + parseint (MX * startangle) + "" + parseint (MX * endangle) + "XE ";
Vpieel. title = This. all [I]. name + "\ n proportion:" + endangle * 100 + "% \ n detailed description:" + this. all [I]. tooltiptext;
Vpieel. _ scale = parseint (360 * (startangle + endangle/2 ));

VaR objfill = Document. createelement ("V: Fill ");
Objfill. Rotate = "T ";
Objfill. Focuses = "100% ";
Objfill. type = "gradient ";
Objfill. angle = parseint (360 * (startangle + endangle/2 ));

VaR objtextbox = Document. createelement ("V: textbox ");
Objtextbox. innerhtml = this. All [I]. Name + ":" + this. All [I]. value;
Objtextbox. inset = "5px 5px 5px 5px ";
Objtextbox. style. width = "100px ";
Objtextbox. style. Height = "20px ";

VaR vcolor = This. randcolor ();
Vpieel. fillcolor = vcolor; // set the color.
// Start to draw a legend
P. innertext = vpieel. outerhtml;
VaR colortip = Document. createelement ("V: rect ");

VaR iheight = parseint (21600/(this. All. length * 2 ));
VaR iwidth = parseint (iheight * parseint (objlegendgroup. style. Height)/parseint (objlegendgroup. style. width)/1.5 );

Colortip. style. Height = iheight;
Colortip. style. width = iwidth;
Colortip. style. Top = iheight * I * 2 + parseint (iheight/2 );
Colortip. style. Left = parseint (iwidth/2 );
Colortip. fillcolor = vcolor;
Colortip. Element = vpieid;
// Colortip. attachevent ("onmouse", legendmouseoverevent );
Colortip. onmouseover = "legendmouseoverevent ()";
Colortip. onmouseout = "legendmouseoutevent ()";

VaR texttip = Document. createelement ("V: rect ");
Texttip. style. Top = parseint (colortip. style. Top)-500;
Texttip. style. Left = iwidth * 2;
Texttip. innerhtml = "<v: textbox style = \" font-size: 12px; font-weight: bold \ ">" + this. all [I]. name + "(" + this. all [I]. value + ") </V: textbox> ";

Objlegendgroup. appendchild (colortip );
Objlegendgroup. appendchild (texttip );

Vgroup. appendchild (vpieel );
}
Now let's take a look at the implementation of the above Code.

1. Create a V: shape, left, top, width, and height respectively and set them to 1000px, 4000px, 15000px, and 14000px. The number is determined based on the approximate position.

2. set the ID of each shape. I use document. uniqueid is the random ID provided by the DOM method. I didn't intend to set this ID, but later, considering the interaction with legend, I set the ID of each shape.

3. set the shape onmouseover and onmouseout events. At the beginning, I implemented them using the attachevent method. Later, I found that it could not work (and I have not found the reason ), calculate the proportion of each data.

4. set the path, which is difficult to understand. First, I find startangle and endangle. The significance of startangle is as follows: assume there are three numbers, 0.2, 0.2, 0.4, for the second item, startangle should be 0.25, endangle is 0.25, startangle is 0.5, and endangle is 0.5. In short, startangle can be expressed as the proportion of the previous data, engangle indicates the proportion of the current data. PATH has many commands. For other commands, I will not explain them much, but here I use M 750 700 AE 750 700 750 700 start end. For shape, I have redefined coordsize = "750,700, 750,700". M indicates moving to, that is, moving to the center defined by shape. AE is used to draw curves. There are 6 parameters in total, the W3C note description is as follows: Center (x, y) size (W, h) Start-angle and end-angle. The first four parameters are not hard to understand, I do not understand the remaining two parameters, but I seeAlgorithmThe following is a 2 ^ 16 * degree, correspondingProgram, It should be startangle * 2 ^ 16*360, because my startangle is proportional.

5. Set fillcolor to set the color of the pie chart, and set the title to provide some prompt information.

6. color the legend and add a text description of the legend.

7. because all coordinate systems are relative, in order to ensure beautiful appearance, for objlegendgroup, I use 1400 * This. all. length + "PX", and the height and width of the colortip in the legend are calculated dynamically.

So far, a VML-based pie has been established through the program, and the rest is the output problem. As mentioned above, the vml I created in Dom mode has no problems in display, but it does not seem to work in Dynamic Interaction. obj. vmlobject is a DOM object. However, if onmouseover, onmouseout, and so on are set directly using the appendchild method, it cannot work at all. When you set innerhtml to generate a VML image, the mouse events can respond. If you have programming in this area, please tell me the specific reason.

Function hoverpie (EL ){}
Function restorepie (EL ){}
Function legendmouseoverevent (){}
Function legendmouseoutevent (){}
These four functions provide simple interaction. The specific code is as follows:

function hoverpie (EL) {
var v_length = 500;
var x_cur = math. cos (El. _ scale * Math. PI/180);
var y_cur = math. sin (El. _ scale * Math. PI/180);
X = parseint (x_cur * v_length);
Y = parseint (y_cur * v_length);
el. style. top = 4000-y;
el. style. left = 1000 + X;
el. strokecolor = "black";

}
Function restorepie (EL ){
El. style. Top = 4000;
El. style. Left = 1000;
El. strokecolor = "white ";

}
Function legendmouseoverevent (){

VaR ESRC = Window. event. srcelement;
VaR vpie = Document. All (ESRC. element );
Hoverpie (vpie );
}
Function legendmouseoutevent (){
VaR ESRC = Window. event. srcelement;
VaR vpie = Document. All (ESRC. element );
Restorepie (vpie );
}
Hoverpie provides a simple function of relative displacement of graphs.

5. vmlpie. Prototype. Zoom

It provides the image zoom-in and zoom-out functions. Since it is a vector image, the zoom-in and zoom-out functions should not cause any image loss. The implementation principle is very simple, you only need to modify the coordinate system of the group. This is the main reason why I have always stressed that all shapes need to be placed in the group. For text, the setting can be performed in the same way as HTML Dom.

Vmlpie. Prototype. Zoom = function (ivalue ){
VaR vx = 21600;
VaR Vy = 21600;
This. vmlobject = Document. All (this. ID );
This. vmlobject. coordsize = parseint (vx/ivalue) + "," + parseint (Vy/ivalue );
VaR texts = This. vmlobject. getelementsbytagname ("textbox ");
For (VAR I = 0; I <texts. length; I ++ ){
If (texts [I]. presize ){
Texts [I]. style. fontsize = parseint (texts [I]. presize) * ivalue + "PX ";
}
Else {
Texts [I]. style. fontsize = 12 * ivalue + "PX ";
}
}
}
So far, all the vmlpie production processes have been introduced. I wrote this article for the first time. It may not be very clear about many things. I hope I can discuss it with you, in addition, the complete Source code I have already posted it on the csdn Forum. You can download it.

Http://expert.csdn.net/Expert/topic/2160/2160456.xml? Temp =. 4498102.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.