TWaver - 专注UI技术

http://twaver.servasoft.com/
posts - 171, comments - 191, trackbacks - 0, articles - 2
  BlogJava :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理

TWaver3D拓扑图之球花绽放

Posted on 2016-11-23 10:32 TWaver 阅读(272) 评论(0)  编辑  收藏


这样一簇绚烂丰满艳丽多姿的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(
004000);
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.4800'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(004000);
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.6700'#'+('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.4800);
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。

只有注册用户登录后才能发表评论。


网站导航: