#私藏项目实操分享#

前言

文章内容以echarts柱状图为例。其它热力图等同样适用。

一、效果图

echarts-根据chart 宽度,获取可显示最大柱子数_数据窗

echarts开发过程中,当我们设定完datazoom 后,当echarts容器宽度变化,所展示的X轴数目不会变化。所有当echarts变宽,每个X轴之间间隔会拉大;当echarts宽度减小,X轴之间间隔会减小,甚至会柱子与柱子之间间隔为0,

所展示的echarts不能随着宽度自适应,如下图 

echarts-根据chart 宽度,获取可显示最大柱子数_数据窗_02

二、解决思路


dataZoom.startValue: 数据窗口范围的起始数值。如果设置了 dataZoom-slider.start 则 startValue 失效。

dataZoom.endValue: 数据窗口范围的结束数值。如果设置了 dataZoom-slider.end 则 endValue 失效。

所以x轴展示数目由stateValue和endValue属性控制,当echarts容器大小发生变化时动态修改控制startValue和endValue即可。

三、示例代码

export function useDataZoom(chart, itemWidth) {
// 根据chart 宽度,获取可显示最大柱子数
function getDataZoomEndValue(options) {
const { left = 0, right = 0 } = Array.isArray(options?.grid)
? options.grid[0]
: options?.grid || {}
const width = chart.value.getWidth()

return Math.floor((width - left - right) / itemWidth) - 1
}

// chart宽度变化,获取最新dataZoom
function getDataZoomByAutoResize(option) {
const endValue = getDataZoomEndValue(option)
const dataZooms = option.dataZoom
dataZooms?.forEach(item => {
item.startValue = 0
item.endValue = endValue
item.end = null
item.start = null
})
return dataZooms
}

/**
* 宽度变化后,更新dataZoom
*/
function autoSizeDrawDataZoom() {
const options = chart.value.getOption()
const dataZooms = getDataZoomByAutoResize(options)
if (dataZooms?.length) {
options.dataZoom = dataZooms
chart.value.clear()
chart.value.setOption(options, { notMerge: true })
}
}

return { dataZoomAutoResize: getDataZoomByAutoResize, autoSizeDrawDataZoom }
}

四、vue引入

<template>
<div class="echarts-content">
<div ref="chartRef" id="mainDataZoom" style="width: 100vw; height: 600px"></div>
</div>
</template>

<script lang="ts" setup>
import {onMounted, ref, shallowRef} from 'vue';
import * as echarts from 'echarts';
import {useDataZoom} from '@/views/Echart/useDataZoom';

const chartRef = shallowRef();

const chart = shallowRef();

onMounted(() => {
const chartDom = document.getElementById('mainDataZoom');
const myChart = echarts.init(chartDom);
chart.value = myChart;
const option = {
grid: {
left: 100,
right: 100
},
xAxis: {
type: 'category',
data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun', 'Mon1', 'Tue1', 'Wed1', 'Thu1', 'Fri1', 'Sat1', 'Sun1', 'Mon2', 'Tue2', 'Wed2', 'Thu2', 'Fri2', 'Sat2', 'Sun2']
},
yAxis: {
type: 'value'
},
series: [
{
data: [120, 200, 150, 80, 70, 110, 130, 120, 200, 150, 80, 70, 110, 130, 120, 200, 150, 80, 70, 110, 130],
type: 'bar',
label: {
show: true,
position: 'top',
fontSize: 13,
fontWeight: 'normal',
color: '#242424'
},
emphasis: {
focus: 'series'
},
barWidth: 30,
barGap: '30%'
}
],
dataZoom: [
{
type: 'slider',
show: true,
filterMode: 'weakFilter',
showDataShadow: false,
showDetail: false,
brushSelect: false,
height: 20,
bottom: 10,
startValue: 0,
endValue: 10
}
]
};

option && myChart.setOption(option);

window.addEventListener('resize',() => {
chart.value.resize()
// autoSizeDrawDataZoom()
});
})

const { autoSizeDrawDataZoom } = useDataZoom(chart, 140)

</script>

<style scoped lang="scss">
.m-2 {
width: 100px;
}
.echarts-content {
width: 100%;
display: grid;
grid-template-columns: repeat(3, 33%);
gap: 20px;
}

.chart-item {
height: 800px;
}
</style>