echarts自定义折线图

echarts实现下图样式

javascript 复制代码
// 折线图公共配置:x 轴两行(下行数值、上行时间),y 轴按 axis 传入的口径分色块
    buildDieLineOption(title, seriesName, times, values, axis) {
      times = times || [];
      values = values || [];
      axis = axis || DIE_LINE_AXIS.huViscosity;
      const zones = axis.zones || [];
      // 分区边界值归上一档,绘制时色块整体左移半格、最高一档向上补满半格,
      // 否则整数刻度正好压在色块交界上,数字看不出归哪个分区
      const bands = zones.map(function(zone) {
        return {
          from: zone.from - 0.5,
          to: zone.to === axis.max ? zone.to + 0.5 : zone.to - 0.5,
          color: zone.color,
          label: zone.label
        };
      });
      // 色块内数值标注的刻度序列
      const pTicks = [];
      for (let v = axis.min; v <= axis.max + 1e-9; v += axis.valueInterval) {
        pTicks.push(Math.round(v * 1000) / 1000);
      }
      // 首格留白不画曲线,折线起点落在「红区/黄区」标题右侧
      const hasData = values.length > 0;
      const axisLead = hasData ? [''] : [];
      const lineValues = hasData ? [null].concat(values) : [];
      // 分区名画在色块左端、与左侧数值列对齐;放色块正中会被曲线压住
      const zoneMarks = times.length ? bands.map(function(band) {
        return [0, (band.from + band.to) / 2, band.label];
      }) : [];
      const tooltipFormatter = function(params) {
        // 折线数据比类目多一个前置占位格,tooltip 取值要退回一格
        var idx = params[0].dataIndex - 1;
        var val = params[0].value;
        return '时间:' + times[idx] + '<br/>数值:' + val;
      };
      return {
        backgroundColor: 'rgba(0,0,0,0)',
        title: {
          text: title,
          left: 'center',
          top: 0,
          textStyle: {
            color: '#ffffff',
            fontSize: 10,
            fontWeight: 'bold'
          }
        },
        tooltip: {
          trigger: 'axis',
          backgroundColor: 'rgba(0,0,0,0.8)',
          borderColor: '#fff',
          textStyle: { color: '#fff', fontSize: 12 },
          formatter: tooltipFormatter
        },
        grid: {
          // 左侧留出数值刻度的文字宽度,色块随之向左铺开
          left: 20,
          right: 40,
          top: 30,
          bottom: 8,
          containLabel: true
        },
        legend: { show: false },
        xAxis: [
          {
            // 第一行(下方,offset=12)------ 数值
            type: 'category',
            data: axisLead.concat(values),
            boundaryGap: false,
            position: 'bottom',
            offset: 12,
            axisLine: { show: false },
            axisTick: { show: false },
            axisLabel: {
              color: '#fff',
              fontSize: 8,
              fontWeight: 'bold',
              showMinLabel: true,
              showMaxLabel: true,
              // 首格占位后类目变窄,自动采样会把时间标签抽稀,固定每格都出
              interval: 0,
              formatter: function(v, idx) {
                return hasData && idx === 0 ? '数值' : v;
              }
            },
            splitLine: { show: false }
          },
          {
            // 第二行(上方,offset=0)------ 时间
            type: 'category',
            data: axisLead.concat(times),
            boundaryGap: false,
            position: 'bottom',
            offset: 0,
            axisLine: { show: false },
            axisTick: { show: false },
            axisLabel: {
              color: '#fff',
              fontSize: 8,
              showMinLabel: true,
              showMaxLabel: true,
              // 首格占位后类目变窄,自动采样会把时间标签抽稀,固定每格都出
              interval: 0,
              formatter: function(v, idx) {
                return hasData && idx === 0 ? '时间' : v;
              }
            },
            splitLine: { show: false }
          }
        ],
        yAxis: [
          {
            // 区域轴:只出红/黄/绿分区名,数值刻度走色块内标注
            type: 'value',
            // 上下各留半格,最低/最高一档色块才完整,整数刻度都落在色块正中
            min: axis.min - 0.5,
            max: axis.max + 0.5,
            interval: axis.outerInterval,
            position: 'left',
            offset: 0,
            axisLine: { show: false },
            axisTick: { show: false },
            // 分区名画在色块上,轴侧不再出字
            axisLabel: { show: false },
            splitLine: { show: false },
            nameTextStyle: { color: '#fff', fontSize: 8 }
          }
        ],
        series: [
          {
            name: seriesName,
            type: 'line',
            data: lineValues,
            smooth: true,
            symbol: 'circle',
            symbolSize: 3,
            lineStyle: {
              color: '#D8051D',
              width: 2
            },
            itemStyle: {
              color: '#D8051D',
              borderColor: '#D8051D',
              borderWidth: 2
            },
            markArea: {
              silent: true,
              itemStyle: { opacity: 1 },
              data: bands.map(function(band) {
                return [{ yAxis: band.from, itemStyle: { color: band.color } }, { yAxis: band.to }];
              })
            }
          },
          {
            // 数值刻度压在分区色块上:放轴外看不出它归哪个分区
            name: 'P值刻度',
            type: 'scatter',
            data: pTicks.map(function(v) { return [0, v]; }),
            symbol: 'circle',
            symbolSize: 1,
            itemStyle: { color: 'transparent' },
            silent: true,
            z: 10,
            tooltip: { show: false },
            label: {
              show: true,
              // 写在网格左外侧:贴网格左缘会与折线起点叠在一起
              position: 'left',
              distance: 5,
              color: '#ffffff',
              fontSize: 9,
              fontWeight: 'bold',
              formatter: function(p) { return p.value[1]; }
            }
          },
          {
            // 分区名压在色块上,代替原来轴侧的文字
            name: '分区',
            type: 'scatter',
            data: zoneMarks,
            symbol: 'circle',
            symbolSize: 1,
            itemStyle: { color: 'transparent' },
            silent: true,
            z: 10,
            tooltip: { show: false },
            label: {
              show: true,
              position: 'right',
              distance: 3,
              color: '#ffffff',
              fontSize: 9,
              fontWeight: 'bold',
              // 曲线起点偶尔会压到分区名,留底衬保证可读
              backgroundColor: 'rgba(0,0,0,0.35)',
              padding: [1, 3],
              borderRadius: 2,
              formatter: function(p) { return p.value[2]; }
            }
          }
        ]
      };
    }
javascript 复制代码
// 折线图模拟数据(真实接口未接通或需要回退展示时使用)
const DIE_LINE_MOCK_TIMES = ['07:35', '08:54', '12:40', '13:45', '14:45', '16:41', '18:45', '19:45'];
const DIE_LINE_MOCK_VALUES = [16, 17, 18, 19, 13, 15, 19, 18];
const DIE_LINE_MOCK_VALUES_TEMP = [56, 57.5, 54, 50.5, 51.5, 55, 53.5, 57.5];

// 折线图 y 轴口径:糊机/瓦机 × 粘度/糊化温度,四张图各自独立
// zones 的 from/to 是业务边界值(不是绘图坐标),边界值归上一档:14 属「14~15」黄区,故绘图时色块整体左移半格
const DIE_LINE_AXIS = {
  // 糊机胶水粘度
  huViscosity: {
     min: 13,
     max: 21,
     outerInterval: 0.5,
     valueInterval: 1,
     zones: [
       { from: 20, to: 21, color: '#EC808D', label: '红区' },
       { from: 19, to: 20, color: '#FFFF80', label: '黄区' },
       { from: 16, to: 19, color: '#CAF982', label: '绿区' },
       { from: 15, to: 16, color: '#FFFF80', label: '黄区' },
       { from: 13, to: 15, color: '#EC808D', label: '红区' }
     ]
   },
   // 糊机胶水糊化温度
   huGelatinize: {
     min: 54,
     max: 62,
     outerInterval: 0.5,
     valueInterval: 1,
     zones: [
       { from: 61, to: 62, color: '#EC808D', label: '红区' },
       { from: 60, to: 61, color: '#FFFF80', label: '黄区' },
       { from: 57, to: 60, color: '#CAF982', label: '绿区' },
       { from: 56, to: 57, color: '#FFFF80', label: '黄区' },
       { from: 54, to: 56, color: '#EC808D', label: '红区' }
     ]
   },
   // 瓦机胶水粘度
   waViscosity: {
     min: 11,
     max: 19,
     outerInterval: 0.5,
     valueInterval: 1,
     zones: [
       { from: 18, to: 19, color: '#EC808D', label: '红区' },
       { from: 17, to: 18, color: '#FFFF80', label: '黄区' },
       { from: 14, to: 17, color: '#CAF982', label: '绿区' },
       { from: 13, to: 14, color: '#FFFF80', label: '黄区' },
       { from: 11, to: 13, color: '#EC808D', label: '红区' }
     ]
   },
   // 瓦机胶水糊化温度
   waGelatinize: {
     min: 50,
     max: 58,
     outerInterval: 0.5,
     valueInterval: 1,
     zones: [
       { from: 57, to: 58, color: '#EC808D', label: '红区' },
       { from: 56, to: 57, color: '#FFFF80', label: '黄区' },
       { from: 53, to: 56, color: '#CAF982', label: '绿区' },
       { from: 52, to: 53, color: '#FFFF80', label: '黄区' },
       { from: 50, to: 52, color: '#EC808D', label: '红区' }
     ]
   }
 };
相关推荐
酷虎软件1 小时前
视频加标题字幕 API 接口文档
java·数据库·mysql
夜雪一千1 小时前
MySQL 触发器有哪些应用场景?从入门场景到避坑实战
数据库·mysql
hunteritself1 小时前
卷卷卷!GPT-6 Sol、Luna 正式发布,OpenAI 开始卷价格了
大数据·前端·人工智能·深度学习·transformer
lusklusklusk2 小时前
Oracle数据库基础之6_外部表临时表分区表_物化视图_约束的介绍
数据库·oracle
何何____2 小时前
Vue 全局事件总线详解
前端·javascript·vue.js
智商偏低2 小时前
【无标题】
服务器·数据库·oracle
雨落在了我的手上2 小时前
MySQL数据库基础(1):MySQL的安装-Windows
数据库·mysql
涉密IT资质笔记3 小时前
涉密人员脱密期管理规范:期限分级模型、就业限制边界与违规认定标准
java·服务器·前端·网络·数据库
honsor3 小时前
PoE温湿度传感器:一根网线供电+通信,即插即用,机房/配电室/仓库温湿度监测首选
运维·服务器·网络·数据库·人工智能·安全