思路:
通过echarts的resize方法加上echarts图表的宽高使用百分比实现echarts图表大小的自适应(为了更好的自适应效果一般建议用来引入echarts组件的的容器的宽高也使用百分比);图表用到的字体和图形的大小也不能写死,而是用当前屏幕的高度和初始屏幕的高度的比值算出一个数值再赋值也就是下文中的transformFontSize方法。
注意:
监听到图表的大小发生变化时需要调用initOption方法,这样图中图形和文字的大小才会发生变化。
具体实现:
1.把echarts封装成组件,以便在要用的地方引入
<template>
<div :id="name" :style="{ width: width + '%', height: height + '%' }"></div>
</template>
<script setup>
import {reactive, nextTick, onMounted, watch, ref, onBeforeUnmount} from "vue";
import * as echarts from "echarts";
import {useRouter} from "vue-router";
import {transformFontSize} from "@/js/utils";
const router = useRouter();
const props = defineProps({
name: String,
width: String,
color: Array,
height: String,
data: Object,
title: String
});
// const data = reactive([]);
let myChart = null;
onMounted(() => {
initChart();
});
watch(() => props.data.data_y, (newValue, oldValue) => {
if(myChart){
initOption();
}
}, {immediate: true, deep: true});
function initChart() {
let container = document.getElementById(props.name);
myChart = echarts.init(container);
initOption()
window.addEventListener("resize", resizeMyChart);
}
const initOption = () => {
// 绘制图表
let option = {
tooltip: {
trigger: 'item',// axis显示该列下所有坐标轴对应数据,item只显示该点数据
formatter: (params) => {
if (props.name === "Bar_dqzc") {
return params.marker + ' ' + params.name + ' ' + params.value + "人"
} else if (props.name === "Bar_yhsb") {
return params.marker + ' ' + params.name + ' ' + params.value + "台"
}
},
},
// legend: {
// top: "3%",
// right: "3%",
// data: [props.title],
// textStyle: {
// color: props.color, // 设置图例文字颜色为红色
// fontSize: transformFontSize(13),
// },
// itemHeight: transformFontSize(13),
// itemWidth: transformFontSize(30),
// },
xAxis: {
data: props.data.data_x,
axisLine: {
lineStyle: {
color: "#fff",
},
},
axisLabel: {
color: "#fff",
fontSize: transformFontSize(13),
margin: transformFontSize(10),
// fontWeight: 'bold' // 设置字体粗细为粗体
// rotate: 35,//35度角倾斜显示
},
axisTick: {
show: true,//x轴齿状
},
},
yAxis: {
// nameTextStyle: {
// color: "#95B3CF",
// fontSize: 16,
// },
axisLine: {
show: true,
lineStyle: {
color: "#fff",
width: transformFontSize(1.5)
},
},
axisLabel: {
color: "#fff",
fontSize: transformFontSize(13),
// fontWeight: 'bold' // 设置字体粗细为粗体
},
splitLine: {
show: false,
lineStyle: {
color: "#0177d4",
},
},
// interval: 100,
// max: 500,
},
series: [
// 底部
{
z: 2,
type: 'pictorialBar',
symbol: 'circle',
symbolOffset: ['0%', '10%'],
symbolSize: [transformFontSize(15), transformFontSize(6)],
toolltip: {
show: false
},
itemStyle: {
color: props.color[1]
},
data: props.data.data_y,
},
//内容区域
{
z: 1,
type: 'bar',
barWidth: transformFontSize(15),
data: props.data.data_y,
itemStyle: {
color: new echarts.graphic.LinearGradient(
0,
0,
0,
1,
[
{
offset: 0,
color: props.color[1],
},
{
offset: 0.5,
color: props.color[0],
},
],
false
),
},
},
//内容的顶部
{
z: 3,
type: 'pictorialBar',
symbol: 'circle',
symbolPosition: 'end',
symbolOffset: ['0%', '-50%'],
symbolSize: [transformFontSize(15), transformFontSize(6)],
toolltip: {
show: false,
},
itemStyle: {
color: props.color[0]
},
data: props.data.data_y,
}
//长方形代码
// {
// name: props.title,
// type: "bar",
// barWidth: transformFontSize(15),
// // itemStyle: {
// // normal: {
// // color: props.color
// // },
// // },
// itemStyle: {
// color: new echarts.graphic.LinearGradient(
// 0,
// 0,
// 0,
// 1,
// [
// {
// offset: 0,
// color: props.color[1],
// },
// {
// offset: 0.5,
// color: props.color[0],
// },
// ],
// false
// ),
// },
// data: props.data.data_y,
// },
],
grid: {
top: "10%",
left: "15%",
right: "15",
bottom: "12%",
// bottom: "20%",
}
};
myChart.setOption(option);
}
function resizeMyChart() {
initOption()
myChart.resize();
}
onBeforeUnmount(() => {
window.removeEventListener("resize", resizeMyChart);
myChart = null;
})
</script>
<style scoped lang="less"></style>
2.引入组件
<div class="echarts">
<Bar :color="['#38F8C7','#259276']" :name="'Bar_dqzc'" :width="'100'"
:height="'100'" :data="barData"
:title="'地区注册用户top5'" v-if="barData.data_y.length!==0">
</Bar>
</div>
3.传入组件数据格式
const barData = reactive({
// data_x: ["北京", "上海", "广州", "重庆", "河北"],
data_x: [],
data_y: []
})
4.组件中使用的transformFontSize方法
/*
*根据当前屏幕大小换算对应的px
* */
export function transformFontSize(fontsize) {
// 获取屏幕宽度
const height = window.innerHeight || document.body.clientHeight
const ratio = height / 953
// 取下整
return parseInt(fontsize * ratio)
}