前言
不知道大家还记不记得这篇HTML5,不只是看上去很美(第三弹:萌萌哒拓扑图分组),哼(傲娇脸),就知道你们忘记了。这个项目是为了展示一个多层的的嵌套关系。
这次,应甲方爸爸的要求,我们利用3D展示了会计报账的流程图,同样涉及到了层与层、层内各个模块中之间的多层嵌套关系。
概述
简单梳理下流程图的大致框架,分为五层:
业务流程层:起点、审批、服务;
应用逻辑层:WEB服务、数据库服务、定时作业服务、接口服务、应用服务;
实例:WEB服务实例、财辅数据库实例、支付服务实例;
OS:EB服务OS、财辅数据库OS;
硬件:主机、交换机。
大体框架
为了让这五层之间的关系一目了然,我们的设计小姐姐提出了以高楼的形式展现,每一层为一楼,层中各个模块就像是每层楼中的房间,话说这样一层楼得值多少钱啊,咳咳,好像跑偏了,这不是在谈论房价。大概就是下图这样子吧,有没有感觉到层次分明呢?
模型
你们不会以为3D流程图中的每个模型就是表面看上去这么简单,NONONO,真是太年轻,他们可是传说中的扫地僧啊,模不可貌相。
层模型:
(为了看得清楚,特意去掉了背景)
表示每层楼的层模型,可是由9个简单模型组合而成,上图给你们看(原谅我图画得渣渣)。
模型1、2、3、4、5均为厚度相同的立方体,模型6、7、8、9为大小相等的1/4圆柱体,9个模型组合成层模型,果真是九九归一啊。
模型1的代码:(模型1,2,3,4,5差不多,就只贴模型1的代码了。)
var centerNode = new mono.Cube({
width: width,
height: height,
depth: depth,
});
centerNode.s({
'm.type': 'phong',
'm.color': color
});
模型6的代码:
var leftTopCylinder = new mono.Cylinder({
radiusTop: radius,
radiusBottom: radius,
height: height,
arcLength: Math.PI / 2, //圆柱的圆弧所占长度
arcStart: Math.PI //圆弧开始的角度
});
leftTopCylinder.s({
'm.type': 'phong',
'm.color': color
});
leftTopCylinder.p(-width / 2, 0, -depth / 2);
9个模型合并:
var combo = new mono.ComboNode([centerNode, leftNode, rightNode, topNode, bottomNode, leftTopCylinder, rightTopCylinder, leftBottomCylinder, rightBottomCylinder],['+'],true);
obj模型:
这两种属于obj模型,是设计小姐姐做的,然后我们通过make.Default.register函数定义模型,通过make.Default.load函数加载使用模型。
为了使效果更逼真,我们给模型做了环境贴图。
object3d.setStyle('m.envmap.image', make.Default.getEnvMap('envmap5'));
对比一下,就知有木有啊。
看起来很清凉有没有,是不是想买回家当地板,整个夏天就凉凉哒。
此外,不仅做了环境贴图,还给所有的obj模型绘制了阴影,当模型旋转在适当的角度时就会出现阴影。绘制阴影则是使用了html5的canvas绘图,然后再贴到obj模型所在的地板上(估且就称为地板吧,很形象啊)。
实体模型:
最底层的模型采用了实体模型,真实感更强烈是不是。
嵌套关系
上面也提到过,层与层、层内各个模块中之间存在错综复杂的多层嵌套关系,为了展现这种关系,那肯定就要连线呀,话不多说,直接上图。
线的类型有两种,层与层之间的连线类型是link,每层模块之间的连线类型是pathLink,创建pathLInk代码如下:
createPathLink: function (data) {
var box = main.sceneManager.getDataBox();
var fromNode = main.sceneManager.getNodeByDataOrId(data.fromId);
var toNode = main.sceneManager.getNodeByDataOrId(data.toId);
var radius = data.path.radius || 3;
var color = data.path.color || 'yellow';
var endCap = data.path.endCap;
var startCap = data.path.startCap;
var linkType = data.routeType;
var flow = data.path.flow || '';
var workflowId = data.workflowId || '';
if (fromNode && toNode) {
var link = new mono.PathLink(fromNode, toNode, data.id);
var plength = link.getPath().getLength();
link.setRadius(radius);
link.s({
'm.type': 'phong',
'm.color': color,
'm.ambient': color
});
link.workflowId = workflowId;
if (endCap) {
var endCapSize = data.path.endCapSize || 10;
var endCapR = data.path.endCapR || 2;
link.setEndCap(endCap);
link.setEndCapSize(endCapSize);
link.setEndCapR(endCapR);
}
if (startCap) {
var startCapSize = data.path.startCapSize || 10;
var startCapR = data.path.startCapR || 2;
link.setStartCap(startCap);
link.setStartCapSize(startCapSize);
link.setStartCapR(startCapR);
}
if (linkType) {
link.setLinkType(linkType);
}
box.add(link);
}
}
link类型连线与pathLink类型连线大体相同,之所以层与层之间选择link类型,有两个原因:一是当镜头拉近时,link类型的连线粗细不会改变,二是便于控制拐点,就是下图中的红圈处。
link.setLinkType('control');//control属性控制连线的拐点
link.setControls(controls);//controls为数组
这样就可以呈现图中的伞状效果啦。
为了增加点朦胧感以及让伞状效果更好,我们特意添加了一点光环,有没有感觉金光从天而降呢?此时请想象自己45°角仰望天空,金光照在脸上(逃)
动画
流程图步骤这么明显的项目,怎么能少得了动画呢?同样,先上图。
点击左边的按钮,出现图中的白色小球,沿着连线运动,完整展现整个流程步骤。当然,镜头会随着小球切换,这样小球时刻在视线正中(此处可以大声高喊,妈妈再也不用担心我的视线被挡住啦)。
镜头切换的代码也很简单:
var pos = link.getPointAt(v);
workflowSphere.p(pos);
billboard.p(pos.clone().add(new mono.Vec3(0, 250, 0)));
var camera = main.sceneManager.network3d.getCamera();
camera.lookAt(pos);
camera.p(pos.clone().sub(this._cameraOffset));
数据
为了方(tou)便(lan),我们将流程图的所有数据都存放在后台。在后端页面,可以设置流程图的结构、逻辑、流程节点的样式等。
利用Ajax获取模型数据,然后三行代码便可建造一个3D流程图系统。
dataManager.addCategoryFromJson(loadData.categories);
dataManager.addDataTypeFromJson(loadData.datatypes);
dataManager.addDataFromJson(loadData.datas);
就问你们厉 ! 不 ! 厉 ! 害 !
同样,可以在后端页面设置连线的样式、颜色、起点、终点等等,获取到连线数据后,利用上文提到的方法便可绘制出所需要的连线。连动画的起点、走向同样可以在后端页面设置。
如果甲方爸爸觉得某个流程有问题,需要修改时,不要怕,默默打开后端页面改几个节点就好了。速度这么快,快夸我快夸我。
总体而言,只需要通过数据配置即可生成不同的3D流程系统,快速定制客户所需。
其他版本
有妹纸同事说,3D流程图整体色彩有点暗沉,能不能做的明亮欢快点。既然妹纸同事提建议,当然要采纳。于是。。。。于是我们又做了一个版本,暗沉还是明亮,任君挑选。
后记
篇幅有限,这一篇就先介绍这么多啦。如果大家有什么意见或建议可以发邮件到xxxxx。