背景:根據(jù)需求在一個(gè)報(bào)告界面需要展示不同的echarts表來使數(shù)據(jù)更友好的顯示。
效果如下:
一.taro支持echarts
官方說明:Taro 文檔支持引用小程序端第三方組件庫
物料文檔:Taro 物料市場 | 讓每一個(gè)輪子產(chǎn)生價(jià)值
二.引入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
請根據(jù)需要自行選擇需要的圖表打包下載,我只選了默認(rèn)的餅圖、柱圖、線圖;
注意點(diǎn):折線圖中如果需要顯示面積圖的平均線,則要下載對應(yīng)的標(biāo)線組件。
經(jīng)過三、四步驟之后會得到兩個(gè)文件,目錄結(jié)構(gòu)如下:
四.封裝組件ec-canvas.vue
<template>
<canvas
type="2d"
class="ec-canvas"
:class="canvasId" // 多個(gè)echarts時(shí)將canvasId作為唯一標(biāo)識,動態(tài)獲取canvasId用于多個(gè) echarts可同時(shí)顯示
:canvas-id="canvasId"
@touchStart="touchStart"
@touchMove="touchMove"
@touchEnd="touchEnd"
></canvas>
</template>
<script lang="js">
import Taro from "@tarojs/taro";
import WxCanvas from "./wx-canvas";
import * as echarts from "./echarts-5.4.1.min";
export default {
name: "EcCanvas",
props: {
canvasId: {
type: String,
default: ""
},
ec: {
type: Object,
default: null
}
},
mounted() {
echarts.registerPreprocessor(option => {
if (option && option.series) {
if (option.series.length > 0) {
option.series.forEach(series => {
series.progressive = 0;
});
} else if (typeof option.series === "object") {
option.series.progressive = 0;
}
}
});
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: {
init(callback) {
this.initByNewWay(callback);
},
initByNewWay(callback) {
const query = Taro.createSelectorQuery();
query
.select(`.${this.canvasId}`) // 根據(jù)canvasId動態(tài)獲取不同的echarts圖表
.fields({
node: true,
size: true
})
.exec(res => {
if (!res || res.length == 0 || res[0] == null || res[0].node == null) {
console.error('未獲取到canvas的dom節(jié)點(diǎn),請確認(rèn)在頁面渲染完成后或節(jié)點(diǎn),taro中頁面渲染完成的生命周期是useReady');
return
}
const canvasNode = res[0].node;
// this.canvasNode = canvasNode;
const canvasDpr = Taro.getSystemInfoSync().pixelRatio;
const canvasWidth = res[0].width;
const canvasHeight = res[0].height;
const ctx = canvasNode.getContext("2d");
const canvas = new WxCanvas(ctx, this.canvasId, true, canvasNode);
echarts.setCanvasCreator(() => {
return canvas;
});
if (typeof callback === "function") {
this.chart = callback(canvas, canvasWidth, canvasHeight, canvasDpr);
} else if (typeof this.ec.onInit === "function") {
this.chart = this.ec.onInit(
canvas,
canvasWidth,
canvasHeight,
canvasDpr
);
} else {
this.triggerEvent('init', {
canvas: canvas,
width: canvasWidth,
height: canvasHeight,
dpr: canvasDpr
})
}
});
},
canvasToTempFilePath(opt) {
const query = Taro.createSelectorQuery().in(this);
query
.select(".ec-canvas")
.fields({
node: true,
size: true
})
.exec(res => {
const canvasNode = res[0].node;
opt.canvas = canvasNode;
Taro.canvasToTempFilePath(opt);
});
},
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(this.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(this.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(this.wrapTouch(e), "end");
}
},
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;
}
}
};
</script>
<style>
.ec-canvas {
width: 100%;
min-height: 400rpx;
flex: 1;
}
</style>
?五.封裝e-chart.vue組件
<template>
<ec-canvas ref="ecCanvasRef" :canvas-id="canvasId" :ec="ec"></ec-canvas>
</template>
<script lang="js">
/**
* 自定義下載的echarts.min.js 文件 要使用需使用js,ts需要聲明文件
* 此組件不能使用setup語法糖,會報(bào)錯(cuò)的.
*/
import Taro, { useLoad } from "@tarojs/taro";
import * as echarts from './ec-canvas/echarts-5.4.1.min'
import EcCanvas from './ec-canvas/ec-canvas.vue'
import { ref, reactive } from "vue";
export default {
components: {
EcCanvas
},
props: {
canvasId: {
type: String,
default: ''
}
},
setup(props, { expose }) {
const ec = reactive({
lazyLoad: true
})
const ecCanvasRef = ref(null);
const refresh = (options) => {
if (!ecCanvasRef.value) {
console.error('ecCanvas未獲取到dom');
return
}
ecCanvasRef.value?.init((canvas, width, height, canvasDpr) => {
const chart = echarts.init(canvas, null, {
width: width,
height: height,
devicePixelRatio: canvasDpr
})
canvas.setChart(chart);
chart.setOption(options);
return chart;
})
}
expose({
refresh,
})
return {// 返回值會暴露給模板和其他的選項(xiàng)式 API 鉤子
ec, ecCanvasRef
}
},
}
</script>
六.使用封裝的組件
此時(shí)封裝的目錄結(jié)構(gòu)如下:
子組件:
<template>
<view class="cards bg-white mx-sm mt-mm">
<view class="text-center pt-xs pb-mm">
<text class="text-md text-dark ml-sm">借貸分析</text>
</view>
<cover-view class="container-echarts">
<e-chart ref="barChat" canvas-id="bar-canvas" />
</cover-view>
</view>
</template>
<script lang="ts">
export default { name: 'loanAnalysis' };
</script>
<script lang="ts" setup>
import Taro, { useReady } from '@tarojs/taro';
import { ref } from 'vue';
import EChart from '../components/echarts/e-chart.vue';
import { getLoanView } from '@/service/report';
import { MoneyNoUnitText, FormatThousand } from '@/units/currency';
const components = { 'e-chart': EChart };
const props = defineProps({
params: { type: Object, required: true }
});
useReady(() => {
initMultiBarChart();
});
const barChat = ref<any>();
let loanAmount = ref<number>();
let repaymentLoanAmount = ref<number>();
let prototypeOption = {
grid: { left: 14, right: 18, bottom: 8, top: 40, containLabel: true },
legend: { show: false },
color: ['#40a9ff', '#FF5652'],
xAxis: [
{
type: 'category',
data: [],
axisLabel: { fontSize: 10, color: 'rgba(0, 0, 0, 0.56)' },
axisLine: { show: false },
axisTick: { show: false }
}
],
yAxis: [
{
type: 'value',
name: '萬元',
nameTextStyle: { padding: [0, 40, 0, 0], color: 'rgba(0,0,0,0.56)' },
axisLabel: { fontSize: 10, color: 'rgba(0, 0, 0, 0.56)' },
axisLine: { show: false },
axisTick: { show: false },
splitNumber: 2
}
],
series: [
{
name: '貸款、借款流入',
type: 'bar',
data: [],
barMaxWidth: 12,
barMinHeight: 1,
stack: 'cr',
itemStyle: {
barBorderRadius: [0, 2, 0, 0]
}
},
{
name: '償還貸款、借款',
type: 'bar',
data: [],
barMaxWidth: 12,
barMinHeight: 1,
stack: 'cr',
itemStyle: {
barBorderRadius: [0, 0, 0, 2]
}
}
]
};
const initMultiBarChart = () => {
getLoanView(props.params).then(res => {
if (res) {
loanAmount.value = MoneyNoUnitText(res.loanAmount || 0);
repaymentLoanAmount.value = MoneyNoUnitText(res.repaymentLoanAmount || 0);
prototypeOption.xAxis[0].data = res.list.map(
i => i.dateId.toString().slice(2, 4) + '.' + i.dateId.toString().slice(4)
);
prototypeOption.yAxis[0].axisLabel = {
formatter: (v: any) => (Math.abs(v) > 0 ? FormatThousand(parseInt(v / 10000), 0) : v),
color: 'rgba(0, 0, 0, 0.56)'
};
prototypeOption.series[0].data = res.list.map(i => (i.loanAmount > 0 ? i.loanAmount : null));
prototypeOption.series[1].data = res.list.map(i =>
i.repaymentLoanAmount > 0 ? -i.repaymentLoanAmount : null
);
Taro.nextTick(() => {
barChat.value.refresh(prototypeOption);
});
}
});
};
</script>
<style>
.container-echarts {
height: 400rpx;
width: 100%;
}
</style>
父組件引用子組件:文章來源:http://www.zghlxwxcb.cn/news/detail-648467.html
import loanAnalysis from './loan-analysis.vue';
<loan-analysis :params="params"></loan-analysis>
【 問題描述 】在小程序使用echarts,圖表展示出來之后不跟隨頁面滾動,浮在最上方。
【 問題原因 】布局中含有position:fixed或absulote的元素,導(dǎo)致echarts圖表無法滑動。
官方文件說明:canvas為原生組件故有一下的性質(zhì): bash 由于原生組件脫離在 WebView
渲染流程外,因此在使用時(shí)有以下限制: 組件的層級是最高的,所以頁面中的其他組件無論設(shè)置
z-index 為多少,都無法蓋在原生組件上。 后插入的原生組件可以覆蓋之前的原生組件。
原生組件還無法在 scroll-view、swiper、picker-view、movable-view 中使用。
部分CSS樣式無法應(yīng)用于原生組件,例如: 無法對原生組件設(shè)置 CSS 動畫 無法定義
原生組件為 position: fixed 不能在父級節(jié)點(diǎn)使用 overflow:hidden 來裁剪
原生組件的顯示區(qū)域
【 解決方法 】所有父級元素(有包含ec-canvas的所有view元素)的position不可為
fixed或absulote,將其改為其他,另外兄弟元素可以為position:absulote或fixed,
否在還是會有重疊
原文鏈接:https://blog.csdn.net/samscat/article/details/126182735
?參考博文:Taro3+Vue3使用echarts_taro使用echarts_江渚清沨的博客-CSDN博客文章來源地址http://www.zghlxwxcb.cn/news/detail-648467.html
到了這里,關(guān)于Taro+Vue3 小程序引入echarts表的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!