2016-01-21 122 views
0

我期待能夠鏈接Chart.js 酒吧圖表中的x標籤。我搜索得非常徹底,並最終試圖提出自己的解決方案:因爲標籤對應於直接位於它們上方的條形圖,並且Chart.js具有內置的getBarsAtEvent(evt)方法,所以我嘗試創建一個事件用戶沒有點擊圖表 - 這個新事件的pageX和pageY直接在初始點擊之上,這樣如果用戶點擊了標籤,新事件將模擬點擊條形圖。但是,調用getBarsAtEvent(createdClickEvent)反覆給我一個Uncaught TypeError(「Can not read property'getBoundingClientRect'of null」),這意味着getBarsAtEvent方法在我的模擬點擊上調用時並不實際返回任何東西。添加鏈接到X標籤Chart.js

任何建議或替代方法將不勝感激,在此先感謝。

回答

2

另一種方法是確定用戶實際點擊的點,並基於該點計算哪個標籤被點擊。爲此,您需要一些關於所創建圖表的信息,並且必須進行一些計算。

下面是這樣做的方法,這裏是一個Fiddle與這種代碼/方法。希望能幫助到你。

$("#canvas").click( 
     function(evt){ 
      var ctx = document.getElementById("canvas").getContext("2d"); 
      // from the endPoint we get the end of the bars area 
      var base = myBar.scale.endPoint; 
      var height = myBar.chart.height; 
      var width = myBar.chart.width; 
      // only call if event is under the xAxis 
      if(evt.pageY > base){ 
       // how many xLabels we have 
       var count = myBar.scale.valuesCount; 
       var padding_left = myBar.scale.xScalePaddingLeft; 
       var padding_right = myBar.scale.xScalePaddingRight; 
       // calculate width for each label 
       var xwidth = (width-padding_left-padding_right)/count; 
       // determine what label were clicked on AND PUT IT INTO bar_index 
       var bar_index = (evt.offsetX - padding_left)/xwidth; 
       // don't call for padding areas 
       if(bar_index > 0 & bar_index < count){ 
        bar_index = parseInt(bar_index); 
        // either get label from barChartData 
        console.log("barChartData:" + barChartData.labels[bar_index]); 
        // or from current data 
        var ret = []; 
        for (var i = 0; i < myBar.datasets[0].bars.length; i++) { 
         ret.push(myBar.datasets[0].bars[i].label) 
        }; 
        console.log("current data:" + ret[bar_index]); 
        // based on the label you can call any function 
       } 
      } 
     } 
); 
+0

我做了一些修改,但是你的邏輯很完美 - 謝謝你。也非常感謝您的代碼中的評論! – user3236859

+0

關於如何製作標籤可搜索文本,您有任何建議嗎?我希望能夠在控制+ F瀏覽器搜索中找到它們。 – user3236859

1

我修改IECS的答案與chartjs工作2.7.1

var that = this; 
this.chart = new Chart($("#chart"), { 
    type: 'bar', 
    data: { 
     labels: labels, 
     datasets: datasets 
    }, 
    options: { 
     events: ["mousemove", "mouseout", "click", "touchstart", "touchmove", "touchend"], 
     onClick: function(e, data) { 
      var ctx = $("#chart")[0].getContext("2d"); 
      var base = that.chart.chartArea.bottom; 
      var height = that.chart.chart.height; 
      var width = that.chart.chart.scales['x-axis-0'].width; 
      var offset = $('#chart').offset().top - $(window).scrollTop(); 
      if(e.pageY > base + offset){ 
       var count = that.chart.scales['x-axis-0'].ticks.length; 
       var padding_left = that.chart.scales['x-axis-0'].paddingLeft; 
       var padding_right = that.chart.scales['x-axis-0'].paddingRight; 
       var xwidth = (width-padding_left-padding_right)/count; 
       // don't call for padding areas 
       var bar_index = (e.offsetX - padding_left - that.chart.scales['y-axis-0'].width)/xwidth; 
       if(bar_index > 0 & bar_index < count){ 
        bar_index = Math.floor(bar_index); 
        console.log(bar_index); 
       } 
      } 
     } 
    } 
}); 

的主要區別是:

  • chartjs較新版本的使用chart.scales陣列,而不是圖表.scale with a bunch of values
  • 我不得不從x偏移量中減去chart.scales ['y-axis-0'] .width獲得正確的bar_index
  • 我改變parseInt函數來Math.floor,只是個人喜好

如果你想光標,當你將鼠標懸停在他們這個改變,「懸停」添加到事件陣列和選項:

onHover: function(e) { 
    var ctx = $("#chart")[0].getContext("2d"); 
    var base = that.chart.chartArea.bottom; 
    var height = that.chart.chart.height; 
    var width = that.chart.chart.scales['x-axis-0'].width; 
    var yOffset = $('#chart').offset().top - $(window).scrollTop(); 
    var xOffset = $('#chart').offset().left - $(window).scrollLeft(); 

    var left = xOffset + that.chart.scales['x-axis-0'].paddingLeft + that.chart.scales['x-axis-0'].left; 
    var right = xOffset + that.chart.scales['x-axis-0'].paddingRight + that.chart.scales['x-axis-0'].left + width; 

    if(e.pageY > base + yOffset && e.pageX > left && e.pageX < right){ 
      e.target.style.cursor = 'pointer'; 
    } 
    else { 
     e.target.style.cursor = 'default'; 
    } 
}