8

Ich verwende Bootstrap 3 tabs für eine Seitenlayouts und Chart.js, um Donut-Diagramme für ein Projekt zu erstellen.Bootstrap 3 Tabs & Chart.js - Diagramme laden nicht auf Tabs

Die Diagramme werden jedoch nicht geladen, wenn Sie auf eine Registerkarte mit einem Diagramm wechseln. Manchmal werden sie geladen, wenn Sie Elemente in Google Chrome jedoch untersuchen. Sie scheinen nur zu rendern, wenn sie auf der ersten sichtbaren Registerkarte geladen werden.

Es gibt einen bekannten Fehler mit dem chart.js Javascript in der Chromkonsole:

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

Und ich denke, das liegt daran, dass Bootstrap die Registerkarten Sichtbarkeit auf keines hat und daher das Diagramm machen nicht richtig oder so ...

Es sollte so suchen:

enter image description here

hat jemand anderes hatte diese Problem & wenn ja; Gibt es einen Workaround?

... Oder sollte ich nach einem anderen Diagrammskript suchen, das gut mit Bootstrap-Registerkarten funktioniert?

Vielen Dank im Voraus :)

+0

this helps http://stackoverflow.com/questions/26178399/chartjs-wont -draw-graph-inside-bootstrap-tab-bis-window-resize – roxid

Antwort

10

Ich hatte dieses Problem. Wenn ich mich richtig erinnere, löste ich es durch das Diagramm js Aufruf machen, wenn die aktive Registerkarte wird angezeigt, mit shown.bs.tab (http://getbootstrap.com/javascript/#tabs) heißt

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

Hoffnung, das hilft.

+0

Dies funktioniert zum ersten Mal, wenn Sie die Registerkarte aufrufen, aber wenn ich weg navigiere und zurück zur Registerkarte mit Grafiken gehe, werden sie nicht erneut geladen. :(Habe aber ein Beispiel mit diesem Vorschlag aktualisiert. –

+2

Hmm. Möglicherweise müssen Sie das Diagramm zuerst zerstören, wenn Sie das Register anzeigen und dann das Diagramm neu initialisieren. Gefunden, das bezieht sich auf das Zerstören eines Diagramms. [Link] (http://stackoverflow.com/questions/24815851/how-do-clear-a-chart-from-a-canvas-so-that-hover-events-cannot-be-triggered) – Clay

0

Haben Sie diese Geige bei Google-Suche. Dies könnte helfen. http://jsfiddle.net/woqsazau/2/

HTML:

<div class="container"> 
    <!-- Nav tabs --> 
    <ul class="nav nav-tabs" role="tablist" id="bs-tabs"> 
     <li><a href="#length" role="tab" data-toggle="tab">Length</a> 

     </li> 
     <li class="active"><a href="#height" role="tab" data-toggle="tab">Height</a> 

     </li> 
    </ul> 
    <!-- Tab panes --> 
    <div class="tab-content"> 
     <div class="tab-pane" id="length"> 
      <div class="canvas-holder"> 
       <canvas id="lengthChart" class="chart"></canvas> 
      </div> 
     </div> 
     <div class="tab-pane active" id="height"> 
      <div class="canvas-holder"> 
       <canvas id="heightChart" class="chart"></canvas> 
      </div> 
     </div> 
    </div> 
</div> 

JS:

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"); 
    }); 
}); 
+0

Bitte erklären, was die Idee für diese Lösung ist Arbeit, danke. – Roberto

1

Für mich ist die Lösung ist einfach tot. Mit der neuesten commit, aktualisieren Sie die Chart.Arc Funktion wie folgt:

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(); 
    } 
} 

});

Zu beachten ist der ternäre Operator am inneren und äußeren Radius, um negative Werte zu vermeiden. Dies wirkte auf meinem Projekt wie ein Zauber. Charts weiterhin reaktionsfähig und es gab KEINE schädlichen Auswirkungen durch die Umwandlung der Radien in natürliche Zahlen (dh: positiv)

0

Da der Ursprung dieses Problems ist keine Registerkarte-Inhalt im Bootstrap anzuzeigen Ich habe dies mit ein wenig gelöst css hacken.

.tab-content>.tab-pane { 
    display: block; 
    height: 0; 
    overflow: hidden; 
} 
.tab-content>.tab-pane.active { 
    height: auto; 
} 
0

Ich habe eine eher einfache und etwas faule Option gefunden.Sie können alle Ihre Tabs „Tabulabereich aktiv“ Auf diese Weise alle Ihre Diagramme auf den Registerkarten zeigen gesetzt und machen, dann

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