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
        }
    ]
}
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值