• 微信小程序使用echarts


    在这里插入图片描述

    思路

    • 五个tab公用一个柱状图组件
    • 切换tab以及切换时间改变数据,传入子组件,子组件监听数据重新更新
    • 点击柱状图显示具体数值
    • 每个时间点有两个柱子(高压和低压),柱状图显示高压的最大值到最小值的范围
    • 除了血压其余只有一条柱子
    • 步数比较特殊,不是范围,而是一个具体的步数数值
    • 根据tab设置不同的最小值
    • 假如最大值==最小值,显示一个点
    • 所有横坐标全部显示,不滚动

    下载wx-echarts

    image.png

    堆叠柱状图子组件

    image.png

    • bar.json
    {
      "component": true,
      "usingComponents": {
        "ec-canvas": "../../../ec-canvas/ec-canvas"
      }
    }
    
    • bar.wxml
    <view class="w100 h100">
      <ec-canvas id="mychart-bar" canvas-id="mychart-bar" ec="{{ ec }}"></ec-canvas>
    </view>
    
    • bar.js
    import * as echarts from '../../../ec-canvas/echarts';
    Component({
      options: {
        addGlobalClass: true,
      },
      data: {
        ec: {
          lazyLoad: true // 懒加载
        },
        time: [],
        low1: [],
        high1: [],
        low2: [],
        high2: [],
        step: []
      },
      properties: {
        list: {
          type: Array,
          observer: function (newVal, oldVal) {
            if (newVal.length || oldVal.length) {
              console.log(newVal, oldVal, 88)
              let time = newVal.map(item => item.date)
              let low1 = newVal.map(item => item.firstLowIndicators * 1)
              let high1 = newVal.map(item => item.firstHighIndicators && item.firstHighIndicators == item.firstLowIndicators ? 'solo' : item.firstHighIndicators * 1 - item.firstLowIndicators * 1)
              // let high1 = newVal.map(item => (item.firstHighIndicators * 1 - item.firstLowIndicators * 1 == 0) ? 1 : item.firstHighIndicators * 1 - item.firstLowIndicators * 1)
              let low2 = newVal.map(item => item.secondLowIndicators * 1)
              let high2 = newVal.map(item => item.secondHighIndicators && item.secondHighIndicators == item.secondLowIndicators ? 'solo' : item.secondHighIndicators * 1 - item.secondLowIndicators * 1)
              // let high2 = newVal.map(item => (item.secondHighIndicators * 1 - item.secondLowIndicators * 1 == 0) ? 1 : item.secondHighIndicators * 1 - item.secondLowIndicators * 1)
              let step = newVal.map(item => item.firstHighIndicators)
              this.setData({
                time,
                low1,
                high1,
                low2,
                high2,
                step
              })
              this.initChart(); // 数据变化时重新初始化图表
            }
          }
        },
        tab: {
          type: Number,
          value: 1
        }
      },
      methods: {
        initChart() {
          // 绑定组件
          this.barComponent = this.selectComponent("#mychart-bar");
          // 初始化柱状图
          this.barComponent.init((canvas, width, height, dpr) => {
            // 初始化图表
            const chart = echarts.init(canvas, null, {
              width: width,
              height: height,
              devicePixelRatio: dpr // 解决模糊显示问题
            })
            // 开发中根据从后端获取barData数据,动态更新图表
            chart.setOption(this.getOption())
            return chart
          })
        },
        getOption() {
          var option = {
            tooltip: {
              trigger: "axis",
              axisPointer: {
                type: "shadow",
              },
              formatter: (params) => {
                // console.log(params)
                if (this.data.tab == 5) {
                  return (
                    params[0].axisValue +
                    "\n" +
                    params[0].marker +
                    params[1].seriesName +
                    ":" +
                    (params[0].value || 0)
                  )
                } else if (this.data.tab == 1) {
                  return (
                    params[0].axisValue +
                    "\n" +
                    params[1].marker +
                    params[0].seriesName +
                    ":" +
                    params[0].value +
                    "~" +
                    (params[0].value + ((params[1].value + '').slice(-6) == '521125' ? 0 : params[1].value)) +
                    "\n" +
                    params[3].marker +
                    params[2].seriesName +
                    ":" +
                    params[2].value +
                    "~" +
                    (params[2].value * 1 + ((params[3].value + '').slice(-6) == '521125' ? 0 : params[3].value * 1))
                  );
                } else {
                  return (
                    params[0].axisValue +
                    "\n" +
                    params[1].marker +
                    params[0].seriesName +
                    ":" +
                    params[0].value +
                    "~" +
                    (params[0].value + ((params[1].value + '').slice(-6) == '521125' ? 0 : params[1].value))
                  )
                }
              },
            },
            grid: {
              top: '8%',
              left: '5%',
              right: '5%',
              bottom: '3%',
              containLabel: true
            },
            // dataZoom: [{
            //   type: 'inside', // 内置型数据区域缩放
            //   show: true,
            //   startValue: 0,
            //   endValue: 5,
            // }],
            xAxis: {
              type: 'category',
              splitLine: {
                show: false
              },
              data: this.data.time
            },
            yAxis: {
              type: 'value',
              min: [40, 80, 50, 34, 0][this.data.tab * 1 - 1],
            },
            series: [{
                name: ['舒张压范围', '血氧范围', '心率范围', '体温范围', '步数'][this.data.tab * 1 - 1],
                type: 'bar',
                stack: 'Total',
                barWidth: 4,
                itemStyle: {
                  borderColor: 'transparent',
                  color: 'transparent'
                },
                data: this.data.tab == 5 ? 0 : this.data.low1
              },
              {
                name: '',
                type: 'bar',
                stack: 'Total',
                barWidth: 4,
                label: {
                  // show: true,
                  position: 'inside'
                },
                itemStyle: {
                  color: '#2bdc70', // 设置整个系列柱子的颜色为蓝色
                  barBorderRadius: 10 // 设置所有柱子的圆角半径为10px
                },
                data: this.data.tab == 5 ? this.data.step : this.data.high1.map(item => item == 'solo' ? [2.0521125, 0.3521125, 1.0521125, 0.12521125, 0][this.data.tab * 1 - 1] : item)
              },
              {
                name: ['舒张压范围', '血氧范围', '心率范围', '体温范围', '步数'][this.data.tab * 1 - 1],
                type: 'bar',
                stack: 'Total1',
                barWidth: 4,
                itemStyle: {
                  borderColor: 'transparent',
                  color: 'transparent',
                },
                data: this.data.low2
              },
              {
                name: '',
                type: 'bar',
                stack: 'Total1',
                barWidth: 4,
                label: {
                  // show: true,
                  position: 'inside'
                },
                itemStyle: {
                  color: '#fa5151', // 设置整个系列柱子的颜色为蓝色
                  barBorderRadius: 10 // 设置所有柱子的圆角半径为10px
                },
                data: this.data.high2.map(item => item == 'solo' ? [2.0521125, 0.3521125, 0.521125, 0.0521125, 0][this.data.tab * 1 - 1] : item)
              }
            ]
          };
          return option
        }
      }
    })
    

    父组件

    <view style="width: 100%; height: 260px;">
        <my-bar list="{{barList}}"></my-bar>
    </view>
    
    "usingComponents": {
        "my-bar": "./components/bar/bar",
        "solo-table": "./components/table/table"
      },
      
      
      barList: [{
             time: this.data.active,
             low1: 50,
             high1: 80,
             low2: 80,
             high2: 140
           }, {
             time: this.data.active,
             low1: 50,
             high1: 90,
             low2: 90,
             high2: 150
           }, {
             time: this.data.active,
             low1: 50,
             high1: 80,
             low2: 70,
             high2: 100
           }, {
             time: this.data.active,
             low1: 50,
             high1: 80,
             low2: 60,
             high2: 140
           }, {
             time: this.data.active,
             low1: 70,
             high1: 100,
             low2: 100,
             high2: 140
           }, ]
    

    定制echarts.min.js

    image.png

    完整父组件

    <view class="w100 min100">
      <van-sticky offset-top="{{ 0 }}">
        <van-tabs style="z-index: 99;" sticky animated class="gray-2 bold bg-white" active="{{ tab }}" bind:change="onChangeTab" color="#217EF7" line-width="{{20}}" line-height="{{4}}">
          <van-tab title="血压" name="1"></van-tab>
          <van-tab title="血氧" name="2"></van-tab>
          <van-tab title="心率" name="3"></van-tab>
          <van-tab title="体温" name="4"></van-tab>
          <van-tab title="步数" name="5"></van-tab>
        </van-tabs>
      </van-sticky>
      <time bindchangeTab="onChangeTime" bindchangeDay="onChangeDay"></time>
    
      <view class="flex w100 pl-30 ptb-20">
        <view class="bold size-32 flex-1">{{title}}统计分析</view>
        <!-- <van-tabs animated type="card" class="gray-2 flex-1" active="{{ active }}" bind:change="onChangeTime" color="#217EF7">
          <van-tab title="日" name="1"></van-tab>
          <van-tab title="周" name="2"></van-tab>
          <van-tab title="月" name="3"></van-tab>
        </van-tabs> -->
      </view>
      <view style="width: 100%; height: 250px;">
        <my-bar list="{{barList}}" tab="{{tab*1}}"></my-bar>
      </view>
      <view class="pd-30">
        <table1 head="{{head}}" list="{{tableList}}" tab="{{tab*1}}">
        </table1>
      </view>
      <view wx:if="{{tab==1}}">
        <view class="bold size-32 flex-1 plr-30 mt-30 mb-30">30天血压趋势情况</view>
        <view style="width: 100%; height: 320px;">
          <my-scatter list="{{scatterList}}"></my-scatter>
        </view>
        <view class="pd-30">
          <solo-table total="{{total}}" list="{{soloTable}}"></solo-table>
        </view>
      </view>
    </view>
    
    {
      "usingComponents": {
        "my-bar": "./components/bar/bar",
        "bar1": "./components/bar1/bar",
        "my-scatter": "./components/scatter/scatter",
        "solo-table": "./components/solo-table/table",
        "table1": "./components/table/table",
        "time": "./components-time/time/time"
      },
      "navigationBarTitleText": "健康监测"
    }
    
     Page({
       data: {
         tab: 1, // 大分类
         title: '血压',
         timeRange: 'day', //时间切换
         queryDate: '', //时间切换
         //  bar
         barList: [],
         stepList: [],
         scatterList: [],
         total: 0,
         soloTable: [],
         //  表格
         head: [{
             text: '指标',
             prop: 'name'
           },
           {
             text: '最高',
             prop: 'max'
           },
           {
             text: '最低',
             prop: 'min'
           },
           {
             text: '参考值',
             prop: 'range'
           }
         ],
         tableList: []
       },
       onLoad(option) {
         let now = this.getNowData(new Date(), 'day')
         this.setData({
           timeRange: 'day',
           queryDate: now.content
         })
         this.getList()
         this.getList30()
       },
       getList() {
         let {
           timeRange,
           queryDate,
           tab
         } = this.data
         console.log(timeRange, queryDate, 8888888888888, timeRange == 'weeks' ? queryDate.split(' 至 ').join(',') : timeRange == 'day' ? queryDate : queryDate.split(' 至 ')[0].split('-')[0] + '-' + queryDate.split(' 至 ')[0].split('-')[1])
         wx.http('occupant/health-records/chartList', Object.assign({
           dataSource: 1, //0 手动录入   1智能手表   2、健康检测
           userId: wx.getStorageSync('userInfo').userId,
           timeRange: timeRange == 'weeks' ? 'week' : timeRange,
           queryDate: timeRange == 'weeks' ? queryDate.split(' 至 ').join(',') : timeRange == 'day' ? queryDate : queryDate.split(' 至 ')[0].split('-')[0] + '-' + queryDate.split(' 至 ')[0].split('-')[1],
           firstIndicator: ['diastolic_blood_pressure', 'blood_oxygen', 'heart_rate', 'temperature', 'step_count'][tab * 1 - 1],
         }, tab == 1 ? {
           secondIndicator: ['systolic_blood_pressure'][tab * 1 - 1]
         } : {})).then(res => {
           if (res.data.table && res.data.table.length) {
             if (tab == 1) {
               res.data.table[0].name = '舒张压'
               res.data.table[0].range = '60-90'
               res.data.table[1].range = '90-140'
               res.data.table[1].name = '收缩压'
             } else if (tab == 2) {
               res.data.table[0].name = '血氧'
               res.data.table[0].range = '95-100%'
             } else if (tab == 3) {
               res.data.table[0].name = '心率'
               res.data.table[0].range = '60-100'
             } else if (tab == 4) {
               res.data.table[0].name = '体温'
               res.data.table[0].range = '35.3-37.3℃'
             } else if (tab == 5) {
               res.data.table[0].name = '步数'
               res.data.table[0].range = '5000-10000步'
             }
           }
           //  if (tab == 5) {
           //    this.setData({
           //      stepList: res.data.charts || [],
           //      tableList: res.data.table
           //    })
           //  } else {
    
           //  }
           this.setData({
             barList: res.data.charts || [],
             tableList: res.data.table
           })
         })
       },
       getList30() {
         wx.http('occupant/health-records/bloodPressureTrend', {
           dataSource: 1, //0 手动录入   1智能手表   2、健康检测
           userId: wx.getStorageSync('userInfo').userId,
         }).then(res => {
           this.setData({
             scatterList: res.data.charts,
             total: res.data.total,
             soloTable: res.data.table,
           })
         })
       },
       onChangeTab(e) {
         this.setData({
           tab: e.detail.name,
           title: e.detail.title
         })
         this.getList()
         if (this.data.tab == 1) {
           this.getList30()
         }
       },
       //  onChangeTime(e) { 
       //    this.setData({
       //      timeRange: e.detail.id, 
       //    }) 
       //  },
       // 点击切换获取默认时间
       getNowData(date, dateType, direction) {
         let updateData = {};
         let content = "";
         let year = date.getFullYear();
         let month = date.getMonth() + 1;
         let day = date.getDate();
         let weeksDay = date.getDay();
         switch (dateType) {
           case 'day': {
             year = date.getFullYear();
             month = date.getMonth() + 1;
             day = date.getDate();
             content = year + "-" + month + "-" + day;
             break;
           }
           case 'weeks': {
    
             //获取当天在这一周是属于第几天,然后计算这一周的起始天日期和结束的日期
             weeksDay = date.getDay();
    
             let starDate = new Date(date.getTime());
             starDate.setDate(date.getDate() - weeksDay + 1);
             let startYear = starDate.getFullYear();
             let startMonth = starDate.getMonth() + 1;
             let startDay = starDate.getDate();
    
             let endDate = new Date(date.getTime());
             let endYear = endDate.getFullYear();
             let endMonth = endDate.getMonth() + 1;
             let endDay = endDate.getDate();
             //  let weeksDay = date.getDay(); // 获取今天是周几,注意:0代表周日,1代表周一
    
             //  // 计算本周第一天(周一)
             //  let startDate = new Date(date.getTime());
             //  if (weeksDay !== 0) { // 如果不是周日
             //    startDate.setDate(date.getDate() - weeksDay + 1); // 减去当前是周几再加1,得到周一
             //  } else {
             //    // 如果是周日,直接使用当前日期即可,因为已经是新的一周的开始
             //  }
             //  let startYear = startDate.getFullYear();
             //  let startMonth = startDate.getMonth() + 1; // 月份需要加1
             //  let startDay = startDate.getDate();
    
             //  // 计算本周最后一天(周日)
             //  let endDate = new Date(startDate.getTime());
             //  endDate.setDate(startDate.getDate() + 6); // 从周一基础上加6天到达周日
             //  let endYear = endDate.getFullYear();
             //  let endMonth = endDate.getMonth() + 1;
             //  let endDay = endDate.getDate();
    
             content = startYear + "-" + startMonth + "-" + startDay + ' 至 ' + endYear + "-" + endMonth + "-" + endDay;
             break;
           }
           case 'month': {
             let starDate = new Date(date.getTime());
             //计算当月的第一天日期
             starDate.setDate(1);
             let startYear = starDate.getFullYear();
             let startMonth = starDate.getMonth() + 1;
             let startDay = starDate.getDate();
    
             let endDate = new Date(date.getTime());
             let endYear = endDate.getFullYear();
             let endMonth = endDate.getMonth() + 1;
             let endDay = endDate.getDate();
    
             content = startYear + "-" + startMonth + "-" + startDay + ' 至 ' + endYear + "-" + endMonth + "-" + endDay;
             break;
           }
         }
         updateData.content = content;
         return updateData;
       },
       onChangeDay(e) {
         console.log(e.detail.id, 999999)
         this.setData({
           queryDate: e.detail.id.date.curDate,
         })
         if (e.detail.id.type) {
           this.setData({
             timeRange: e.detail.id.type,
           })
         }
         this.getList()
       },
     });
    
  • 相关阅读:
    5个超好用的视频素材网站,视频剪辑必备。
    pyecharts世界地图用:国家中英文对照表.xlsx
    20240309-1-校招前端面试常见问题-前端框架及常用工具
    uniapp开发小程序中实现骨架屏
    自动驾驶技术简史
    hot100----字串
    python获取已安装程序列表
    Security ❀ 安全设备学习规范(第二版)
    2022年数学建模国赛--赛后总结
    C++ primer plus第十一章编程练习答案
  • 原文地址:https://blog.csdn.net/weixin_43848576/article/details/139311403