uniapp项目使用官网echarts(h5)以及移动端问题解决方案(最后有完整实例代码)

一、效果图

1.终端安装

npm install echarts --save

2.在使用页面引入echarts

import *as echarts from 'echarts'

2.在使用页面引入echarts

问题一:区别pc端,移动端要用canvas布局,不要用div

	<!-- ECharts 容器 -->
			<view class="charts-box" @tap="handleTap">
				<canvas style="width:100%;height: 100%;zoom: 1 ;" id="mychart1" ref="echartsRef" canvas-id="mychart"
					:canvas-type="canvasType">
				</canvas>
			</view>

问题二:tooltip弹窗点击不显示 、保证点击事件和坐标轴不能错位(上文布局中我已经使用了@tap="handleTap"绑定了事件
下面就是核心代码:通过uni.createSelectorQuery获取创建的元素)

<script module="echartsScript" lang="renderjs">
		handleTap(event) {
				this.onClick(event);
			},
			onClick(event) {
				const query = uni.createSelectorQuery().in(this);
				query.select('#mychart1').boundingClientRect((rect) => {
					if (rect) {
						const x = event.detail.x - rect.left; // 修正为相对于画布的 X 坐标
						const y = event.detail.y - rect.top; // 修正为相对于画布的 Y 坐标

						const xIndex = this.myEcharts.convertFromPixel({
							seriesIndex: 0
						}, [x, y])[0];

						this.myEcharts.dispatchAction({
							type: 'showTip',
							seriesIndex: 0,
							dataIndex: xIndex
						});
					}
				}).exec();
			},


<script/>

问题三:echarts显示文字不清晰、:通过svg渲染

const ctx = document.getElementById('mychart1');
				const canvasWidth = ctx.offsetWidth;
				const canvasHeight = ctx.offsetHeight;

				this.myEcharts = echarts.init(ctx, null, {
					width: canvasWidth,
					height: canvasHeight,
					renderer: 'svg'
				});

问题四 :echarts使用rpx单位,使用字符串形式

	left: '40rpx',

问题五 :使用resize事件进行实时布局适配

			window.addEventListener('resize', this.handleResize);



          handleResize() {
				this.$nextTick(() => {
					if (this.myEcharts) {
						const ctx = document.getElementById('mychart1');
						const canvasWidth = ctx.offsetWidth;
						const canvasHeight = ctx.offsetHeight;
						this.myEcharts.resize({
							width: canvasWidth,
							height: canvasHeight
						});
					}
				});
			},

问题六:echarts横坐标文字太长,需要换行展示 (使用formatter方法)

					xAxis: [{
						type: 'category',
						data: this.list.map(item => item.name),
						axisLabel: {
							align: 'center',
							color: '#303133',
							interval: 0,
							lineHeight: 20, // 控制行间距
							formatter: function(value) {
								let str = '';
								const num = 2;
								const valLength = value.length;
								const rowNum = Math.ceil(valLength / num);
								for (let i = 0; i < rowNum; i++) {
									const start = i * num;
									const temp = value.substring(start, start + num);
									str += temp + '\n';
								}
								return str.trim();
							}
						},
						axisLine: {
							lineStyle: {
								type: 'dashed',
								color: '#dcdfe6'
							}
						},
						axisTick: {
							alignWithLabel: true,
							show: false
						},

					}],

四:完整代码(uniapp框架有兴趣的朋友可以拿去试试,记得改接口),有帮助的话,双击、收藏不迷路

<template>
	<view class="card">
		<view class="card-title">
			<view class="card-title-left">
				<view class="line"></view>
				<view>你的标题</view>
			</view>
			<view class="card-title-right">
				<view>
					<u-picker @cancel="cancel" @confirm="confirm" :show="show" :columns="columns"></u-picker>
					<view @click="show = true" class="year-container">
						<text class="year-text">{{ year }}</text>
						<u-icon v-show="!show" name="arrow-down-fill" size="20" color="#1890ff" class="year-icon"></u-icon>
						<u-icon v-show="show" name="arrow-up-fill" size="20" color="#1890ff" class="year-icon"></u-icon>
					</view>
				</view>
			</view>
		</view>
		<view class="card-body">
			<!-- ECharts 容器 -->
			<view class="charts-box" @tap="handleTap">
				<canvas style="width:100%;height: 100%;zoom: 1 ;" id="mychart1" ref="echartsRef" canvas-id="mychart"
					:canvas-type="canvasType">
				</canvas>
			</view>
		</view>
	</view>
</template>

<script module="echartsScript" lang="renderjs">
	import * as echarts from 'echarts'
	import {
		getSelectDictionaryData
	} from '@/api/systemData/dictionary'
	import {
		investmentAmountInBusinessAreas,
		getProjectByBusinessArea
	} from '@/api/investmentOverview'

	export default {
		data() {
			return {
				show: false,
				canvasType: '2d',
				columns: this.generateYears(),
				year: new Date().getFullYear(),
				myEcharts: null,
				list: [],
				businessareaOptions: [],
				maxValue: 100,
				title: '',
				loading: false,
				projectList: []
			};
		},
		async mounted() {
			await Promise.allSettled([
				this.getDicData('SELECT', 'businessarea', {
					dicCode: 'BusinessArea'
				})
			]);
			await this.getData();
			this.$nextTick(() => {
				this.init();
			});
			window.addEventListener('resize', this.handleResize);
		},
		beforeDestroy() {
			window.removeEventListener('resize', this.handleResize);
		},
		methods: {
			handleTap(event) {
				this.onClick(event);
			},
			onClick(event) {
				const query = uni.createSelectorQuery().in(this);
				query.select('#mychart1').boundingClientRect((rect) => {
					if (rect) {
						const x = event.detail.x - rect.left; // 修正为相对于画布的 X 坐标
						const y = event.detail.y - rect.top; // 修正为相对于画布的 Y 坐标

						const xIndex = this.myEcharts.convertFromPixel({
							seriesIndex: 0
						}, [x, y])[0];

						this.myEcharts.dispatchAction({
							type: 'showTip',
							seriesIndex: 0,
							dataIndex: xIndex
						});
					}
				}).exec();
			},
			async getDicData(tag, prop, extra) {
				if (tag === 'SELECT' && !extra.options) {
					const res = await getSelectDictionaryData(extra.dicCode);
					const list = res.data;
					const options = prop + 'Options';
					this[options] = list.map(v => ({
						value: +v.enCode,
						label: v.fullName
					}));
				}
			},
			init() {
				const ctx = document.getElementById('mychart1');
				const canvasWidth = ctx.offsetWidth;
				const canvasHeight = ctx.offsetHeight;

				this.myEcharts = echarts.init(ctx, null, {
					width: canvasWidth,
					height: canvasHeight,
					renderer: 'svg'
				});
				const option = {
					title: {
						text: '',
						left: 'center',
						textStyle: {
							color: '#222',
							fontWeight: 500,
							fontSize: 24
						}
					},
					tooltip: {
						trigger: 'axis',
						axisPointer: {
							type: 'shadow'
						},
						borderWidth: 0,
						backgroundColor: 'rgba(0,0,0,0.5)',
						textStyle: {
							color: '#ffffff'
						},
						// enterable: true,
						position: function(point, params, dom, rect, size) {
							// point 是鼠标位置,params 是提示框数据
							var x = point[0]; // 获取鼠标的 x 坐标
							var y = point[1]; // 获取鼠标的 y 坐标

							// 提示框高度
							const tooltipHeight = size.contentSize[1];

							// 保持提示框在鼠标的上方显示,防止超出上边界
							if (y < tooltipHeight) {
								return [x + 10, y + 10];
							} else {
								return [x + 10, y - tooltipHeight - 10];
							}
						},
						confine: true, // 防止提示框超出画布边界
						formatter: function(params) {
							return params[0].name + ':' + params[0].value + '亿元';
						}

					},
					grid: {
						left: '40rpx',
						right: '0rpx',
						bottom: '90rpx',
						top: '32rpx'
					},
					xAxis: [{
						type: 'category',
						data: this.list.map(item => item.name),
						axisLabel: {
							align: 'center',
							color: '#303133',
							interval: 0,
							lineHeight: 20, // 控制行间距
							formatter: function(value) {
								let str = '';
								const num = 2;
								const valLength = value.length;
								const rowNum = Math.ceil(valLength / num);
								for (let i = 0; i < rowNum; i++) {
									const start = i * num;
									const temp = value.substring(start, start + num);
									str += temp + '\n';
								}
								return str.trim();
							}
						},
						axisLine: {
							lineStyle: {
								type: 'dashed',
								color: '#dcdfe6'
							}
						},
						axisTick: {
							alignWithLabel: true,
							show: false
						},

					}],
					yAxis: [{
						name: '亿元',
						type: 'value',
						min: 0,
						max: this.maxValue,
						interval: this.maxValue / 4,
						axisLine: {
							show: false
						},
						axisLabel: {
							// fontSize: '24rpx'
						},
						splitLine: {
							lineStyle: {
								type: 'dashed',
								color: '#dcdfe6'
							}
						},
						axisTick: {
							show: false
						}
					}],
					series: [{
						type: 'bar',
						itemStyle: {
							color: '#1890ff'
						},
						// barWidth: Math.max(36, 300 / this.list.length),
						barWidth: 20,
						data: this.list
					}],
					animationEasing: 'elasticOut'
				};
				this.myEcharts.setOption(option);
			},
			handleResize() {
				this.$nextTick(() => {
					if (this.myEcharts) {
						const ctx = document.getElementById('mychart1');
						const canvasWidth = ctx.offsetWidth;
						const canvasHeight = ctx.offsetHeight;
						this.myEcharts.resize({
							width: canvasWidth,
							height: canvasHeight
						});
					}
				});
			},
			async getData() {
				let res = await investmentAmountInBusinessAreas({
					year: this.year
				});
				if (res.code == 200) {
					this.list = [];
					this.businessareaOptions.forEach(item => {
						const options = res.data.find(v => v.businessarea == item.value);
						this.list.push({
							name: item.label,
							value: options?.deliveryamount || 0,
							projectcount: options?.projectcount || 0,
							enCode: item.value
						});
					});
					const maxCount = Math.ceil(Math.max(...this.list.map(item => item.value)) || 100);
					this.maxValue = Math.ceil(maxCount / Math.pow(10, String(maxCount).length - 1)) * Math.pow(10, String(
						maxCount).length - 1);
				}
			},
			confirm(arr) {
				this.year = arr.value[0];
				this.show = false;
				this.getData();
			},
			cancel() {
				this.show = false;
			},
			generateYears() {
				const year = new Date().getFullYear();
				const years = Array.from({
					length: 10
				}, (_, i) => year - i);
				years.push('全部');
				return [years];
			},
		}
	};
</script>




<style scoped lang="scss">
	.card {
		width: 100%;
		height: 540rpx;
		display: flex;
		flex-direction: column;
		border-radius: 12rpx;
		box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.1);
		background-color: #fff;
		overflow: hidden;
		z-index: 10;

		.card-title {
			display: flex;
			justify-content: space-between;
			padding: 30rpx;
			border-bottom: 1rpx solid #ccc;

			.line {
				width: 8rpx;
				height: 32rpx;
				background-color: #1890ff;
				margin-right: 12rpx;
				border-radius: 20rpx;
			}

			.card-title-left {
				display: flex;
				align-items: center;
			}

			.year-container {
				display: flex;
				align-items: center;
				white-space: nowrap;
				cursor: pointer;
			}

			.year-text {
				font-size: 28rpx;
				color: #000;
				margin-right: 10rpx;
			}

			.year-icon {
				vertical-align: middle;
			}
		}

		.card-body {
			// width: 100%;
			height: 100%;
			padding: 28rpx 20rpx;

			/* 请根据实际需求修改父元素尺寸,组件自动识别宽高 */

		}
	}

	.charts-box {
		width: 100%;
		height: 600rpx;
	}
</style>

可以使用uni-app提供的插件uni-echarts来在H5页面中使用echarts。具体步骤如下: 1. 安装uni-echarts插件:在HBuilderX中打开项目,点击菜单栏的工具 -> 插件市场,在搜索框中输入uni-echarts,点击安装即可。 2. 在需要使用echarts的页面引入echarts库和uni-echarts组件: ```html <template> <view> <uni-echarts :option="option" :height="300px"></uni-echarts> </view> </template> <script> import * as echarts from 'echarts'; import uniEcharts from '@/components/uni-echarts/uni-echarts.vue'; export default { components: { uniEcharts }, data() { return { option: { // echarts配置项 } } }, mounted() { // 初始化echarts实例 const chart = echarts.init(this.$refs.echarts); // 设置option chart.setOption(this.option); } } </script> ``` 3. 在option中配置echarts图表的相关参数,例如: ```javascript option: { title: { text: '某站点用户访问来源', subtext: '纯属虚构', left: 'center' }, tooltip: { trigger: 'item', formatter: '{a} <br/>{b} : {c} ({d}%)' }, legend: { orient: 'vertical', left: 'left', data: ['直接访问', '邮件营销', '联盟广告', '视频广告', '搜索引擎'] }, series: [ { name: '访问来源', type: 'pie', radius: '55%', center: ['50%', '60%'], data: [ {value: 335, name: '直接访问'}, {value: 310, name: '邮件营销'}, {value: 234, name: '联盟广告'}, {value: 135, name: '视频广告'}, {value: 1548, name: '搜索引擎'} ], emphasis: { itemStyle: { shadowBlur: 10, shadowOffsetX: 0, shadowColor: 'rgba(0, 0, 0, 0.5)' } } } ] } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值