小程序也可以echarts

lxf2023-12-14 13:10:02

准备工作

本人开发小程序使用的是uniapp,添加uni-ec-canvas,目录结构如下

小程序也可以echarts

uni-ec-canvas.js文件中的代码

<template>  <canvas type="2d" v-if="isUseNewCanvas" class="ec-canvas" :canvas-id="canvasId" @init="init" @touchstart="touchStart"    @touchmove="touchMove" @touchend="touchEnd">  </canvas>  <canvas v-else class="ec-canvas" :canvas-id="canvasId" @init="init" @touchstart="touchStart" @touchmove="touchMove"    @touchend="touchEnd">  </canvas></template><script>  import WxCanvas from "./wx-canvas";  import * as echarts from "./echarts.min.js";  let ctx;  function wrapTouch(event) {    for (let i = 0; i < event.touches.length; ++i) {      const touch = event.touches[i];      touch.offsetX = touch.x;      touch.offsetY = touch.y;    }    return event;  }  export default {    props: {      canvasId: {        type: String,        default: () => {          return "ec-canvas";        }      },      ec: {        type: Object      },      forceUseOldCanvas: {        type: Boolean,        value: false      }    },    data() {      return {        $curChart: {},        toHandleList: [],        isUseNewCanvas: true      };    },    watch: {      "ec.option": {        deep: true,        handler(val, oldVal) {          this.setOption(val);        }      }    },    onReady: function() {      if (!this.ec) {        console.warn(          '组件需绑定 ec 变量,例:<ec-canvas id="mychart-dom-bar" ' +          'canvas-id="mychart-bar" ec="{{ ec }}"></ec-canvas>'        );        return;      }      if (!this.ec.lazyLoad) {        this.init();      }    },    methods: {      compareVersion(v1, v2) {        v1 = v1.split(".");        v2 = v2.split(".");        const len = Math.max(v1.length, v2.length);        while (v1.length < len) {          v1.push("0");        }        while (v2.length < len) {          v2.push("0");        }        for (let i = 0; i < len; i++) {          const num1 = parseInt(v1[i]);          const num2 = parseInt(v2[i]);          if (num1 > num2) {            return 1;          } else if (num1 < num2) {            return -1;          }        }        return 0;      },      init(callback) {        const version = wx.getSystemInfoSync().SDKVersion;        let canUseNewCanvas = this.compareVersion(version, "2.9.0") >= 0;        if (this.forceUseOldCanvas) {          if (canUseNewCanvas) console.warn("开发者强制使用旧canvas,建议关闭");          canUseNewCanvas = false;        }        this.isUseNewCanvas = canUseNewCanvas && !this.forceUseOldCanvas;        if (this.isUseNewCanvas) {          console.log('微信基础库版本大于2.9.0,开始使用<canvas type="2d"/>');          // 2.9.0 可以使用 <canvas type="2d"></canvas>          this.initByNewWay(callback);        } else {          const isValid = this.compareVersion(version, "1.9.91") >= 0;          if (!isValid) {            console.error(              "微信基础库版本过低,需大于等于 1.9.91。" +              "参见:https://github.com/ecomfe/echarts-for-weixin" +              "#%E5%BE%AE%E4%BF%A1%E7%89%88%E6%9C%AC%E8%A6%81%E6%B1%82"            );            return;          } else {            console.warn(              "建议将微信基础库调整大于等于2.9.0版本。升级后绘图将有更好性能"            );            this.initByOldWay(callback);          }        }      },      initByOldWay(callback) {        // 1.9.91 <= version < 2.9.0:原来的方式初始化        ctx = wx.createCanvasContext(this.canvasId, this);        const canvas = new WxCanvas(ctx, this.canvasId, false);        const that = this        echarts.setCanvasCreator(() => {          return canvas;        });        // const canvasDpr = wx.getSystemInfoSync().pixelRatio // 微信旧的canvas不能传入dpr        const canvasDpr = 1;        var query = wx.createSelectorQuery().in(this);        query          .select(".ec-canvas")          .boundingClientRect(res => {            if (typeof callback === "function") {              that.$curChart = callback(canvas, res.width, res.height, canvasDpr);            } else if (that.ec) {              that.initChart(canvas, res.width, res.height, canvasDpr)            } else {              that.triggerEvent("init", {                canvas: canvas,                width: res.width,                height: res.height,                devicePixelRatio: canvasDpr // 增加了dpr,可方便外面echarts.init              });            }          })          .exec();      },      initByNewWay(callback) {        const that = this        // version >= 2.9.0:使用新的方式初始化        const query = wx.createSelectorQuery().in(this);        query          .select(".ec-canvas")          .fields({            node: true,            size: true          })          .exec(res => {            const canvasNode = res[0].node;            const canvasDpr = wx.getSystemInfoSync().pixelRatio;            const canvasWidth = res[0].width;            const canvasHeight = res[0].height;            const ctx = canvasNode.getContext("2d");            const canvas = new WxCanvas(ctx, that.canvasId, true, canvasNode);            echarts.setCanvasCreator(() => {              return canvas;            });            if (typeof callback === "function") {              that.$curChart = callback(                canvas,                canvasWidth,                canvasHeight,                canvasDpr              );            } else if (that.ec) {              that.initChart(canvas, canvasWidth, canvasHeight, canvasDpr)            } else {              that.triggerEvent("init", {                canvas: canvas,                width: canvasWidth,                height: canvasHeight,                devicePixelRatio: canvasDpr              });            }          });      },      setOption(val) {        if (!this.$curChart || !this.$curChart.setOption) {          this.toHandleList.push(val);        } else {          this.$curChart.setOption(val);        }      },      canvasToTempFilePath(opt) {        if (this.isUseNewCanvas) {          // 新版          const query = wx.createSelectorQuery().in(this);          query            .select(".ec-canvas")            .fields({              node: true,              size: true            })            .exec(res => {              const canvasNode = res[0].node;              opt.canvas = canvasNode;              wx.canvasToTempFilePath(opt);            });        } else {          // 旧的          if (!opt.canvasId) {            opt.canvasId = this.canvasId;          }          ctx.draw(true, () => {            wx.canvasToTempFilePath(opt, this);          });        }      },      touchStart(e) {        if (this.ec.stopTouchEvent) {          e.preventDefault();          e.stopPropagation();          return;        }        this.$emit("touchstart", e);        if (this.$curChart && e.touches.length > 0) {          var touch = e.touches[0];          var handler = this.$curChart.getZr().handler;          if (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.ec.stopTouchEvent) {          e.preventDefault();          e.stopPropagation();          return;        }        this.$emit("touchmove", e);        if (this.$curChart && e.touches.length > 0) {          var touch = e.touches[0];          var handler = this.$curChart.getZr().handler;          if (handler) {            handler.dispatch("mousemove", {              zrX: touch.x,              zrY: touch.y            });            handler.processGesture(wrapTouch(e), "change");          }        }      },      touchEnd(e) {        if (this.ec.stopTouchEvent) {          e.preventDefault();          e.stopPropagation();          return;        }        this.$emit("touchend", e);        if (this.$curChart) {          const touch = e.changedTouches ? e.changedTouches[0] : {};          var handler = this.$curChart.getZr().handler;          if (handler) {            handler.dispatch("mouseup", {              zrX: touch.x,              zrY: touch.y            });            handler.dispatch("click", {              zrX: touch.x,              zrY: touch.y            });            handler.processGesture(wrapTouch(e), "end");          }        }      },      initChart(canvas, width, height, canvasDpr) {        this.$curChart = echarts.init(canvas, null, {          width: width,          height: height,          devicePixelRatio: canvasDpr        });        canvas.setChart(this.$curChart);        this.$curChart.setOption(this.ec.option);      }    }  };</script><style lang="scss">  .ec-canvas {    width: 100%;    height: 100%;    display: block;  }</style>

wx-canvas.js文件中的代码:

export default class WxCanvas {  constructor(ctx, canvasId, isNew, canvasNode) {    this.ctx = ctx;    this.canvasId = canvasId;    this.chart = null;    this.isNew = isNew    if (isNew) {      this.canvasNode = canvasNode;    } else {      this._initStyle(ctx);    }    // this._initCanvas(zrender, ctx);    this._initEvent();  }  getContext(contextType) {    if (contextType === '2d') {      return this.ctx;    }  }  // canvasToTempFilePath(opt) {  //   if (!opt.canvasId) {  //     opt.canvasId = this.canvasId;  //   }  //   return wx.canvasToTempFilePath(opt, this);  // }  setChart(chart) {    this.chart = chart;  }  attachEvent() {    // noop  }  detachEvent() {    // noop  }  _initCanvas(zrender, ctx) {    zrender.util.getContext = function () {      return ctx;    };    zrender.util.$override('measureText', function (text, font) {      ctx.font = font || '12px sans-serif';      return ctx.measureText(text);    });  }  _initStyle(ctx) {    var 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 = () => {      return 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.touches[0];        this.chart.getZr().handler.dispatch(name.ecName, {          zrX: name.wxName === 'tap' ? touch.clientX : touch.x,          zrY: name.wxName === 'tap' ? touch.clientY : touch.y        });      };    });  }  set width(w) {    if (this.canvasNode) this.canvasNode.width = w  }  set height(h) {    if (this.canvasNode) this.canvasNode.height = h  }  get width() {    if (this.canvasNode)      return this.canvasNode.width    return 0  }  get height() {    if (this.canvasNode)      return this.canvasNode.height    return 0  }}

echarts.min.js是在echarts官网中自己生成的,可以按需引入,就可以减少体积哦~

使用过程

在文件中引入刚刚准备的包

import { UniEcCanvas } from '@/uni_modules/uni-ec-canvas/uni-ec-canvas'

记得写组件声明哟~

components: { UniEcCanvas, },

然后在template中使用,当做一个组件来使用

<UniEcCanvas class="uni-ec-canvas" canvas-id="canvasId" :ec="ec" />

这里的ec就是在echarts中配置的东西,我每次都是在echarts官网中来配好,再贴过来,例如我这里的:

小程序也可以echarts

最终效果

一个简单的echarts圆环图就好啦~

小程序也可以echarts

本网站是一个以CSS、JavaScript、Vue、HTML为核心的前端开发技术网站。我们致力于为广大前端开发者提供专业、全面、实用的前端开发知识和技术支持。 在本网站中,您可以学习到最新的前端开发技术,了解前端开发的最新趋势和最佳实践。我们提供丰富的教程和案例,让您可以快速掌握前端开发的核心技术和流程。 本网站还提供一系列实用的工具和插件,帮助您更加高效地进行前端开发工作。我们提供的工具和插件都经过精心设计和优化,可以帮助您节省时间和精力,提升开发效率。 除此之外,本网站还拥有一个活跃的社区,您可以在社区中与其他前端开发者交流技术、分享经验、解决问题。我们相信,社区的力量可以帮助您更好地成长和进步。 在本网站中,您可以找到您需要的一切前端开发资源,让您成为一名更加优秀的前端开发者。欢迎您加入我们的大家庭,一起探索前端开发的无限可能!