使用烛线图展示二进制01离散量趋势图

自动控制领域里的遥信量一般是离散的只有0 1 两个值的,如果要做图展示需要跟常见的趋势图不同。这里是个例子

javascript 复制代码
<!--
	此示例下载自 https://echarts.apache.org/examples/zh/editor.html?c=candlestick-touch
  烛线图,类似粗线是蜡烛身体,细线是火焰。但这个是横着放的。
  细线代表0,粗线代表1
-->
<!DOCTYPE html>
<html lang="en" style="height: 100%">
<head>
  <meta charset="utf-8">
</head>
<body style="height: 100%; margin: 0">
  <div id="container" style="height: 100%"></div> 
  <script type="text/javascript" src="https://fastly.jsdelivr.net/npm/echarts@5/dist/echarts.min.js"></script>
  
  <script type="text/javascript">
    var dom = document.getElementById('container');
    var myChart = echarts.init(dom, null, {
      renderer: 'canvas',
      useDirtyRect: false
    });
    
    var option;

    // 生成简单的时间轴(每分钟一个数据点)
    const dates = [];
    const now = new Date();
    for (let i = 0; i < 50; i++) {
      const time = new Date(now.getTime() - (49 - i) * 60000);
      dates.push(time.toLocaleTimeString('zh-CN', { hour: '2-digit', minute: '2-digit' }));
    }
    console.log('时间轴:', dates);
    // 二进制数据 (0, 1) - 0表示细线,1表示粗线
    // prettier-ignore
    const data = [0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0];
    console.log('数据:', data);
    // 为了实现不同线宽但连续的线条,创建分段数据
    function createSegmentData() {
      const segments = [];
      let start = 0;
      
      for (let i = 1; i <= data.length; i++) {
        // 当值发生变化时,或到达数组末尾时,创建一个段
        if (i === data.length || data[i] !== data[i - 1]) {
          const segmentData = [];
          // 创建该段的所有数据点
          for (let j = start; j < i; j++) {
            segmentData.push([j, 0.5]);
          }
          // 如果不是最后一段,添加下一个点以保证连续性
          if (i < data.length) {
            segmentData.push([i, 0.5]);
          }
          console.log('分段数据:', segmentData);
          segments.push({
            data: segmentData,
            lineWidth: data[start] === 0 ? 3 : 10,
            color: data[start] === 0 ? '#52c41a' : '#ff4d4f'
          });
          
          start = i;
        }
      }
      
      return segments;
    }

    const segments = createSegmentData();
    console.log('分段数据:', segments);
    option = {
      animation: false,
      title: {
        left: 'center',
        text: '二进制状态图'
      },
      tooltip: {
        trigger: 'axis',
        formatter: function (params) {
          // 用第一个系列的点的全局索引获取时间          
          // console.log('params------:', params);
          const globalIndex = params[0].data[0];// params[0].data[params[0].dataIndex][0];
          const time = dates[globalIndex];
          let html = time + '<br/>';
            let p = params[0];           
            const val = data[globalIndex];            
            html += `${p.marker}系列A: ` + (val === 0 ? '低电平(0)' : '高电平(1)') + '<br/>';          
          return html;
        }
      },
      xAxis: {
        type: 'category',
        data: dates,
        boundaryGap: false,
        axisLine: { lineStyle: { color: '#777' } },
        axisLabel: {
          show: true,
          color: '#666'
        }
      },
      yAxis: {
        type: 'value',
        show: false,  // 隐藏y轴信息
        min: 0,
        max: 1
      },
      grid: {
        left: 20,
        right: 20,
        top: 80,
        bottom: 50
      },
      series: segments.map((segment, index) => ({
        name: `状态段${index}`,
        type: 'line',
        data: segment.data,
        showSymbol: false,
        lineStyle: {
          width: segment.lineWidth,
          color: segment.color
        }
      }))
    };

    if (option && typeof option === 'object') {
      myChart.setOption(option);
    }

    window.addEventListener('resize', myChart.resize);
  </script>
</body>
</html>

双系列,多系列

javascript 复制代码
<!--
	此示例下载自 https://echarts.apache.org/examples/zh/editor.html?c=candlestick-touch
  烛线图,类似粗线是蜡烛身体,细线是火焰。但这个是横着放的。
  细线代表0,粗线代表1
-->
<!DOCTYPE html>
<html lang="en" style="height: 100%">
<head>
  <meta charset="utf-8">
</head>
<body style="height: 100%; margin: 0">
  <div id="container" style="height: 100%"></div> 
  <script type="text/javascript" src="https://fastly.jsdelivr.net/npm/echarts@5/dist/echarts.min.js"></script>
  
  <script type="text/javascript">
    var dom = document.getElementById('container');
    var myChart = echarts.init(dom, null, {
      renderer: 'canvas',
      useDirtyRect: false
    });
    
    var option;

    // 生成简单的时间轴(每分钟一个数据点)
    const dates = [];
    const now = new Date();
    for (let i = 0; i < 50; i++) {
      const time = new Date(now.getTime() - (49 - i) * 60000);
      dates.push(time.toLocaleTimeString('zh-CN', { hour: '2-digit', minute: '2-digit' }));
    }

    // 二进制数据 (0, 1) - 0表示细线,1表示粗线
    // prettier-ignore
    const data = [0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0];
    console.log('数据:', data);

    // 第二条离散量数据
    const data2 = [1, 0, 1, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0];
    console.log('数据2:', data2);
    // 为了实现不同线宽但连续的线条,创建分段数据
    function createSegmentData() {
      const segments = [];
      let start = 0;
      
      for (let i = 1; i <= data.length; i++) {
        // 当值发生变化时,或到达数组末尾时,创建一个段
        if (i === data.length || data[i] !== data[i - 1]) {
          const segmentData = [];
          // 创建该段的所有数据点
          for (let j = start; j < i; j++) {
            segmentData.push([j, 0.5]);
          }
          // 如果不是最后一段,添加下一个点以保证连续性
          if (i < data.length) {
            segmentData.push([i, 0.5]);
          }
          
          segments.push({
            data: segmentData,
            lineWidth: data[start] === 0 ? 3 : 10,
            color: data[start] === 0 ? '#52c41a' : '#ff4d4f'
          });
          
          start = i;
        }
      }
      
      return segments;
    }

    const segments = createSegmentData();

      // 第二条线的分段数据生成
      function createSegmentData2() {
        const segments = [];
        let start = 0;
        for (let i = 1; i <= data2.length; i++) {
          if (i === data2.length || data2[i] !== data2[i - 1]) {
            const segmentData = [];
            for (let j = start; j < i; j++) {
              segmentData.push([j, 0.2]); // 第二条线y值不同,避免重叠
            }
            if (i < data2.length) {
              segmentData.push([i, 0.2]);
            }
            segments.push({
              data: segmentData,
              lineWidth: data2[start] === 0 ? 3 : 10,
              color: data2[start] === 0 ? '#1890ff' : '#faad14' // 蓝色/橙色
            });
            start = i;
          }
        }
        return segments;
      }
      const segments2 = createSegmentData2();
    
    option = {
      animation: false,
      title: {
        left: 'center',
        text: '二进制状态图'
      },
      tooltip: {
        trigger: 'axis',
        formatter: function (params) {
          if (!params || !params.length) return '';
          // console.log('params------:', params);
          // const dataIndex = params[0].dataIndex;
          // const time = dates[dataIndex];
          const dataIndex = params[0].data[0];// params[0].data[params[0].dataIndex][0];
          const time = dates[dataIndex];
          let result = time + '<br/>';
          let serAry = []
          for (var i =0;i<params.length;i++) {
            let item = params[i];            
 
          // 判断是第一个系列还是第二个系列
            let seriesLabel = item.seriesName.startsWith('系列1') ? '系列1' : '系列2';
            if (serAry.includes(seriesLabel)) {
              // 已经处理过了,就忽略
              continue;
            }
            serAry.push(seriesLabel);
            // 判断当前系列用哪个数据源
            let value = seriesLabel === '系列1' ? data[dataIndex] : data2[dataIndex];
            let valueText = value === 0 ? '低电平(0)' : '高电平(1)';
            result += `${seriesLabel}: ${valueText}<br/>`;
          };
          return result;
        }
      },
      xAxis: {
        type: 'category',
        data: dates,
        boundaryGap: false,
        axisLine: { lineStyle: { color: '#777' } },
        axisLabel: {
          show: true,
          color: '#666'
        }
      },
      yAxis: {
        type: 'value',
        show: false,  // 隐藏y轴信息
        min: 0,
        max: 1
      },
      grid: {
        left: 20,
        right: 20,
        top: 80,
        bottom: 50
      },
      series: [
        ...segments.map((segment, index) => ({
          name: `系列1-段${index}`,
          type: 'line',
          data: segment.data,
          showSymbol: false,
          lineStyle: {
            width: segment.lineWidth,
            color: segment.color
          }
        })),
        ...segments2.map((segment, index) => ({
          name: `系列2-段${index}`,
          type: 'line',
          data: segment.data,
          showSymbol: false,
          lineStyle: {
            width: segment.lineWidth,
            color: segment.color
          }
        }))
      ]
    };

    if (option && typeof option === 'object') {
      myChart.setOption(option);
    }

    window.addEventListener('resize', myChart.resize);
  </script>
</body>
</html>
相关推荐
csgo打的菜又爱玩11 小时前
Vue 基础(实战模板与命名指南)
前端·javascript·vue.js
ding_zhikai12 小时前
SD:在一个 Ubuntu 系统安装 stable diffusion Web UI
前端·ubuntu·stable diffusion
gerrgwg13 小时前
Vue-library-start,一个基于Vite的vue组件库开发模板
前端·javascript·vue.js
你的人类朋友14 小时前
【Node】单线程的Node.js为什么可以实现多线程?
前端·后端·node.js
iナナ15 小时前
Spring Web MVC入门
java·前端·网络·后端·spring·mvc
驱动探索者15 小时前
find 命令使用介绍
java·linux·运维·服务器·前端·学习·microsoft
开心不就得了15 小时前
自定义脚手架
前端·javascript
星晨雪海17 小时前
怎么格式化idea中的vue文件
前端·vue.js·intellij-idea
没事多睡觉66617 小时前
Vue 虚拟列表实现方案详解:三种方法的完整对比与实践
前端·javascript·vue.js
white-persist17 小时前
Burp Suite模拟器抓包全攻略
前端·网络·安全·web安全·notepad++·原型模式