乐趣区

将拓扑图和图表绘制在-3D-六面体上

突然有个想法,如果能把一些用到不同的知识点放到同一个界面上,并且放到一个盒子里,这样我如果要看什么东西就可以很直接显示出来,而且这个盒子一定要能打开。我用 HT 实现了我的想法,代码一百多行,这么少的代码能实现这种效果我觉得还是牛的。

先来看看效果图:

这个例子最基础的就是最外层的盒子了,所以我们先来看看如何实现它:

var box = new ht.CSGBox();
dataModel.add(box);

用 HT 可以很轻易地实现这个盒子,在 HT 中封装了很多基础图元类型,我们经常用到的 ht.Node 也是其中一个,这样我们可以不用反复地写相同的代码来完成基础的实现。

这个例子中用的封装好的基础图元是 ht.CSGBox,一个盒子模型,可以参考 HT for Web 建模手册,我们在手册中可以看到,在 CSGBox 中我们只能操作这个盒子的各个面,如果你想要自己设置一些特殊的功能,只需要操作 ht.Style(HT for Web 风格手册)即可。

要想实现在盒子上的一个面上添加贴图,我能想到的只有 HT 封装的 ht.Default.setImage 函数了。

我想你们都注意到了盒子上有模型化的水泵,上面有扇叶在旋转,调用 graphView.deserialize(json) 来将 json 文件导出成可视化的 2d 模型并设置 animation 动画,再立即刷新到这个水泵,否则就算设置了动画,水泵上的扇叶旋转也不会生效。

ht.Default.xhrLoad('displays/demo/pump.json', function(text){const json = ht.Default.parse(text);
    pumpDM.deserialize(json);
    var currentRotation = 0;
    var lastTime = new Date().getTime();

    setInterval(function(){var time = new Date().getTime();
        var deltaTime = time - lastTime;
        currentRotation += deltaTime * Math.PI / 180 * 0.3;
        lastTime = time;

        pumpDM.getDataByTag('fan1').setRotation(currentRotation);
        pumpDM.getDataByTag('fan2').setRotation(currentRotation);
        box.iv();
        // g3d.iv(); 这边也可以刷新 g3d,但是局部刷新更省
        pumpGV.validateImpl();}, 10);
}, 10);

这个时候我不能把水泵的 graphView 和 g3d 都加到底层 div 上,并且我的意图是把水泵的 graphView 加到 g3d 中的 CSGBox 中的一面上,所以为了让水泵显示出来 必须设置水泵所在的 graphView 的宽高,而这个宽高必须比我 json 画出来的图占的面积要大,不然显示不完整。如果想看这个宽高对显示的影响,可以自己改改看来玩玩。

pumpGV.getWidth = function() { return 600;}
pumpGV.getHeight = function(){ return 600;}
pumpGV.getCanvas().dynamic = true; // 设置这个是为了让 canvas 能动态显示 

这边还要特别说明一个函数 getDataByTag(tagName) 这个函数是获取标识号,在 HT 中 tag 属性是唯一标识,虽然 HT 中也有 id,但是 id 是 HT 中 Data 类型对象构造时内部自动被赋予的一个 id 属性,可以通过 data.getId() 和 data.setId(id) 获取和设置,Data 对象添加到 DataModel 之后不允许修改 id 值,可以通过 dataModel.getDataById(id) 快速查找 Data 对象。

一般我们建议 id 属性由 HT 自动分配,用户业务意义的唯一标示可存在于 tag 属性上,通过 data.setTag(tag) 函数允许任意动态改变 tag 值,通过 dataModel.getDataByTag(tag) 可查找到对应的 Data 对象,并支持通过 dataModel.removeDataByTag(tag) 删除 Data 对象。

你可能会好奇在代码中我们并没有提到“fan1”这个 tag 标识,这个标识是在水泵的 json 中设置的,关于扇叶的一个标识,我们获取到扇叶,然后设置其旋转。

echarts 图表的显示也是很基础的,但是我们会发现,在将 echarts 图表添加进 graphView 中它的动画效果会不显示,所以我们首先要将这个 echarts 图表所在的图表的 dynamic 设置为 true,即将其设置为动态:

function charts(option){
    var info = {canvas: document.createElement('canvas')
    };
    info.canvas.dynamic = true; // 设置 info.canvas 为动态
    info.chart = echarts.init(info.canvas);
    info.chart.setOption(option);
    return info.canvas;
}

最后,只需要将这两个回传的 canvas 传入 ht.Default.setImage 中即可:

ht.Default.setImage('echart', charts(option));
ht.Default.setImage('pump', pumpGV.getCanvas());

ht.Default.drawImage 函数生成新的图实际上就是在 canvas 上画图,所以我们只要把我们已经画好的 canvas 传到 ht.Default.setImage 就可以生成图片了。

退出移动版