apertureless / vue-chartjs

📊 Vue.js wrapper for Chart.js
https://vue-chartjs.org
MIT License
5.55k stars 837 forks source link

Custom tooltips (not tooltip callback) stretching the graph? #451

Closed dmrickey closed 5 years ago

dmrickey commented 5 years ago

Expected Behavior

https://www.chartjs.org/samples/latest/tooltips/custom-line.html https://github.com/chartjs/Chart.js/blob/master/samples/tooltips/custom-line.html

Actual Behavior

I'm trying to get the example to work. I've copied the source in and stepped through it and I can see the html is correct, but I'm getting lost at what I'm seeing on the screen. When I hover over the tooltip, it gets stuck in a loop and the graph expands vertically until closed. I've copied the source from the example (also linked above).

const { reactiveProp } = mixins;

export default {
  extends: Line,
  mixins: [reactiveProp],
  props: {
    options: {
      type: Object,
      default: () => {},
    },
  },
  watch: {
    chartData() {
      if(this._chart) {
        this._chart.update();
      }
    },
  },
  data() {
    return {
      tooltips: {
        enabled: false,
        mode: 'index',
        position: 'nearest',
        custom: this.customTooltips,
      },
    };
  },
  methods: {
    customTooltips(tooltip) {
    // Tooltip Element
      let tooltipEl = document.getElementById('chartjs-tooltip');

      if(!tooltipEl) {
        tooltipEl = document.createElement('div');
        tooltipEl.id = 'chartjs-tooltip';
        tooltipEl.innerHTML = '<table></table>';
        this._chart.canvas.parentNode.appendChild(tooltipEl);
      }

      // Hide if no tooltip
      if(tooltip.opacity === 0) {
        tooltipEl.style.opacity = 0;
        return;
      }

      // Set caret Position
      tooltipEl.classList.remove('above', 'below', 'no-transform');
      if(tooltip.yAlign) {
        tooltipEl.classList.add(tooltip.yAlign);
      }
      else {
        tooltipEl.classList.add('no-transform');
      }
      function getBody(bodyItem) {
        return bodyItem.lines;
      }

      // Set Text
      if(tooltip.body) {
        const titleLines = tooltip.title || [];
        const bodyLines = tooltip.body.map(getBody);
        let innerHtml = '<thead>';

        titleLines.forEach(function(title) {
          innerHtml += '<tr><th>' + title + '</th></tr>';
        });
        innerHtml += '</thead><tbody>';
        bodyLines.forEach(function(body, i) {
          const colors = tooltip.labelColors[i];
          let style = 'background:' + colors.backgroundColor;

          style += '; border-color:' + colors.borderColor;
          style += '; border-width: 2px';
          const span = '<span class="chartjs-tooltip-key" style="' + style + '"></span>';

          innerHtml += '<tr><td>' + span + body + '</td></tr>';
        });
        innerHtml += '</tbody>';
        const tableRoot = tooltipEl.querySelector('table');

        tableRoot.innerHTML = innerHtml;
      }
      const positionY = this._chart.canvas.offsetTop;
      const positionX = this._chart.canvas.offsetLeft;

      // Display, position, and set styles for font

      tooltipEl.style.opacity = 1;
      tooltipEl.style.left = positionX + tooltip.caretX + 'px';
      tooltipEl.style.top = positionY + tooltip.caretY + 'px';
      tooltipEl.style.fontFamily = tooltip._bodyFontFamily;
      tooltipEl.style.fontSize = tooltip.bodyFontSize + 'px';
      tooltipEl.style.fontStyle = tooltip._bodyFontStyle;
      tooltipEl.style.padding = tooltip.yPadding + 'px ' + tooltip.xPadding + 'px';
    },
  },
  mounted() {
    this.renderChart(this.chartData, Object.assign(this.options, { tooltips: this.tooltips }));
  },
};

the options being passed in

    responsive: true,
    maintainAspectRatio: false,
    scales: {
        xAxes: [{
            type: 'time',
            distribution: 'linear',
        }, ],

        yAxes: [{
                id: 'd1',
                fill: false,
                type: 'linear',
                position: 'left',
                ticks: {
                    beginAtZero: false,
                    reverse: true,
                },
            },
            {
                id: 'd2',
                fill: false,
                type: 'linear',
                position: 'right',
                ticks: {
                    reverse: true,
                },
            },
        ],
    },
}

(above stuff was copied from code, and is objects defined in js (so quotes for properties), below was copied from copy(this.chartData.datasets) in the chrome debugger so is json (hence quotes for properties). Some sample datasets

[
  {
    "data": [
      {
        "x": "2018-11-13T14:00:46.000Z",
        "y": 283,
      },
      {
        "x": "2018-11-15T12:58:39.000Z",
        "y": 214,
      },
      {
        "x": "2018-11-16T14:41:00.000Z",
        "y": 226,
      },
      {
        "x": "2018-11-18T08:04:19.000Z",
        "y": 179,
      },
      {
        "x": "2018-11-19T17:22:10.000Z",
        "y": 163,
      },
      {
        "x": "2018-11-21T05:19:36.000Z",
        "y": 116,
      },
      {
        "x": "2018-11-27T15:41:32.000Z",
        "y": 249,
      },
      {
        "x": "2018-11-29T10:44:59.000Z",
        "y": 119,
      },
      {
        "x": "2018-11-29T12:26:10.000Z",
        "y": 132,
      }
    ],
    "label": "d1",
    "yAxisID": "d1",
    "fill": false,
    "borderColor": "#1298d5"
  },
  {
    "data": [
      {
        "x": "2018-11-14T01:00:00.000Z",
        "y": 66215.35
      },
      {
        "x": "2018-11-15T01:00:00.000Z",
        "y": 93667.33
      },
      {
        "x": "2018-11-16T01:00:00.000Z",
        "y": 37665
      },
      {
        "x": "2018-11-17T01:00:00.000Z",
        "y": 43149.13
      },
      {
        "x": "2018-11-18T01:00:00.000Z",
        "y": 38815.7
      },
      {
        "x": "2018-11-19T01:00:00.000Z",
        "y": 74280.07
      },
      {
        "x": "2018-11-20T01:00:00.000Z",
        "y": 104979.6
      },
      {
        "x": "2018-11-21T01:00:00.000Z",
        "y": 121957.47
      },
      {
        "x": "2018-11-22T01:00:00.000Z",
        "y": 60269.31
      },
      {
        "x": "2018-11-23T01:00:00.000Z",
        "y": 53361.19
      },
      {
        "x": "2018-11-24T01:00:00.000Z",
        "y": 77262.13
      },
      {
        "x": "2018-11-25T01:00:00.000Z",
        "y": 93664.47
      },
      {
        "x": "2018-11-26T01:00:00.000Z",
        "y": 36363.44
      },
      {
        "x": "2018-11-27T01:00:00.000Z",
        "y": 57041.14
      },
      {
        "x": "2018-11-28T01:00:00.000Z",
        "y": 34981.18
      }
    ],
    "label": "d2",
    "yAxisID": "d2",
    "fill": false,
    "borderColor": "#901245",
    "hidden": true
  }
]

Environment

dmrickey commented 5 years ago

Simple mistake. I didn't take into account the styling. What apparently was happening was the div (the tooltip) was being added to the bottom. Though I'm not sure why it was stretching repeatedly instead of once since I couldn't get to the bottom once it started happening. But once I added in the css from the example for the tooltip it worked as expected.