ChartJS图表不在选项卡中生成

时间:2015-03-24 17:06:37

标签: javascript jquery tabs chart.js

我试图在标签系统中使用ChartsJS。渲染第一个选项卡中的第一个图表,但后续图表不会。

我认为这是因为标签有display:none,所以当首次生成图表时,它们是在零维度的div中创建的。

这解决了问题,但打破了标签:

.vertical-nav>div.tab-content {
    display: block !important;
}

考虑到这一点,我在选项卡打开后尝试了各种方法来重新生成图表,或者在生成图表之前强制display:block。什么都行不通。

我尝试重新生成图表:

jQuery(document).ready(function() {

    jQuery('.vertical-nav ul li span').click(function(){

        // Target the canvas within the correct tab
        var tabIndex = jQuery(this).parent().index();
        var canvasID = jQuery('.vertical-nav .tab-content:eq( ' + tabIndex + ' ) canvas').attr('id');

        theChart = charts[canvasID].chart;
        builtChart = charts[canvasID].builtChart;

        // Destroy all of the charts so that we can rebuild them
        for (var key in charts) {
            if (charts.hasOwnProperty(key)) {
                charts[key].builtChart.destroy();
            }
        }

        // get the chart data and options from the charts object
        newData = charts[canvasID].data;
        newOptions = charts[canvasID].options;

        // create the new chart
        newChart = document.getElementById(canvasID).getContext("2d");
        new Chart(newChart).Line(newData, newOptions);

    });
})

暂存网站为:http://telcomplusplc.uberleaf.com/company/?tab=our-growth

我甚至尝试设置超时来延迟图表生成,直到显示标签,但没有运气。

您可以在上面的URL中看到第一个图表生成并重新生成。它只是其他人的不足(大概是因为他们第一代有display:none div。)

非常感谢任何帮助。如果需要,很乐意提供更多信息。

更新

调整窗口大小时,将重绘图表。这是代码(在chart.js中):

// Attach global event to resize each chart instance when the browser resizes
helpers.addEvent(window, "resize", (function(){
    // Basic debounce of resize function so it doesn't hurt performance when resizing browser.
    var timeout;
    return function(){
        clearTimeout(timeout);
        timeout = setTimeout(function(){
            each(Chart.instances,function(instance){
                // If the responsive flag is set in the chart instance config
                // Cascade the resize event down to the chart.
                if (instance.options.responsive){
                    instance.resize(instance.render, true);
                }
            });
        }, 50);
    };
})());

我认为我需要的是能够通过点击功能触发它。我尝试过失败了,我的JS技能并不好。

5 个答案:

答案 0 :(得分:4)

如果你使用display:none,那么chartjs不知道制作图表的大小,然后就不知道了。如果切换到jquery.hide()/ show(),它将起作用。这是jsfiddle

*没有它的小提琴工作,但如果你有很多内容,那么你可能还需要暂时隐藏该区域。

的Javascript

var data1 = {
    labels: ["January", "February", "March", "April", "May", "June", "July"],
    datasets: [{ data: [65, 59, 80, 81, 56, 55, 40] }]
};
var data2 = {
    labels: ["January", "February", "March", "April", "May", "June", "July"],
    datasets: [{ data: [65, 59, 80, 81, 56, 55, 40] }]
};

// Load each chart and hide() the tab immediately.

var ctx = document.getElementById('chart1').getContext('2d');
var chart1 = new Chart(ctx).Bar(data1);
$('#tab1').hide();

var ctx = document.getElementById('chart2').getContext('2d');
var chart2 = new Chart(ctx).Line(data2);
$('#tab2').hide();

/* 
// will not work because chart is not rendered
$('#tab1_btn').on('click',function(){ 
    $('#tab1').css('display','block'); 
    $('#tab2').css('display','none') })
$('#tab2_btn').on('click',function(){ 
    $('#tab1').css('display','none'); 
    $('#tab2').css('display','block') })
*/

$('#tab1_btn').on('click',function(){ 
    $('#tab1').show(); 
    $('#tab2').hide() 
})
$('#tab2_btn').on('click',function(){ 
    $('#tab1').hide(); 
    $('#tab2').show() 
})

// if you have a lot of content in multiple tabs 
// it may be necessary to temporarily cover the content
$('#tab_cover').hide();

HTML

<button id="tab1_btn">tab1</button>
<button id="tab2_btn">tab2</button>
<div id="tab_cover"> </div>
<div id="tabs">
    <div id="tab1" class="tab">
        <canvas id="chart1" class="chart" width="400" height="300"></canvas>
    </div>
    <div id="tab2" class="tab">
        <canvas id="chart2" class="chart" width="400" height="300"></canvas>
    </div>
</div>

CSS

/* will not work because chart is not rendered
.tab { display:none } */
.chart { width:50% }
.float { float:right; width:50%; }
#tab_cover { background:#9ff; height: 100% !important; width:100%; position: absolute; z-index: 300; }

答案 1 :(得分:2)

我找到了解决方案。我接近我在问题中的代码。我似乎需要销毁和调整图表的大小。

我还必须手动更改标签的display状态。

这对我有用:

    function createNewChart(canvasID) {
        // get the chart data and options from the charts object
        newData = charts[canvasID].data;
        newOptions = charts[canvasID].options;

        // create the new chart
        theChart = document.getElementById(canvasID).getContext("2d"); console.dir(theChart);
        new Chart(theChart).Line(newData, newOptions);
    }

    jQuery('.vertical-nav ul li').click(function(){

        // Target the canvas within the correct tab
        var tabIndex = jQuery(this).index();
        var canvasID = jQuery('.vertical-nav .tab-content:eq( ' + tabIndex + ' ) canvas').attr('id');

        theChart = charts[canvasID].chart;
        builtChart = charts[canvasID].builtChart;

        // Destroy all of the charts so that we can rebuild them
        for (var key in charts) {
            if (charts.hasOwnProperty(key)) {
                jQuery('.vertical-nav .tab-content:eq( ' + tabIndex + ' )').css('display', 'block');
                jQuery('.vertical-nav .tab-content:eq( ' + tabIndex + ' ) .tab-content-chart').css('display', 'block');
                charts[key].builtChart.destroy();
                charts[key].builtChart.resize();
            }
        }

        createNewChart(canvasID);

    }); 

答案 2 :(得分:0)

当使用隐藏的div时,我遇到了同样的问题,这些div只显示在下拉菜单中的某些选项上。我发现的工作方式类似于ow3n所做的。我创建了图表,然后只有在选择完成后才生成它们。

HTML:

<div>
    <select>
        <option value="option-1">Option 1</option>
        <option value="option-2">Option 2</option>
        <option value="option-3">Option 3</option>
    </select>
</div>
<div class="chart1">
    <canvas id="chart1"></canvas>
</div>

<div class="chart2">
    <canvas id="chart2"></canvas>
</div>

<div class="chart3">
    <canvas id="chart3"></canvas>
</div>

使用Javascript:

//example of chart variables (I only included 1 example)
    var chart1 = {
        labels : ["2009","2010","2011","2012","2013","2014"],
        labelAlign: 'center',
        datasets : [
            {
                label: "Visitor Average",
                fillColor : "rgba(255,255,255,0)",
                strokeColor : "rgba(0,34,221,1)",
                pointColor : "rgba(0,34,221,1)",
                pointStrokeColor : "#fff",
                pointHighlightFill : "#fff",
                pointHighlightStroke : "rgba(0,34,221,1)",
                data: [28, 48, 40, 19, 86, 27]
            },
            {
                label: "Baseline Average",
                fillColor : "rgba(255,255,255,0)",
                strokeColor : "rgba(255,0,0,1)",
                pointColor : "rgba(255,0,0,1)",
                pointStrokeColor : "#fff",
                pointHighlightFill : "#fff",
                pointHighlightStroke : "rgba(255,0,0,1)",
                data: [65, 59, 80, 81, 56, 55]
            }
        ]

    }

window.onload = function(){
    var ctx1 = document.getElementById("chart1").getContext("2d");
    window.myLine1 = new Chart(ctx1).Line(chart1,  {
        responsive: true,
    });
}

//change graph per drop-down selection
    $(document).ready(function(){
        $("select").change(function(){
            $( "select option:selected").each(function(){
                if($(this).attr("value")=="option-1"){
                    $(".chart2").hide();
                    $(".chart3").hide();
                    $(".chart1").show();
                    var ctx1 = document.getElementById("chart1").getContext("2d");
                    window.myLine1 = new Chart(ctx1).Line(chart1,  {
                        responsive: true,
                    });
                }
                if($(this).attr("value")=="option-2"){
                    $(".chart2").show();
                    $(".chart1").hide();
                    $(".chart3").hide();
                    var ctx2 = document.getElementById("chart2").getContext("2d");
                    window.myLine2 = new Chart(ctx2).Line(chart2, {
                        responsive: true,
                    });
                }
                if($(this).attr("value")=="option-3"){
                    $(".chart3").show();
                    $(".chart1").hide();
                    $(".chart2").hide();
                    var ctx3 = document.getElementById("chart3").getContext("2d");
                    window.myLine3 = new Chart(ctx3).Line(chart3, {
                        responsive: true,
                    });
                }
            });
        }).change();
    }); 

答案 3 :(得分:0)

以bootstrap的选项卡为例,我的解决方案是在使用chart.js渲染之前将.loading-data添加到.tab-content,并在渲染完成后删除该类。

.tab-content.loading-data .tab-pane {
  display: block;
}

通过这种方式,.tab-pane将显示在chartjs渲染的瞬间。

答案 4 :(得分:0)

试试这个,我尝试了所有其他方法,但最终还是用了这段代码。

$("a").click(function(e){
        let val = '#'+ e.target.href.split("#")[1]
        localStorage.setItem('tab', val)
        window.location.reload();
    })
    $(document).ready(function()
    {
        $('a[href="' + localStorage.getItem('tab') + '"]').parent().addClass('active')
        $(document.getElementById(localStorage.getItem('tab').slice(1))).addClass('active')
    });

另外,试试这些方法

window.dispatchEvent(new Event('resize'))
Chartkick.charts["<id of chart element like chart-1>"].redraw()