Динамическая вертикальная ось для размещения линий тренда в линейной диаграмме Google - PullRequest
2 голосов
/ 04 ноября 2019

Я новичок в кодировании, но за последние несколько месяцев мне удалось найти свой путь через создание веб-сайта, который использует линейную диаграмму Google и встроенную линейную линию тренда для отображения исторического среднего уровня моря и скорости среднего моряПовышение уровня в различных местах вокруг Новой Зеландии и Тихого океана. Каждое местоположение имеет свою собственную линейную диаграмму Google с линейной линией тренда, чтобы показать скорость изменения среднего уровня моря за выбранный пользователем период. Теперь я хочу расширить функциональность каждой линейной диаграммы Google, чтобы линейная и полиномиальная трендовая линия доходила до 2120 года (в настоящее время они отображаются только до 2018 года), хотя имеющиеся данные, на основе которых они рассчитаны, используют данные наблюдений вверх. до 2018 года. Это позволит пользователю прогнозировать высоту уровня моря до 2020 года. Я понимаю, что это объяснение может сбивать с толку, поэтому, пожалуйста, посетите мой веб-сайт www.sealevel.nz, чтобы увидеть существующие графики, которые, я надеюсь,помощь в понимании моей проблемы.

Ниже приведен код для расширенной версии диаграммы, которая показывает линию тренда как полинома линейной, так и второй степени с осью х диаграммы Google Line, теперь показывающей 2120 год. проблема заключается в том, что мне нужно, чтобы ось у динамически корректировалась, чтобы показать совокупность обеих линий тренда независимо от того, какой период времени выбрал пользователь. Например, если выбрать ползунок диапазона дат 1971 и 2018 гг., То обе линии тренда будут отрезаны в 2017 г. (линейный) и 2031 (полиномиальный) соответственно. Мне нужно иметь возможность видеть обе линии тренда и их значения до 2120 года.

Пожалуйста, извините за мои навыки начинающего программиста. Мой код:

<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
<script src="https://unpkg.com/mathjs/dist/math.min.js"></script>
<script type="text/javascript">

google.load('visualization', 'current', {'packages':['controls','corechart']});
google.setOnLoadCallback(initialize);
function initialize() {
  var query = new google.visualization.Query('https://docs.google.com/spreadsheets/d/1vn1iuhsG33XzFrC4QwkTdUnxOGdcPQOj-cuaEZeX-eA/edit#gid=0');
  query.send(drawDashboard);
}
function drawDashboard(response) {
  var data = response.getDataTable();
//Asign units of 'mm' to data.
    var formatMS = new google.visualization.NumberFormat({
    pattern: '# mm'
  });
  // format into data mm..
  for (var colIndex = 1; colIndex < data.getNumberOfColumns(); colIndex++) {
    formatMS.format(data, colIndex);
  }
 var YearPicker = new google.visualization.ControlWrapper({
    'controlType': 'NumberRangeFilter',
    'containerId': 'filter_div',
    'options': {
      'filterColumnLabel': 'Year',
        'ui': {
       cssClass: 'filter-date',
          'format': { pattern: '0000' },
      'labelStacking': 'vertical',
      'allowTyping': false,
      'allowMultiple': false    
      }
    },
  });
  var MSLChart = new google.visualization.ChartWrapper({
    'chartType': 'LineChart',
    'containerId': 'chart_div',
    'options': {  
    'fontSize': '14', 
    'title': 'Timbucktoo Annual Mean Sea Level Summary',
        hAxis: {title: 'Year', format:'0000', maxValue: 2120},
        vAxis: {title: 'Height above Chart Datum (mm)', format:'0000'},
        'height': 600,
    chartArea: {height: '81%', width: '85%', left: 100},
    'legend': {'position': 'in', 'alignment':'end', textStyle: {fontSize: 13} },
    colors: ['blue'],
    trendlines: {
            0: {
                type: 'polynomial',
                degree: 2,
                color: 'green',
                visibleInLegend: true,
            },
            1: {
                type: 'linear',
                color: 'black',
                visibleInLegend: true,
            },
        },
        series: {
            0: { visibleInLegend: true },
            1: { visibleInLegend: false },
        },    
    },
    'view': {'columns': [0,1,2]}
  });

  var dashboard = new google.visualization.Dashboard(document.getElementById('dashboard_div')).
    bind(YearPicker, MSLChart).

  draw(data)
 </script>

1 Ответ

2 голосов
/ 04 ноября 2019

Во-первых, я не уверен, почему на графике будет нарисована линия тренда, которая не видна
, что делает это немного сложным, потому что сначала мы должны нарисовать график
, чтобы найтиминимальное и максимальное значения по оси Y.

но есть диаграммы методы , которые мы можем использовать, чтобы найти максимальное значение.

сначала мы получаем интерфейс макета диаграммы.

var chartLayout = MSLChart.getChart().getChartLayoutInterface();

, поскольку мы используем ChartWrapper, мы должны получить диаграмму из оболочки (MSLChart.getChart()).

Далее мы используем метод getBoundingBox, чтобы найти минимальное и максимальное значения каждой строки.

var yAxisCoords = {min: null, max: null};
var lineIndex = 0;
var boundsLine = chartLayout.getBoundingBox('line#' + lineIndex);
do {
  yAxisCoords.max = yAxisCoords.max || boundsLine.top;
  yAxisCoords.max = Math.min(yAxisCoords.max, boundsLine.top);
  yAxisCoords.min = yAxisCoords.min || (boundsLine.top + boundsLine.height);
  yAxisCoords.min = Math.max(yAxisCoords.min, (boundsLine.top + boundsLine.height));
  lineIndex++;
  boundsLine = chartLayout.getBoundingBox('line#' + lineIndex);
} while (boundsLine !== null);

, затем мы используем метод getVAxisValue, чтобы определить, каким должно быть каждое значение по оси Y,
, установите viewWindow по оси Y, и заново нарисуйте диаграмму.

MSLChart.setOption('vAxis.viewWindow.max', chartLayout.getVAxisValue(yAxisCoords.max));
MSLChart.setOption('vAxis.viewWindow.min', chartLayout.getVAxisValue(yAxisCoords.min));
MSLChart.draw();

мы делаем все это в функции.
мы используем одноразовое событие 'ready' в оболочке диаграммы для первого вычисления.
затем снова на диаграмме.

google.visualization.events.addOneTimeListener(MSLChart, 'ready', filterChange);

function filterChange() {
  // get chart layout
  var chartLayout = MSLChart.getChart().getChartLayoutInterface();

  // get y-axis bounds
  var yAxisCoords = {min: null, max: null};
  var lineIndex = 0;
  var boundsLine = chartLayout.getBoundingBox('line#' + lineIndex);
  do {
    yAxisCoords.max = yAxisCoords.max || boundsLine.top;
    yAxisCoords.max = Math.min(yAxisCoords.max, boundsLine.top);
    yAxisCoords.min = yAxisCoords.min || (boundsLine.top + boundsLine.height);
    yAxisCoords.min = Math.max(yAxisCoords.min, (boundsLine.top + boundsLine.height));
    lineIndex++;
    boundsLine = chartLayout.getBoundingBox('line#' + lineIndex);
  } while (boundsLine !== null);

  // re-draw chart
  MSLChart.setOption('vAxis.viewWindow.max', chartLayout.getVAxisValue(yAxisCoords.max));
  MSLChart.setOption('vAxis.viewWindow.min', chartLayout.getVAxisValue(yAxisCoords.min));
  MSLChart.draw();
  google.visualization.events.addOneTimeListener(MSLChart.getChart(), 'ready', filterChange);
}

см. Следующий рабочий фрагмент ...
(при запуске фрагмента нажмите «полная страница» в правом верхнем углу)

google.charts.load('current', {
  packages: ['controls']
}).then(initialize);

function initialize() {
  var query = new google.visualization.Query('https://docs.google.com/spreadsheets/d/1vn1iuhsG33XzFrC4QwkTdUnxOGdcPQOj-cuaEZeX-eA/edit#gid=0');
  query.send(drawDashboard);
}

function drawDashboard(response) {
  var data = response.getDataTable();

  //Asign units of 'mm' to data.
  var formatMS = new google.visualization.NumberFormat({
    pattern: '# mm'
  });

  // format into data mm..
  for (var colIndex = 1; colIndex < data.getNumberOfColumns(); colIndex++) {
    formatMS.format(data, colIndex);
  }

  var YearPicker = new google.visualization.ControlWrapper({
    controlType: 'NumberRangeFilter',
    containerId: 'filter_div',
    options: {
      filterColumnLabel: 'Year',
      ui: {
        cssClass: 'filter-date',
        format: {pattern: '0000'},
        labelStacking: 'vertical',
        allowTyping: false,
        allowMultiple: false
      }
    },
  });

  var MSLChart = new google.visualization.ChartWrapper({
    chartType: 'LineChart',
    containerId: 'chart_div',
    dataTable: data,
    options: {
      fontSize: '14',
      title: 'Timbucktoo Annual Mean Sea Level Summary',
      hAxis: {title: 'Year', format: '0000', maxValue: 2120},
      vAxis: {title: 'Height above Chart Datum (mm)', format:'###0'},
      height: 600,
      chartArea: {height: '81%', width: '85%', left: 100},
      legend: {position: 'in', alignment: 'end', textStyle: {fontSize: 13}},
      colors: ['blue'],
      trendlines: {
        0: {
          type: 'polynomial',
          degree: 2,
          color: 'green',
          visibleInLegend: true,
        },
        1: {
          type: 'linear',
          color: 'black',
          visibleInLegend: true,
        },
      },
      series: {
        0: { visibleInLegend: true },
        1: { visibleInLegend: false },
      },
    },
    view: {columns: [0,1,2]}
  });

  google.visualization.events.addOneTimeListener(MSLChart, 'ready', filterChange);

  function filterChange() {
    // get chart layout
    var chartLayout = MSLChart.getChart().getChartLayoutInterface();

    // get y-axis bounds
    var yAxisCoords = {min: null, max: null};
    var lineIndex = 0;
    var boundsLine = chartLayout.getBoundingBox('line#' + lineIndex);
    do {
      yAxisCoords.max = yAxisCoords.max || boundsLine.top;
      yAxisCoords.max = Math.min(yAxisCoords.max, boundsLine.top);
      yAxisCoords.min = yAxisCoords.min || (boundsLine.top + boundsLine.height);
      yAxisCoords.min = Math.max(yAxisCoords.min, (boundsLine.top + boundsLine.height));
      lineIndex++;
      boundsLine = chartLayout.getBoundingBox('line#' + lineIndex);
    } while (boundsLine !== null);

    // re-draw chart
    MSLChart.setOption('vAxis.viewWindow.max', chartLayout.getVAxisValue(yAxisCoords.max));
    MSLChart.setOption('vAxis.viewWindow.min', chartLayout.getVAxisValue(yAxisCoords.min));
    MSLChart.draw();
    google.visualization.events.addOneTimeListener(MSLChart.getChart(), 'ready', filterChange);
  }

  var dashboard = new google.visualization.Dashboard(
    document.getElementById('dashboard_div')
  ).bind(YearPicker, MSLChart).draw(data);
}
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="dashboard_div">
  <div id="chart_div"></div>
  <div id="filter_div"></div>
</div>

примечание: похоже, вы используете старый оператор load для загрузки диаграммы Google.
см. Приведенный выше фрагмент для обновления. ..

...