
這樣一簇絢爛豐滿艷麗多姿的3D小球花,要多少代碼才能完成?其實不足百行,您信嗎?下面咱就看一下具體實現過程,讓您分分鐘學會用TWaver HTML5制作3D拓撲圖。
搭建3D空間
首先為花簇的綻放建一個展示的舞臺。接觸過TWaver2D的都知道,box、network是必不可少的,但對3D場景來說,還遠遠不夠。一是要添加鏡頭位置,確定我們在什么角度和距離進行觀察;二是要加上燈光,否則再美的畫面也看不見。燈光分為點光源和環境光,一般來說要一個環境光和若干點光源搭配才能出來好的效果。
var box = new mono.DataBox();
var network= new mono.Network3D(box, null, monoCanvas);
mono.Utils.autoAdjustNetworkBounds(network,document.documentElement,'clientWidth','clientHeight');
network.getCamera().setPosition(0, 0, 4000);
network.isSelectable=function(){return false};
network.setClearColor('black');
var pointLight = new mono.PointLight(0xFFFFFF,0.8);
box.add(pointLight);
var pointLight = new mono.PointLight(0xFFFFFF,0.5);
pointLight.setPosition(500,2000,0);
box.add(pointLight);
box.add(new mono.AmbientLight(0x888888));
創建3D小球花瓣
每一個3D小球就是一個花瓣,是整個花簇的基礎部件,也是最容易做的,只要幾行代碼而已。
function createNode(color){
//var color = color || '#'+('00000'+(Math.random()*0x1000000<<0).toString(16)).slice(-6);
var node=new mono.Sphere(10,BALL_SEGMENT,BALL_SEGMENT);
node.s({
'm.type': 'phong',
'm.color': color,
'm.ambient': color,
});
return node;
}
其中的BALL_SEGMENT是球體切片數量,數量越大生成的球體越圓滑,但計算量也就越大。解除注釋掉的那條語句將會每次生成一個隨機顏色的小球,這種五顏六色的感覺也別有趣味。

生成3D花朵
正如若干花瓣組成一朵小花,我們也要將若干個小球連接在一起。這一步最重要的是花瓣的排列,既要隨機有活力,又要規律有造型。實例中是將小球隨機排列在一個球面的局部。
function getSpherePoint(r, angle1, angle2){
var x=r*Math.sin(angle1)*Math.cos(angle2);
var y=r*Math.cos(angle1);
var z=r*Math.sin(angle1)*Math.sin(angle2);
return new mono.Vec3(x, y, z);
}
有了花瓣的擺放位置,一朵花也就很容易開放了:
function createTree(box, count, range, offset, color){
var angleStep=Math.PI/50;
var center=new mono.Sphere(10,BALL_SEGMENT,BALL_SEGMENT);
center.s({
'm.type': 'phong',
'm.color': color,
'm.ambient': color,
});
box.add(center);
for(var i=0;i<count;i++){
var node= createNode(color);
var r=1000;
var angle1=range*Math.random()/5;
var angle2=Math.PI*2*Math.random();
var point=getSpherePoint(r, angle1, angle2);
point.y-=offset;
node.setPosition(point);
node.setParent(center);
box.add(node);
box.add(createLink(center, node));
}
return center;
}
通過改變其參數,可以開出不同的花朵。其中count是花瓣的數量,range是花朵球面的角度,offset是花瓣到花托的長度,color是花朵的顏色。
綻放3D花簇
剩下的工作就極其簡單了,先建一個中心小球,再通過兩個循環,就生成了有兩層花朵的球狀花簇。
var center=createNode('red');
box.add(center);
for(var i=0;i<40;i++){
var angle1=Math.random()*Math.PI;
var angle2=Math.random()*Math.PI*2;
var point=getSpherePoint(1000, angle1, angle2);
var tree=createTree(box, 100, Math.PI*0.4, 800, 'yellow');
tree.setPosition(point.x, point.y, point.z);
var rotation=point.rotationTowards(new mono.Vec3(0,1,0), point);
tree.setRotation(rotation);
box.add(createLink(center, tree));
}
當然,你可以說這根本不像什么花簇。其實本來也不是要做一個現實的什么東西,只是為了用一段小而美的程序,讓大家領略TWaver3D拓撲圖的風采。如果您從中get到了什么技能和興趣,那才是我們的真正目的!
實際上,這個例子稍作變化,就可以用來展示豐富的3D網絡拓撲圖、各種復雜數據的樹狀關系圖。你一定可以讓它綻放的更加美麗!
為了證實代碼確實不足百行,特附上完整源碼:
1 <!DOCTYPE html>
2 <html>
3 <head>
4 <title>Mono Test</title>
5 <script type="text/javascript" src = "t.js"></script>
6 <script type="text/javascript">
7 var BALL_SEGMENT=7;
8 function init(){
9 var box = new mono.DataBox();
10 var network= new mono.Network3D(box, null, monoCanvas);
11 mono.Utils.autoAdjustNetworkBounds(network,document.documentElement,'clientWidth','clientHeight');
12 network.getCamera().setPosition(0, 0, 4000);
13 network.isSelectable=function(){return false};
14 network.setClearColor('black');
15 var pointLight = new mono.PointLight(0xFFFFFF,0.8);
16 box.add(pointLight);
17 var pointLight = new mono.PointLight(0xFFFFFF,0.5);
18 pointLight.setPosition(500,2000,0);
19 box.add(pointLight);
20 box.add(new mono.AmbientLight(0x888888));
21 var center=createNode('red');
22 box.add(center);
23 for(var i=0;i<10;i++){
24 var angle1=Math.random()*Math.PI;
25 var angle2=Math.random()*Math.PI*2;
26 var point=getSpherePoint(300, angle1, angle2);
27 var tree=createTree(box, 100, Math.PI*0.6, 700, '#'+('00000'+(Math.random()*0x1000000<<0).toString(16)).slice(-6));
28 tree.setPosition(point.x, point.y, point.z);
29 var rotation=point.rotationTowards(new mono.Vec3(0,1,0), point);
30 tree.setRotation(rotation);
31 box.add(createLink(center, tree));
32 }
33 for(var i=0;i<40;i++){
34 var angle1=Math.random()*Math.PI;
35 var angle2=Math.random()*Math.PI*2;
36 var point=getSpherePoint(1000, angle1, angle2);
37 var tree=createTree(box, 100, Math.PI*0.4, 800);
38 tree.setPosition(point.x, point.y, point.z);
39 var rotation=point.rotationTowards(new mono.Vec3(0,1,0), point);
40 tree.setRotation(rotation);
41 box.add(createLink(center, tree));
42 }
43 }
44 function createTree(box, count, range, offset, color){
45 var angleStep=Math.PI/50;
46 var center=new mono.Sphere(10,BALL_SEGMENT,BALL_SEGMENT);
47 center.s({
48 'm.type': 'phong',
49 'm.color': color,
50 'm.ambient': color,
51 });
52 box.add(center);
53 for(var i=0;i<count;i++){
54 var node= createNode(color);
55 var r=1000;
56 var angle1=range*Math.random()/5;
57 var angle2=Math.PI*2*Math.random();
58 var point=getSpherePoint(r, angle1, angle2);
59 point.y-=offset;
60 node.setPosition(point);
61 node.setParent(center);
62 box.add(node);
63 box.add(createLink(center, node));
64 }
65 return center;
66 }
67 function getSpherePoint(r, angle1, angle2){
68 var x=r*Math.sin(angle1)*Math.cos(angle2);
69 var y=r*Math.cos(angle1);
70 var z=r*Math.sin(angle1)*Math.sin(angle2);
71 return new mono.Vec3(x, y, z);
72 }
73 function createNode(color){
74 var color = color || '#'+('00000'+(Math.random()*0x1000000<<0).toString(16)).slice(-6);
75 var node=new mono.Sphere(10,BALL_SEGMENT,BALL_SEGMENT);
76 node.s({
77 'm.type': 'phong',
78 'm.color': color,
79 'm.ambient': color,
80 });
81 return node;
82 }
83 function createLink(node1, node2){
84 var link=new mono.Link(node1, node2);
85 link.s({
86 'm.transparent': true,
87 'm.opacity': 0.2,
88 });
89 return link;
90 }
91 </script>
92 </head>
93 <body onload = 'init()'>
94 <div>
95 <canvas id="monoCanvas"/>
96 </div>
97 </body>
98 </html>
如有任何問題,可以留言,或者發郵件給我們:tw-service@servasoft.com。