关于javascript:Bootstrap 3标签和Chart.js-标签上未加载图表

Bootstrap 3 tabs & Chart.js - charts not loading on tabs

我正在使用Bootstrap 3选项卡进行页面布局,并使用Chart.js为项目创建甜甜圈图。

但是,当更改为带有图表的选项卡时,图表不会加载。 有时候,当您开始检查google chrome中的元素时,它们会加载。
仅当将它们加载到第一个可见选项卡上时,它们才会呈现。

chrome控制台中的chart.js javascript存在一个已知错误:

Uncaught IndexSizeError: Failed to execute 'arc' on 'CanvasRenderingContext2D': The radius provided (-0.5) is negative.

我认为这是因为Bootstrap的标签可见性设置为none,因此图表无法正确显示或其他内容。

它应该看起来像这样:

enter image description here

还有其他人有这个问题吗? 有解决方法吗?

...或者我应该寻找另一个可以很好地与Bootstrap选项卡一起使用的图表脚本。

先感谢您 :)


由于此问题的根源是在引导程序中不显示任何制表符内容,因此我通过一点CSS hack解决了此问题。

1
2
3
4
5
6
7
8
.tab-content>.tab-pane {
    display: block;
    height: 0;
    overflow: hidden;
}
.tab-content>.tab-pane.active {
    height: auto;
}


我有这个问题。如果我没记错的话,我会使用shown.bs.tab(http://getbootstrap.com/javascript/#tabs)在显示活动标签时调用图表js渲染来解决此问题

1
2
3
4
$('a[data-toggle="tab"]').on('shown.bs.tab', function (e) {
  e.target // newly activated tab
  //call chart to render here
});

希望能有所帮助。


对我而言,解决方案非常简单。使用最新的提交,如下更新Chart.Arc函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
Chart.Arc = Chart.Element.extend({
    inRange: function (chartX, chartY) {

    var pointRelativePosition = helpers.getAngleFromPoint(this, {
        x: chartX,
        y: chartY
    });

    //Check if within the range of the open/close angle
    var betweenAngles = (pointRelativePosition.angle >= this.startAngle && pointRelativePosition.angle <= this.endAngle),
        withinRadius = (pointRelativePosition.distance >= this.innerRadius && pointRelativePosition.distance <= this.outerRadius);

    return (betweenAngles && withinRadius);
    //Ensure within the outside of the arc centre, but inside arc outer
},
tooltipPosition: function () {
    var centreAngle = this.startAngle + ((this.endAngle - this.startAngle) / 2),
        rangeFromCentre = (this.outerRadius - this.innerRadius) / 2 + this.innerRadius;
    return {
        x: this.x + (Math.cos(centreAngle) * rangeFromCentre),
        y: this.y + (Math.sin(centreAngle) * rangeFromCentre)
    };
},
draw: function (animationPercent) {

    var easingDecimal = animationPercent || 1;

    var ctx = this.ctx;
    var innerRadius = (this.innerRadius < 0) ? this.innerRadius * -1 : this.innerRadius;
    var outerRadius = (this.outerRadius < 0) ? this.outerRadius * -1 : this.outerRadius;

    ctx.beginPath();

    ctx.arc(this.x, this.y, outerRadius, this.startAngle, this.endAngle);

    ctx.arc(this.x, this.y, innerRadius, this.endAngle, this.startAngle, true);

    ctx.closePath();
    ctx.strokeStyle = this.strokeColor;
    ctx.lineWidth = this.strokeWidth;

    ctx.fillStyle = this.fillColor;

    ctx.fill();
    ctx.lineJoin = 'bevel';

    if (this.showStroke) {
        ctx.stroke();
    }
}

});

需要注意的是内半径和外半径上的三元运算符,以防止出现负值。这对我的项目来说就像是一种魅力。图表继续保持响应状态,并且通过将半径转换为自然数(即:正数)没有有害影响


我发现了一个相当简单且有些懒惰的选择。您可以将所有标签设置为"活动标签窗格",这样,标签上的所有图表都会显示和呈现,然后

1
2
3
4
5
setTimeout(yourFunction, 250);
function yourFunction()
{
$('.nav-tabs a[href="#anytabExceptdefault"]').tab('show')
$('.nav-tabs a[href="#backtoyourdefaultTab"]').tab('show')

在Google搜索上弄了些小提琴。这可能会有所帮助。 http://jsfiddle.net/woqsazau/2/

HTML:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
    <!-- Nav tabs -->
    <ul class="nav nav-tabs" role="tablist" id="bs-tabs">
       
<li>
Length

       
</li>

        <li class="active">Height

       
</li>

   
</ul>

    <!-- Tab panes -->
   
       
           
                <canvas id="lengthChart" class="chart"></canvas>
           
       
       
           
                <canvas id="heightChart" class="chart"></canvas>

JS:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
 function getJSON() {

    var data = {
       "Series": {
           "height": [{
               "Date":"2014-09-19",
                   "Value": 85
            }, {
               "Date":"2014-09-23",
                   "Value": 74
            }]
        }
    };


    console.log(data);
    var series = {};

    // This loop is looping across all the series.
    // x will have all the series names (heights, lengths, etc.).
    for (var x in data.Series) {
        var dates = [];
        var values = [];
        // Loop across all the measurements for every serie.
        for (var i = 0; i < data.Series[x].length; i++) {
            var obj = data.Series[x][i];
            // Assuming that all the different series (heights, lengths, etc.) have the same two Date, Value attributes.
            dates.push(moment(obj.Date).format("MMMM Mo"));
            values.push(obj.Value);
        }
        // Keep the list of dates and values by serie name.
        series[x] = {
            dates: dates,
            values: values
        };
    }

    console.log(series.height.dates);
    console.log(series.height.values);
    //---------
    //valueArray.push(Value);
    //dateArray.push(moment(date).format("MMMM Mo"));

    var dataArray = {
        labels: series.height.dates,
        datasets: [{
            label:"Height",

            strokeColor:"rgb(26, 188, 156)",
            pointColor:"rgba(220,220,220,1)",
            pointStrokeColor:"#fff",
            pointHighlightFill:"#fff",
            pointHighlightStroke:"rgba(220,220,220,1)",
            data: series.height.values
        }]
    };

    function chartFunc(dataArray) {

        var ctx = document.getElementById("heightChart").getContext("2d");
        var myLineChart = new Chart(ctx).Line(dataArray, {
            scaleShowGridLines: true,
            bezierCurve: true,
            bezierCurveTension: 0.4,
            datasetStroke: false,
            fillColor:"rgba(0,0,0,0)",
            datasetFill: false,
            responsive: true,
            showTooltips: true,
            animation: false
        });
    } //chartFunc

    chartFunc(dataArray);
} //getJSON


$(document).ready(function () {

    getJSON();

    $(document).on('shown.bs.tab', 'a[data-toggle="tab"]', function (e) {
        console.log("tab changed");
    });
});