ThingJS 开发使用感悟

前言

近日,笔者所在公司购买了一个付费 JS 三维可视化框架开发平台——thingjs, 打算基于 thingjs 制作一个数字乡村可视化平台,笔者大概花了 3 个月的时间了解学习 thingjs 并初步制作了一版符合 UI 设计稿及交互的前端项目。初步完成后感触良多,这里写下一些个人感悟点用于有相关业务的开发人员避坑。

什么是 ThingJS

ThingJS 隶属于北京优锘科技有限公司,是优锘科技旗下物联网三维可视化开发平台。ThingJS采用JavaScript开发语言,主要面向前端程序员和实施人员。ThingJS平台让传统企业无需组建3D可视化开发团队,也能开发3D可视化应用。

以上解释来自百度百科,我相信应该是由其官方人员编写的。简单的说,ThingJS 是由国人开发的(北京优锘),需要付费使用的,基于 ThreeJS 封装的一个 3d 可视化开发平台。

为何要使用一个付费产品, 不采用开源解决方案?

因为传统上,如果我们需要开发图表类的应用,比如说常见的大屏应用,我们可以使用百度的echarts, 阿里的AntV,开源大热的D3JS,但是这些框架本质上说都是 2d 的图表展示效果,当然,它们也提供了一些三维图表,但是总体上说,echarts等平台提供的三维图表不满足很多复杂的带有一些特定交互场景的业务,所以在 web 开发方面,尤其是当下智慧城市方向特别火热时,我们有必要寻求一款可以在 web 端进行较复杂 3d 可视化场景开发的平台。那么在这一方向,目前的技术/框架有:WebGL, ThreeJS. 那它们的关系如何呢:

WebGL可以处理3D图像,听起来是非常高兴的一件事,但是WebGL实在是太底层了,WebGl解决是如何再画布上画图的问题,怎么画点,线,面,怎么上色,怎么贴图,怎么处理光线,视角转动之后怎么换算绘制等等。这些对于一个做3D应用的开发者来说要学的东西太多了。 Threejs库的出现解决了底层的渲染细节和复杂的数据结构,终于将复杂的底层细节抽象出来,使得大家开发3d应用更容易了一些。和很多开发者交流threejs都是他们首次接触的WebGL 3D库,并能很容易的就能开始做一些实验。 但是使用Threejs开发应用还是门槛很高,单就一个加载模型,调光,选择模型弹框的功能,就能干出Threejs上百行代码。同时还有很多复杂的3D概念需要理解。这时就需要ThingJS了。

来自来自 ThingJS 团队的文章。

简单的说,WebGL 是需要从零开发 3d 场景的基础知识,而 ThreeJS 封装了 WebGL 的很多底层细节,用 ThreeJS 来做 3d 开发更简便,而 ThingJS 在 ThreeJS 的基础上又做了一层封装,进一步简化非专业人员开发 3d 场景的门槛。

如何使用 ThingJS

笔者以公司目前需要开发的一个业务场景为例:笔者所在公司需要开发一个 3d 可视化的智慧乡村场景,在这个 3d 场景上加上一些 echarts 大屏的图表,同时还会有一些交互。大致场景如下: 该项目的地图背景是一个倾斜摄影模型,当然倾斜摄影模型只是一部分,在其外围是一个普通的,由 ThingJS 官方提供的一个三维底图。我们需要在这个模型基础上加入一些图表的展示,同时在此模型上加入大量的地图点位,每个地图点位都是一个摄像头,可以通过点击地图点位播放实时监控视频。 开发流程

首先便是购买 ThingJS 付费服务 来自 thingjs 官网,可以说是价格不菲了,入手需谨慎。

其次,导入倾斜摄影模型,倾斜摄影模型的源数据来自无人机航拍。这里也是 ThingJS 提供的付费服务,我们只需付钱,将源数据交给官方人员,平台帮我们生成倾斜摄影模型。 到此开始正式开发,我们的思路是将项目分成两部分,即地图模型端和图表端。地图模型端主要负责处理地图模型的一些交互,如切换地图底图;从后端获取地图点位数据并渲染到地图上;点击地图点位显示点位信息,并支持视频播放。最终项目在运行时,地图模型端是以一个 iframe 的形式嵌入到图表端的。 这里有一点值得注意的是如果要实现最终的效果,不把项目分成两部分也是可以的,即把 echarts 图表部分也写在地图模型端,这样做的好处时之后不需要考虑 iframe 交互的问题。官方也提供了一个类似的例子。于是第一个坑点出现了,thingjs 是不支持目前主流的 JS 模块化方案的(ESM,UMD, CMD……),引入模块化文件需要靠官方提供的一个 api

const loadViedeJs = async () => {

return new Promise(resolve => {

THING.Utils.dynamicLoad([

"https://www.thingjs.com/uploads/wechat/xxxx/static/video-js.min.css",

"https://www.thingjs.com/uploads/wechat/xxxx/static/video.min.js"],

function (result) {

resolve(true)

},

true, // 选填 是否带时间戳

true, // 选填 是否按顺序下载

false //选填 文件是否包含加密文件

)

})

}

类似如上的写法,而如果要实现一个较为庞大复杂的业务场景时,就不太方便了,所以项目一开始便是分为地图模型端和图表端两部分的。

开发流程

在开发流程上笔者先开发了项目的图表端的主要内容,之后再开发地图端部分。因为相比之下图表端的部分以 echarts和传统 html 网页为主,开发起来较为简单。先易后难的开发流程较好。

图表端

静态文件的编写 这里笔者新建了一个本地代码备份调试仓库,将所有静态代码现在本地用最基本的 html 文件实现出来。下面以设计稿中的乡村文明-农村基层党建为例 要开发这个小模块,还需要将其细分为两部分,即 echarts 图表和普通 html 部分。新建一个 html 静态文件编写开发内容:

HTML

农村基层党建

500

基层党支部数量

echarts 前端 javascript ThingJS 开发使用感悟  第1张

党员类型

4,961

预备党员 2,845 44%

预备党员 2,845 44%

echarts 前端 javascript ThingJS 开发使用感悟  第1张党员年龄分布情况

200

大专以以上学历

柱状图预留

echarts 前端 javascript ThingJS 开发使用感悟  第1张男女占比

男生

567

echarts 前端 javascript ThingJS 开发使用感悟  第4张

echarts 前端 javascript ThingJS 开发使用感悟  第4张

echarts 前端 javascript ThingJS 开发使用感悟  第4张

echarts 前端 javascript ThingJS 开发使用感悟  第4张

echarts 前端 javascript ThingJS 开发使用感悟  第4张

echarts 前端 javascript ThingJS 开发使用感悟  第4张

echarts 前端 javascript ThingJS 开发使用感悟  第4张

echarts 前端 javascript ThingJS 开发使用感悟  第4张

echarts 前端 javascript ThingJS 开发使用感悟  第4张

echarts 前端 javascript ThingJS 开发使用感悟  第4张

女生

567

注意这里笔者没有把样式代码写在 style 标签中,之前是考虑到最终 html 代码会以模板的形式加入到 JS 代码中去,感觉如果将 CSS 代码写在 style 标签会不好插入到模板中。但是后面笔者发现其实将 CSS 代码写在模板中也未尝不可,但是需要注意的时类名的命名上尽量不要重复,因为一旦类名重复可能会影响到其他组件的样式(推荐使用 BEM 方法进行命名)。

将静态文件改写成能在 thingjs 图表端空白文件中运行的 JS 文件 如下:

this.clearDom() //在每次进入创建DOM之前必须清除之前的DOM

let dom = this.getDom() //获取DOM节点

let jq = this.getJquery() //获取Jquery

let data = this.getComponentData() //获取组件数据

let topTitle = data.topTitle //标签数据

let title = data.title //标题数据

let content = data.content //内容数据

const aa = `

style="padding: 2px 0 4px 29px;

background: url(/uploads/wechat/oLX7p00hNvyDvp6C44l-mJtTtmAo/file/数字清水/static/images/common/title-bg.png) no-repeat;

font-family: YouSheBiaoTiHei;

font-size: 20px;

color: rgba(255, 247, 224, 0.9);

letter-spacing: 0.4px;">

农村基层党建

style="margin-top: 4px;

padding: 35px 20px;

padding-top: 0;

background: url(/uploads/wechat/oLX7p00hNvyDvp6C44l-mJtTtmAo/file/数字清水/static/images/common/data-bg.png) no-repeat;

background-size: cover;

overflow: hidden;">

style="margin: 21px auto;

width: 140px;

text-align: center;

background: url(/uploads/wechat/oLX7p00hNvyDvp6C44l-mJtTtmAo/file/数字清水/static/images/common/blue.png) no-repeat;

background-size: cover;">

style="font-family: DINAlternate-Bold;

text-align: center;

font-size: 32px;

color: #409aff;

text-shadow: 0 0 20px #19acb5;">

500