uniapp引入echarts App端 formatter无效问题
前言
在开发中有时候根据需求需要添加总和之类的特殊要求,发现在web端没有问题在App端解析不了formatter 里面函数
解决方案
问题原因;需要在setOption之前手动设置,如下
封装echarts.vue组件,主要在这里面设置 formatter函数
<template>
<view>
<view class="echarts" :prop="option" :change:prop="echarts.update"></view>
</view>
</template>
<script>
export default {
name: 'Echarts',
props: {
option: {
type: Object,
required: true
},
numLeng:{
type:Number
}
}
}
</script>
<script module="echarts" lang="renderjs">
export default {
data() {
return {
chart: null
}
},
mounted() {
if (typeof window.echarts === 'object') {
this.init()
} else {
// 动态引入类库
const script = document.createElement('script')
script.src = './static/echarts.js'
// script.src = './static/echarts/echarts.min.js'
script.onload = this.init
document.head.appendChild(script)
}
},
methods: {
/**
* 初始化echarts
*/
init() {
this.chart = echarts.init(this.$el)
this.update(this.option)
},
/**
* 监测数据更新
* @param {Object} option
*/
update(option) {
if (this.chart) {
// 因App端,回调函数无法从renderjs外传递,故在此自定义设置相关回调函数
if (option) {
// tooltip
if (option.tooltip) {
// 判断是否设置tooltip的位置
if (option.tooltip.positionStatus) {
option.tooltip.position = this.tooltipPosition()
}
// 判断是否格式化tooltip
if (option.tooltip.formatterStatus) {
// this.tooltipFormatter 里面的参数对应 tooltip里面自定义的名字 在这里设置 往下看
option.tooltip.formatter = this.tooltipFormatter(option.tooltip.formatterUnit, option.tooltip.formatFloat2, option.tooltip.formatThousands,option.tooltip.formatFunDefeat,option.tooltip.formatFunClue)
}
// if (option.tooltip.formatterStatus) {
// if( this.numLeng==2){
// option.tooltip.formatter = this.formatFunDefeat()
// }
// }
}
}
// 设置新的option
this.chart.setOption(option, option.notMerge)
}
},
/**
* 设置tooltip的位置,防止超出画布
*/
tooltipPosition() {
return (point, params, dom, rect, size) => {
//其中point为当前鼠标的位置,size中有两个属性:viewSize和contentSize,分别为外层div和tooltip提示框的大小
let x = point[0]
let y = point[1]
let viewWidth = size.viewSize[0]
let viewHeight = size.viewSize[1]
let boxWidth = size.contentSize[0]
let boxHeight = size.contentSize[1]
let posX = 0 //x坐标位置
let posY = 0 //y坐标位置
if (x < boxWidth) { //左边放不开
posX = 5
} else { //左边放的下
posX = x - boxWidth
}
if (y < boxHeight) { //上边放不开
posY = 5
} else { //上边放得下
posY = y - boxHeight
}
return [posX, posY]
}
},
/**
* tooltip格式化
* @param {Object} unit 数值后的单位
* @param {Object} formatFloat2 是否保留两位小数
* @param {Object} formatThousands 是否添加千分位
*/
// this.numLeng==2
tooltipFormatter(unit, formatFloat2, formatThousands,formatFunDefeat,formatFunClue) {
return params => {
let result = ''
var arrTip=[]
unit = unit ? unit : ''
for (let i in params) {
let value = ''
if (params[i].data !== null) {
value = params[i].data
// 保留两位小数
if (formatFloat2) {
value = this.formatFloat2(value)
}
// 添加千分位
if (formatThousands) {
value = this.formatThousands(value)
}
//战败量
if(formatFunDefeat){
value=`<span style='color: #FFFFFF'>战败量:${params[i].value}</span> <br/>`
}
//线索量变化
if(formatFunClue){
var res = ''
var sum = 0
var arrTip=[]
sum += params[i].value
res = `${params[i].marker} <span style='color: #FFFFFF'>${params[i].seriesName} : ${params[i].value}</span> <br/>`
arrTip.unshift(res)
if(i==params.length-1) {
res = `<span style='color: #FFFFFF'>总数 : ${sum}</span>`
arrTip.push(res)
}
arrTip=arrTip.join().replace(/,/g,"");
}
}
if(formatFunClue){
value=arrTip
}
// #ifdef H5
result += value
// #endif
// #ifdef APP-PLUS
result += value
// #endif
}
return result
}
},
/**
* 保留两位小数
* @param {Object} value
*/
formatFloat2(value) {
let temp = Math.round(parseFloat(value) * 100) / 100
let xsd = temp.toString().split('.')
if (xsd.length === 1) {
temp = (isNaN(temp) ? '0' : temp.toString()) + '.000'
return temp
}
if (xsd.length > 1) {
if (xsd[1].length < 2) {
temp = temp.toString() + '0'
}
return temp
}
},
/**
* 添加千分位
* @param {Object} value
*/
formatThousands(value) {
if (value === undefined || value === null) {
value = ''
}
if (!isNaN(value)) {
value = value + ''
}
let re = /\d{1,3}(?=(\d{3})+$)/g
let n1 = value.replace(/^(\d+)((\.\d+)?)$/, function(s, s1, s2) {
return s1.replace(re, '$&,') + s2
})
return n1
},
/**
* 战败量
* @param {Object} value
*/
formatFunDefeat(data,value){
console.log(data,value)
let appdata=''
if(this.numLeng==1){
appdata= 'APP1'
}else if(this.numLeng==2){
appdata= '战败量:'+value
}
return appdata
}
}
}
</script>
<style lang="scss" scoped>
.echarts {
width: 100%;
height: 100%;
}
</style>
创建echartsStackCon.vue,这里是我封装的一个 堆叠图组件
echartsData:是传递过来的数据
<template>
<view>
<view class="clueQuantity_change_title">线索量变化</view>
<view class="clueQuantity_change" :style="{height: height+'rpx'}">
<view class="qiun-columns" style="overflow: hidden;">
<slot></slot>
<view><echarts :option="optionStackFun()" :numLeng='1' :style="{height: height+'rpx'}"></echarts></view>
</view>
</view>
</view>
</template>
<script>
import echarts from '@/components/echarts/echarts.vue';
export default {
data() {
return {
//堆叠柱状图数据
optionStack: {}, //堆叠柱状图配置
color: ['#FD5757', '#FECD2F', '#7CDEBC', '#3CB3D0', '#5D9BFC'],
};
},
props:{
echartsData:{
type:Object
},
height:{
type:String,
default:'420'
},
},
watch:{
echartsData(Val){
return Val
},
},
components: {
echarts
},
computed:{
level(){
let levelArr=[]
this.echartsData['series'].forEach((v,i)=>{
levelArr.unshift(v.name)
})
return levelArr
},
},
created() {
},
methods: {
//堆叠柱状图数据
optionStackFun() {
console.log(this.echartsData,this.level,'-----------堆叠柱状图数据')
return {
tooltip: {
trigger: 'axis',
confine:true,
axisPointer: {
// 坐标轴指示器,坐标轴触发有效
type: 'shadow' // 默认为直线,可选为:'line' | 'shadow'
},
formatterStatus:true,//开启自定义
formatFunClue:'formatFunClue',//对应echarts.vue
backgroundColor: '#222222',
extraCssText: 'box-shadow: 0px 4px 8px rgba(0, 0, 0, 0.16);',
// formatter:function(data) {
// var res = ''
// var sum = 0
// var arrTip=[]
// data.forEach((item,index) => {
// sum += item.value
// res = `${item.marker} <span style='color: #FFFFFF'>${item.seriesName} : ${item.value}</span> <br/>`
// arrTip.unshift(res)
// if(index==data.length-1) {
// res = `<span style='color: #FFFFFF'>总数 : ${sum}</span>`
// arrTip.push(res)
// }
// })
// arrTip=arrTip.join().replace(/,/g,"");
// return arrTip
// }
},
// color: this.color,
legend: {
data: this.level,
left: 30,
top:20,
icon: "circle",
itemGap: 20,
itemWith:10,
itemHeight:10
},
grid: {
left: '3%',
right: '4%',
bottom: '3%',
containLabel: true
},
xAxis: [
{
type: 'category',
data: this.echartsData.categories,
axisLine: {
show: false
},
axisTick: {
show: false
}
}
],
yAxis: [
{
type: 'value',
axisLabel: {
show: true,
interval: 'auto',
// formatter: '{value} %'
},
show: true,
axisLine: {
show: false
},
axisTick: {
show: false
},
splitLine: {
show: false
},
splitLine: {
lineStyle: {
type: "dashed",
},
show: true,
},
}
],
series: this.echartsData.series,
};
},
},
};
</script>
<style scoped lang="scss">
.clueQuantity_change_title {
font-size: 32rpx;
color: #43425d;
padding-left: 30rpx;
background-color: #f5f6fa;
width: 100%;
height: 80rpx;
line-height: 80rpx;
font-weight: 500;
}
.clueQuantity_change {
width: 100%;
height: 440rpx;
background-color: #ffffff;
}
</style>
echartsData数据格式
{
"categories": [
"03/29"
],
"series": [
{
"name": "A级",
"data": [
3
],
"type": "bar",
"stack": "stackone",
"itemStyle": {
"normal": {
"color": "#7CDEBC"
}
},
"barWidth": 20
},
{
"name": "H级",
"data": [
1
],
"type": "bar",
"stack": "stackone",
"itemStyle": {
"normal": {
"color": "#FECD2F"
}
},
"barWidth": 20
},
{
"name": "O级",
"data": [
3
],
"type": "bar",
"stack": "stackone",
"itemStyle": {
"normal": {
"color": "#FD5757"
}
},
"barWidth": 20
}
]
}
还没有评论,来说两句吧...