uni-app使用echarts图表封装组件

uni-app 加载echarts图表

代码如下:

	<template>
		<view 
			class="echarts" 
			@click="echarts.onClick" 
			:prop="option" 
			:change:prop="echarts.update"
		>
		</view>
	</template>
	<script>
	export default {
		name: 'Echarts',
		props: {
		},
		data(){
			return {
				option:null
			}
		},
		mounted(){
		},
		methods:{
		}
	}
</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/js/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) {
						this.chart.setOption(option)
					}
				}
			},
		}
	}
</script>

自定义图表配置数据引入

ps:因为是自定义所以可以自由配置,但最好设定后做好注释或写好配置文档|ू・ω・` )

<script>
	import round from './charts/round.js'// 圆形图表
	import doubleColumnLine from './charts/doubleColumnLine.js'// 双柱折线图表
	import triangle from './charts/triangle.js'// 倒三角图表
	export default {
		name: 'Echarts',
		props: {
			options: {
				type: Object,
				default() {
					return null;
				},
			},
			cardData:{
				type:Array,
				default:() => { return [] }
			},
			// 自有数据样式
			// round 圆形
			cardType:{
				type:String,
				default:'round'
			},
			// 主标题
			title:{
				type:String,
				default:null
			},
			// 副标题
			subtitle:{
				type:String,
				default:null
			},
			// 颜色
			colorArr:{
				type:Array,
				default:() => { return [] }
			},
			// 图例名称
			nameTheLegend:{
				type:Array,
				default:() => { return [] }
			},
			// 图例显示
			legend:{
				type:Boolean,
				default:true
			},
		},
		data(){
			return {
				option:null
			}
		},
		mounted(){
			
			// 是否使用只有数据
			if(this.options == null){
				this.option = this.getOption()
				this.modifyChartData()
			}else{
				this.option = Object.assign({}, this.options) 
			}
		},
		methods:{
			getOption() {
				// 这里根据相应的cardType返回不同的默认option
				switch (this.cardType) {
					case "round":// 圆形图表
						return round(this.cardData);
					case "doubleColumnLine":// 双柱折线图表
						return doubleColumnLine(this.cardData);
					case "triangle":// 倒三角图表
						return triangle(this.cardData);
					default:
						break;
				}
			},
			// 修改chart数据
			modifyChartData(){
				// 这里根据相应的cardType返回不同的默认option
				switch (this.cardType) {
					case "round":// 圆形图表
						// 主标题
						if(this.title){
							this.option.title.text = this.title
						}
						// 副标题 超过8个字符换行
						if(this.subtitle){
							this.option.title.subtext = this.subtitle.length<=8?this.subtitle:this.subtitle.slice(0,8)+'\n'+this.subtitle.slice(8)
						}
						break
					case "doubleColumnLine":// 双柱折线图表
							// 颜色
							if(this.colorArr.length){
								this.option.series.forEach((item,index)=>{
									item.itemStyle.normal.color = this.colorArr[index]
								})
							}
							// 图例显示
							if(!this.legend){
								this.option.legend=null
							}
							let nameList =[]
							// 图例名称
							if(this.nameTheLegend.length){
								nameList=this.nameTheLegend
							}else{
								nameList=['总人数','缺勤数','出勤率']
							}
							if(nameList.length){
								this.option.series.forEach((item,index)=>{
									item.name = nameList[index]
								})
						break
					default:
						break;
				}
			}
		}
	}
</script>

以下是option 的js配置代码之一,可供参考

export default (data = [])=>{
	data = data.length ? data : [{ name: "暂无1", value1: 25 ,value2: 2,value3: 9}]
	// 滚动条长度
	const lengthTheScrollBar=data.length>4?Math.round((3/data.length)*100):100
	// console.log('lengthTheScrollBar',lengthTheScrollBar)
	// 总人数
	let totalNumberOf = 0
	// 缺勤数
	let numberAbsences = 0
	data.forEach(item=>{ totalNumberOf += item.value1 })
	data.forEach(item=>{ numberAbsences += item.value2 })
	// 出勤率
	let attendance = ((totalNumberOf-numberAbsences)/totalNumberOf)*100
	// 名称字数计算
	function titleToCalculate(name){
		if(name.length>4){
			if(name.length>8){
				return name.slice(0,4)+'\n'+name.slice(4,7)+'...'
			}else{
				return name.slice(0,4)+'\n'+name.slice(4,name.length)
			}
		}else{
			return name
		}
	}
	
	return {
		  tooltip: {
		    trigger: 'axis',
				formatter:'{b}<br />{a}: {c0}<br />{a1}: {c1}<br />{a2}: {c2}%'
			grid: {
				top: 70,
				right: 20,
				bottom: 30,
				left: 20,
				containLabel: true
			},
			dataZoom:lengthTheScrollBar!=100?[
				{
					type: 'slider', 
					start: 0, 
					end: lengthTheScrollBar, 
					show: 0,
					realtime: true,
					zoomLock: true,
					height: 10, 
					bottom: '3%' 
				},
				{
					type: 'inside',
					start: 0,
					end: lengthTheScrollBar,
					realtime: true,
					zoomLock: true,
					show: 0,
				}
			]:null,
		  legend: {
				orient:'horizontal',
				icon: 'circle',
				x: 'right', 
				y: 30,
				itemWidth: 10,
				itemGap: 5,
				//注意配置文件中不能使用formatter函数,会包无限递归错误
				// formatter: (name) => {
				// 	if(name=='总人数'){
				// 		return name+':'+totalNumberOf+'人'
				// 	}
				// 	if(name=='缺勤数'){
				// 		return name+':'+numberAbsences+'人'
				// 	}
				// 	if(name=='出勤率'){
				// 		return name+':'+attendance.toFixed(1)+'%\t'
				// 	}
				// }
		  },
		  xAxis: [
		    {
		      type: 'category',
		      data: data.map(item=>titleToCalculate(item.name)),
		    }
		  ],
		  yAxis: [
		    {
		      type: 'value',
					name : '(人数)',
		      nameTextStyle : {
		      	color : "#000",
		      	padding : [0,30,10,0]
		      },
		      axisLabel: {
		        formatter: '{value} '
		      },
					splitLine: {
					  show: true,
						lineStyle : {
							type : 'none'
						}
					},
					axisLine : {
						show : false,
						lineStyle : {
							color : '#CCCCCC',
						}
					},
					axisTick : {
						show : false,
					}
		    },
		    {
		      type: 'value',
		      axisLabel: {
		        formatter: '{value} %'
		      },
					splitLine: {
					  show: false
					},
					axisLine : {
						show : false,
						lineStyle : {
							color : '#CCCCCC'
						}
					},
					axisTick : {
						show : false,
					}
		    }
		  ],
		  series: [
		    {
		      name: '总人数',
		      type: 'bar',
					barWidth: 10,
		      data: data.map(item=>item.value1),
					itemStyle : {
					  normal: {
					    barBorderRadius: [10, 10, 0, 0],
							color : '#43B3FF',
					  },
					}
		    },
		    {
		      name: '缺勤数',
		      type: 'bar',
					barWidth: 10,
		      data: data.map(item=>item.value2),
					itemStyle : {
						normal: {
						  barBorderRadius: [10, 10, 0, 0],
							color : '#ff5f51',
						},
					}
		    },
		    {
		      name: '出勤率',
		      type: 'line',
		      yAxisIndex: 1,
					symbolSize : 5,
		      data: data.map(item=>item.value3),
					itemStyle : {
						normal: {
							color : '#5FE9A4',
						},
					}
		    }
		  ]
	}
}

配置文件中不能使用formatter函数,如何自定义想要的chart

<script module="echarts" lang="renderjs">
	let functionStr = ''
	export default {
		data() {
			return {
				chart: null,
			}
		},
		mounted() {
			if (typeof window.echarts === 'object') {
				this.init()
			} else {
				// 动态引入类库
				const script = document.createElement('script')
				script.src = 'static/js/echarts.min.js'
				script.onload = this.init
				document.head.appendChild(script)
			}
		},
		
		methods: {
			//初始化echarts
			init() {
				let _this = this;
				this.chart = echarts.init(this.$el)
				this.update(this.option)
				  
			},
			/**
			 * 监测数据更新
			 * @param {Object} option
			 */
			update(option) {
				if (this.chart) {
					// 因App端,回调函数无法从renderjs外传递,故在此自定义设置相关回调函数
					if (option) {
						// 设置新的option
						switch(option.series[0].type){
							case "pie":// 圆形图表
									option.series[0].label.normal.formatter=(param)=>{
									// console.log(param)
										const name = param.name.length > 11 ? param.name.substr(0, 11) + "..." : param.name;
										if(param.data.title){
											return `${name}\n${param.value}\t\t${param.data.value1}%`;
										}
										if(param.name.indexOf('率')!=-1){
											return `${name}\n${param.value}个\t\t${param.percent}%`;
										}else{
											return `${name}\n${param.value}\t\t${param.percent}%`;
										}
									}
									functionStr = JSON.stringify(option.series[0].label.normal.formatter)
								break
							case "bar":// 双柱折线图
								if(option.legend&&!option.legend.formatter){
									option.legend.formatter=(name)=>{
										if(name.indexOf('观看')!=-1){
											return name
										}
										let note=''
										let num = 0
										option.series.forEach(item=>{
											if(item.name==name){
												item.data.forEach(each=>{
													num+=Number(each)
												})
											}
										})
										if(name.indexOf('率')!=-1){
											// 总人数
											let totalNumberOf = 0
											// 缺勤数
											let numberAbsences = 0
											option.series.forEach((item,index)=>{
												item.data.forEach(each=>{
													if(index==0){
														totalNumberOf+=Number(each)
													}else if(index==1){
														numberAbsences+=Number(each)
													}
												})
											})
											// 出勤率
											let attendance = ((totalNumberOf-numberAbsences)/totalNumberOf)*100
											note=name+'\t\t'+attendance.toFixed(1)+'%'
										}else{
											note=name+'\t\t'+num+'人'
										}
										return note
									}		
								}
								break
							case "funnel":// 倒三角图表
								break
							default:
								break;
						}		
						this.chart.setOption(option)
					}
				}
			},
		}
	}
</script>

完整组件代码,及点击事件触发

<template>
	<view class="echarts" @click="echarts.onClick" :prop="option" :change:prop="echarts.update"></view>
</template>
 
<!-- 

	注意: 调用接口用v-if进行数据刷新,接口调用结束v-if=true
	
	使用方式1<EncapsulatingChart v-if='flase' cardType="round" :title="'500'" :subtitle="'出勤总人数'" :annotation="annotation"></EncapsulatingChart>
		cardType:是自有的一些样式模板 字符串类型 值有 (圆形 'round')
		title:标题 字符串类型
		subtitle:副标题 字符串类型
		//annotation:延伸注释 函数类型
	<EncapsulatingChart v-if='flase' cardType="doubleColumnLine" :colorArr="['#828BFF','#FF5F51','#5FE9A4']"></EncapsulatingChart>
		cardType:是自有的一些样式模板 字符串类型 值有 (双柱折线图 'doubleColumnLine')
		colorArr:颜色 字符串数组类型
		nameTheLegend:图例名称 字符串数组类型
	<EncapsulatingChart v-if='flase' cardType="triangle" ></EncapsulatingChart>
		cardType:是自有的一些样式模板 字符串类型 值有 (倒三角图表 'triangle')
	
	使用方式2: 自有的一些样式模板不满足需求
	<EncapsulatingChart v-if='flase' :options="options"></EncapsulatingChart> 
		options: 自定义chart数据 对象类型 
		
-->
	
	
<script>
	import round from './charts/round.js'// 圆形图表
	import doubleColumnLine from './charts/doubleColumnLine.js'// 双柱折线图表
	import triangle from './charts/triangle.js'// 倒三角图表
	export default {
		name: 'Echarts',
		props: {
			options: {
				type: Object,
				default() {
					return null;
				},
			},
			cardData:{
				type:Array,
				default:() => { return [] }
			},
			// 自有数据样式
			// round 圆形
			cardType:{
				type:String,
				default:'round'
			},
			// 主标题
			title:{
				type:String,
				default:null
			},
			// 副标题
			subtitle:{
				type:String,
				default:null
			},
			// 颜色
			colorArr:{
				type:Array,
				default:() => { return [] }
			},
			// 图例名称
			nameTheLegend:{
				type:Array,
				default:() => { return [] }
			},
			// 图例显示
			legend:{
				type:Boolean,
				default:true
			},
			// 图表点击事件
			chartClick:{
				type:Function,
				default:(params)=>{
				}
			}
		},
		data(){
			return {
				option:null
			}
		},
		mounted(){
			
			// 是否使用只有数据
			if(this.options == null){
				this.option = this.getOption()
				this.modifyChartData()
			}else{
				this.option = Object.assign({}, this.options) 
			}
		},
		methods:{
			//父级回调 
			parentCallback(params){
				this.$emit('chartClick',params)
			},
			getOption() {
				// 这里根据相应的cardType返回不同的默认option
				switch (this.cardType) {
					case "round":// 圆形图表
						return round(this.cardData);
					case "doubleColumnLine":// 双柱折线图表
						return doubleColumnLine(this.cardData);
					case "triangle":// 倒三角图表
						return triangle(this.cardData);
					default:
						break;
				}
			},
			// 修改chart数据
			modifyChartData(){
				// 这里根据相应的cardType返回不同的默认option
				switch (this.cardType) {
					case "round":// 圆形图表
						// 主标题
						if(this.title){
							this.option.title.text = this.title
						}
						// 副标题 超过8个字符换行
						if(this.subtitle){
							this.option.title.subtext = this.subtitle.length<=8?this.subtitle:this.subtitle.slice(0,8)+'\n'+this.subtitle.slice(8)
						}
						break
					case "doubleColumnLine":// 双柱折线图表
							// 颜色
							if(this.colorArr.length){
								this.option.series.forEach((item,index)=>{
									item.itemStyle.normal.color = this.colorArr[index]
								})
							}
							// 图例显示
							if(!this.legend){
								this.option.legend=null
							}
							let nameList =[]
							// 图例名称
							if(this.nameTheLegend.length){
								nameList=this.nameTheLegend
							}else{
								nameList=['总人数','缺勤数','出勤率']
							}
							if(nameList.length){
								this.option.series.forEach((item,index)=>{
									item.name = nameList[index]
								})
							}
						break
					default:
						break;
				}
			}
		}
	}
</script>
 
<script module="echarts" lang="renderjs">
	let functionStr = ''
	let asyncClick
	export default {
		data() {
			return {
				chart: null,
			}
		},
		mounted() {
			if (typeof window.echarts === 'object') {
				this.init()
			} else {
				// 动态引入类库
				const script = document.createElement('script')
				script.src = 'static/js/echarts.min.js'
				script.onload = this.init
				document.head.appendChild(script)
			}
		},
		
		methods: {
			//初始化echarts
			init() {
				let _this = this;
				this.chart = echarts.init(this.$el)
				this.update(this.option)
				this.chart.on('click', function(params){ 
					console.log(params)
					asyncClick = params
				});   
			},
			/**
			 * 监测数据更新
			 * @param {Object} option
			 */
			update(option) {
				if (this.chart) {
					// 因App端,回调函数无法从renderjs外传递,故在此自定义设置相关回调函数
					if (option) {
						// 设置新的option
						switch(option.series[0].type){
							case "pie":// 圆形图表
									option.series[0].label.normal.formatter=(param)=>{
									// console.log(param)
										const name = param.name.length > 11 ? param.name.substr(0, 11) + "..." : param.name;
										if(param.name.indexOf('率')!=-1){
											return `${name}\n${param.value}个\t\t${param.percent}%`;
										}else{
											return `${name}\n${param.value}\t\t${param.percent}%`;
										}
									}
									functionStr = JSON.stringify(option.series[0].label.normal.formatter)
								break
							case "bar":// 双柱折线图
								if(option.legend&&!option.legend.formatter){
									option.legend.formatter=(name)=>{
										if(name.indexOf('观看')!=-1){
											return name
										}
										let note=''
										let num = 0
										option.series.forEach(item=>{
											if(item.name==name){
												item.data.forEach(each=>{
													num+=Number(each)
												})
											}
										})
										if(name.indexOf('率')!=-1){
											// 总人数
											let totalNumberOf = 0
											// 缺勤数
											let numberAbsences = 0
											option.series.forEach((item,index)=>{
												item.data.forEach(each=>{
													if(index==0){
														totalNumberOf+=Number(each)
													}else if(index==1){
														numberAbsences+=Number(each)
													}
												})
											})
											// 出勤率
											let attendance = ((totalNumberOf-numberAbsences)/totalNumberOf)*100
											note=name+'\t\t'+attendance.toFixed(1)+'%'
										}else{
											note=name+'\t\t'+num+'人'
										}
										return note
									}		
								}
								break
							case "funnel":// 倒三角图表
								break
							default:
								break;
						}		
						this.chart.setOption(option)
					}
				}
			},
			onClick(event, ownerInstance) {
				if (asyncClick) {
					let obj = Object.assign({}, asyncClick)
					delete obj.event //必须删除这个属性,否则无法传输对象,此字段是元素本身 JSON.stringify 不能转化无限递归对象
					ownerInstance.callMethod('parentCallback', obj)
					asyncClick = null;
				}
			},
		}
	}
</script>
 
<style lang="scss" scoped>
	.echarts {
		width: 100%;
		height: 100%;
	}
</style>

不删除则会包错,错误如下
在这里插入图片描述

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
uni-app使用echarts的详细教程如下: 1. 安装echarts插件 在uni-app项目的根目录下,打开终端,执行以下命令安装echarts插件: ```shell npm install echarts --save ``` 2. 在页面中引入echarts 在需要使用echarts的页面中,引入echarts的js文件。可以在`<script>`标签中使用`import`语句引入echarts: ```javascript import * as echarts from 'echarts' ``` 3. 创建echarts实例 在页面的`<template>`标签中,添加一个容器元素用于显示echarts图表: ```html <view class="chart-container" id="chart"></view> ``` 4. 初始化echarts实例 在页面的`<script>`标签中,使用`uni.createSelectorQuery()`方法获取到容器元素的节点,然后使用`echarts.init()`方法初始化echarts实例: ```javascript onReady() { uni.createSelectorQuery().select('#chart').fields({ node: true, size: true }).exec((res) => { const canvas = res[0].node const ctx = canvas.getContext('2d') const dpr = uni.getSystemInfoSync().pixelRatio canvas.width = res[0].width * dpr canvas.height = res[0].height * dpr const chart = echarts.init(canvas, null, { width: res[0].width, height: res[0].height, devicePixelRatio: dpr }) this.chart = chart }) } ``` 5. 配置echarts图表 在页面的`<script>`标签中,使用`this.chart.setOption()`方法配置echarts图表的选项,例如: ```javascript this.chart.setOption({ title: { text: '柱状图示例' }, xAxis: { data: ['A', 'B', 'C', 'D', 'E'] }, yAxis: {}, series: [{ name: '销量', type: 'bar', data: [5, 20, 36, 10, 10] }] }) ``` 6. 渲染echarts图表 在页面的`<script>`标签中,使用`this.chart.render()`方法将echarts图表渲染到页面上: ```javascript this.chart.render() ``` 以上是uni-app使用echarts的详细教程。你可以根据需要进行配置和定制,实现各种类型的图表展示。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值