本质是通过renderjs封装了一个极简echarts组件,可扩展性高,自由度高,已在安卓app中使用过
 

<template>
  <view class="content-echarts">
    <!-- #ifdef APP-PLUS || H5 -->
    <view
      id="echarts"
      class="echarts"
      :prop="renderOption"
      :change:prop="echarts.updateEcharts"
      @click="echarts.onClick"
    />
    <!-- #endif -->
  </view>
</template>

<script>
export default {
  name: 'DynamicEcharts',
  data() {
    return {
      // 初始给空对象,避免第一次 null
      renderOption: {}
    };
  },
  methods: {
    /* 父组件通过 this.$refs.xxx.setChart(option) 调用 */
    setChart(option) {
      this.renderOption = JSON.parse(JSON.stringify(option));
    }
  }
};
</script>

<!-- ============ renderjs 逻辑 ============ -->
<script module="echarts" lang="renderjs">
let myChart = null;
let inited  = false;

/* 统一的时间轴 formatter */
function timeFormatter(val) {
  // val 形如 11-21 09:33
  const [date, time] = val.split(' ');
  const [m, d] = date.split('/');
  return `${m}-${d}\n${time}`;
}

export default {
  beforeDestroy() {
    /* 关键:组件被 v-if 销毁时释放原生内存 */
    if (myChart) {
      myChart.dispose();
      myChart = null;
    }
    inited = false;
  },

  methods: {
    /* change:prop 入口 */
    updateEcharts(newOption) {
      if (!newOption || !Object.keys(newOption).length) return;

      if (!inited) {
        // 动态加载 echarts
        if (typeof window.echarts === 'function') {
          this.doInit(newOption);
        } else {
          const script = document.createElement('script');
          script.src = 'static/echarts.js';
          script.onload = () => this.doInit(newOption);
          document.head.appendChild(script);
        }
      } else {
        // 直接更新
        if (newOption.xAxis?.axisLabel) {
          newOption.xAxis.axisLabel.formatter = timeFormatter;
        }
        myChart.setOption(newOption, true);
      }
    },

    doInit(option) {
      myChart = window.echarts.init(document.getElementById('echarts'));
      inited  = true;
      if (option.xAxis?.axisLabel) {
        option.xAxis.axisLabel.formatter = timeFormatter;
      }
      if(typeof option.series[0] === 'object'){
        option.series[0].areaStyle = {
          opacity: 0.8,
          color: new window.echarts.graphic.LinearGradient(0, 0, 0, 1, [
            {
              offset: 0,
              color: "#80C962",
            },
            {
              offset: 1,
              color: "transparent",
            },
          ]),
        }
      }
      if(typeof option.series[1] === 'object'){
        option.series[1].areaStyle = {
          opacity: 0.8,
          color: new window.echarts.graphic.LinearGradient(0, 0, 0, 1, [
            {
              offset: 0,
              color: "#19A5E9",
            },
            {
              offset: 1,
              color: "transparent",
            },
          ]),
        }
      }
      myChart.setOption(option);
    },

    onClick(event, ownerInstance) {
      // 如需向逻辑层抛事件,用 ownerInstance.callMethod
      // ownerInstance.callMethod('onViewClick', { test: 'test' });
    }
  }
};
</script>

<style scoped>
.content-echarts {
  width: 1180px;
  height: 422px;
  overflow: hidden;
  background: #fafafa;
  border-radius: 14px;
}
.echarts {
  width: 1180px;
  height: 422px;
}
</style>

下面是模拟的调用方式

const categories = [];
const tempData = [];
const humiData = [];
let [t, h, m] = [25, 26, 33];          // 初始值
const total = 50;                       // 数据条数(任意改)

// 随机波动函数
function randomFluctuation(base, range) {
  return base + Math.random() * range - range / 2;
}

for (let i = 0; i < total; i++) {
  categories.push(`11-21 09:${String(++m).padStart(2, '0')}`);

  // 温度数据,以初始值为基础,加上随机波动
  t = randomFluctuation(t, 2); // 波动范围为 ±1
  tempData.push(t.toFixed(2)); // 保留两位小数

  // 湿度数据,以初始值为基础,加上随机波动
  h = randomFluctuation(h, 3); // 波动范围为 ±1.5
  humiData.push(h.toFixed(2)); // 保留两位小数
}
/* 统一白色样式 */
const whiteStyle = {
  color: '#222',
  fontSize: 16,        // 字号
  lineStyle: {
    color: '#555', // Y 轴颜色
    width: 2          // Y 轴粗细
  }
};
let option = {
  backgroundColor: 'transparent',   // 透明背景,适应黑色主题
  title: { show: false },
  legend: {
    data: ['温度', '湿度'],
    textStyle: whiteStyle,          // 图例文字白色
    top: 20,
  },
  grid: { left: '1.5%', right: '1.5%', bottom: '5%', top: '12%', containLabel: true },
  xAxis: {
    type: 'category',
    boundaryGap: false,
    data: categories,
    axisLine: { ...whiteStyle, onZero: false },      // ❌ 去掉 X 轴轴线
    axisTick: { show: false },      // 刻度线也隐藏(可选)
    axisLabel: {
      showMinLabel: true,   // 保证第一个
      showMaxLabel: true,    // 保证最后一个
      ...whiteStyle,               // 文字白色
    }
  },
  yAxis: [
    {
      type: 'value',
      name: '℃',
      nameTextStyle: whiteStyle,
      axisLabel: whiteStyle,
      axisLine: whiteStyle,         // Y 轴线想保留就留,颜色白色
      axisTick: whiteStyle,
      splitLine: { show: false },
      alignTicks: true,
    },
    {
      type: 'value',
      name: '%',
      alignTicks: true,
      nameTextStyle: whiteStyle,
      axisLabel: whiteStyle,
      axisLine: whiteStyle,
      axisTick: whiteStyle,
      splitLine: { show: false }
    }
  ],
  series: [
    {
      showSymbol: false,
      name: '温度',
      type: 'line',
      yAxisIndex: 0,
      data: tempData,
      smooth: true,
      itemStyle: { color: '#80C962' },
      lineStyle: {
        color: '#80C962',
        width: 2          // ← 加粗
      },

    },
    {
      showSymbol: false,
      name: '湿度',
      type: 'line',
      yAxisIndex: 1,
      data: humiData,
      smooth: true,
      itemStyle: { color: '#19A5E9' },
      lineStyle: {
        color: '#19A5E9',
        width: 2         // ← 加粗
      },

    }
  ]
};

this.$refs.chart.setChart(option);

          <view style="flex:1;width:100%;overflow:hidden;">
            <EchartsDom ref="chart" />
          </view>

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐