古希腊掌管while循环的神 2025-07-20 19:31 采纳率: 50%
浏览 4
已结题

Javascript小程序无法显示图表

JavaScript开发温度传感小程序,从硬件端通过蓝牙读取温度数据并实时显示,在屏幕下端画出温度走势图。现在可以显示温度但是走势图没反应,能不能帮我看看是少写了什么?

// 在文件顶部添加引入语句
import * as echarts from '../../ec-canvas/echarts';

Page({
  data: {
    devices: [], // 设备列表数据
    bluetoothStatus: '未连接',
    bluetoothConnected: false,
    currentTemp: null,
    tempData: [],
    ec: {} // 图表配置容器
  },

  onLoad() {
    // 先加载历史数据,再初始化图表
    this.loadHistory(() => {
      this.initChart();
    });
  },
  

  // 初始化蓝牙
  initBluetooth() {
    if (this.data.bluetoothConnected) {
      this.closeBluetooth();
      return;
    }

    wx.openBluetoothAdapter({
      success: () => {
        this.startDiscovery();
        this.listenDeviceFound();
      },
      fail: (err) => this.showToast('蓝牙初始化失败: ' + err.errMsg)
    });
  },

  // 开始设备发现
  startDiscovery() {
    wx.startBluetoothDevicesDiscovery({
      allowDuplicatesKey: false,
      success: () => this.showToast('正在搜索设备...'),
      fail: (err) => this.showToast('搜索失败: ' + err.errMsg)
    });
  },

  // 监听发现设备事件
  listenDeviceFound() {
    wx.onBluetoothDeviceFound(devices => {
      if (!devices.devices) return;
      
      // 过滤重复设备
      const newDevices = devices.devices.filter(device => 
        !this.data.devices.some(d => d.deviceId === device.deviceId)
      );
      
      this.setData({
        devices: this.data.devices.concat(newDevices)
      });
    });
  },

  // 设备选择处理
  selectDevice(e) {
    const deviceId = e.currentTarget.dataset.deviceid;
    this.connectDevice(deviceId);
  },

  // 连接设备
  connectDevice(deviceId) {
    wx.createBLEConnection({
      deviceId,
      success: () => {
        this.setData({ 
          bluetoothStatus: '已连接',
          bluetoothConnected: true,
          devices: [] // 清空设备列表
        });
        this.getService(deviceId);
      },
      fail: (err) => this.showToast('连接失败: ' + err.errMsg)
    });
  },

  // 初始化图表
  initChart() {
    this.chartComponent = this.selectComponent('#chart');
    // 确保图表配置初始化
    this.option = {
      title: {
        text: '温度变化曲线',
        left: 'center'
      },
      tooltip: {
        trigger: 'axis'
      },
      xAxis: {
        type: 'time',

        splitLine: { show: false }
      },
      yAxis: {
        type: 'value',
        min:10,
        max:30,
        name: '温度(℃)'
      },
      series: [{
        name: '温度',
        type: 'line',
        smooth: false,
        linestyle: { //线颜色
          color: '#000000',
          width: 5,
        },
        itemstyle: { //数据点颜色
          color: '#000000',
        },
        data: []
      }]
    };
    this.setData({
      ec: {
        onInit: (canvas, width, height) => {
          const chart = echarts.init(canvas, null, { width, height });
          chart.setOption(this.option);
          this.chartInstance = chart; // 保存实例
          return chart;
        }
      }
    });
  },

  // 加载历史数据
  loadHistory(callback) {
    // const history = wx.getStorageSync('tempHistory') || [];
    // this.setData({ tempData: history }, () => {
    //   if (typeof callback === 'function') {
    //     callback(); // 数据加载完成后执行回调(初始化图表)
    //   }
    // });      //这个是有存储功能的
    const history = []; 
      this.setData({ tempData: history }, () => {
      if (typeof callback === 'function') {
        callback(); // 继续执行图表初始化回调
      }
    }); //这段用来测试阶段,删去了存储功能
  },

    // 更新图表数据(优化版)
  updateChart(data) {
    // 直接检查页面保存的图表实例
    if (!this.chartInstance) {
      console.warn('图表实例未初始化,延迟更新');
      setTimeout(() => this.updateChart(data), 300);
      return;
    }

    // 后续逻辑直接使用 this.chartInstance
    const chartData = data.map(item => {
      const timestamp = new Date(item.time).getTime();
      return { name: item.time, value: [timestamp, item.temp] };
    }).filter(item => !isNaN(item.value[0]));

    const option = this.chartInstance.getOption();
    if (option.series && option.series[0]) {
      option.series[0].data = chartData;
      // ... 动态Y轴逻辑 ...
      this.chartInstance.setOption(option); // 直接用实例更新
    }
  },

  // 监听数据变化
  listenData(deviceId, serviceId, characteristicId) {
    wx.notifyBLECharacteristicValueChange({
      deviceId,
      serviceId,
      characteristicId,
      state: true,
    });

    wx.onBLECharacteristicValueChange(res => {
      // 打印原始数据用于调试
      const uint8Arr = new Uint8Array(res.value);
      console.log('原始字节数组:', Array.from(uint8Arr));
      
      const rawHex = this.ab2hex(res.value);
      console.log('原始16进制数据:', rawHex);
      
      // 移除TextDecoder相关代码,使用兼容方式解析
      
      // 数据解析逻辑(根据原始数据[21, 1] = 0x1501进行适配)
      let temp = null;
      
      // 针对2字节数据的解析(根据实际设备通信协议调整)
      if (uint8Arr.length === 2) {
        // 假设是16位无符号整数,小端模式,单位为0.1℃
        const tempRaw = uint8Arr[0] + (uint8Arr[1] << 8);
        temp = tempRaw / 10;
        console.log('解析后的温度:', temp);
      }

      // 最终校验
      if (!isNaN(temp) && temp >= -50 && temp <= 150) {
        const time = new Date().toLocaleTimeString();
        this.setData({ currentTemp: temp.toFixed(1) });
        this.saveData({ temp, time });
      } else {
        console.warn('无法解析有效温度', { rawHex });
      }
    });
  },

  // 保存数据
  saveData(data) {
    // const newData = [...this.data.tempData, data];
    // this.setData({ tempData: newData });
    // wx.setStorageSync('tempHistory', newData);
    // this.updateChart(newData);  //同样,这里也是为了调试而删去存储功能
    const newData = [...this.data.tempData, data];
    this.setData({ tempData: newData });
    this.updateChart(newData);
  },

  // 清除历史数据(增加图表初始化检查)
  clearHistory() {
    // this.setData({ tempData: [], currentTemp: null });
    // wx.removeStorageSync('tempHistory');
    // // 确保图表已初始化
    // if (this.option) {
    //   this.updateChart([]);
    // }  //不必多言
    this.setData({ tempData: [], currentTemp: null });
    if (this.option) {
      this.updateChart([]);
    }
  },

  // ArrayBuffer转16进制字符串
  ab2hex(buffer) {
    return Array.prototype.map.call(new Uint8Array(buffer), x => ('00' + x.toString(16)).slice(-2)).join('');
  },

  // 关闭蓝牙连接
  closeBluetooth() {
    wx.closeBluetoothAdapter();
    this.setData({
      bluetoothStatus: '未连接',
      bluetoothConnected: false
    });
  },

  // 显示提示
  showToast(title) {
    wx.showToast({ title, icon: 'none' });
  },

  // 获取服务
  getService(deviceId) {
    wx.getBLEDeviceServices({
      deviceId,
      success: (res) => {
        if (res.services && res.services.length > 0) {
          console.log("所有服务列表:", res.services);
          
          // 筛选出Unknown Service(排除标准服务UUID)
          const unknownService = res.services.find(service => 
            !service.uuid.includes('1800') && !service.uuid.includes('1801')
          );
          
          if (unknownService) {
            this.getCharacteristics(deviceId, unknownService.uuid);
          } else {
            // 找不到则使用第一个服务
            const serviceId = res.services[0].uuid;
            this.getCharacteristics(deviceId, serviceId);
          }
        } else {
          this.showToast('未找到可用服务');
        }
      },
      fail: (err) => this.showToast('获取服务失败: ' + err.errMsg)
    });
  },
  
  // 获取特征值(放宽筛选条件)
  getCharacteristics(deviceId, serviceId) {
    wx.getBLEDeviceCharacteristics({
      deviceId,
      serviceId,
      success: (res) => {
        if (res.characteristics && res.characteristics.length > 0) {
          console.log("所有特征值:", res.characteristics.map(c => c.uuid));
          
          // 优先选择支持通知且可读写的特征值
          const targetChar = res.characteristics.find(c => 
            c.properties.notify && (c.properties.read || c.properties.write)
          );
          
          if (targetChar) {
            this.listenData(deviceId, serviceId, targetChar.uuid);
          } else {
            // 退而求其次选择第一个可用特征值
            const firstChar = res.characteristics.find(c => 
              c.properties.notify || c.properties.read
            );
            if (firstChar) {
              this.listenData(deviceId, serviceId, firstChar.uuid);
            } else {
              this.showToast('未找到可用特征值');
            }
          }
        }
      },
      fail: (err) => this.showToast('获取特征值失败: ' + err.errMsg)
    });
  }
});

  • 写回答

5条回答 默认 最新

  • 宝码香车 优质创作者: JavaScript技术领域 2025-07-20 19:33
    关注

    让【宝码香车】来帮你解答,本回答参考DeepSeek编写,并整理提供。

    如果还有疑问可以点击头像关注私信或评论。如果答案让您满意,请采纳、点赞、关注,非常感谢!
     
    若您愿意支持,欢迎直接打赏,将不胜感激!
     

    根据提供的代码,图表无法显示的问题可能出在以下几个方面。我将逐一分析并提供解决方案:

    1. ECharts组件未正确配置

    在WXML中需要有对应的ec-canvas组件声明:

    <ec-canvas id="chart" canvas-id="temp-chart" ec="{{ec}}"></ec-canvas>
    

    2. 图表数据格式问题

    当前代码中updateChart方法的数据转换需要调整:

    updateChart(data) {
      if (!this.chartInstance) {
        console.warn('图表实例未初始化,延迟更新');
        setTimeout(() => this.updateChart(data), 300);
        return;
      }
    
    
      // 修正数据格式转换
      const chartData = data.map(item => {
        return {
          name: item.time,
          value: [new Date(item.time).getTime(), item.temp]
        };
      });
    
    
      this.chartInstance.setOption({
        series: [{
          data: chartData
        }]
      });
    }
    

    3. 完整解决方案步骤

    "图表不显示"

    4. 关键修正点

    1. 确保ec-canvas组件存在
    <!-- 在页面wxml文件中 -->
    <view class="chart-container">
      <ec-canvas id="chart" canvas-id="temp-chart" ec="{{ec}}"></ec-canvas>
    </view>
    
    1. 样式设置
    /* 在对应的wxss文件中 */
    .chart-container {
      width: 100%;
      height: 300px;
    }
    
    1. 数据格式修正
    // 修改saveData方法
    saveData(data) {
      const newData = [...this.data.tempData, {
        time: new Date().toISOString(), // 使用标准时间格式
        temp: parseFloat(data.temp)
      }];
      this.setData({ tempData: newData });
      this.updateChart(newData);
    }
    
    1. 初始化顺序保障
    onReady() {
      // 确保在页面渲染完成后初始化
      this.initChart();
    }
    

    5. 调试建议

    1. 在控制台打印图表实例:
    console.log('图表实例:', this.chartInstance);
    
    1. 检查数据转换结果:
    console.log('转换后的图表数据:', chartData);
    
    1. 验证ECharts版本:
    console.log('ECharts版本:', echarts.version);
    

    如果按照以上步骤修正后仍然无法显示,请检查:

    • 是否正确引入了ECharts组件
    • 开发者工具是否开启了"不校验合法域名"选项
    • 真机调试时是否配置了业务域名

    建议先使用静态数据进行测试:

    // 测试数据
    const testData = [
      { time: '2023-01-01T10:00:00', temp: 22.5 },
      { time: '2023-01-01T10:05:00', temp: 23.1 },
      { time: '2023-01-01T10:10:00', temp: 22.8 }
    ];
    this.updateChart(testData);
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(4条)

报告相同问题?

问题事件

  • 已结题 (查看结题原因) 8月19日
  • 已采纳回答 8月19日
  • 创建了问题 7月20日