项目介绍
智慧工厂数据可视化系统,融合工业大数据、物联网、人工智能等各类信息技术,整合厂区现有信息系统的数据资源,实现数字孪生工厂、设备运维监测、智能管网监测、综合安防监测、便捷通行监测、能效管理监测、生产管理监测、仓储物流监测等多种功能,有效提高厂区综合监管能力、降低企业厂区运营成本,实现管理精细化、决策科学化和服务高效化。
项目展示
我们使用canvas,echarts,three.js开发绘制数字孪生工厂、设备运维监测、能效管理监测等页面,下面是项目中的一些案例
1.数字孪生工厂案例
2.设备运维监测案例

3.能效管理监测
项目开发
 
下面我们将通过项目实战教会大家如何利用canvas绘制一个智慧工厂数据可视化场景页面。
本文章以设备运维监测页面为案例讲解
1.场景画布绘制
针对智慧工厂数据可视化系统各种场景的绘制,首先我们使用canvas绘制一个画布,然后定义全局的canvas和ctx对象。
<canvas id="canvas" width="1880" height="900"></canvas>
let canvas = document.getElementById('canvas');
let ctx = canvas.getContext('2d'); 
2.场景元素绘制
首先我们把模型的图片准备好,然后我们写一个函数createPic可以传入模型的坐标位置,模型的大小和模型的路径。
2.1 绘制模型
createPic前2个参数是坐标xy轴的位置,我们这边坐标点是10,10 就会在画布的左上角绘制模型。createPic第3个第四个参数是模型的大小,我们这边定义模型的大小是222,232 。createPic最后一个参数数模型图片的位置。
createPic(10,10,222,232,'../scanboard4/model/水池.png');//调节池 
 
2.2 createPic函数实现
创建一个Image对象,把图片的路径src赋值给Image对象,在Image的onload方法中拿到Image图片并通过ctx对象(canvas上下文对象)的drawImage的方法把模型加载到画布上
2.3 绘制标签
给模型添加名称,实际设备参数
createPic(50,50,222,232,'../scanboard4/model/水池.png');//调节池
drawLabel(125,40,'pH:3.21');
drawTitle(125,159,'调节池'); 

2.4 drawTitle和drawLabel函数实现
我们使用canvasAPI中的fillText绘制文字,设备参数是动态参数经常会变,我们需要每次绘制的时候把上一次的文字抹除掉,这边我们通过clearRect方法把上一次的文字抹除,因为文字大小和长度不一样的,每次抹除的范围不一样,我们通过canvasAPI中的measureText(text)可以得到文字的长度和高度去抹除
//绘制标题
function drawTitle(x,y,title,color,font){
    ctx.beginPath();
    if(!font){
        ctx.font="18px Arial";
    }else{
        ctx.font = font; 
    }
    
    if(!color){
        ctx.fillStyle = "#F6DC2C"; 
    }else{
        ctx.fillStyle = color; 
    }
    ctx.textAlign="left";
    
    ctx.fillText(title,x,y); 
    ctx.closePath();  
    ctx.restore();    
}
//绘制指标
function drawLabel(x,y,text,color,font){
    ctx.beginPath();
    if(!font){
        ctx.font="14px Arial";
    }else{
        ctx.font = font; 
    }
    
    if(!color){
        ctx.fillStyle = "#fff"; 
    }else{
        ctx.fillStyle = color; 
    }
    var textWidth = ctx.measureText(text).width +50;
    var hangingBaseline = ctx.measureText(text).hangingBaseline;
    ctx.clearRect(x-3,y-(hangingBaseline+3),textWidth,(hangingBaseline+8));
    
    ctx.textAlign="left";
    ctx.fillText(text,x,y);
    ctx.closePath();      
} 
2.5绘制管道
设备与设备之间会有管道转接,我们这边有金属风格、蓝色风格、绿色风格的管子,我们这边通过
drawTunnelLine和drawTunnelInterface 2个函数分别绘制管道和管道转接。
createPic(50,50,222,232,'../scanboard4/model/水池.png');//调节池
drawLabel(125,40,'pH:3.21');
drawTitle(125,159,'调节池');
//金属风格管道
drawTunnelLine(271, 87,387,87);
drawTunnelInterface(386,86,3);
drawTunnelLine(387,86,387,56);
//蓝色风格管道
drawTunnelLine1(271, 165,387,165);
//绿色风格管道
drawTunnelLine2(271, 256,387,256);
drawTunnelInterface2(387,267,2);
drawTunnelLine2(398,267,398,356); 

2.6 drawTunnelLine和drawTunnelInterface函数实现
drawTunnelLine函数传入4个函数,分别是起点坐标和终点坐标。我们通过canvasAPI中fillRect绘制管道,通过createLinearGradient设置渐变色实现金属风格的渐变效果。
drawTunnelInterface函数传入3个函数,转接管的坐标点以及转接管的朝向。我通过canvasAPI中arc绘制圆弧,然后通过createRadialGradient设置渐变色实现金属风格的渐变效果。
// 绘制金属管道
function drawTunnelLine(x1, y1, x2, y2) {
    lineWidth = 10;  // 设置线条宽度
    // 计算线条的矩形范围
    let dx = x2 - x1;
    let dy = y2 - y1;
    let length = Math.sqrt(dx*dx + dy*dy);  // 线段长度
    let angle = Math.atan2(dy, dx);  // 线段的角度
    // 绘制矩形
    ctx.save();  // 保存当前上下文状态
    ctx.translate(x1, y1);  // 平移到起始点
    ctx.rotate(angle);  // 旋转到线段的角度
    var g1 = ctx.createLinearGradient(0, 0, 0,  lineWidth);
    g1.addColorStop(0.2, '#7A8383'); 
    g1.addColorStop(0.6, '#fff');
    g1.addColorStop(0.8, '#7A8383'); 
    ctx.fillStyle = g1;
    ctx.fillRect(0, 0, length, lineWidth);  // 绘制矩形
    ctx.restore();  // 恢复上下文状态
}
// 绘制金属管道转接口
function drawTunnelInterface(x,y,rotate){
    var RADIUS = 11;
    ctx.beginPath();
    ctx.lineWidth=0.01;
    ctx.moveTo(x, y);
    var rotate = (Math.PI/2) *rotate;
    ctx.arc(x, y, RADIUS, Math.PI / 2 + rotate, Math.PI + rotate); //sAngle 90 ,eAngle 180
    var g1 = ctx.createRadialGradient(
        x, // 内圆中心的 x 坐标
        y, // 内圆中心的 y 坐标
        0, // 内圆的半径
        x, // 外圆中心的 x 坐标
        y, // 外圆中心的 y 坐标
        RADIUS // 外圆的半径,这里设置为整个 Canvas 的一半
    );
    g1.addColorStop(0.2, '#7A8383'); 
    g1.addColorStop(0.6, '#fff');
    g1.addColorStop(0.8, '#7A8383'); 
    ctx.fillStyle = g1;
    ctx.fill();
    ctx.restore();
    ctx.stroke();
} 
项目结束
以上我们一个简单的案例基础功能就完成了,通过此案例简单的介绍了一下canvas的一些功能,大家可以根据自己的需求场景绘制自己的可视化场景。
最后给大家看一下我在工作中绘制的一些别的场景
























