Taro中使用ec-canvas遇到的那点事

Aditya2021-12-31开发问题TaroCanvas

引子

在开发过程中从最初的引用、异步加载、循环渲染,到最后的打包上传,大大小小的坑无数……

使用

  1. 先下载ecomfe/echarts-for-weixinopen in new window中 ec-canvas 整个文件夹里面的文件
  2. 引用:然后在你的页面中 的 json文件中 引用。当然你也可以作为全局组件写在app.json 中。

1. 在页面配置文件中配置 usingComponents 属性。

// page.config.js
export default {
  usingComponents: {
    // 定义需要引入的第三方组件
    // 1. key 值指定第三方组件名字,以小写开头
    // 2. value 值指定第三方组件 js 文件的相对路径
    'ec-canvas': '../../components/ec-canvas/ec-canvas'
  }
}

2. 页面使用

Taro3版本之前异步加载数据配置项中使用lazyload延迟加载来实现:

import * as echarts from '../../common/ec-canvas/echarts.js';
const optionDta = {...};

class MainPage extends Component {
  state = {
    ec: {lazyLoad: true}
  }
  componentDidMount() {
    this.refs['mychart-dom-area'].init((canvas, width, height) => {
      // 初始化图表
      const chart = echarts.init(canvas, null, {
        width: width,
        height: height
      });
      chart.setOption(option);
      // 注意这里一定要返回 chart 实例,否则会影响事件处理等
      return chart;
    })
  }
  render () {
    <View>
      <ec-canvas
         id='mychart-dom-area'
         canvas-id='mychart-area'
         ref='mychart-dom-area'
         ec={ec}
       />
    </View>
  }
}

但是升级为Taro3之后,无法获取到this.Chart的原生实例对象。
所以在Taro3内无法执行chart的init方法,同时页面也未渲染ec-canvas节点。 是因为在Taro@3内使用原生第三方组件或插件需要在page级页面内注册组件,在子组件内注册无效。 因为获取不到正确的this.Chart,所以最后通过它的onInit事件实现:

import * as echarts from '../../common/ec-canvas/echarts.js';
let chart = null

function initChart(canvas, width, height) { // 初始化图表
  console.log("init");
  chart = echarts.init(canvas, null, {
    width: width,
    height: height
  });
  canvas.setChart(chart);
  setChartData();
  return chart;
}

function setChartData () {
    let option = {
        ...
    }
    chart.setOption(option);
}

class MainPage extends Component {
  state = {
    ec: {
        onInit: 
    }
  }
  componentDidMount() {
    // ...
    setTimeout(() => {
      setChartData()
    }, 2000); // 异步获取到图表数据并更新
  }
  render () {
    <View>
      <ec-canvas
         id='mychart-dom-area'
         canvas-id='mychart-area'
         ref='mychart-dom-area'
         ec={ec}
       />
    </View>
  }
}

ec-canvas引用空白问题

图表需要一层元素包裹,并且给他设置宽高,否则会显示空白

<view class="container">
  <ec-canvas
   id="mychart-dom-bar" 
   canvas-id="mychart-bar" 
   ec="{{ ec }}">
  </ec- canvas>
</view>

循环渲染问题

<template>
<view class="echartMain" v-if="isShowEchart">
  <view class="echart" v-for="(item, index) in followPoint" :key="item._id">
    <ec-canvas ref="echart" id="echart" class="mychart-dom-bar" style="width:100%;height:600px;" canvas-id="mychart-bar" :ec="ECOptions[index]"></ec-canvas>
  </view>
</view>
</template>

<script>
import * as echarts from "../../components/ec-canvas/echarts";
let EChart = []
export default {
  data () {
    return {
      dataList: [],
      index: -1,
      ECOptions: [],
      isShowEchart: false, // 渲染图表
    }
  },
  async mounted() {
    this.onRenderEChart()
  },
  methods: {
    async onRenderEChart () {
      await Promise.all([this.onGetUserViewpoint(), this.onGetBitcoin()])
        .then(() => {
          this.followPoint.map((item, index) => {
            console.log(EChart)
            setTimeout(() => {
              this.$nextTick(() => {
                this.getOption()
              })
            }, 2000)
          })
        })
        .catch(err => {
          console.log(err)
        })
    },
    onGetUserViewpoint () {
      return new Promise(resolve => {
        Taro.request({
          url: `${this.baseUrl}/api/weapp/user/viewpoint`,
          data: {
            id: this.userInfo._id
          },
          success: res => {
            this.followPoint = res.data.result
            this.followPoint.forEach((item, index) => {
                this.ECOptions.push(
                  {
                    onInit: this.initChart
                  }
                )
              })
            this.isShowEchart = true
            resolve()
          }
        })
      })
    },
    onGetBitcoin () {
      return new Promise(resolve => {
        Taro.request({
          url: `${this.baseUrl}/api/weapp/coin/list`,
          data: {
            size: 72
          },
          success: res => {
            this.bitcoinData = res.data.result
              .map(item => {
                item.timestamp = Number(item.timestamp)
                return item
              })

            resolve()
          }
        })
      })
    },
    initChart(canvas, width, height, dpr) {
      let chart = echarts.init(canvas, null, {
        width: width,
        height: height,
        devicePixelRatio: dpr // 像素
      });
      canvas.setChart(chart);

      EChart.push(chart)
      return chart;
    },
    getOption () {
      this.index += 1
      let option =  {
        tooltip: {
          trigger: 'axis'
        },
        grid: {
          left: '20%'
        },
        xAxis: {
          type: 'category',
          data: this.bitcoinData.map(item => {
            return moment(item.timestamp).format('MM-DD hh:00')
          })
        },
        yAxis: {
          type: 'value'
        },
        series: [{
          data: this.bitcoinData.map(item => {
            if (moment(this.followPoint[this.index].meta.createdAt).valueOf() < item.timestamp) {
              return Math.floor(item.price) + Math.floor(item.price) * (this.followPoint[this.index].proportion / 100)
            }
          }),
          type: 'line'
        },{
          data: this.bitcoinData.map(item => {
            return  Math.floor(item.price)
          }),
          type: 'line'
        }]
      };
      EChart[this.index].setOption(option);
    }
  }
}
</script>

打包体积过大问题

  1. 打包时跳过echarts.js的编译
  2. 定制echarts
  3. 分包
  4. 一系列优化 Taro 解决使用echarts体积过大的问题open in new window
Last Updated 2024/12/27 11:36:49