echarts X轴类目名太长时隐藏,hover时显示全部

echarts图表X轴

在柱状图中,X轴类目名如果数据太长;
echarts会默认进行隐藏部分字段;
如果我们想让每一个类目名都显示出来,需要进行额外的处理

X轴类目名太长时,默认只显示一部分类目名

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>4.9.0</title>
    <script src="https://cdn.staticfile.net/echarts/4.9.0-rc.1/echarts-en.common.js"></script>
</head>

<body>
  <div style="width: 400px;height: 300px;"></div>
  <script>
    let myChart = echarts.init(document.querySelector('div'))
    let colors = ['#4C98FB', '#83CCE7', '#26C7C8', '#73DEBD'];
    let option = {
      xAxis: {
        type: 'category',
        data: ['我是字段1cccccccc', '我是字段2', '我是字段3', '我是字段4', '我是字段5', '我是字段6', '我是字段7']
      },
      yAxis: {
        type: 'value'
      },
      series: [
        {
          data: [120, 200, 150, 80, 70, 110, 130],
          type: 'bar'
        }
      ]
    };
    myChart.setOption(option);
  </script>
</body>
</html>

分析原因

通过上面的现象,我们发现:
展示不出来的原因是水平标签过多导致;
我们如果可以让它倾斜的话,说不定可以全部展示出来;
我们可以使用 xAxis下的 axisLabel中的 rotate属性来解决;
rotate:刻度标签旋转角度;这个值在 【90,-90】的范围类
在类目轴的类目标签显示不下的时候可以通过旋转防止标签之间重叠。

使用倾斜角度让每一个类目名显示出来

xAxis: {
  type: 'category',
  data: ['我是字段1cccccccc2', '我是字段2', '段3', '我是字段4', '我是字段5', '我', '我是字段7'],
  axisLabel: {  
    interval:0,  
    rotate:-20  // 表示倾斜的角度
  }  
},

interval这个属性的简单介绍

interval:坐标轴刻度标签的显示间隔,在类目轴中有效。
默认会采用标签不重叠的策略显示标签。
可以设置成0表示强制显示所有标签。
如果设置为 1,表示『隔一个标签』
可以用数值表示间隔的数据,也可以通过回调函数控制。
回调函数格式如下:
interval:(index:number, value: string) => {
  // index表示该类目名的下标
  // string表示该类目名
  console.log(index,string)
  return 1
},
如果返回的是true,表示显示该类目名;
也就是说:可以返回数字或者布尔值

let option = {
  xAxis: {
    type: 'category',
    axisLabel: {  
      interval:2, // x轴间隔2个类目名
    },
    data: ['我是1', '我是2', '我是3', '我是4', '我是5', '我是6', '我是7']
  },
}

换行\n来处理这个问题

我们通过倾斜可以完全的把这个问题处理了;
可是有些时候,我们ui不想倾斜;那还有其他办法吗?可以换行
换行的话我们有两种方式;
第1种:直接在data中通过\n换行
不推荐第1种这样的方式去做;是因为如果图表还有tooltip的话,会影响。
第2种:在formatter函数中去处理

xAxis: {
  type: 'category',
  data: ['我是\n字段1', '我是\n字段2', '段3', '我是\n字段4', 
    '我是\n字段5', '我是\n字段6', '我是\n字段7'
  ],
},

在data中通过\n换行会在 tooltip 会产生一个空格【不推荐有有副作用】

tooltip: {
  // 使用formatter回调函数自定义显示内容
  formatter: function (params) {
    // params是包含数据信息的对象
    return params.name + ': ' + params.value;
  }
},
xAxis: {
  type: 'category',
  data: ['我是\n字段1', '我是\n字段2', '段3', '我是\n字段4', 
    '我是\n字段5', '我是\n字段6', '我是\n字段7'
  ],
},

通过 axisLabel中的formatter函数来换行 【推荐】没有副作用

我们可以通过xAxis下的axisLabel下的formatter函数来进行换行,
这样做不会改变原始数组,tooltip也不会出现任何问题;
如果像上面那样做;改变原始数据;

 tooltip: {
    // 使用formatter回调函数自定义显示内容
    formatter: function (params) {
      // params是包含数据信息的对象
      return params.name + ': ' + params.value;
    }
  },
 xAxis: {
  interval: 0, 
  type: 'category',
  data: ['我是字段1', '我是字段2', '我是字段3', 
  '我是字段4', '我是字段5', '我是字段6', '我是字段7'],
  axisLabel: {  
    formatter: function (params) {
      console.log('x',params)
      return params.substring(0,2) + '\n' + params.substring(2)
    }
  }
},

超出进行隐藏部分名称,hover显示全部

现在我们要做这样一个效果,
X轴中的类目名默认显示2个字,超出部分隐藏,hover的时候显示全部;
我们需要使用到echarts中的 mouseover 事件;
同时设置xAxis中的triggerEvent为true
xAxis: {
  triggerEvent: true,
  interval: 0, 
  type: 'category',
  ...其他配置项...
}
如果我们不设置triggerEvent: true鼠标移入X轴的类名不会被触发

myChart.on('mouseover', (e) => {
  console.log('鼠标移入X轴的类名不会被触发',e)
})

实现的思路

我们需要动态创建一个dom节点,通过createElement来实现
注册鼠标移入事件 myChart.on('mouseover',(e)=>{ })
通过e.event可以拿到offsetX和offsetY
紧接着将这个元素赋值(X轴类的全名称),添加到html页面中
鼠标的移出事件 myChart.on('mouseout',(e)=>{ })

let option = {
  xAxis: {
    // X轴的类目名必须设置这个属性,移入事件才会被触发
    triggerEvent: true,
    interval: 0, 
    type: 'category',
    data: ['我是字段111111', '我是字段222222', '我是字段33333', '我是字段4', '我是字段5', '我是字段6', '我是字段7'],
    axisLabel: {  
      formatter: function (params) {
        return params.substring(0,2) + '...'
      }
    }
  },
  ... 其他配置项
}
myChart.setOption(option);

myChart.on('mouseover', (e) => {
  console.log('鼠标移入',e)
  if(e.componentType === "xAxis"){
    // 我们这里先判断一个创建的dom节点是否存在
    let tipNameDom = document.getElementById('tipNameDom')
    console.log(1, tipNameDom)
    // 如果不存在我们创建一个dom节点
    if(!tipNameDom){
      // 创建一个元素
      var createDivElement = document.createElement('div')
      // 给这个元素设置属性
      createDivElement.setAttribute('id', 'tipNameDom')
      // // 设置元素的位置
      createDivElement.style.display = 'block'
      createDivElement.style.position = 'absolute'
      // 获取当前位置
      createDivElement.style.top =  e.event.offsetY + 15 + 'px'
      createDivElement.style.left = e.event.offsetX - 10 + 'px'
      // 这里需要使用 innerHTML,因为我们设置了一样html的属性
      createDivElement.innerHTML = e.value
      // document.querySelector('body').appendChild(createDivElement)
      document.querySelector('body').appendChild(createDivElement)
    }else {
      tipNameDom.style.display = 'block'
      tipNameDom.style.position = 'absolute'
      // 获取当前位置
      tipNameDom.style.top =  e.event.offsetY + 15 + 'px'
      tipNameDom.style.left = e.event.offsetX - 10 + 'px'
      // 这里需要使用 innerHTML,因为我们设置了一样html的属性
      tipNameDom.innerHTML = e.value
    }
  }
})

//  移入事件如果被多次触发,则hover的时候无法显示全部
myChart.on('mouseout', function(params) {
  console.log('移除元素',params )
  if (params.componentType === 'xAxis') {
    let elementDiv = document.querySelector('#tipNameDom')
    console.log('elementDiv', elementDiv)
    elementDiv.style.display = 'none'
  }  
})

是不是这样就OK了?

其实,并不是的;
如果小伙伴们多次移入移出;
偶尔会出现光标明明是移入的状态,但是类目名并没有全部显示出来;
此时已发现了移入事件被多次触发;
怎么解决这个问题呢?
目前的我,并不知道如何去解决。我感觉是echarts的bug;
如果知道的大佬;可以解答一下,万分感激; 


全部代码

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>4.9.0</title>
  <!-- <script src="https://cdn.staticfile.org/echarts/4.3.0/echarts.min.js"></script> -->
  <script src="https://cdn.staticfile.net/echarts/4.9.0-rc.1/echarts-en.common.js"></script>
  <script>
    window.onload =function (){
      let myChart = echarts.init(document.querySelector('.echars'))
      let colors = ['#4C98FB', '#83CCE7', '#26C7C8', '#73DEBD'];
      let option = {
        tooltip: {
          // 使用formatter回调函数自定义显示内容
          formatter: function (params) {
            // params是包含数据信息的对象
            return params.name + ': ' + params.value;
          }
        },
        xAxis: {
          // X轴的类目名必须设置这个属性,移入事件才会被触发
          triggerEvent: true,
          interval: 0, 
          type: 'category',
          data: ['我是字段111111', '我是字段222222', '我是字段33333', '我是字段4', '我是字段5', '我是字段6', '我是字段7'],
          axisLabel: {  
            formatter: function (params) {
              return params.substring(0,2) + '...'
            }
          }
        },
        yAxis: {
          type: 'value'
        },
        series: [
          {
            data: [120, 200, 150, 80, 70, 110, 130],
            type: 'bar'
          }
        ]
      };
      myChart.setOption(option);

      myChart.on('mouseover', (e) => {
        console.log('鼠标移入',e)
        if(e.componentType === "xAxis"){
          // 我们这里先判断一个创建的dom节点是否存在
          let tipNameDom = document.getElementById('tipNameDom')
          console.log(1, tipNameDom)
          // 如果不存在我们创建一个dom节点
          if(!tipNameDom){
            // 创建一个元素
            var createDivElement = document.createElement('div')
            // 给这个元素设置属性
            createDivElement.setAttribute('id', 'tipNameDom')
            // // 设置元素的位置
            createDivElement.style.display = 'block'
            createDivElement.style.position = 'absolute'
            // 获取当前位置
            createDivElement.style.top =  e.event.offsetY + 15 + 'px'
            createDivElement.style.left = e.event.offsetX - 10 + 'px'
            // 这里需要使用 innerHTML,因为我们设置了一样html的属性
            createDivElement.innerHTML = e.value
            // document.querySelector('body').appendChild(createDivElement)
            document.querySelector('body').appendChild(createDivElement)
          }else {
            tipNameDom.style.display = 'block'
            tipNameDom.style.position = 'absolute'
            // 获取当前位置
            tipNameDom.style.top =  e.event.offsetY + 15 + 'px'
            tipNameDom.style.left = e.event.offsetX - 10 + 'px'
            // 这里需要使用 innerHTML,因为我们设置了一样html的属性
            tipNameDom.innerHTML = e.value
          }
        }
      })

      //  移入事件如果被多次触发,则hover的时候无法显示全部
      myChart.on('mouseout', function(params) {
        console.log('移除元素',params )
        if (params.componentType === 'xAxis') {
          let elementDiv = document.querySelector('#tipNameDom')
          console.log('elementDiv', elementDiv)
          elementDiv.style.display = 'none'
        }  
      })
  }
</script>
</head>
<body>
  <div style="width: 400px;height: 300px;" class="echars"></div>
</body>

</html>

尾声

如果你觉得我写的不错的话,点一下推荐。感谢了
我已经几个月没有人给我推荐了。
听说打赏的小哥哥都追到女朋友了,
咦!你不信,不信你给我打赏看一下!
保准你追到到喜欢的Ta