小程序实战(十六)带你从零到一 在小程序引入echarts - 新闻资讯 - 云南小程序开发|云南软件开发|云南网站建设-昆明葵宇信息科技有限公司

159-8711-8523

云南网建设/小程序开发/软件开发

知识

不管是网站,软件还是小程序,都要直接或间接能为您产生价值,我们在追求其视觉表现的同时,更侧重于功能的便捷,营销的便利,运营的高效,让网站成为营销工具,让软件能切实提升企业内部管理水平和效率。优秀的程序为后期升级提供便捷的支持!

您当前位置>首页 » 新闻资讯 » 小程序相关 >

小程序实战(十六)带你从零到一 在小程序引入echarts

发表时间:2021-1-4

发布人:葵宇科技

浏览次数:91

本文主要介绍从原生小程序如何引入echarts,文章末尾会给出原生小程序引入echarts的仓库地址和uniapp引入echarts的仓库地址。

第一步:引入echarts

正常情况下,例如在web端,直接做法是npm install echarts --save 。 不过在小程序中直接安装的话,会导致编译后代码包过大的问题,因此,我们可以使用echart的压缩版本, echart.min.js。将这个文件放在ec-canvas文件夹下。或者去文末的仓库地址去查看。


第二歩: 实现canvas组件
  1. ec-canvas.js 值得一提的是,一般绘制图表的数据都是服务器返回的,因此lazyLoad这个属性默认为true,意思为当拿到数据之后再进行图表的初始化。

我们会发现这个文件中引入一个WxCanvas,这是一个用于绘制canvas的封装工具。

// ec-canvas.js
import WxCanvas from './wx-canvas';
import * as echarts from './echart';
let ctx;

Component({
  properties: {
    canvasId: {
      type: String,
      value: 'ec-canvas'
    },
    lazyLoad: {
      type: Boolean,
      value: false
    },
    disableTouch: {
      type: Boolean,
      value: false
    },
    throttleTouch: {
      type: Boolean,
      value: false
    }
  },
  ready: function() {
    if (!this.lazyLoad) this.init();
  },
  methods: {
    init: function (callback) {
      ctx = wx.createCanvasContext(this.data.canvasId, this);

      const canvas = new WxCanvas(ctx, this.data.canvasId);

      echarts.setCanvasCreator(() => {
        return canvas;
      });

      var query = wx.createSelectorQuery().in(this);
      query.select('.ec-canvas').boundingClientRect(res => {
        if (typeof callback === 'function') {
          this.chart = callback(canvas, res.width, res.height);
        }
        else if (this.data.ec && typeof this.data.ec.onInit === 'function') {
          this.chart = this.data.ec.onInit(canvas, res.width, res.height);
        }
        else {
          this.triggerEvent('onInit', {
            canvas: canvas,
            width: res.width,
            height: res.height
          });
        }
      }).exec();
    },

    canvasToTempFilePath(opt) {
      if (!opt.canvasId) {
        opt.canvasId = this.data.canvasId;
      }

      ctx.draw(true, () => {
        wx.canvasToTempFilePath(opt, this);
      });
    },

    touchStart(e) {
      if (this.chart && e.touches.length > 0) {
        var touch = e.touches[0];
        var handler = this.chart.getZr().handler;
        handler.dispatch('mousedown', {
          zrX: touch.x,
          zrY: touch.y
        });
        handler.dispatch('mousemove', {
          zrX: touch.x,
          zrY: touch.y
        });
        handler.processGesture(wrapTouch(e), 'start');
      }
    },

    touchMove(e) {
      if (this.chart && e.touches.length > 0) {
        var touch = e.touches[0];
        var handler = this.chart.getZr().handler;
        handler.dispatch('mousemove', {
          zrX: touch.x,
          zrY: touch.y
        });
        handler.processGesture(wrapTouch(e), 'change');
      }
    },

    touchEnd(e) {
      if (this.chart) {
        const touch = e.changedTouches ? e.changedTouches[0] : {};
        var handler = this.chart.getZr().handler;
        handler.dispatch('mouseup', {
          zrX: touch.x,
          zrY: touch.y
        });
        handler.dispatch('click', {
          zrX: touch.x,
          zrY: touch.y
        });
        handler.processGesture(wrapTouch(e), 'end');
      }
    }
  }
})
复制代码
// wx-canvas.js
export default class WxCanvas {
  constructor(ctx, canvasId) {
    this.ctx = ctx;
    this.canvasId = canvasId;
    this.chart = null;

    WxCanvas.initStyle(ctx);
    this.initEvent();
  }

  getContext(contextType) {
    return contextType === '2d' ? this.ctx : null;
  }

  setChart(chart) {
    this.chart = chart;
  }

  attachEvent () {
    // noop
  }

  detachEvent() {
    // noop
  }

  static initStyle(ctx) {
    const styles = [
      'fillStyle',
      'strokeStyle',
      'globalAlpha',
      'textAlign',
      'textBaseAlign',
      'shadow',
      'lineWidth',
      'lineCap',
      'lineJoin',
      'lineDash',
      'miterLimit',
      'fontSize'
    ]

    styles.forEach((style) => {
      Object.defineProperty(ctx, style, {
        set: (value) => {
          if ((style !== 'fillStyle' && style !== 'strokeStyle')
            || (value !== 'none' && value !== null)
          ) {
            ctx[`set${style.charAt(0).toUpperCase()}${style.slice(1)}`](value);
          }
        },
      });
    });

    ctx.createRadialGradient = () => ctx.createCircularGradient(arguments);
  }

  initEvent() {
    this.event = {};
    const eventNames = [{
      wxName: 'touchStart',
      ecName: 'mousedown',
    }, {
      wxName: 'touchMove',
      ecName: 'mousemove',
    }, {
      wxName: 'touchEnd',
      ecName: 'mouseup',
    }, {
      wxName: 'touchEnd',
      ecName: 'click',
    }];

    eventNames.forEach((name) => {
      this.event[name.wxName] = (e) => {
        const touch = e.mp.touches[0];
        this.chart._zr.handler.dispatch(name.ecName, {
          zrX: name.wxName === 'tap' ? touch.clientX : touch.x,
          zrY: name.wxName === 'tap' ? touch.clientY : touch.y,
        });
      };
    });
  }
}
复制代码
  1. ec-canvas.wxml
<block wx:if="{{ canvasId }}">
  <canvas
    class="ec-canvas"
    id="{{ canvasId }}"
    canvasId="{{ canvasId }}"
    bindtouchstart="touchStart"
    bindtouchmove="touchMove"
    bindtouchend="touchEnd"
    binderror="error"
  ></canvas>
</block>
复制代码
  1. ec-canvas.json 和 ec-canvas.wxss
{
  "component": true,
  "usingComponents": {}
}
复制代码
.ec-canvas {
  width: 100%;
  height: 100%;
  flex: 1;
}
复制代码

第三歩:在页面中引入chart组件
  1. index.js
// index.js
import * as echarts from '../../ec-canvas/echart';

Page({
  data: {
  },
  onLoad: function () {
    this.initChart()
  },

  // 初始化图表
  initChart() {
    const chartComponent = this.selectComponent('#chart')
    chartComponent.init((canvas, width, height) => {
      const chart = echarts.init(canvas, null, {
        width,
        height
      })
      
      const option = {
        tooltip: {
          trigger: 'axis',
          axisPointer: {
            type: 'shadow'
          }
        },
        legend: {
          orient: 'vertical',
          x: 'right',
          data: ['开单金额'],
          textStyle: {
            fontSize: 12,
            color: '#999999'
          }
        },
        grid: {
          left: '2%',
          right: '5%',
          bottom: '5%',
          top: "15%",
          containLabel: true
        },
        color: ['#87E7FF'],
        xAxis: {
          type: 'category',
          data: ['2020-07-18', '2020-07-19', '2020-07-20', '2020-07-21', '2020-07-22', '2020-07-23', '2020-07-24'],
          axisLabel: {
            textStyle: {
              fontSize: 12,
              color: '#999999'
            }
          },
          axisTick: {
            alignWithLabel: true
          }
        },
        yAxis: {
          type: 'value',
          axisTick: {
            inside: true
          },
          scale: true,
          axisLabel: {
            textStyle: {
              fontSize: 12,
              color: '#999999'
            },
            margin: 5,
            formatter: function (value) {
              if (value >= 1000) {
                value = http://www.wxapp-union.com/value / 1000 + "k";
              }
      
              return value;
            }
          }
        },
        series: [{
          name: '金额',
          stack: '-',
          type: 'bar',
          data: [ 572011, 2204, 44337, 62701, 106909, 44410, 146850],
          value: [ 572011, 2204, 44337, 62701, 106909, 44410, 146850]
        }]
      };
      chart.setOption(option)
      return chart
    })
  }
})
复制代码

  1. index.wxml
<view class="container">
  <view class="ec">
    <ec-canvas id="chart" lazyLoad="{{ true }}"></ec-canvas>
  </view>
</view>
复制代码

最后一步

此时如果发现页面上并没有图表,控制台也没有任何的报错,那么就很有可能忘记了一个关键环节:为ec-canvas组件添加父级元素,并设置宽高。

.ec {
  margin-top: 40rpx;
  width: 100%;
  height: 400rpx;
}
复制代码

Uniapp中引入echarts与原生很类似,实现的原理也相同。有需要的小伙伴可以去仓库里自取。


相关案例查看更多