How to fix overlapping Google Chart legend

2020-04-12 09:56发布

问题:

This has been something I've been working on for hours now and I can't seem to find a solution that works. I have a page (ASP.NET Core) that has bootstrap tabs on it. Each tab displays a different chart. I've read various answers and tried so many different things from this and other sites but I'm sure what I'm doing wrong.

This is a proof of concept page I'm making and from what I understand I need to stall the loading of the chart until the nav-tab is selected. That is what I am unsure of how to do.

My View:

<html>
<head>
<link rel="stylesheet" href="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" />
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script type="text/javascript" src="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>


<!--Load the AJAX API-->
<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>

@Html.Partial("~/Views/Shared/Chart_ByMonth.cshtml")
@Html.Partial("~/Views/Shared/Chart_ByMonthAndQuarter.cshtml")
@Html.Partial("~/Views/Shared/Chart_ByLeaseAdmin.cshtml")
@Html.Partial("~/Views/Shared/Chart_Fourth.cshtml")

<script type="text/javascript">
    // Load the Visualization API and the corechart package.
    google.charts.load('current', {'packages':['corechart']});

    // Set a callback to run when the Google Visualization API is loaded.
    google.charts.setOnLoadCallback(drawMonthChart);
    google.charts.setOnLoadCallback(drawMonthAndQuarterChart);
    google.charts.setOnLoadCallback(drawLeaseAdminChart);
    google.charts.setOnLoadCallback(drawFourthChart);
</script>

<body>
<ul class="nav nav-tabs" id="tabs">
        <li class="active" id="tab_1"><a data-toggle="tab" href="#home">By Month</a></li>
        <li id="tab_2"><a data-toggle="tab" href="#menu1">By Month & Quarter</a></li>
        <li id="tab_3"><a data-toggle="tab" href="#menu2">By Lease Admin</a></li>
        <li id="tab_4"><a data-toggle="tab" href="#menu3">Fourth Chart</a></li>
    </ul>
    <div class="tab-content">
        <div id="home" class="tab-pane fade in active">
            <h3>By Month</h3>
            <select>
                <option selected>January</option>
                <option>February</option>
                <option>March</option>
                <option>April</option>
                <option>May</option>
                <option>June</option>
                <option>July</option>
                <option>August</option>
                <option>September</option>
                <option>October</option>
                <option>November</option>
                <option>December</option>
            </select>
            <select>
                <option>2016</option>
                <option>2017</option>
            </select>
            <button type="submit" class="btn btn-success">Submit</button>
            <div id="chart_month_div" style="padding-top: 20px;"></div>
        </div>
.....
</div>
</body>

The partial view for that chart is just hard-coded data, again a proof of concept page:

<script type="text/javascript">


function drawMonthAndQuarterChart() {

    // Create the data table.
    var data = google.visualization.arrayToDataTable([
        ['Type', 'Cash', 'Credit', { role: 'annotation' }],
        ['January', 10, 24, ''],
        ['February', 16, 22, ''],
        ['March', 28, 19, '']
    ]);

    // Set chart options
    var options = {
        width: 1200,
        height: 400,
        legend: { position: 'top', maxLines: 3 },
        bar: { groupWidth: '75%' },
        isStacked: true,

        hAxis: {
            minValue: 0,
            title: 'Approvals for the month & quarter'
        }

    };


    // Instantiate and draw our chart, passing in some options.
    var chartMonthandquarter = new google.visualization.BarChart(document.getElementById('chart_monthandquarter_div'));
    chartMonthandquarter.draw(data, options);
}

The charts all load fine when tabs are selected. The legend is overlapped with itself on all but the initially shown chart. I've tried defaulting the chart divs to be hidden and having an onclick event for each tab that overrides the styling, I've tried doing events where a tab is active, nothing seems to work and I've just been banging my head against the wall.

I suspect it has something to do with the fact that I'm calling

google.charts.setOnLoadCallback(drawMonthAndQuarterChart);
google.charts.setOnLoadCallback(drawLeaseAdminChart);
google.charts.setOnLoadCallback(drawFourthChart);

and since the charts are already drawn right on page creation, there's no way to redraw them. What I am not sure how to do is successfully get the charts to draw only when a new tab is active or something similar.

回答1:

as you've gathered,
the problem is a result of drawing the chart while the tab is hidden

need to wait until the tab is shown before drawing for the first time

as such, only draw the first chart using the callback...

google.charts.load('current', {'packages':['corechart']});
google.charts.setOnLoadCallback(drawMonthChart);

once the callback fires, you don't have to call it again,
you can draw as many charts as needed afterwards

then wait for the tabs to be clicked before drawing the next chart...

here, a switch statement is used on the href attribute,
to determine which tab was clicked,
then draw its chart...

$('a[data-toggle="tab"]').on('shown.bs.tab', function (e) {
    switch ($(e.target).attr('href')) {
      case '#home':
        drawMonthChart();
        break;

      case '#menu1':
        drawMonthAndQuarterChart();
        break;

      case '#menu2':
        drawLeaseAdminChart();
        break;

      case '#menu3':
        drawFourthChart();
        break;
    }
});