45fan.com - 路饭网

搜索: 您的位置主页 > 网络频道 > 阅读资讯:如何利用javascript+VML在网页中实现折线图?

如何利用javascript+VML在网页中实现折线图?

2016-09-03 14:10:21 来源:www.45fan.com 【

如何利用javascript+VML在网页中实现折线图?

作者:ybbqy

欢迎访问ybbqy的BLOG :http://blog.csdn.net/ybbqy

言规正传:

今天的主题就是在网页上画图!

网页上画图?文本描述的HTTP浏览感觉很悬吧?其实网上已经有很多相关的技术,我这里就用VML来实现。(注:VML目前只被IE6.0下支持,并且微软也将打算不再支持VML,这里只作抛砖引玉,相信认真的读者会做到举一反三。想实用、兼容性好,建议还是在服务器端生成图片或用JAVA.applet吧。在我的试用下,IE5.0不支持容器的相对坐标,一切坐标都从网页右上角开始,在这里也请达人指教。)

思路:

首先我们画一个坐标,坐标的映射我没有用vml自身的,因为失量的计算会使速度变得非常的慢。

坐标的实际坐标宽为600素,高为200象素,逻辑宽由数据个数决定,逻辑高由最大数据决定。

比例因子是实际象素数除逻辑数。我们知道一个逻辑象素,乘上比例因子可以得到相应的实际象素坐标。

在此基础之上我们利用JAVASCRIPT控制来画出需要的折线图.

首先必须vml要用的东东,我也不清楚干嘛的,听说和xml有关,感兴趣的可以查资料地说~

<html xmlns:v="urn:schemas-microsoft-com:vml">

<STYLE>

v/:* { Behavior: url(#default#VML) }

</STYLE>

准备一个table(表格)做图的容器,把画的图放里面

折线的颜色

最多可用10组

var tmdColor1 = new Array();

tmdColor1[0] = "#d1ffd1";

tmdColor1[1] = "#ffbbbb";

tmdColor1[2] = "#ffe3bb";

tmdColor1[3] = "#cff4f3";

tmdColor1[4] = "#d9d9e5";

tmdColor1[5] = "#ffc7ab";

tmdColor1[6] = "#ecffb7";

tmdColor1[7] = "#FFE6E7";

tmdColor1[8] = "#FFF5D0";

tmdColor1[9] = "#C4C4FF";

var tmdColor2 = new Array();

tmdColor2[0] = "#00ff00";

tmdColor2[1] = "#ff0000";

tmdColor2[2] = "#ff9900";

tmdColor2[3] = "#33cccc";

tmdColor2[4] = "#666699";

tmdColor2[5] = "#993300";

tmdColor2[6] = "#99cc00";

tmdColor2[7] = "#FFAEAD";

tmdColor2[8] = "#FFCB00";

tmdColor2[9] = "#0000FF";

函数的声名,这个函数可以画一个坐标,很好看地~~~

// 生成坐标。参数:实际宽,实际高,逻辑宽,逻辑高

function get_coord(container_width, container_height, logic_width, logic_height, org_x, org_y , data_title)

这里是逻辑单位和实际象素比例,vml也有坐标系统,但我推荐不要用,原因是当数值太大时vml不能胜任,因为vml的坐标系统宽和高最大只支持到8位数,用javascript就不会出现这个问题.以前我也是直接看教程用的vml坐标,但发现不实用,也不好控制,所以自己进行映射.

得到的比例因子乘上逻辑单位就是实际的像素数.

// 比例因子=容器/逻辑

var x_scale = container_width/logic_width;

var y_scale = container_height/logic_height;

然后设置整个坐标, 这里的高因为是以数值最大大小来决定的,所以算法可以由读者来重写.

// 坐标大小

var coord_width = logic_width;

var coord_height= (parseInt(logic_height.toString().substring(0,1))+1) * Math.pow(10, logic_height.toString().length - 1);

这里是画坐标的刻度

// 画纵 坐标

for (var loop = 0; loop <= coord_height; loop += coord_height/10)

{

// 映射为象素

var coord_line_x1 = org_x;

var coord_line_y1 = y_scale*loop + org_y;

var coord_line_x2 = x_scale*coord_width + org_x;

var coord_line_y2 = y_scale*loop + org_y;

var across_num_x1 = org_x;

var across_num_y1 = coord_line_y1;

var across_num_x2 = org_x;

var across_num_y2 = coord_line_y2;

str +=

// 画纵坐标的虚线

'<v:line from="'+org_x+','+coord_line_y1+'" to="'+coord_line_x2+','+coord_line_y2+'" style="Z-INDEX:0;" strokeweight="1pt">'

+ '<v:stroke dashstyle="Dot"/>'

+ '</v:line>'

// 画纵坐标数字

+ '<v:line from="'+across_num_x1+','+across_num_y1+'" to="'+across_num_x2+','+across_num_y2+'" style="Z-INDEX:0;" strokeweight="1pt">'

+ '<v:TextBox inset="-50pt,0pt,0pt,50pt" style="font-size:9pt;">'

+ '<font color="0"><p align="right">'+Math.floor(loop)+'</p></font>'

+ '</v:TextBox>'

+ '</v:line>';

}

纵轴的坚线

str += ''

+ '<v:line from="'+org_x+',0" to="'+(coord_line_x2 )+',0" style="Z-INDEX:8;" strokeweight="1pt">'

+ '</v:line>'

+ '<v:line from="'+org_x+',0" to="'+org_x+','+(y_scale*(loop+1))+'" style="Z-INDEX:8;" strokeweight="1pt">'

+ '</v:line>';

说明每条线代表的意义.以样标题显示在坐标间。

// 画各数据标题

for (var i=0; i < data_title.length; i++)

{

title_left = 500-i*100;

title_top = y_scale*coord_height-10;

title_width = 10;

title_height = 10;

str += '<v:Rect style="position:relative;left:'+(title_left)+';top='+(title_top)+';width:'+title_width+'px;height:'+title_height+'px;" StrokeWeight="1pt" fillcolor = "#'+tmdColor2[i]+'" StrokeWeight="0pt";>' +'</v:Rect>'

+'<v:line from="'+(title_left+title_width)+','+(title_top)+'" to="'+(title_left+title_width)+','+(title_top)+'" style="position:relative;">'

+'<v:TextBox inset="0pt,-2pt,-'+(50)+'pt,50pt" style="font-size:9pt;">'+data_title[i]+'</v:TextBox>'

+'</v:line>'

;

}

以上是坐标部份,已经完成一半啦~

下面来讲真正画折线,感觉比画坐标简单~ 活活

函数声名:

// 数据数组,说明数据意义数组,数据周期说明数组,x轴的标题,y轴的标题

function fold_line(data, data_title, bottom_title, x_title, y_title)

这个是容器的宽和高

// 容器作标

var container_width = 600;

var container_height= -200;

容器的原点位置

var org_x=50;

var org_y=0;

逻辑大小

// 逻辑坐标

var logic_width = 0;

var logic_height= 0;

最后都放这个变量里再打印到网页上

// 图表生成文本存放变量

var fold_line = '<html xmlns:v="urn:schemas-microsoft-com:vml">'

+ '<STYLE>'

+ 'v/:* { Behavior: url(#default#VML) }'

+ '</STYLE>';

计算逻辑高和逻辑宽:计算宽简单,就是数据的周期有多少个宽就是多少,高就需要取最大的才能容下了.

// 计算逻辑高和逻辑宽

for (var i=0; i < data.length ; i++)

{

var item = data[i].split(/[',']/);

// 最大的列数设置为逻辑宽度

if (logic_width < item.length)

{

logic_width = item.length;

}

// 最大数据为逻辑高度

for (var j=0; j < item.length; j++)

{

if (logic_height < parseInt(item[j]))

{

logic_height = item[j];

}

}

}

计算比例因子

// 比例因子=容器/逻辑

var x_scale = container_width/logic_width;

var y_scale = container_height/logic_height;

为0 时

// 为0 时

if (logic_height < 1)

{

logic_height = -container_height;

}

画容器和坐标,前面的计算用上了吧~~~

// 画容器

fold_line += ' <v:group ID="group1" style="position:relative;WIDTH:'+container_width+';HEIGHT:'+container_height+';LEFT:0;TOP:10;" CoordSize="'+container_width+', '+container_height+'" >'

// 画坐标画面

fold_line += get_coord(container_width, container_height, logic_width, logic_height, org_x, org_y ,

data_title );

画x轴线上的标题

// 画横坐标,数据周期

for (var loop=0; loop < logic_width; loop++)

{

// 映射为象素

var coord_title_x1 = x_scale*loop + org_x;

var coord_title_y1 = org_y;

var coord_title_x2 = x_scale*loop + org_x;

var coord_title_y2 = 10 + org_y;

fold_line +=

'<v:line from="'+coord_title_x1+','+coord_title_y1+'" to="'+coord_title_x2+','+coord_title_y2+'" style="Z-INDEX:8;" StrokeWeight="1pt"/>'

+ '<v:line from="'+(x_scale*(loop)+org_x)+',0" to="'+(x_scale*(loop+1)+org_x)+',0" style="Z-INDEX:8;" StrokeWeight="1pt">'

+ '<v:TextBox inset="0pt,0pt,50pt,50pt" style="font-size:9pt;">'

+ '<font color="0"><p align="center">'+ bottom_title[loop]+ '</p></font>'

+ '</v:TextBox>'

+ '</v:line>'

;

}

循环从左到右,从上到下画折线咯!~~~

// 开始逐一画折线

for (var i=0; i < data.length ; i++)

{

var item = data[i].split(/[',']/);

for (var j=0; j < logic_width - 1; j++)

{

var fold_line_x1 = x_scale*j + org_x;

var fold_line_y1 = y_scale*item[j] + org_y;

var fold_line_x2 = x_scale*(j+1) + org_x;

var fold_line_y2 = y_scale*item[j+1] + org_y;

fold_line +='<v:line from="'+fold_line_x1+','+fold_line_y1+'" to="'+fold_line_x2+','+fold_line_y2+'" style="Z-INDEX:8;" StrokeWeight="1pt"; StrokeColor="'+tmdColor2[i]+'">'

+ '<v:shadow on="T" type="single" color="#b3b3b3" offset="1px,1px"/>'

+ '</v:line>'

// 画小方块

+ '<v:rect style="position:relative;Z-INDEX:10;left:'+(fold_line_x2-(5/2))+';top:'+(fold_line_y2-(5/2))+';width:'+5+';height:'+5+'" fillcolor = "#'+tmdColor2[i]+'" StrokeWeight="0pt";/>'

;

}

}

完工~~~

// 容器结束

fold_line += '</v:group>';

打印~~~

document.write(fold_line);

到此一个完美的折线已经画完~~~

调用方法也很简单:

在script块下调用fold_line函数即可,具体方法如下:

建三个数组

data是数据,data_title是说明每维数据的表述的意义,bottom_title是周期的标题(这也是用bottom的意义,因为周期在横坐标上表示,横坐标在底下的嘛!)

var data = new Array();

var data_title = new Array();

var bottom_title = new Array();

data[0] = '2,34456565,53434346,7454545,8,45445459,67676774,45656566,26767674,24545678,94456789,26543456';

data[1] = '13434342,33434342,34343435,30454545,56566737,30788980,23345645,34344576,67676786,56567353,28989896,19899467';

data[2] = '22323233,23434341,24545454,55656564,67667676,78787857,56788903,13233452,45566782,23545562,23434344,34343442';

data[3] = '33434343,42323235,33434344,54545456,55656567,76767678,77878788,67676762,56565672,45454552,5656662,56565662';

data_title[0] = 'blog.csdn.net/ybbqy的访问量';

data_title[1] = 'blog.csdn.net/ybbqy的访问量-2';

data_title[2] = 'blog.csdn.net/ybbqy的访问量-3';

data_title[3] = 'blog.csdn.net/ybbqy的访问量-4';

bottom_title[0] = '1月';

bottom_title[1] = '2月';

bottom_title[2] = '3月';

bottom_title[3] = '4月';

bottom_title[4] = '5月';

bottom_title[5] = '6月';

bottom_title[6] = '7月';

bottom_title[7] = '8月';

bottom_title[8] = '9月';

bottom_title[9] = '10月';

bottom_title[10] = '11月';

bottom_title[11] = '12月';

bottom_title[12] = '11月';

//*/

fold_line(data, data_title, bottom_title);

完整源码(粘贴后存成.htm文件看效果)

 

<html xmlns:v="urn:schemas-microsoft-com:vml">

<STYLE>

v/:* { Behavior: url(#default#VML) }

</STYLE>

<TABLE>

<TR>

<TD>

<script language="JavaScript">

var tmdColor1 = new Array();

tmdColor1[0] = "#d1ffd1";

tmdColor1[1] = "#ffbbbb";

tmdColor1[2] = "#ffe3bb";

tmdColor1[3] = "#cff4f3";

tmdColor1[4] = "#d9d9e5";

tmdColor1[5] = "#ffc7ab";

tmdColor1[6] = "#ecffb7";

tmdColor1[7] = "#FFE6E7";

tmdColor1[8] = "#FFF5D0";

tmdColor1[9] = "#C4C4FF";

var tmdColor2 = new Array();

tmdColor2[0] = "#00ff00";

tmdColor2[1] = "#ff0000";

tmdColor2[2] = "#ff9900";

tmdColor2[3] = "#33cccc";

tmdColor2[4] = "#666699";

tmdColor2[5] = "#993300";

tmdColor2[6] = "#99cc00";

tmdColor2[7] = "#FFAEAD";

tmdColor2[8] = "#FFCB00";

tmdColor2[9] = "#0000FF";

// 生成坐标。参数:实际宽,实际高,逻辑宽,逻辑高

function get_coord(container_width, container_height, logic_width, logic_height, org_x, org_y , data_title)

{

var str = '';

// 比例因子=容器/逻辑

var x_scale = container_width/logic_width;

var y_scale = container_height/logic_height;

// 坐标大小

var coord_width = logic_width;

var coord_height= (parseInt(logic_height.toString().substring(0,1))+1) * Math.pow(10, logic_height.toString().length - 1);

// 画纵 坐标

for (var loop = 0; loop <= coord_height; loop += coord_height/10)

{

// 映射为象素

var coord_line_x1 = org_x;

var coord_line_y1 = y_scale*loop + org_y;

var coord_line_x2 = x_scale*coord_width + org_x;

var coord_line_y2 = y_scale*loop + org_y;

var across_num_x1 = org_x;

var across_num_y1 = coord_line_y1;

var across_num_x2 = org_x;

var across_num_y2 = coord_line_y2;

str +=

// 画纵坐标的虚线

'<v:line from="'+org_x+','+coord_line_y1+'" to="'+coord_line_x2+','+coord_line_y2+'" style="Z-INDEX:0;" strokeweight="1pt">'

+ '<v:stroke dashstyle="Dot"/>'

+ '</v:line>'

// 画纵坐标数字

+ '<v:line from="'+across_num_x1+','+across_num_y1+'" to="'+across_num_x2+','+across_num_y2+'" style="Z-INDEX:0;" strokeweight="1pt">'

+ '<v:TextBox inset="-50pt,0pt,0pt,50pt" style="font-size:9pt;">'

+ '<font color="0"><p align="right">'+Math.floor(loop)+'</p></font>'

+ '</v:TextBox>'

+ '</v:line>';

}

str += ''

+ '<v:line from="'+org_x+',0" to="'+(coord_line_x2 )+',0" style="Z-INDEX:8;" strokeweight="1pt">'

+ '</v:line>'

+ '<v:line from="'+org_x+',0" to="'+org_x+','+(y_scale*(loop+1))+'" style="Z-INDEX:8;" strokeweight="1pt">'

+ '</v:line>';

// 画各数据标题

for (var i=0; i < data_title.length; i++)

{

title_left = 500-i*100;

title_top = y_scale*coord_height-10;

title_width = 10;

title_height = 10;

str += '<v:Rect style="position:relative;left:'+(title_left)+';top='+(title_top)+';width:'+title_width+'px;height:'+title_height+'px;" StrokeWeight="1pt" fillcolor = "#'+tmdColor2[i]+'" StrokeWeight="0pt";>' +'</v:Rect>'

+'<v:line from="'+(title_left+title_width)+','+(title_top)+'" to="'+(title_left+title_width)+','+(title_top)+'" style="position:relative;">'

+'<v:TextBox inset="0pt,-2pt,-'+(50)+'pt,50pt" style="font-size:9pt;">'+data_title[i]+'</v:TextBox>'

+'</v:line>'

;

}

return str;

}

function fold_line(data, data_title, bottom_title, x_title, y_title)

{

// 容器作标

var container_width = 600;

var container_height= -200;

var org_x=50;

var org_y=0;

// 逻辑坐标

var logic_width = 0;

var logic_height= 0;

// 图表生成文本存放变量

var fold_line = '<html xmlns:v="urn:schemas-microsoft-com:vml">'

+ '<STYLE>'

+ 'v/:* { Behavior: url(#default#VML) }'

+ '</STYLE>';

// 计算逻辑高和逻辑宽

for (var i=0; i < data.length ; i++)

{

var item = data[i].split(/[',']/);

// 最大的列数设置为逻辑宽度

if (logic_width < item.length)

{

logic_width = item.length;

}

// 最大数据为逻辑高度

for (var j=0; j < item.length; j++)

{

if (logic_height < parseInt(item[j]))

{

logic_height = item[j];

}

}

}

// 比例因子=容器/逻辑

var x_scale = container_width/logic_width;

var y_scale = container_height/logic_height;

// 为0 时

if (logic_height < 1)

{

logic_height = -container_height;

}

// 画容器

fold_line += ' <v:group ID="group1" style="position:relative;WIDTH:'+container_width+';HEIGHT:'+container_height+';LEFT:0;TOP:10;" CoordSize="'+container_width+', '+container_height+'" >'

// 画坐标画面

fold_line += get_coord(container_width, container_height, logic_width, logic_height, org_x, org_y ,

data_title );

// 画横坐标,数据周期

for (var loop=0; loop < logic_width; loop++)

{

// 映射为象素

var coord_title_x1 = x_scale*loop + org_x;

var coord_title_y1 = org_y;

var coord_title_x2 = x_scale*loop + org_x;

var coord_title_y2 = 10 + org_y;

fold_line +=

'<v:line from="'+coord_title_x1+','+coord_title_y1+'" to="'+coord_title_x2+','+coord_title_y2+'" style="Z-INDEX:8;" StrokeWeight="1pt"/>'

+ '<v:line from="'+(x_scale*(loop)+org_x)+',0" to="'+(x_scale*(loop+1)+org_x)+',0" style="Z-INDEX:8;" StrokeWeight="1pt">'

+ '<v:TextBox inset="0pt,0pt,50pt,50pt" style="font-size:9pt;">'

+ '<font color="0"><p align="center">'+ bottom_title[loop]+ '</p></font>'

+ '</v:TextBox>'

+ '</v:line>'

;

}

// 开始逐一画折线

for (var i=0; i < data.length ; i++)

{

var item = data[i].split(/[',']/);

for (var j=0; j < logic_width - 1; j++)

{

var fold_line_x1 = x_scale*j + org_x;

var fold_line_y1 = y_scale*item[j] + org_y;

var fold_line_x2 = x_scale*(j+1) + org_x;

var fold_line_y2 = y_scale*item[j+1] + org_y;

fold_line +='<v:line from="'+fold_line_x1+','+fold_line_y1+'" to="'+fold_line_x2+','+fold_line_y2+'" style="Z-INDEX:8;" StrokeWeight="1pt"; StrokeColor="'+tmdColor2[i]+'">'

+ '<v:shadow on="T" type="single" color="#b3b3b3" offset="1px,1px"/>'

+ '</v:line>'

// 画小方块

+ '<v:rect style="position:relative;Z-INDEX:10;left:'+(fold_line_x2-(5/2))+';top:'+(fold_line_y2-(5/2))+';width:'+5+';height:'+5+'" fillcolor = "#'+tmdColor2[i]+'" StrokeWeight="0pt";/>'

;

}

}

// 容器结束

fold_line += '</v:group>';

document.write(fold_line);

}

//*/

 

 

 

 

 

 

 

 

var data = new Array();

var data_title = new Array();

var bottom_title = new Array();

data[0] = '2,34456565,53434346,7454545,8,45445459,67676774,45656566,26767674,24545678,94456789,26543456';

data[1] = '13434342,33434342,34343435,30454545,56566737,30788980,23345645,34344576,67676786,56567353,28989896,19899467';

data[2] = '22323233,23434341,24545454,55656564,67667676,78787857,56788903,13233452,45566782,23545562,23434344,34343442';

data[3] = '33434343,42323235,33434344,54545456,55656567,76767678,77878788,67676762,56565672,45454552,5656662,56565662';

data_title[0] = 'blog.csdn.net/ybbqy的访问量';

data_title[1] = 'blog.csdn.net/ybbqy的访问量-2';

data_title[2] = 'blog.csdn.net/ybbqy的访问量-3';

data_title[3] = 'blog.csdn.net/ybbqy的访问量-4';

bottom_title[0] = '1月';

bottom_title[1] = '2月';

bottom_title[2] = '3月';

bottom_title[3] = '4月';

bottom_title[4] = '5月';

bottom_title[5] = '6月';

bottom_title[6] = '7月';

bottom_title[7] = '8月';

bottom_title[8] = '9月';

bottom_title[9] = '10月';

bottom_title[10] = '11月';

bottom_title[11] = '12月';

bottom_title[12] = '11月';

//*/

fold_line(data, data_title, bottom_title);

</script>

</TD>

</TR>

</TABLE>

 

本文地址:http://www.45fan.com/a/question/71805.html
Tags: 原创 JavaScript vml
编辑:路饭网
关于我们 | 联系我们 | 友情链接 | 网站地图 | Sitemap | App | 返回顶部