echart动态渲染宽高度
先说需求与思路
-
需求:三个按钮,分别是展示前十、后十、与全部 下方的图表要动态的配置宽高,(通常情况下是某一边)
-
思路: 父组件根据传入数组长度动态设置overflow 如果是
auto
,则会根据子元素即echart容器是否溢出来显示滚动条,内部的echart元素可以根据长度来动态设置宽高,初始值可以自行调整
本例中为动态设置高,给父元素加scrollRef是为了让其在按钮切换时可以将高度重置为0
dom
<div ref={scrollRef} style={{ overflowY: myArr.length > 10 ? 'auto' : 'hidden', overflowX: 'hidden', height: 400 }}>
<div ref={divRef} style={{
height: 400
}} >
</div>
</div>
逻辑
// 本组件为echart图表 前后都为十条,全部则所有的数据
function MyEchart({receive}){
// receive:源数据 divRef:echart元素 scrollRef:echart父元素
const divRef = useRef()
const scrollRef = useRef()
// 初始化时,默认渲染前十条
const [myArr, setmyArr] = useState(receive.slice(0, 10))
// 单选框
const [showType, setShowType] = useState('0')
// 过滤方法,根据key动态切割源数据
const filterArr = {
'0': () => receive.slice(0, 10),
'1': () => receive.slice(-10),
'2': () => receive
}
// 切割数组的方法
const streamRepairList = (index) => {
setmyArr(pre => filterArr[index]())
}
// 在useeffect中,定义echart并动态定义宽高
useEffect(() => {
if (!divRef.current) return
let timer
// 如果父元素有current,则将其父元素的高度设为0
if (scrollRef.current) {
scrollRef.current.scrollTop = 0
}
const option = {...} // 不再赘述
// 如果有chart实例,则让其重渲染
if (myChart) {
myChart.resize()
}
// 这里为根据myarr高度动态定义的单个柱子的长度
const echartHeight = myArr.length > 10 ? 40 : 46
// 生成mychart实例
const myChart = echarts.getInstanceByDom(divRef.current) ?? echarts.init(divRef.current, ECHARTS_THEME)
// 关键代码!!!!!!!!!!!!!!!动态设置echart元素的高度
myChart.getDom().style.height = `${myArr.length * echartHeight}px`
// 关键代码!!!!!!!!!!!!!!!
myChart.setOption(option)
// 如果屏幕宽高有变化,则重新渲染
window.onresize = () => {
myChart.resize()
}
// 判断外部传入数组是否有值,如果有则执行延时器
if (myArr.length > 0) {
timer = setTimeout(() => {
myChart?.resize()
}, 10)
}
return () => {
timer && clearTimeout(timer)
// 卸载前销毁echart便节省性能
myChart.dispose()
}
},[myArr]}
//return的dom在上方有写
}
想到可能有的读者想看下y轴
与services
series: [
{
data: myArr.map(v => v.num),
type: 'bar',
barGap: 10,
smooth: true,
barWidth: 20,
label: {
show: true,
position: 'right',
// formatter: "{c}",
offset: [5, -2]
},
}
],
yAxis: {
type: 'category',
inverse: true, // 是否倒叙
axisTick: false,
axisLine: {
show: true
},
splitLine: {
lineStyle: {
color: '#00000026',
}
},
axisLabel: {
show: true,
color: '#00000073',
fontSize: 12,
interval: 0,
textStyle: {
lineHeight: 16,
},
},
data: myArr.map(v => v.name)
},
以上。