Taro中使用ec-canvas遇到的那点事
引子
在开发过程中从最初的引用、异步加载、循环渲染,到最后的打包上传,大大小小的坑无数……
使用
- 先下载ecomfe/echarts-for-weixin中 ec-canvas 整个文件夹里面的文件
- 引用:然后在你的页面中 的 json文件中 引用。当然你也可以作为全局组件写在app.json 中。
1. 在页面配置文件中配置 usingComponents 属性。
// page.config.js
export default {
usingComponents: {
// 定义需要引入的第三方组件
// 1. key 值指定第三方组件名字,以小写开头
// 2. value 值指定第三方组件 js 文件的相对路径
'ec-canvas': '../../components/ec-canvas/ec-canvas'
}
}
2. 页面使用
Taro3版本之前异步加载数据配置项中使用lazyload延迟加载来实现:
import * as echarts from '../../common/ec-canvas/echarts.js';
const optionDta = {...};
class MainPage extends Component {
state = {
ec: {lazyLoad: true}
}
componentDidMount() {
this.refs['mychart-dom-area'].init((canvas, width, height) => {
// 初始化图表
const chart = echarts.init(canvas, null, {
width: width,
height: height
});
chart.setOption(option);
// 注意这里一定要返回 chart 实例,否则会影响事件处理等
return chart;
})
}
render () {
<View>
<ec-canvas
id='mychart-dom-area'
canvas-id='mychart-area'
ref='mychart-dom-area'
ec={ec}
/>
</View>
}
}
但是升级为Taro3之后,无法获取到this.Chart的原生实例对象。
所以在Taro3内无法执行chart的init方法,同时页面也未渲染ec-canvas节点。 是因为在Taro@3内使用原生第三方组件或插件需要在page级页面内注册组件,在子组件内注册无效。 因为获取不到正确的this.Chart,所以最后通过它的onInit事件实现:
import * as echarts from '../../common/ec-canvas/echarts.js';
let chart = null
function initChart(canvas, width, height) { // 初始化图表
console.log("init");
chart = echarts.init(canvas, null, {
width: width,
height: height
});
canvas.setChart(chart);
setChartData();
return chart;
}
function setChartData () {
let option = {
...
}
chart.setOption(option);
}
class MainPage extends Component {
state = {
ec: {
onInit:
}
}
componentDidMount() {
// ...
setTimeout(() => {
setChartData()
}, 2000); // 异步获取到图表数据并更新
}
render () {
<View>
<ec-canvas
id='mychart-dom-area'
canvas-id='mychart-area'
ref='mychart-dom-area'
ec={ec}
/>
</View>
}
}
ec-canvas引用空白问题
图表需要一层元素包裹,并且给他设置宽高,否则会显示空白
<view class="container">
<ec-canvas
id="mychart-dom-bar"
canvas-id="mychart-bar"
ec="{{ ec }}">
</ec- canvas>
</view>
循环渲染问题
<template>
<view class="echartMain" v-if="isShowEchart">
<view class="echart" v-for="(item, index) in followPoint" :key="item._id">
<ec-canvas ref="echart" id="echart" class="mychart-dom-bar" style="width:100%;height:600px;" canvas-id="mychart-bar" :ec="ECOptions[index]"></ec-canvas>
</view>
</view>
</template>
<script>
import * as echarts from "../../components/ec-canvas/echarts";
let EChart = []
export default {
data () {
return {
dataList: [],
index: -1,
ECOptions: [],
isShowEchart: false, // 渲染图表
}
},
async mounted() {
this.onRenderEChart()
},
methods: {
async onRenderEChart () {
await Promise.all([this.onGetUserViewpoint(), this.onGetBitcoin()])
.then(() => {
this.followPoint.map((item, index) => {
console.log(EChart)
setTimeout(() => {
this.$nextTick(() => {
this.getOption()
})
}, 2000)
})
})
.catch(err => {
console.log(err)
})
},
onGetUserViewpoint () {
return new Promise(resolve => {
Taro.request({
url: `${this.baseUrl}/api/weapp/user/viewpoint`,
data: {
id: this.userInfo._id
},
success: res => {
this.followPoint = res.data.result
this.followPoint.forEach((item, index) => {
this.ECOptions.push(
{
onInit: this.initChart
}
)
})
this.isShowEchart = true
resolve()
}
})
})
},
onGetBitcoin () {
return new Promise(resolve => {
Taro.request({
url: `${this.baseUrl}/api/weapp/coin/list`,
data: {
size: 72
},
success: res => {
this.bitcoinData = res.data.result
.map(item => {
item.timestamp = Number(item.timestamp)
return item
})
resolve()
}
})
})
},
initChart(canvas, width, height, dpr) {
let chart = echarts.init(canvas, null, {
width: width,
height: height,
devicePixelRatio: dpr // 像素
});
canvas.setChart(chart);
EChart.push(chart)
return chart;
},
getOption () {
this.index += 1
let option = {
tooltip: {
trigger: 'axis'
},
grid: {
left: '20%'
},
xAxis: {
type: 'category',
data: this.bitcoinData.map(item => {
return moment(item.timestamp).format('MM-DD hh:00')
})
},
yAxis: {
type: 'value'
},
series: [{
data: this.bitcoinData.map(item => {
if (moment(this.followPoint[this.index].meta.createdAt).valueOf() < item.timestamp) {
return Math.floor(item.price) + Math.floor(item.price) * (this.followPoint[this.index].proportion / 100)
}
}),
type: 'line'
},{
data: this.bitcoinData.map(item => {
return Math.floor(item.price)
}),
type: 'line'
}]
};
EChart[this.index].setOption(option);
}
}
}
</script>
打包体积过大问题
- 打包时跳过echarts.js的编译
- 定制echarts
- 分包
- 一系列优化 Taro 解决使用echarts体积过大的问题