uni-app微信小程序平台兼容常用图表库

avatar
公众号「 微医大前端技术 」

56.gif

作者:陈建波,微医前端技术部,喜欢唱、跳、rap!

前言

  从使用场景上来说,这篇更应该看作是如何在微信小程序中使用常用 h5 图表库(antv/f2、echarts 等)。但是得益于 uni-app 的跨平台能力,能让我们使用更加熟悉的 vue 框架来实现微信小程序的开发。对于 uni-app 用户来说,如若使用图表能力,只能去dcloud 社区插件中搜寻,亦或是自己动手。下面来看一下,如何自己封装组件去使用这些 h5 图表库。

antv/f2

  由于新的 4.x 版本使用的是 jsx 语法,不是很习惯。这里演示的是3.x版本。 在官方文档中我们很容易发现: F2 是基于  CanvasRenderingContext2D  的标准接口绘制的,所以只要能提供标准  CanvasRenderingContext2D  接口的实现对象,F2 就能进行图表绘制。

  因为在小程序中给的  context  对象不是标准的  CanvasRenderingContext2D ,封装的核心思路是将  context  和  CanvasRenderingContext2D  对齐,所以 F2 针对支付宝和微信这 2 个常见的场景做了一层  context  的对齐,详情可见:github.com/antvis/f2-c…,其他小程序也可以按同样的思路封装。

  当然微信小程序,f2 已经兼容过,在使用的时候可以省略这一步。


首先在 src(基于 vue-cli)目录下 components 文件夹下新建组件f2-uni,在 f2-uni.vue 文件的 template 中添加。

<template>
  <canvas
    type="2d"
    class="f2-canvas"
    @touchstart="touchStart"
    @touchmove="touchMove"
    @touchend="touchEnd"
  >
  </canvas>
</template>

给容器设定个宽高。

<style lang="less">
.f2-canvas {
  width: 100%;
  height: 600rpx;
}
</style>

组件接收一个参数 onInit,用来接收 F2 构造方法和 config。

props: {
    onInit: {
      type: Function,
      default: () => {}
    }
  },

注册组件初始化的时候调用方法,从这里也能看出,小程序与 h5 在 dom 操作时选择器方法的差别。

const query = uni.createSelectorQuery().in(this);
query
  .select(".f2-canvas")
  .fields({
    node: true,
    size: true,
  })
  .exec((res) => {
    const { node, width, height } = res[0];
    const context = node.getContext("2d"); // 微信基础库2.7.0 以上支持
    const pixelRatio = uni.getSystemInfoSync().pixelRatio;
    // 高清设置
    node.width = width * pixelRatio;
    node.height = height * pixelRatio;

    const config = { context, width, height, pixelRatio };
    const chart = this.onInit(F2, config);
    if (chart) {
      this.canvasEl = chart.get("el");
    }
  });

注:canvas.getContext 基础库 2.7.0 开始支持,如果对兼容性有要求可参考官方兼容处理

touch 事件处理(其它两个同理)。

function wrapEvent (e) {
  if (!e) return
  if (!e.preventDefault) {
    e.preventDefault = function () {}
  }
  return e
}
touchStart (e) {
  const canvasEl = this.canvasEl
  if (!canvasEl) {
    return
  }
  canvasEl.dispatchEvent('touchstart', wrapEvent(e))
}

至此组件主体封装已完成,在页面中使用。

    <f2-uni class="f2-chart" :onInit="onInitChart"></f2-uni>
methods: {
    onInitChart: (F2Constructor, config) => {
      const chart = new F2Constructor.Chart(config)
      const data = [
        { value: 63.4, city: 'New York', date: '2011-10-01' },
        { value: 62.7, city: 'Alaska', date: '2011-10-01' },
        { value: 72.2, city: 'Austin', date: '2011-10-01' },
        { value: 58, city: 'New York', date: '2011-10-02' },
        { value: 59.9, city: 'Alaska', date: '2011-10-02' },
        { value: 67.7, city: 'Austin', date: '2011-10-02' },
        { value: 53.3, city: 'New York', date: '2011-10-03' },
        { value: 59.1, city: 'Alaska', date: '2011-10-03' },
        { value: 69.4, city: 'Austin', date: '2011-10-03' }
      ]
      chart.source(data, {
        date: {
          range: [0, 1],
          type: 'timeCat',
          mask: 'MM-DD'
        },
        value: {
          max: 300,
          tickCount: 4
        }
      })
      chart.area().position('date*value').color('city').adjust('stack')
      chart.line().position('date*value').color('city').adjust('stack')
      chart.render()
      // 注意:需要把chart return 出来
      return chart
    }
  }
}

成功渲染出示例图表。 image.png

本文旨在提供思路,具体封装可以更加灵活易用。

完整代码:

echarts

  与上面同理,主要针对小程序的 dom 选择器和 canvas context 做一些兼容处理。具体封装可参考 dcloud 社区中一款不错的插件 echarts for uniapp 下载插件 zip 包,可查看源码。

  如果只在微信小程序平台编译使用,且条件编译不生效,我提炼了纯净版。

别忘记对我素质三连,点赞、关注、评论^_^

前往微医互联网医院在线诊疗平台,快速问诊,3分钟为你找到三甲医生。

健康知识.gif