我怎样才能用 Google 图表 API 绘制两个 material 图表而不是空的?

How can I draw two material charts with the Google Charts API without one being empty?

我正在尝试使用 Google 图表 API 绘制两个图表。我这样设置 HTML:

<div id="page_views" data-title="{{ report['page_views']['title'] }}" data-labels="{{ report['page_views']['labels'] }}" data-rows="{{ report['page_views']['rows'] }}"></div>
<div id="event_views" data-title="{{ report['event_views']['title'] }}" data-labels="{{ report['event_views']['labels'] }}" data-rows="{{ report['event_views']['rows'] }}"></div>

模板渲染时填充数据属性的地方。然后我使用以下 javascript 尝试绘制图表:

google.load('visualization', '1.0', {packages: ['line']});
google.setOnLoadCallback(drawCharts);

function drawPageViews() {
    var data = new google.visualization.DataTable();
    var page_views = document.getElementById("page_views");
    var labels = eval(page_views.dataset.labels);
    data.addColumn('number', "Day");
    for(var i = 0; i < labels.length; i++) {
        data.addColumn('number', labels[i]);
    }

    var rows = eval(page_views.dataset.rows);
    data.addRows(rows);

    var options = {
        chart: {
            title: page_views.dataset.title
        },
        width: 900,
        height: 500
    };

    var chart = new google.charts.Line(document.getElementById('page_views'));
    chart.draw(data, options);
}

function drawEventViews() {
    var data = new google.visualization.DataTable();
    var event_views = document.getElementById("event_views");
    var labels = eval(event_views.dataset.labels);
    data.addColumn('number', "Day");
    for(var i = 0; i < labels.length; i++) {
        data.addColumn('number', labels[i]);
    }

    var rows = eval(event_views.dataset.rows);
    data.addRows(rows);

    var options = {
        chart: {
            title: event_views.dataset.title
        },
        width: 900,
        height: 500
    };

    var chart = new google.charts.Line(document.getElementById('event_views'));
    chart.draw(data, options);
}

function drawCharts() {
    drawPageViews();
    drawEventViews();
}

我得到的结果是绘制了其中一张图表,而另一张图表包含一个带有空标签且没有其他内容的 SVG。绘制哪个图表是随机的。注释掉任一绘图函数会使另一个图表按预期绘制。

似乎必须有某种共享的全局状态或变量,但在我看来,一切都在不同的绘图函数中定义。当我查找类似的问题时,人们提供的解决方案看起来与我正在做的非常相似。我错过了什么?

似乎此行为与 draw 功能有关,特别是在页面上呈现多个图表时会发生这种情况。

根据the documentation

The draw() method is asynchronous: that is, it returns immediately, but the instance that it returns might not be immediately available.

要在页面上呈现多个图表,您可以考虑采用以下方法:在呈现前一个图表后呈现下一个图表,这就是 ready 事件的救星。

话虽如此,解决方案是替换:

function drawCharts() {
  drawPageViews();
  drawEventViews();
}

function drawCharts() {
    drawPageViews(function(){
       drawEventViews();
    });
}

哪里

function drawPageViews(chartReady) {
    //...
    var chart = new google.charts.Line(document.getElementById('page_views'));
    if (typeof chartReady !== 'undefined') google.visualization.events.addOneTimeListener(chart, 'ready', chartReady);
    chart.draw(data, options);
}

function drawEventViews(chartReady) {
    //...
    var chart = new google.charts.Line(document.getElementById('event_views'));
    if (typeof chartReady !== 'undefined') google.visualization.events.addOneTimeListener(chart, 'ready', chartReady);
    chart.draw(data, options);
}

工作示例

google.load('visualization', '1.0', { packages: ['line'] });
google.setOnLoadCallback(drawCharts);

function drawPageViews(chartReady) {
    var data = new google.visualization.DataTable();
    var page_views = document.getElementById("page_views");
    var labels = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];

    data.addColumn('string', 'Day');
    data.addColumn('number', 'PageViews');

   
    var rows = new Array();
    for (var i = 0; i < labels.length; i++) {
        rows.push([labels[i], getRandomInt(0, 100)]);
    }
    data.addRows(rows);


    var options = {
        chart: {
            title: 'Page views'
        },
        width: 900,
        height: 500
    };

    var chart = new google.charts.Line(document.getElementById('page_views'));
    if(typeof chartReady !== 'undefined') google.visualization.events.addOneTimeListener(chart, 'ready', chartReady);
    chart.draw(data, options);
}

function drawEventViews(chartReady) {
    var data = new google.visualization.DataTable();
    var event_views = document.getElementById("event_views");
   
    var labels = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];

    data.addColumn('string', 'Day');
    data.addColumn('number', 'EventViews');
    var rows = new Array();
    for (var i = 0; i < labels.length; i++) {
        rows.push([labels[i], getRandomInt(0, 100)]);
    }
    data.addRows(rows);

    var options = {
        chart: {
            title: 'Event views'
        },
        width: 900,
        height: 500
    };

    var chart = new google.charts.Line(document.getElementById('event_views'));
    if(typeof chartReady !== 'undefined') google.visualization.events.addOneTimeListener(chart, 'ready', chartReady);
    chart.draw(data, options);
}

function drawCharts() {
    drawPageViews(function(){
        drawEventViews();
    });
}


function getRandomInt(min, max) {
    return Math.floor(Math.random() * (max - min + 1)) + min;
}
<script type="text/javascript" src="https://www.google.com/jsapi"></script> 
<div id="page_views"></div>
<div id="event_views"></div>