echarts X軸類目名太長時隱藏,hover時顯示全部

南风晚来晚相识發表於2024-04-11

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

相關文章