如何从外部触发数据标签-插件(active)- ChartJS

aydmsdu9  于 2023-05-17  发布在  Chart.js
关注(0)|答案(1)|浏览(143)

我在玩这个代码:https://jsfiddle.net/netquik/e3jp2k5o/37/
首先创建了一个插件,当鼠标悬停在图表栏上时,可以在x轴上高亮显示标签(刻度)(现在使用mousemove)。然后我尝试在外部触发图表和工具提示的setActiveElements。而且看起来像预期的那样工作。
expected result

我的问题是我不能找到一种方法来“更新”数据标签在同一时间,所以它可以显示我的数据标签。在代码中,你可以看到我尝试手动启用$datalabels的一些$context属性,但没有成功。在外部setActiveElements之后,我在调试中看到,数据标签在图表更新后会自动触发,并尝试

display: function (context) {
                              return context.active; // display labels if active
                          },

但即使chart中的元素是“active”,也会返回假context. active。可能是交互模式的问题?谢谢你的帮助。trigger result without datalabel

var SCRIPTOBJ = null;
var LABEL = ["Gino", "Samantha", "Vercingetorige"];
var DATA = [5, 28, 500];
var MAX = Math.max(...DATA);

var ctx = $('#stat');

Chart.defaults.font.size = 14;
Chart.register(ChartDataLabels);

var lastLabelH = null;
var stat = new Chart(ctx, {
type: 'bar',

data: {
  labels: LABEL,
  datasets: [{
    minBarLength: 15,
    barPercentage: 1,
    label: '# VOTES',
    data: DATA,
    backgroundColor: [
      'rgba(255, 99, 132, 0.5)',
      'rgba(54, 162, 235, 0.5)',
      'rgba(255, 206, 86, 0.5)',
      'rgba(75, 192, 192, 0.5)',
      'rgba(153, 102, 255, 0.5)',
      'rgba(255, 159, 64, 0.5)'
    ],
    borderColor: [
      'rgba(255, 99, 132, 1)',
      'rgba(54, 162, 235, 1)',
      'rgba(255, 206, 86, 1)',
      'rgba(75, 192, 192, 1)',
      'rgba(153, 102, 255, 1)',
      'rgba(255, 159, 64, 1)'
    ],
    hoverBackgroundColor: [
      'rgba(255, 99, 132, 1.0)',
      'rgba(54, 162, 235, 1.0)',
      'rgba(255, 206, 86, 1.0)',
      'rgba(75, 192, 192, 1.0)',
      'rgba(153, 102, 255, 1.0)',
      'rgba(255, 159, 64, 1.0)'
    ],
    borderWidth: 1
  }]
},
plugins: [{
  id: 'LabelHighlight',
  beforeEvent(c, args, pluginOptions) {
    const event = args.event;
    if (event.type === 'mouseout') {
      if (lastLabelH != null) {
        //c.scales.x._labelItems[lastLabelH].color = "rgba(255, 159, 64, 1)";
        c.update();
        lastLabelH = null;
      }
    } else if (event.type === 'mousemove') {
      if (c._active.length > 0) {
        let labelindex = c._active[0].index;
        if (c.scales.x._labelItems) {
          let label = c.scales.x._labelItems[labelindex];
          label.color = "rgba(255, 255, 64, 1)";
        }
        if (lastLabelH != null && lastLabelH != labelindex) {
          if (c.scales.x._labelItems) {
            c.scales.x._labelItems[lastLabelH].color = "rgba(255, 159, 64, 1)";
          }
        }

        lastLabelH = labelindex;

      } else {
        if (lastLabelH != null) {
          if (c.scales.x._labelItems) {
            c.scales.x._labelItems[lastLabelH].color = "rgba(255, 159, 64, 1)";
          }
          lastLabelH = null;
        }

      }

    }
  }
}],
options: {
  responsive: false,
  interaction: {
    mode: 'index',
    intersect: true
  },
  /*            onHover: function (event, elements, c) {
                 if (elements && elements.length) {
                     if (c._active.length > 0) {
                         let labelindex = c._active[0].index;
                         let label = c.scales.x._labelItems[labelindex];
                         label.color = "rgba(255, 255, 64, 1)";
                         lastLabelH = labelindex;
                     }
                 } else {
                     if (lastLabelH != null) {
                         c.scales.x._labelItems[lastLabelH].color = "rgba(255, 159, 64, 1)";
                         lastLabelH = null;
                     }

                 }
             }, */
  layout: {
    padding: {
      top: 50,
      left: 0,
      right: 0,
      bottom: 0
    }
  },
  indexAxis: 'x',
  scales: {
    x: {
      beginAtZero: true,
      ticks: {
        display: true,
        color: 'rgba(255, 159, 64, 1)',

        autoSkip: false,
        maxRotation: 90,
        minRotation: 90,
        labelOffset: -8,
        textStrokeColor: 'rgba(0, 0, 0, 0.5)',
        textStrokeWidth: '2',
        font: {
          weight: 'bold',
          family: 'Arial',
          size: 16
        },
        align: 'start'
      }
    },
    y: {
      max: MAX + 1,
      beginAtZero: true,
      ticks: {
        color: 'rgba(255, 159, 64, 1)',
        stepSize: 1

      }
    }
  },

  plugins: {

    legend: {
      display: false

    },
    datalabels: {
      listeners: {
        enter: function(context) {
          // Receives `enter` events for any labels of any dataset. Indices of the
          // clicked label are: `context.datasetIndex` and `context.dataIndex`.
          // For example, we can modify keep track of the hovered state and
          // return `true` to update the label and re-render the chart.
          context.hovered = true;
          return true;
        },
        leave: function(context) {
          // Receives `leave` events for any labels of any dataset.
          context.hovered = false;
          return true;
        }
      },
      display: function(context) {
        return context.active; // display labels with an odd index
      },
      font: {
        size: '24px'
      },
      padding: '6',
      align: 'end',
      anchor: 'end',
      borderRadius: 4,
      backgroundColor: function(context) {
        return context.active ? context.dataset.hoverBackgroundColor : context.dataset.backgroundColor;
      },
      borderColor: function(context) {
        return context.dataset.borderColor;
      },
      borderWidth: 1,
      color: 'rgb(253, 225, 186)',
      textShadowBlur: 4,
      textShadowColor: 'rgb(0, 0, 0)',
      formatter: Math.round
    }
  }
}
});
 if (stat) {
 console.log(stat);
 $('#activate').click(function() {
  if (stat.getActiveElements().length > 0) {
    stat.setActiveElements([]);
  } else {
    stat.setActiveElements([{
      datasetIndex: 0,
      index: 2,
    }]);
    //stat.$datalabels._hovered = true;
    stat.$datalabels._datasets[0][1]._el.$context.active = true;
    stat.$datalabels._datasets[0][1].$context.active = true;
    stat.$datalabels._labels[1].$context.active = true;
    stat.$datalabels._labels[1]._el.active = true;
    stat.$datalabels._labels[1]._el.$context.active = true;

    stat.$datalabels._datasets[0][1].update(stat.$datalabels._datasets[0][1].$context);
    stat.$datalabels._labels[1].update(stat.$datalabels._labels[1].$context);
  }
  const tooltip = stat.tooltip;
  if (tooltip.getActiveElements().length > 0) {
    tooltip.setActiveElements([], {
      x: 0,
      y: 0
    });
  } else {
    const chartArea = stat.chartArea;
    tooltip.setActiveElements([{
      datasetIndex: 0,
      index: 2,
    }], {
      x: (chartArea.left + chartArea.right) / 2,
      y: (chartArea.top + chartArea.bottom) / 2,
    });
  }
  stat.update();

});
}
nfzehxib

nfzehxib1#

找到了一个解决方案我只是修改了数据标签的显示函数,集成了我的外部变量lastLabelH

var SCRIPTOBJ = null;
var LABEL = ["Gino", "Samantha", "Vercingetorige"];
var DATA = [5, 28, 500];
var MAX = Math.max(...DATA);

var ctx = $('#stat');

Chart.defaults.font.size = 14;
Chart.register(ChartDataLabels);

var lastLabelH = null;
var stat = new Chart(ctx, {
  type: 'bar',

  data: {
    labels: LABEL,
    datasets: [{
      minBarLength: 15,
      barPercentage: 1,
      label: '# USERS',
      data: DATA,
      backgroundColor: [
        'rgba(255, 99, 132, 0.5)',
        'rgba(54, 162, 235, 0.5)',
        'rgba(255, 206, 86, 0.5)',
        'rgba(75, 192, 192, 0.5)',
        'rgba(153, 102, 255, 0.5)',
        'rgba(255, 159, 64, 0.5)'
      ],
      borderColor: [
        'rgba(255, 99, 132, 1)',
        'rgba(54, 162, 235, 1)',
        'rgba(255, 206, 86, 1)',
        'rgba(75, 192, 192, 1)',
        'rgba(153, 102, 255, 1)',
        'rgba(255, 159, 64, 1)'
      ],
      hoverBackgroundColor: [
        'rgba(255, 99, 132, 1.0)',
        'rgba(54, 162, 235, 1.0)',
        'rgba(255, 206, 86, 1.0)',
        'rgba(75, 192, 192, 1.0)',
        'rgba(153, 102, 255, 1.0)',
        'rgba(255, 159, 64, 1.0)'
      ],
      borderWidth: 1
    }]
  },
  plugins: [{
    id: 'LabelHighlight',
    beforeEvent(c, args, pluginOptions) {
      const event = args.event;
      /* if (event.type === 'mouseout') {
          if (lastLabelH != null) {
              //c.scales.x._labelItems[lastLabelH].color = "rgba(255, 159, 64, 1)";
              c.update();
              lastLabelH = null;
          }
      } else */
      labelcolor(c);
    }
  }],
  options: {
    responsive: false,
    interaction: {
      mode: 'index',
      intersect: true
    },
    /*            onHover: function (event, elements, c) {
                   if (elements && elements.length) {
                       if (c._active.length > 0) {
                           let labelindex = c._active[0].index;
                           let label = c.scales.x._labelItems[labelindex];
                           label.color = "rgba(255, 255, 64, 1)";
                           lastLabelH = labelindex;
                       }
                   } else {
                       if (lastLabelH != null) {
                           c.scales.x._labelItems[lastLabelH].color = "rgba(255, 159, 64, 1)";
                           lastLabelH = null;
                       }

                   }
               }, */
    layout: {
      padding: {
        top: 50,
        left: 0,
        right: 0,
        bottom: 0
      }
    },
    indexAxis: 'x',
    scales: {
      x: {
        beginAtZero: true,
        ticks: {
          display: true,
          color: function(c) {
            return lastLabelH != null && c.index == lastLabelH ? "rgba(255, 255, 64, 1)" : "rgba(255, 159, 64, 1)";

          },

          autoSkip: false,
          maxRotation: 90,
          minRotation: 90,
          labelOffset: -8,
          textStrokeColor: 'rgba(0, 0, 0, 0.5)',
          textStrokeWidth: '2',
          font: {
            weight: 'bold',
            family: 'Arial',
            size: 16
          },
          align: 'start'
        }
      },
      y: {
        max: MAX + 1,
        beginAtZero: true,
        ticks: {
          color: 'rgba(255, 159, 64, 1)',
          stepSize: 1

        }
      }
    },

    plugins: {

      legend: {
        display: false

      },
      datalabels: {
        listeners: {
          enter: function(context) {
            // Receives `enter` events for any labels of any dataset. Indices of the
            // clicked label are: `context.datasetIndex` and `context.dataIndex`.
            // For example, we can modify keep track of the hovered state and
            // return `true` to update the label and re-render the chart.
            context.hovered = true;
            return true;
          },
          leave: function(context) {
            // Receives `leave` events for any labels of any dataset.
            context.hovered = false;
            return true;
          }
        },
        display: function(context) {
          return lastLabelH != null && context.dataIndex == lastLabelH || context.active;
        },
        font: {
          size: '24px'
        },
        padding: '6',
        align: 'end',
        anchor: 'end',
        borderRadius: 4,
        backgroundColor: function(context) {
          return context.active ? context.dataset.hoverBackgroundColor : context.dataset.backgroundColor;
        },
        borderColor: function(context) {
          return context.dataset.borderColor;
        },
        borderWidth: 1,
        color: 'rgb(253, 225, 186)',
        textShadowBlur: 4,
        textShadowColor: 'rgb(0, 0, 0)',
        formatter: Math.round
      }
    }
  }
});

function labelcolor(c) {
  if (c._active.length > 0) {
    let labelindex = c._active[0].index;
    if (c.scales.x._labelItems) {
      let label = c.scales.x._labelItems[labelindex];
      label.color = "rgba(255, 255, 64, 1)";
    }
    if (lastLabelH != null && lastLabelH != labelindex) {
      if (c.scales.x._labelItems) {
        c.scales.x._labelItems[lastLabelH].color = "rgba(255, 159, 64, 1)";

      }
    }

    lastLabelH = labelindex;

  } else {
    if (lastLabelH != null) {
      if (c.scales.x._labelItems) {
        c.scales.x._labelItems[lastLabelH].color = "rgba(255, 159, 64, 1)";
      }
      lastLabelH = null;
      c.update();
    }

  }

}
if (stat) {
  $('#activate').click(function() {
    if (stat.getActiveElements().length > 0) {
      stat.setActiveElements([]);
    } else {
      stat.setActiveElements([{
        datasetIndex: 0,
        index: 2,
      }]);
      labelcolor(stat);
    }
    const tooltip = stat.tooltip;
    if (tooltip.getActiveElements().length > 0) {
      tooltip.setActiveElements([], {
        x: 0,
        y: 0
      });
    } else {
      const chartArea = stat.chartArea;
      tooltip.setActiveElements([{
        datasetIndex: 0,
        index: 2,
      }], {
        x: (chartArea.left + chartArea.right) / 2,
        y: (chartArea.top + chartArea.bottom) / 2,
      });
    }
    stat.update();

  });
}
body {
  background-color: grey;
}

#stat {
  margin-top: auto;
}

#content {
  width: 300px;
  margin: auto;
}

;
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.5.0/chart.min.js"></script>
<div>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/chartjs-plugin-datalabels/2.0.0/chartjs-plugin-datalabels.min.js"></script>

  <div id="content">
    <canvas id="stat" width="300" height="300" style="margin-top:10px"></canvas>
    <input id="activate" type="button" value="Vergingetorige">
  </div>
</div>

不得不修改颜色函数,以便在设置null时更新lastLabelH,我还从外部触发器添加颜色标签
更新jsfiddle https://jsfiddle.net/netquik/e3jp2k5o/41/

相关问题