2016-01-21 121 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'; 
    } 
}