Pregunta

I'm writing a Google Chart. It has stacked columns. On top of that I want to draw 2 lines, which indicate min and max allowed value.

enter image description here

The only solution I came up with, was modifying the first example of ComboCharts. My result looks like this:

enter image description here

Which isn't sufficient. The graph is variable, so if there's only 1 Quartal shown, the line will solely be a dot. My Questions are:

  • Is there a way to draw the line further, so it hits the left and right boundary of the Graph?
  • Can I draw markup lines into the graph, without pretending it's another datapoint?

You can fiddle with a ComboChart here if you want.

¿Fue útil?

Solución

You can't get the lines to go edge-to-edge with a discrete (string-based) x-axis. If you switch to a continuous (number, date, datetime, timeofday) axis, then you can add one row before your real data and one row after that contain the goal lines (and nulls for the other data series):

function drawChart() {
    var data = new google.visualization.DataTable();
    data.addColumn('number', 'Quarter');
    data.addColumn('number', 'Value 1');
    data.addColumn('number', 'Value 2');
    data.addColumn('number', 'Value 3');
    data.addColumn('number', 'Goal 1');
    data.addColumn('number', 'Goal 2');
    data.addRows([
        [0, null, null, null, 10, 14],
        [1, 5, 4, 7, null, null],
        [2, 6, 9, 6, null, null],
        [3, 2, 6, 4, null, null],
        [4, 3, 6, 4, null, null],
        [5, null, null, null, 10, 14]
    ]);
    
    var chart = new google.visualization.ComboChart(document.querySelector('#chart_div'));
    chart.draw(data, {
        height: 400,
        width: 600,
        isStacked: true,
        legend: {
            position: 'top'
        },
        seriesType: 'bars',
        interpolateNulls: true,
        series: {
            3: {
                type: 'line'
            },
            4: {
                type: 'line'
            }
        },
        hAxis: {
            format: 'Q#',
            ticks: [1, 2, 3, 4],
            viewWindow: {
                min: 0.5,
                max: 4.5
            }
        },
        chartArea: {
            left: '10%',
            width: '80%'
        }
    });
}
google.load('visualization', '1', {packages:['corechart'], callback: drawChart});

See working example: http://jsfiddle.net/asgallant/W67qU/

Here is some explanation of what is going on (edit on Nov 24, 2022 by Jorr.it): At the top and bottom of the DataTable there are extra rows added with the goals only. With the hAxis.viewWindow option the two new goal dots are just cut off the chart, but resulting in a full line over the whole width of the chart. Finally option "interpolateNulls" needs to be set to connect the two invisible dots "over" the null values in the bar rows.

Otros consejos

Maybe a bit late but I faced the same issue. I was trying to set max and min lines into a line chart with a lot of data points in the serie and I wanted to avoid adding new series with a lot of repeated points so I used overlays ( https://developers.google.com/chart/interactive/docs/overlays#javascript2 ).

Here are an example, It's just a draft in which I'm working now but maybe can help:

<html>
  <head>
    <script
      type="text/javascript"
      src="https://www.gstatic.com/charts/loader.js"
    ></script>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.0/jquery.min.js"></script>
    <style>
      #container {
        position: relative;
        width: 900px;
        height: 500px;
      }
      .min-bar {
        height: 1px;
        background-color: red;
        position: absolute;
        left: 0;
        right: 0;
      }
    </style>
    <script type="text/javascript">
      $(function() {
        $.get(
          "https://firebasestorage.googleapis.com/v0/b/manasav-pricetracker.appspot.com/o/products%2F-L6O-CtBKZAc2NTCFq7Z.data?alt=media&token=60e06bb6-59b7-41a9-8fd0-f82f4ddc75f2",
          function(data) {
            google.charts.load("current", { packages: ["corechart"] });
            google.charts.setOnLoadCallback(drawChart);

            var downloadedData = JSON.parse("[" + data);

            function drawChart() {
              var dataTable = [["Time", "New"]];
              let min = Number.MAX_VALUE;

              let rowMin;
              for (var i in downloadedData) {
                var d = downloadedData[i];
                if (d.new < min) {
                  rowMin = i;
                  min = d.new;
                }
                dataTable.push([new Date(d.date), d.new]);
              }

              var data = google.visualization.arrayToDataTable(dataTable);

              var options = {
                title: "Price evolution",
                legend: { position: "bottom" },
                trendlines: { 0: {} }
              };

              var chart = new google.visualization.LineChart(
                document.getElementById("curve_chart")
              );

              function placeMarker(dataTable) {
                var cli = this.getChartLayoutInterface();
                var chartArea = cli.getChartAreaBoundingBox();
                document.querySelector(".min-bar").style.top =
                  Math.floor(cli.getYLocation(min)) + "px";

                document.querySelector(".min-bar").style.left =
                  Math.floor(cli.getXLocation(dataTable.getValue(0,0))) - 25 + "px";

                  document.querySelector(".min-bar").style.right =
                  (document.querySelector("#container").offsetWidth - Math.floor(cli.getXLocation(dataTable.getValue(dataTable.getNumberOfRows()-1,0)))) - 25 + "px";
                // document.querySelector(".min-bar").style.top =
                // Math.floor(cli.getXLocation(dataTable.getValue(rowMin, 1))) +
                // "px";
              }
              google.visualization.events.addListener(
                chart,
                "ready",
                placeMarker.bind(chart, data)
              );
              chart.draw(data, options);
            }
          }
        );
      });
    </script>
  </head>
  <body>
    <div id="container">
      <div id="curve_chart" style="width: 900px; height: 500px"></div>
      <div class="min-bar"></div>
    </div>
  </body>
</html>

Jsfiddle demo => https://jsfiddle.net/jRubia/8z7ao1nh/

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top