ChartJS Line Graph - Multiple Lines, Show one Value on Tooltip

前端 未结 1 1301
爱一瞬间的悲伤
爱一瞬间的悲伤 2020-12-31 15:32

I\'m trying to make a Graph which has to show the Account movement from each Customer.

What I\'m trying to do

I\'ve tree lines ; First line

相关标签:
1条回答
  • 2020-12-31 16:11

    To achieve this you can extend the line graph to add an option to show/hide tool-tips on a per dataset basses. The annoying thing is there are only a few changes but whole methods have to be overridden to get the changes in there so the below looks like a lot but its basically 3 changes to the following methods

    • Initialize - added option to store showTooltip option in each point

    • getPointsAtEvent - added check to make sure we want to disaply a tool tip when getting points

    • showTooltip - added check again to make sure we want to dispaly a tool tip

    to then use it the chart is set up the same but instead you make it a LineTooltip (thats what i have called the extended chart) and pass anextra option in the datasets call showToolip.

     datasets: [{
            label: "My First dataset",
            fillColor: "rgba(220,220,220,0.5)",
            strokeColor: "rgba(220,220,220,0.8)",
            highlightFill: "rgba(220,220,220,0.75)",
            highlightStroke: "rgba(220,220,220,1)",
            showTooltip: false, //NEW OPTION DON"T NEED TO INCLUDE IT IF YOU WANT TO DISPLAY BUT WON"T HURT IF YOU DO
            data: [15, 10, 10, 10, 10, 10, 10]
        }, {
            label: "My second dataset",
            fillColor: "rgba(220,220,220,0.5)",
            strokeColor: "rgba(220,220,220,0.8)",
            highlightFill: "rgba(220,220,220,0.75)",
            highlightStroke: "rgba(220,220,220,1)",
            showTooltip: false, //NEW OPTION DON"T NEED TO INCLUDE IT IF YOU WANT TO DISPLAY BUT WON"T HURT IF YOU DO
            data: [100, 100, 100, 100, 100, 100, 100]
        }, {
            label: "My third dataset",
            fillColor: "rgba(151,187,205,0.5)",
            strokeColor: "rgba(151,187,205,0.8)",
            highlightFill: "rgba(151,187,205,0.75)",
            highlightStroke: "rgba(151,187,205,1)",
            data: [28, 48, 40, 19, 86, 27, 90]
        }]
    

    i have added bigger comment banners in the below code to try and highlight where the changes got made. I have also added this feature to my fork of chartjs as this could be useful to more people https://github.com/leighquince/Chart.js, using this you can just use a normal line chart and add the showTooltip

    Below is the example of extending the Line into a custom chart to include this feature, ive called in LineTooltip as but could be called anything you like that.

    Chart.types.Line.extend({
    
      name: "LineTooltip",
      /*
       * we have to add one item in the init so need to rewrite it again here with the one edit
       */
      initialize: function(data) {
        //have to get the helpers as we are using this outside chart where it was declared
        var helpers = Chart.helpers;
        //Declare the extension of the default point, to cater for the options passed in to the constructor
        this.PointClass = Chart.Point.extend({
          strokeWidth: this.options.pointDotStrokeWidth,
          radius: this.options.pointDotRadius,
          display: this.options.pointDot,
          hitDetectionRadius: this.options.pointHitDetectionRadius,
          ctx: this.chart.ctx,
          inRange: function(mouseX) {
            return (Math.pow(mouseX - this.x, 2) < Math.pow(this.radius + this.hitDetectionRadius, 2));
          }
        });
    
        this.datasets = [];
    
        //Set up tooltip events on the chart
        if (this.options.showTooltips) {
          helpers.bindEvents(this, this.options.tooltipEvents, function(evt) {
            var activePoints = (evt.type !== 'mouseout') ? this.getPointsAtEvent(evt) : [];
            this.eachPoints(function(point) {
              point.restore(['fillColor', 'strokeColor']);
            });
            helpers.each(activePoints, function(activePoint) {
              activePoint.fillColor = activePoint.highlightFill;
              activePoint.strokeColor = activePoint.highlightStroke;
            });
            this.showTooltip(activePoints);
          });
        }
    
        //Iterate through each of the datasets, and build this into a property of the chart
        helpers.each(data.datasets, function(dataset) {
          var datasetObject = {
            label: dataset.label || null,
            fillColor: dataset.fillColor,
            strokeColor: dataset.strokeColor,
            pointColor: dataset.pointColor,
            pointStrokeColor: dataset.pointStrokeColor,
            showTooltip: dataset.showTooltip,
            points: []
          };
    
          this.datasets.push(datasetObject);
    
    
          helpers.each(dataset.data, function(dataPoint, index) {
            //Add a new point for each piece of data, passing any required data to draw.
            datasetObject.points.push(new this.PointClass({
    
              /*
               * set wether to show the tooltip or not, left this as being able to be undfined
               * and default to true
               */
              showTooltip: dataset.showTooltip === undefined ? true : dataset.showTooltip,
              value: dataPoint,
              label: data.labels[index],
              datasetLabel: dataset.label,
              strokeColor: dataset.pointStrokeColor,
              fillColor: dataset.pointColor,
              highlightFill: dataset.pointHighlightFill || dataset.pointColor,
              highlightStroke: dataset.pointHighlightStroke || dataset.pointStrokeColor
            }));
          }, this);
    
          this.buildScale(data.labels);
    
    
          this.eachPoints(function(point, index) {
            helpers.extend(point, {
              x: this.scale.calculateX(index),
              y: this.scale.endPoint
            });
            point.save();
          }, this);
    
        }, this);
    
    
        this.render();
      },
      /*
       * need to edit how points at event works so it only uses points that we want to show the tool tip for
       */
      getPointsAtEvent: function(e) {
        //have to get the helpers as we are using this outside chart where it was declared
        var helpers = Chart.helpers;
        var pointsArray = [],
          eventPosition = helpers.getRelativePosition(e);
        helpers.each(this.datasets, function(dataset) {
          helpers.each(dataset.points, function(point) {
            if (point.inRange(eventPosition.x, eventPosition.y) && point.showTooltip) pointsArray.push(point);
          });
        }, this);
        return pointsArray;
      },
      /*
       * also need to change how the core showTooltip functions as otherwise, it trys to be helpful
       * and grab any points it thinks also need to be displayed
       */
      showTooltip: function(ChartElements, forceRedraw) {
        //have to get the helpers as we are using this outside chart where it was declared
        var helpers = Chart.helpers;
        var each = helpers.each;
        var indexOf = helpers.indexOf;
        var min = helpers.min;
        var max = helpers.min;
        // Only redraw the chart if we've actually changed what we're hovering on.
        if (typeof this.activeElements === 'undefined') this.activeElements = [];
    
        var isChanged = (function(Elements) {
          var changed = false;
    
          if (Elements.length !== this.activeElements.length) {
            changed = true;
            return changed;
          }
    
          each(Elements, function(element, index) {
            if (element !== this.activeElements[index]) {
              changed = true;
            }
          }, this);
          return changed;
        }).call(this, ChartElements);
    
        if (!isChanged && !forceRedraw) {
          return;
        } else {
          this.activeElements = ChartElements;
        }
        this.draw();
        if (ChartElements.length > 0) {
          // If we have multiple datasets, show a MultiTooltip for all of the data points at that index
          if (this.datasets && this.datasets.length > 1) {
            var dataArray,
              dataIndex;
    
            for (var i = this.datasets.length - 1; i >= 0; i--) {
              dataArray = this.datasets[i].points || this.datasets[i].bars || this.datasets[i].segments;
              dataIndex = indexOf(dataArray, ChartElements[0]);
              if (dataIndex !== -1) {
                break;
              }
            }
            var tooltipLabels = [],
              tooltipColors = [],
              medianPosition = (function(index) {
    
                // Get all the points at that particular index
                var Elements = [],
                  dataCollection,
                  xPositions = [],
                  yPositions = [],
                  xMax,
                  yMax,
                  xMin,
                  yMin;
                helpers.each(this.datasets, function(dataset) {
                  dataCollection = dataset.points || dataset.bars || dataset.segments;
                  /*
                   *check to make sure we want to show the point
                   */
                  if (dataCollection[dataIndex] && dataCollection[dataIndex].hasValue() && (dataCollection[dataIndex].showTooltip === undefined || dataCollection[dataIndex].showTooltip)) {
                    Elements.push(dataCollection[dataIndex]);
                  }
                });
    
                helpers.each(Elements, function(element) {
                  xPositions.push(element.x);
                  yPositions.push(element.y);
    
    
                  //Include any colour information about the element
                  tooltipLabels.push(helpers.template(this.options.multiTooltipTemplate, element));
                  tooltipColors.push({
                    fill: element._saved.fillColor || element.fillColor,
                    stroke: element._saved.strokeColor || element.strokeColor
                  });
    
                }, this);
    
                yMin = min(yPositions);
                yMax = max(yPositions);
    
                xMin = min(xPositions);
                xMax = max(xPositions);
    
                return {
                  x: (xMin > this.chart.width / 2) ? xMin : xMax,
                  y: (yMin + yMax) / 2
                };
              }).call(this, dataIndex);
    
            new Chart.MultiTooltip({
              x: medianPosition.x,
              y: medianPosition.y,
              xPadding: this.options.tooltipXPadding,
              yPadding: this.options.tooltipYPadding,
              xOffset: this.options.tooltipXOffset,
              fillColor: this.options.tooltipFillColor,
              textColor: this.options.tooltipFontColor,
              fontFamily: this.options.tooltipFontFamily,
              fontStyle: this.options.tooltipFontStyle,
              fontSize: this.options.tooltipFontSize,
              titleTextColor: this.options.tooltipTitleFontColor,
              titleFontFamily: this.options.tooltipTitleFontFamily,
              titleFontStyle: this.options.tooltipTitleFontStyle,
              titleFontSize: this.options.tooltipTitleFontSize,
              cornerRadius: this.options.tooltipCornerRadius,
              labels: tooltipLabels,
              legendColors: tooltipColors,
              legendColorBackground: this.options.multiTooltipKeyBackground,
              title: ChartElements[0].label,
              chart: this.chart,
              ctx: this.chart.ctx
            }).draw();
    
          } else {
            each(ChartElements, function(Element) {
              var tooltipPosition = Element.tooltipPosition();
              new Chart.Tooltip({
                x: Math.round(tooltipPosition.x),
                y: Math.round(tooltipPosition.y),
                xPadding: this.options.tooltipXPadding,
                yPadding: this.options.tooltipYPadding,
                fillColor: this.options.tooltipFillColor,
                textColor: this.options.tooltipFontColor,
                fontFamily: this.options.tooltipFontFamily,
                fontStyle: this.options.tooltipFontStyle,
                fontSize: this.options.tooltipFontSize,
                caretHeight: this.options.tooltipCaretSize,
                cornerRadius: this.options.tooltipCornerRadius,
                text: template(this.options.tooltipTemplate, Element),
                chart: this.chart
              }).draw();
            }, this);
          }
        }
        return this;
      },
    
    });
    
    
    
    
    var ctx = document.getElementById("chart").getContext("2d");
    var data = {
      labels: ["January", "February", "March", "April", "May", "June", "July"],
      datasets: [{
        label: "My First dataset",
        fillColor: "rgba(220,220,220,0.5)",
        strokeColor: "rgba(220,220,220,0.8)",
        highlightFill: "rgba(220,220,220,0.75)",
        highlightStroke: "rgba(220,220,220,1)",
        showTooltip: false, //TO USE JUST ADD THIS NEW OPTION ONLY REALLY NEEDS TO PRESENT IF SETTING TO FALSE
        data: [15, 10, 10, 10, 10, 10, 10]
      }, {
        label: "My second dataset",
        fillColor: "rgba(220,220,220,0.5)",
        strokeColor: "rgba(220,220,220,0.8)",
        highlightFill: "rgba(220,220,220,0.75)",
        highlightStroke: "rgba(220,220,220,1)",
        showTooltip: false, //TO USE JUST ADD THIS NEW OPTION ONLY REALLY NEEDS TO PRESENT IF SETTING TO FALSE
        data: [100, 100, 100, 100, 100, 100, 100]
      }, {
        label: "My third dataset",
        fillColor: "rgba(151,187,205,0.5)",
        strokeColor: "rgba(151,187,205,0.8)",
        highlightFill: "rgba(151,187,205,0.75)",
        highlightStroke: "rgba(151,187,205,1)",
        data: [28, 48, 40, 19, 86, 27, 90]
      }]
    };
    
    
    var myBarChart = new Chart(ctx).LineTooltip(data);
    <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/1.0.2/Chart.min.js"></script>
    <canvas id="chart" width="600px"></canvas>

    and a fiddle if you find that easy to view http://jsfiddle.net/leighking2/1Lammwpt/

    0 讨论(0)
提交回复
热议问题