当前位置:   article > 正文

Taro3+Vue3使用echarts_echarts-taro3-vue

echarts-taro3-vue

先上图,无图言吊

一.taro支持echarts

官方说明:https://taro-docs.jd.com/blog/2018-09-18-taro-1-0-0#支持引用小程序端第三方组件库

二.引入echarts-for-weixin插件

github地址: https://github.com/ecomfe/echarts-for-weixin

只引入ec-canvas文件夹下的wx-canvas.js

三.自定义 下载echarts

地址: https://echarts.apache.org/zh/builder.html

可自行选择版本,笔者测试了5.3.3和5.4.1都支持

下载后得到echarts.min.js

请根据需要自行选择需要的图表打包下载,我只选了默认的饼图、柱图、线图;

四.封装组件ec-canvas.vue

  1. <template>
  2. <canvas type="2d" class="ec-canvas" :canvas-id="canvasId" @touchStart="touchStart" @touchMove="touchMove"
  3. @touchEnd="touchEnd"></canvas>
  4. </template>

引入刚才下载的echarts.min.js和wx-canvas

  1. import Taro from "@tarojs/taro";
  2. import WxCanvas from "./wx-canvas";
  3. import * as echarts from "./echarts-5.4.1.min";
  1. <script lang="js">
  2. //自定义下载的echarts.min.js 文件 要使用需使用js,ts需要声明文件
  3. import Taro from "@tarojs/taro";
  4. import WxCanvas from "./wx-canvas";
  5. import * as echarts from "./echarts-5.4.1.min";
  6. export default {
  7. name: "EcCanvas",
  8. props: {
  9. canvasId: {
  10. type: String,
  11. default: ""
  12. },
  13. ec: {
  14. type: Object,
  15. default: null
  16. }
  17. },
  18. mounted() {
  19. echarts.registerPreprocessor(option => {
  20. if (option && option.series) {
  21. if (option.series.length > 0) {
  22. option.series.forEach(series => {
  23. series.progressive = 0;
  24. });
  25. } else if (typeof option.series === "object") {
  26. option.series.progressive = 0;
  27. }
  28. }
  29. });
  30. if (!this.ec) {
  31. console.warn(
  32. '组件需绑定 ec 变量,例:<ec-canvas id="mychart-dom-bar" ' +
  33. 'canvas-id="mychart-bar" ec="{{ ec }}"></ec-canvas>'
  34. );
  35. return;
  36. }
  37. if (!this.ec.lazyLoad) {
  38. this.init();
  39. }
  40. },
  41. methods: {
  42. init(callback) {
  43. this.initByNewWay(callback);
  44. },
  45. initByNewWay(callback) {
  46. const query = Taro.createSelectorQuery();
  47. query
  48. .select(".ec-canvas")
  49. .fields({
  50. node: true,
  51. size: true
  52. })
  53. .exec(res => {
  54. if (!res || res.length == 0 || res[0] == null || res[0].node == null) {
  55. console.error('未获取到canvas的dom节点,请确认在页面渲染完成后或节点,taro中页面渲染完成的生命周期是useReady');
  56. return
  57. }
  58. const canvasNode = res[0].node;
  59. // this.canvasNode = canvasNode;
  60. const canvasDpr = Taro.getSystemInfoSync().pixelRatio;
  61. const canvasWidth = res[0].width;
  62. const canvasHeight = res[0].height;
  63. const ctx = canvasNode.getContext("2d");
  64. const canvas = new WxCanvas(ctx, this.canvasId, true, canvasNode);
  65. echarts.setCanvasCreator(() => {
  66. return canvas;
  67. });
  68. if (typeof callback === "function") {
  69. this.chart = callback(canvas, canvasWidth, canvasHeight, canvasDpr);
  70. } else if (typeof this.ec.onInit === "function") {
  71. this.chart = this.ec.onInit(
  72. canvas,
  73. canvasWidth,
  74. canvasHeight,
  75. canvasDpr
  76. );
  77. } else {
  78. this.triggerEvent('init', {
  79. canvas: canvas,
  80. width: canvasWidth,
  81. height: canvasHeight,
  82. dpr: canvasDpr
  83. })
  84. }
  85. });
  86. },
  87. canvasToTempFilePath(opt) {
  88. const query = Taro.createSelectorQuery().in(this);
  89. query
  90. .select(".ec-canvas")
  91. .fields({
  92. node: true,
  93. size: true
  94. })
  95. .exec(res => {
  96. const canvasNode = res[0].node;
  97. opt.canvas = canvasNode;
  98. Taro.canvasToTempFilePath(opt);
  99. });
  100. },
  101. touchStart(e) {
  102. if (this.chart && e.touches.length > 0) {
  103. var touch = e.touches[0];
  104. var handler = this.chart.getZr().handler;
  105. handler.dispatch("mousedown", {
  106. zrX: touch.x,
  107. zrY: touch.y
  108. });
  109. handler.dispatch("mousemove", {
  110. zrX: touch.x,
  111. zrY: touch.y
  112. });
  113. handler.processGesture(this.wrapTouch(e), "start");
  114. }
  115. },
  116. touchMove(e) {
  117. if (this.chart && e.touches.length > 0) {
  118. var touch = e.touches[0];
  119. var handler = this.chart.getZr().handler;
  120. handler.dispatch("mousemove", {
  121. zrX: touch.x,
  122. zrY: touch.y
  123. });
  124. handler.processGesture(this.wrapTouch(e), "change");
  125. }
  126. },
  127. touchEnd(e) {
  128. if (this.chart) {
  129. const touch = e.changedTouches ? e.changedTouches[0] : {};
  130. var handler = this.chart.getZr().handler;
  131. handler.dispatch("mouseup", {
  132. zrX: touch.x,
  133. zrY: touch.y
  134. });
  135. handler.dispatch("click", {
  136. zrX: touch.x,
  137. zrY: touch.y
  138. });
  139. handler.processGesture(this.wrapTouch(e), "end");
  140. }
  141. },
  142. wrapTouch(event) {
  143. for (let i = 0; i < event.touches.length; ++i) {
  144. const touch = event.touches[i];
  145. touch.offsetX = touch.x;
  146. touch.offsetY = touch.y;
  147. }
  148. return event;
  149. }
  150. }
  151. };
  152. </script>
  153. <style>
  154. .ec-canvas {
  155. width: 100%;
  156. height: 100%;
  157. }
  158. </style>

五.封装e-chart.vue组件

  1. <script lang=js>

使用js避免引入echarts.min.js报错,要求写声明文件.d.ts

  1. 不要使用setup语法糖 <script lang=js setup> 会报错

  1. const ecCanvasRef = ref(null); vue3中使用ref获取组件实例 声明与template中ref变量一致

  1. expose vue3向外暴漏子组件方法,同<setup>语法糖里的defineExpose

  1. <template>
  2. <ec-canvas ref="ecCanvasRef" :canvas-id="canvasId" :ec="ec"></ec-canvas>
  3. </template>
  4. <script lang="js">
  5. /**
  6. * 自定义下载的echarts.min.js 文件 要使用需使用js,ts需要声明文件
  7. * 此组件不能使用setup语法糖,会报错的.
  8. */
  9. import Taro, { useLoad } from "@tarojs/taro";
  10. import * as echarts from './ec-canvas/echarts-5.4.1.min'
  11. import EcCanvas from './ec-canvas/ec-canvas.vue'
  12. import { ref, reactive } from "vue";
  13. export default {
  14. components: {
  15. EcCanvas
  16. },
  17. props: {
  18. canvasId: {
  19. type: String,
  20. default: ''
  21. }
  22. },
  23. setup(props, { expose }) {
  24. const ec = reactive({
  25. lazyLoad: true
  26. })
  27. const ecCanvasRef = ref(null);
  28. const refresh = (options) => {
  29. if (!ecCanvasRef.value) {
  30. console.error('ecCanvas未获取到dom');
  31. return
  32. }
  33. ecCanvasRef.value?.init((canvas, width, height, canvasDpr) => {
  34. const chart = echarts.init(canvas, null, {
  35. width: width,
  36. height: height,
  37. devicePixelRatio: canvasDpr
  38. })
  39. canvas.setChart(chart);
  40. chart.setOption(options);
  41. return chart;
  42. })
  43. }
  44. expose({
  45. refresh,
  46. })
  47. return {// 返回值会暴露给模板和其他的选项式 API 钩子
  48. ec, ecCanvasRef
  49. }
  50. },
  51. }
  52. </script>

六.使用封装的组件

  1. <template>
  2. <view class="page">
  3. <view class="bar-chart">
  4. <EChart ref="barChat" canvas-id="bar-canvas" />
  5. </view>
  6. <button type="primary" :plain="true" @tap="onRefreshData">刷新数据</button>
  7. </view>
  8. </template>
  9. <script lang="ts" setup>
  10. import Taro, { useReady } from "@tarojs/taro";
  11. import { ref } from "vue";
  12. import { randomArray } from '@/utils/array-util';
  13. const colors = ref(["#3cb2ef", "#ffed65", "#FD665F", "#59d4d4", "#52d378", "#cc33cc", "#336666"]);
  14. useReady(() => {
  15. initMultiBarChart();
  16. })
  17. const barChat = ref<any>();
  18. const onRefreshData = () => {
  19. initMultiBarChart();
  20. }
  21. const initMultiBarChart = () => {
  22. let yData = [
  23. {
  24. Name: "收入",
  25. Value: randomArray(1000, 12)
  26. },
  27. {
  28. Name: "支出",
  29. Value: randomArray(992, 12)
  30. },
  31. ];
  32. const options = {
  33. tooltip: {
  34. trigger: "axis",
  35. axisPointer: {
  36. type: "cross",
  37. crossStyle: {
  38. color: "#999",
  39. },
  40. },
  41. },
  42. grid: {
  43. y: 80,
  44. y2: 20,
  45. borderWidth: 1,
  46. // top: '90px',//内边距
  47. // left: '100px',
  48. // right: '0px',
  49. // bottom: '0px'
  50. },
  51. color: colors.value,
  52. legend: {
  53. data: ["收入", "支出"],
  54. left: "center",
  55. top: "1%",
  56. },
  57. xAxis: [
  58. {
  59. type: "category",
  60. data: ["1月",
  61. "2月",
  62. "3月",
  63. "4月",
  64. "5月",
  65. "6月",
  66. "7月",
  67. "8月",
  68. "9月",
  69. "10月",
  70. "11月",
  71. "12月",],
  72. axisPointer: {
  73. type: "shadow",
  74. },
  75. },
  76. ],
  77. yAxis: [
  78. {
  79. type: "value",
  80. name: "元",
  81. axisLabel: {
  82. formatter: "{value}",
  83. },
  84. },
  85. ],
  86. series: yData.map((item) => {
  87. return {
  88. name: item.Name,
  89. type: "bar",
  90. barMaxWidth: 30,
  91. data: item.Value,
  92. };
  93. }),
  94. };
  95. Taro.nextTick(() => {
  96. barChat.value.refresh(options)
  97. })
  98. }
  99. </script>
  100. <style lang="scss">
  101. .bar-chart {
  102. width: 100%;
  103. min-height: 500px;
  104. flex: 1;
  105. }
  106. </style>

七.易错点

  1. ec-canvas中使用Taro.createSelectorQuery()获取不到dom节点

  1. const query = Taro.createSelectorQuery();
  2. query
  3. .select(".ec-canvas")
  4. .fields({
  5. node: true,
  6. size: true
  7. })
  8. .exec(res=>{
  9.    
  10. })

Taro.createSelectorQuery()获取节点必须在页面渲染完成后,否则获取到的是null;

在组件和页面里获取略有不同,Taro.createSelectorQuery().in(this)在页面里获取

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/空白诗007/article/detail/777979
推荐阅读
相关标签
  

闽ICP备14008679号