Threejs物联网,工厂3D可视化,加载模型,水流监测,标签动态数据展示

简介: Threejs物联网,工厂3D可视化,加载模型,水流监测,标签动态数据展示

1,介绍


该示例使用的是 r95版本Three.js库。

主要实现功能:引用水厂模型进行展示,模拟水流效果,动态显示数据信息。效果图如下:



2,主要说明


1,加载模型设置模型颜色效果并添加到场景中。

2,创建管道并添加纹理,这里不过多介绍具体可查看上一篇文章。

3,添加标签并实时刷新渲染实时数据


引入模型设置颜色效果并添加到场景中,这里只介绍添加模型方法


function initShuiChang() {
  var loader = new THREE.GLTFLoader();
  // assets/models/fang/shapan.glb'
  loader.load('assets/models/shuichang/shuichang.glb', function(result) {
    var object = result.scene;
    console.log(object)
    object.traverse(function(item) {
      if (item instanceof THREE.Mesh) {
        item.material.color.set(0x1DA9FC);
        item.material.transparent = true;
        item.material.opacity = 0.5;
      }
    });
    object.scale.set(2, 2, 2);
    object.rotateY(3.14);
    scene.add(object);
  });
}


添加标签并实时刷新渲染实时数据


function createPath(pointsArr) {
  pointsArr = pointsArr.map((point) => new THREE.Vector3(...point)); // 将参数数组转换成点数组的形式
  // 方法一:自定义三维路径 curvePath
  const path = new THREE.CurvePath();
  for (let i = 0; i < pointsArr.length - 1; i++) {
    const lineCurve = new THREE.LineCurve3(pointsArr[i], pointsArr[i + 1]); // 每两个点之间形成一条三维直线
    path.curves.push(lineCurve); // curvePath有一个curves属性,里面存放组成该三维路径的各个子路径
  }
  return path;
}
const count = 200
const gColor = '#28f260'
const prop1 = {
  width: 416,
  height: 112,
  pos: [60, 35, 30],
  // scale:[24, 6, 0]
  scale: [0.24375 * count, 0.065625 * count, 0]
}
const tab1 = [
  ['一级高压泵后压力:', '20.2bar', gColor],
  ['一级循环泵后压力:', '0.2bar', ]
]
const prop2 = {
  width: 352,
  height: 196,
  pos: [-60, 40, 0],
  scale: [0.20625 * count, 0.11484375 * count, 0],
}
const tab2 = [
  ['进水情况', ''],
  ['进水温度:', '25.6℃', gColor],
  ['进水流量:', '2.5m³', ],
  ['进水电导:', '28.5ms/cm', gColor],
]
const prop3 = {
  width: 384,
  height: 256,
  pos: [5, 60, -60],
  scale: [0.225 * count, 0.15 * count, 0]
}
const tab3 = [
  ['产水情况', ''],
  ['一级回收率:', '58%', gColor],
  ['一级产水流量:', '1.75㎡', ],
  ['一级产水电量:', '980.5/cm', gColor],
  ['一级产水电量:', '0.5bar', gColor],
]
const prop4 = {
  width: 256,
  height: 64,
  pos: [-85, 30, 40],
  scale: [0.15 * count, 0.0375 * count, 0],
}
const tab4 = [
  ['泵机状态 ', '• 开启', gColor],
]
const prop5 = {
  width: 256,
  height: 64,
  pos: [-10, 50, 30],
  scale: [0.15 * count, 0.0375 * count, 0],
}
const tab5 = [
  ['阀门状态 ', '• 开启', gColor],
]
const props = [prop1, prop2, prop3, prop4, prop5]
const tabs = [tab1, tab2, tab3, tab4, tab5]
// 调用渲染标签,并定时刷新
handleDatachange();
setInterval(handleDatachange, 2000)
function handleDatachange() {
  let r = (Math.random() * 10 + 20).toFixed(2)
  tab2[1][1] = r + '℃'
  if (r > 25) tab2[1][2] = 'red'
  else tab2[1][2] = gColor
  r = Math.random().toFixed(2)
  tab3[4][1] = r + 'bar'
  if (r > 0.5) tab3[4][2] = 'red';
  else tab3[4][2] = gColor
  if (Math.random() > 0.5) {
    tab5[0][1] = '• 开启'
    tab5[0][2] = gColor
  } else {
    tab5[0][1] = '• 关闭'
    tab5[0][2] = 'red'
  }
  console.time('render sprite')
  initSprite()
  console.timeEnd('render sprite')
}
function initSprite() {
  clearSprite();
  (scene.children || []).forEach((v, idx) => {
    if (v.type == 'Mesh') {
      const borderColor = 'rgba(39, 179, 236, 1)'
      const color = 'rgba(255,255,255, 1)'
      makeTextSprite(scene, tabs, props, {
        color: color,
        borderColor,
        backgroundColor: 'rgba(255,255,255,0.05)'
      });
    }
  });
}
// 清空雪碧图
function clearSprite(type = 'Sprite') {
  const children = [];
  (scene.children || []).forEach((v, idx) => {
    if (v.type !== type) {
      children.push(v);
    }
  });
  scene.children = children;
}


/* 创建字体精灵 */
function makeTextSprite(scene, tabs, props, parameters) {
  if (parameters === undefined) parameters = {}
  tabs.forEach((tab, k) => {
    let {
      width,
      height
    } = props[k]
    /* 创建画布 */
    let canvas = document.createElement('canvas');
    let context = canvas.getContext('2d')
    canvas.width = width
    canvas.height = height
    let gap = 10
    let fontface = parameters.hasOwnProperty("fontface") ? parameters["fontface"] : "sans-serif"
    /* 字体大小 */
    let fontsize = parameters.hasOwnProperty("fontsize") ?
      parameters["fontsize"] : 30
    let color = parameters.hasOwnProperty("color") ? parameters["color"] : 'rgba(0, 0, 0, 1.0)'
    /* 边框厚度 */
    let borderWith = parameters.hasOwnProperty("borderWith") ? parameters["borderWith"] : 2
    /* 边框颜色 */
    let borderColor = parameters.hasOwnProperty("borderColor") ? parameters["borderColor"] : {
      r: 0,
      g: 0,
      b: 0,
      a: 1.0
    }
    /* 背景颜色 */
    let backgroundColor = parameters.hasOwnProperty("backgroundColor") ? parameters["backgroundColor"] : {
      r: 255,
      g: 255,
      b: 255,
      a: 1.0
    }
    /* 字体加粗 */
    // context.font = "Bold " + fontsize + "px " + fontface
    context.font = fontsize + "px " + fontface
    let unit = gap + fontsize
    /* 背景颜色 */
    context.fillStyle = backgroundColor
    /* 边框的颜色 */
    context.strokeStyle = borderColor
    context.lineWidth = borderWith
    /* 绘制圆角矩形 */
    roundRect(context, gap, gap, width - gap, height - gap, 4)
    tab.forEach((d, i) => {
      context.fillStyle = color;
      context.fillText(d[0], gap * 2, gap + unit * (i + 1))
      if (d[2]) {
        context.fillStyle = d[2]
      }
      context.fillText(d[1], gap * 2 + measureText(d[0], context), gap + unit * (i + 1))
    })
    /* 画布内容用于纹理贴图 */
    let texture = new THREE.Texture(canvas);
    texture.needsUpdate = true
    let spriteMaterial = new THREE.SpriteMaterial({
      map: texture,
      // sizeAttenuation:false,
      // transparent:true
    });
    let sprite = new THREE.Sprite(spriteMaterial)
    // console.log(sprite.spriteMaterial)
    /* 缩放比例 */
    sprite.scale.set(...props[k].scale)
    sprite.center = new THREE.Vector2(0, 0);
    scene.add(sprite);
    sprite.position.set(...props[k].pos);
  })
}
function measureText(text, ctx, font) {
  if (font) ctx.font = font
  return ctx.measureText(text).width;
}
/* 绘制圆角矩形 */
function roundRect(ctx, x, y, w, h, r) {
  ctx.beginPath();
  ctx.moveTo(x + r, y);
  ctx.lineTo(x + w - r, y);
  ctx.quadraticCurveTo(x + w, y, x + w, y + r);
  ctx.lineTo(x + w, y + h - r);
  ctx.quadraticCurveTo(x + w, y + h, x + w - r, y + h);
  ctx.lineTo(x + r, y + h);
  ctx.quadraticCurveTo(x, y + h, x, y + h - r);
  ctx.lineTo(x, y + r);
  ctx.quadraticCurveTo(x, y, x + r, y);
  ctx.closePath();
  // ctx.shadowColor = "#qb95cf";
  // ctx.shadowOffsetX = 0;
  // ctx.shadowOffsetY = 0;
  // ctx.shadowBlur = 4;
  ctx.fill();
  ctx.stroke();
  ctx.shadowColor = "";
  ctx.shadowOffsetX = 0;
  ctx.shadowOffsetY = 0;
  ctx.shadowBlur = 0;
}
相关实践学习
钉钉群中如何接收IoT温控器数据告警通知
本实验主要介绍如何将温控器设备以MQTT协议接入IoT物联网平台,通过云产品流转到函数计算FC,调用钉钉群机器人API,实时推送温湿度消息到钉钉群。
阿里云AIoT物联网开发实战
本课程将由物联网专家带你熟悉阿里云AIoT物联网领域全套云产品,7天轻松搭建基于Arduino的端到端物联网场景应用。 开始学习前,请先开通下方两个云产品,让学习更流畅: IoT物联网平台:https://iot.console.aliyun.com/ LinkWAN物联网络管理平台:https://linkwan.console.aliyun.com/service-open
目录
相关文章
|
关系型数据库 物联网 PostgreSQL
沉浸式学习PostgreSQL|PolarDB 11: 物联网(IoT)、监控系统、应用日志、用户行为记录等场景 - 时序数据高吞吐存取分析
物联网场景, 通常有大量的传感器(例如水质监控、气象监测、新能源汽车上的大量传感器)不断探测最新数据并上报到数据库. 监控系统, 通常也会有采集程序不断的读取被监控指标(例如CPU、网络数据包转发、磁盘的IOPS和BW占用情况、内存的使用率等等), 同时将监控数据上报到数据库. 应用日志、用户行为日志, 也就有同样的特征, 不断产生并上报到数据库. 以上数据具有时序特征, 对数据库的关键能力要求如下: 数据高速写入 高速按时间区间读取和分析, 目的是发现异常, 分析规律. 尽量节省存储空间
782 1
|
消息中间件 传感器 监控
IoT企业物联网平台,数据服务开发实战
IoT企业物联网平台开发实战
438 0
|
4月前
|
物联网 数据管理 Apache
拥抱IoT浪潮,Apache IoTDB如何成为你的智能数据守护者?解锁物联网新纪元的数据管理秘籍!
【8月更文挑战第22天】随着物联网技术的发展,数据量激增对数据库提出新挑战。Apache IoTDB凭借其面向时间序列数据的设计,在IoT领域脱颖而出。相较于传统数据库,IoTDB采用树形数据模型高效管理实时数据,具备轻量级结构与高并发能力,并集成Hadoop/Spark支持复杂分析。在智能城市等场景下,IoTDB能处理如交通流量等数据,为决策提供支持。IoTDB还提供InfluxDB协议适配器简化迁移过程,并支持细致的权限管理确保数据安全。综上所述,IoTDB在IoT数据管理中展现出巨大潜力与竞争力。
121 1
|
1月前
|
传感器 安全 算法
物联网发布者在数据传输过程中如何防止数据被篡改
在物联网数据传输中,为防止数据被篡改,可采用加密技术、数字签名、数据完整性校验等方法,确保数据的完整性和安全性。
|
1月前
|
存储 安全 算法
物联网发布者在发送数据时如何保证数据的安全性和完整性
数据加密、密钥管理和数据完整性验证是物联网安全的重要组成部分。对称加密(如AES)和非对称加密(如RSA)分别适用于大量数据和高安全需求的场景。密钥需安全存储并定期更新。数据完整性通过MAC(如HMAC-SHA256)和数字签名(如RSA签名)验证。通信协议如MQTT over TLS/SSL和CoAP over DTLS增强传输安全,确保数据在传输过程中的机密性和完整性。
|
6月前
|
传感器 数据采集 存储
物联网技术在智能环境监测中的部署与优化
物联网技术在智能环境监测中的部署与优化
|
4月前
|
存储 传感器 监控
理解并利用物联网(IoT)数据的技术探索
【8月更文挑战第11天】物联网数据是数字化转型的重要资源。通过深入理解物联网数据的特性和价值,并采取有效的收集、处理和分析策略,我们可以更好地利用这些数据为企业决策提供支持、优化运营效率、创造新的商业模式并推动数字化转型的深入发展。
|
4月前
|
存储 安全 物联网
物联网中的通信模型
【8月更文挑战第23天】
51 0
|
5月前
|
物联网
好的资源链接,gitee全糖咖啡,B站视频转成mp4,全糖咖啡 / 物联网网关数据上传,,全糖咖啡 / springboot+百度智能车牌检测
好的资源链接,gitee全糖咖啡,B站视频转成mp4,全糖咖啡 / 物联网网关数据上传,,全糖咖啡 / springboot+百度智能车牌检测
|
7月前
|
传感器 机器学习/深度学习 算法
LabVIEW开发工业物联网状态监测
LabVIEW开发工业物联网状态监测
82 2

相关产品

  • 物联网平台