vue-echarts/echarts结合flex布局,v-show,charts无法自动计算容器大小自适应
<template>
<v-chart ref="child" class="chart" :autoresize="true" :option="option" />
</template>
问题1: 首先设置一个非常简单的echarts或v-charts,注意autoresize=true这个参数一定要设置,否则echart无法自动适应容器大小变化
<template>
<button
v-for="(show, index) in chartShows"
:key="index"
@click="changeShow(index)"
style="width: 200px"
>
helloword{{ index + 1 }}
</button>
<ChangeableChart
v-show="show"
:autoresize="true"
v-for="(show, index) in chartShows"
:key="index"
/>
</template>
<script lang="ts" setup>
import ChangeableChart from './components/ChangeableChart.vue'
import { nextTick, getCurrentInstance, ref, reactive } from 'vue'
const chartShows = reactive([true, true, true, true])
const textStyle = ref(true)
const vChart = ref()
const changeShow = (id) => {
chartShows[id] = !chartShows[id]
}
</script>
问题2 这种写法的问题是隐藏后,echart的display:none,变化为display:block后无法在次获取到布局的大小,虽然可见但没有高度
解决方式是在echarts外面包裹一层div
<div
class="content"
v-show="show"
:autoresize="true"
v-for="(show, index) in chartShows"
:key="index"
>
<ChangeableChart ref="vChart" />
</div>
问题3 经过上述操作后,div可见度可以调整,图表可以适应容器大小变化,但是多个图表隐藏一个后,其余的放大以适应屏幕,重新显示时,无法根据变化缩小,导致溢出到屏幕外面
原因可能是echart自适应不能响应div变化
解决方式:在div变化完成后,在手动调用图表自适应api调整大小
const changeShow = (id) => {
chartShows[id] = !chartShows[id]
nextTick(() => {
vChart.value.forEach((item, index) => {
if (index !== id) {
item.resize()
}
})
})
}
最后贴上完整代码
<template>
<v-chart ref="child" class="chart" :autoresize="true" :option="option" />
</template>
<script setup>
import { getCurrentInstance, onBeforeMount, onMounted, reactive, ref, computed } from 'vue'
import 'echarts'
const child = ref(null)
import VChart from 'vue-echarts'
const data = ref([
['2000-06-05', 116],
['2000-06-06', 129],
['2000-06-07', 135],
['2000-06-08', 86],
['2000-06-09', 73],
['2000-06-10', 85],
['2000-06-11', 73],
['2000-06-12', 68],
['2000-06-13', 92],
['2000-06-14', 130],
['2000-06-15', 245],
['2000-06-16', 139],
['2000-06-17', 115],
['2000-06-18', 111],
['2000-06-19', 309],
['2000-06-20', 206],
['2000-06-21', 137],
['2000-06-22', 128],
['2000-06-23', 85],
['2000-06-24', 94],
['2000-06-25', 71],
['2000-06-26', 106],
['2000-06-27', 84],
['2000-06-28', 93],
['2000-06-29', 85],
['2000-06-30', 73],
['2000-07-01', 83],
['2000-07-02', 125],
['2000-07-03', 107],
['2000-07-04', 82],
['2000-07-05', 44],
['2000-07-06', 72],
['2000-07-07', 106],
['2000-07-08', 107],
['2000-07-09', 66],
['2000-07-10', 91],
['2000-07-11', 92],
['2000-07-12', 113],
['2000-07-13', 107],
['2000-07-14', 131],
['2000-07-15', 111],
['2000-07-16', 64],
['2000-07-17', 69],
['2000-07-18', 88],
['2000-07-19', 77],
['2000-07-20', 83],
['2000-07-21', 111],
['2000-07-22', 57],
['2000-07-23', 55],
['2000-07-24', 60],
['2000-07-25', 44],
['2000-07-26', 127],
['2000-07-27', 114],
['2000-07-28', 86],
['2000-07-29', 73],
['2000-07-30', 52],
['2000-07-31', 69],
['2000-08-01', 86],
['2000-08-02', 118],
['2000-08-03', 56],
['2000-08-04', 91],
['2000-08-05', 121],
['2000-08-06', 127],
['2000-08-07', 78],
['2000-08-08', 79],
['2000-08-09', 46],
['2000-08-10', 108],
['2000-08-11', 80],
['2000-08-12', 79],
['2000-08-13', 69],
['2000-08-14', 80],
['2000-08-15', 105],
['2000-08-16', 119],
['2000-08-17', 105],
['2000-08-18', 55],
['2000-08-19', 74],
['2000-08-20', 41],
['2000-08-21', 62],
['2000-08-22', 104],
['2000-08-23', 118],
['2000-08-24', 121],
['2000-08-25', 126],
['2000-08-26', 99],
['2000-08-27', 92],
['2000-08-28', 75],
['2000-08-29', 91],
['2000-08-30', 94],
['2000-08-31', 69],
['2000-09-01', 93],
['2000-09-02', 124],
['2000-09-03', 120],
['2000-09-04', 93],
['2000-09-05', 26],
['2000-09-06', 32],
['2000-09-07', 70],
['2000-09-08', 89],
['2000-09-10', 117],
['2000-09-11', 144]
])
const resize = () => {
child.value.resize()
}
const option = computed(() => {
return {
title: {
show: true,
text: 'Beijing AQI',
left: '1%',
top: '10%',
textStyle: {
color: 'white'
}
},
// tooltip: {
// show: false,
// trigger: 'axis'
// },
grid: {
top: 20,
left: 60,
right: 20,
bottom: 40
},
xAxis: {
axisLabel: {
color: '#FFF'
},
axisLine: {
show: false
},
axisTick: {
show: false
},
data: data.value.map(function (item) {
return item[0]
})
},
yAxis: {
//隐藏y轴标签
axisLabel: {
show: false
},
//隐藏y刻度线
splitLine: {
show: false
}
},
// toolbox: {
// right: 10,
// feature: {
// dataZoom: {
// yAxisIndex: 'none'
// },
// restore: {},
// saveAsImage: {}
// }
// },
// dataZoom: [
// {
// startValue: '2014-06-01'
// },
// {
// type: 'inside'
// }
// ],
visualMap: {
show: false,
top: 50,
right: 10,
pieces: [
{
gt: 0,
lte: 50,
color: '#93CE07'
},
{
gt: 50,
lte: 100,
color: '#FBDB0F'
},
{
gt: 100,
lte: 150,
color: '#FC7D02'
},
{
gt: 150,
lte: 200,
color: '#FD0100'
},
{
gt: 200,
lte: 300,
color: '#AA069F'
},
{
gt: 300,
color: '#AC3B2A'
}
],
outOfRange: {
color: '#999'
}
},
series: {
name: 'Beijing AQI',
type: 'line',
axisTick: {
show: false
},
axisLine: { show: false },
data: data.value.map(function (item) {
return item[1]
}),
//标线设置
markLine: {
symbol: 'none', // 移除箭头
silent: true,
lineStyle: {
type: 'solid', // 设置为实线
width: 2 // 设置线宽
},
label: {
show: true, // 显示标签
color: 'white', // 设置默认标签文字颜色
position: 'start',
distance: 20
},
data: [
{
yAxis: 50,
lineStyle: {
color: '#8C1C3E'
}
},
{
yAxis: 100,
lineStyle: {
color: '#8C9C3E'
}
},
{
yAxis: 150,
lineStyle: {
color: '#0B6136'
}
},
{
yAxis: 200,
lineStyle: {
color: '#BFC822'
}
},
{
yAxis: 250,
lineStyle: {
color: '#8C1C3E'
}
}
]
}
}
}
})
const setData = () => {
setInterval(() => {
data.value.forEach((item) => {
item[1] = Math.round(Math.random() * 2)
})
}, 500)
}
const { proxy } = getCurrentInstance()
const emits = defineEmits([])
const props = defineProps({})
const state = reactive({})
onBeforeMount(() => {})
onMounted(() => {
// setData()
})
defineExpose({ resize })
</script>
<style scoped>
.chart {
border-top: 2px solid #3d76e9;
border-right: 2px solid #3d76e9;
border-left: 2px solid #3d76e9;
border-bottom: none;
/* background-color: #1a397d; */
box-sizing: border-box; /* 更改盒模型计算方式 */
}
</style>
<script lang="ts" setup>
import ChangeableChart from './components/ChangeableChart.vue'
import { nextTick, getCurrentInstance, ref, reactive } from 'vue'
const chartShows = reactive([true, true, true, true])
const textStyle = ref(true)
const vChart = ref()
const changeShow = (id) => {
chartShows[id] = !chartShows[id]
nextTick(() => {
vChart.value.forEach((item, index) => {
if (index !== id) {
item.resize()
}
})
})
}
</script>
<template>
<button
v-for="(show, index) in chartShows"
:key="index"
@click="changeShow(index)"
style="width: 200px"
>
helloword{{ index + 1 }}
</button>
<div class="charts">
<div
class="content"
v-show="show"
:autoresize="true"
v-for="(show, index) in chartShows"
:key="index"
>
<ChangeableChart ref="vChart" />
</div>
</div>
</template>
<style scoped>
header {
line-height: 1.5;
}
.charts {
display: flex;
flex-direction: column;
flex: 1;
}
.logo {
display: block;
margin: 0 auto 2rem;
}
.content {
flex: 1;
overflow: hidden;
/* display: flex;
flex-direction: column; */
}
.wrapper {
height: 100%;
width: 100%;
overflow: hidden;
}
@media (min-width: 1024px) {
header {
place-items: center;
padding-right: calc(var(--section-gap) / 2);
}
.logo {
margin: 0 2rem 0 0;
}
header .wrapper {
display: flex;
place-items: flex-start;
flex-wrap: wrap;
}
}
</style>