2016-01-26 13 views

Odpowiedz

3

Stosując tę ​​samą metodę co w poprzedniej odpowiedzi, jedyną rzeczą, która wymaga zmiany, jest rozszerzenie typu wykresu. Tym razem jest to rozszerzenie wykresu liniowego, a konfiguracja jest nieco inna, ponieważ skala wykresów liniowych jest tworzona w skali budowania, więc tym razem jest ona nadpisywana, tak że używana jest niestandardowa skala i nowa opcja overrideRotation może być przekazane. initialize jest również przesłonięte, ale tylko dlatego, że super inicjalizacja może być wywołana i uzyskać piłkę toczącą się na budowaniu wykresu.

var helpers = Chart.helpers; 
 
Chart.MyScale = Chart.Scale.extend({ 
 
    calculateXLabelRotation: function() { 
 
    //Get the width of each grid by calculating the difference 
 
    //between x offsets between 0 and 1. 
 

 
    this.ctx.font = this.font; 
 

 
    var firstWidth = this.ctx.measureText(this.xLabels[0]).width, 
 
     lastWidth = this.ctx.measureText(this.xLabels[this.xLabels.length - 1]).width, 
 
     firstRotated, 
 
     lastRotated; 
 

 

 
    this.xScalePaddingRight = lastWidth/2 + 3; 
 
    this.xScalePaddingLeft = (firstWidth/2 > this.yLabelWidth + 10) ? firstWidth/2 : this.yLabelWidth + 10; 
 

 
    this.xLabelRotation = 0; 
 
    if (this.display) { 
 
     var originalLabelWidth = helpers.longestText(this.ctx, this.font, this.xLabels), 
 
     cosRotation, 
 
     firstRotatedWidth; 
 
     this.xLabelWidth = originalLabelWidth; 
 
     //Allow 3 pixels x2 padding either side for label readability 
 
     var xGridWidth = Math.floor(this.calculateX(1) - this.calculateX(0)) - 6; 
 

 
     if (this.overrideRotation) { 
 
     this.xLabelRotation = this.overrideRotation; 
 
     cosRotation = Math.cos(helpers.radians(this.xLabelRotation)); 
 
     // We're right aligning the text now. 
 
     if (firstRotated + this.fontSize/2 > this.yLabelWidth + 8) { 
 
      this.xScalePaddingLeft = firstRotated + this.fontSize/2; 
 
     } 
 
     this.xScalePaddingRight = this.fontSize/2; 
 
     this.xLabelWidth = cosRotation * originalLabelWidth; 
 
     } else { 
 
     //Max label rotate should be 90 - also act as a loop counter 
 
     while ((this.xLabelWidth > xGridWidth && this.xLabelRotation === 0) || (this.xLabelWidth > xGridWidth && this.xLabelRotation <= 90 && this.xLabelRotation > 0)) { 
 
      cosRotation = Math.cos(helpers.radians(this.xLabelRotation)); 
 

 
      firstRotated = cosRotation * firstWidth; 
 
      lastRotated = cosRotation * lastWidth; 
 

 
      // We're right aligning the text now. 
 
      if (firstRotated + this.fontSize/2 > this.yLabelWidth + 8) { 
 
      this.xScalePaddingLeft = firstRotated + this.fontSize/2; 
 
      } 
 
      this.xScalePaddingRight = this.fontSize/2; 
 

 

 
      this.xLabelRotation++; 
 
      this.xLabelWidth = cosRotation * originalLabelWidth; 
 

 
     } 
 
     } 
 
     if (this.xLabelRotation > 0) { 
 
     this.endPoint -= Math.sin(helpers.radians(this.xLabelRotation)) * originalLabelWidth + 3; 
 
     } 
 
    } else { 
 
     this.xLabelWidth = 0; 
 
     this.xScalePaddingRight = this.padding; 
 
     this.xScalePaddingLeft = this.padding; 
 
    } 
 

 
    }, 
 

 
}); 
 

 
Chart.types.Line.extend({ 
 
    name: "MyLine", 
 
    initialize: function(data) { 
 
    Chart.types.Line.prototype.initialize.apply(this, arguments); 
 
    }, 
 

 
    buildScale: function(labels) { 
 
    var self = this; 
 

 
    var dataTotal = function() { 
 
     var values = []; 
 
     self.eachPoints(function(point) { 
 
     values.push(point.value); 
 
     }); 
 

 
     return values; 
 
    }; 
 

 
    var scaleOptions = { 
 
     templateString: this.options.scaleLabel, 
 
     height: this.chart.height, 
 
     width: this.chart.width, 
 
     ctx: this.chart.ctx, 
 
     textColor: this.options.scaleFontColor, 
 
     offsetGridLines: this.options.offsetGridLines, 
 
     fontSize: this.options.scaleFontSize, 
 
     fontStyle: this.options.scaleFontStyle, 
 
     fontFamily: this.options.scaleFontFamily, 
 
     valuesCount: labels.length, 
 
     beginAtZero: this.options.scaleBeginAtZero, 
 
     integersOnly: this.options.scaleIntegersOnly, 
 
     calculateYRange: function(currentHeight) { 
 
     var updatedRanges = helpers.calculateScaleRange(
 
      dataTotal(), 
 
      currentHeight, 
 
      this.fontSize, 
 
      this.beginAtZero, 
 
      this.integersOnly 
 
     ); 
 
     helpers.extend(this, updatedRanges); 
 
     }, 
 
     xLabels: labels, 
 
     font: helpers.fontString(this.options.scaleFontSize, this.options.scaleFontStyle, this.options.scaleFontFamily), 
 
     lineWidth: this.options.scaleLineWidth, 
 
     lineColor: this.options.scaleLineColor, 
 
     showHorizontalLines: this.options.scaleShowHorizontalLines, 
 
     showVerticalLines: this.options.scaleShowVerticalLines, 
 
     gridLineWidth: (this.options.scaleShowGridLines) ? this.options.scaleGridLineWidth : 0, 
 
     gridLineColor: (this.options.scaleShowGridLines) ? this.options.scaleGridLineColor : "rgba(0,0,0,0)", 
 
     padding: (this.options.showScale) ? 0 : this.options.pointDotRadius + this.options.pointDotStrokeWidth, 
 
     showLabels: this.options.scaleShowLabels, 
 
     display: this.options.showScale, 
 
     overrideRotation: this.options.overrideRotation, 
 
    }; 
 

 
    if (this.options.scaleOverride) { 
 
     helpers.extend(scaleOptions, { 
 
     calculateYRange: helpers.noop, 
 
     steps: this.options.scaleSteps, 
 
     stepValue: this.options.scaleStepWidth, 
 
     min: this.options.scaleStartValue, 
 
     max: this.options.scaleStartValue + (this.options.scaleSteps * this.options.scaleStepWidth) 
 
     }); 
 
    } 
 

 

 
    this.scale = new Chart.MyScale(scaleOptions); 
 
    }, 
 
}); 
 

 

 

 
var randomScalingFactor = function() { 
 
    return Math.round(Math.random() * 100) 
 
}; 
 

 
var barChartData = { 
 
    labels: ["January", "February", "March", "April", "May", "June", "July"], 
 
    datasets: [{ 
 
    fillColor: "rgba(20,20,220,0.2)", 
 
    strokeColor: "rgba(20,20,220,1)", 
 
    pointColor: "rgba(20,20,220,1)", 
 
    pointStrokeColor: "#fff", 
 
    pointHighlightFill: "#fff", 
 
    pointHighlightStroke: "rgba(20,20,220,1)", 
 
    data: [randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()] 
 
    }, { 
 
    fillColor: "rgba(120,120,120,0.2)", 
 
    strokeColor: "rgba(120,220,120,1)", 
 
    pointColor: "rgba(120,120,120,1)", 
 
    pointStrokeColor: "#fff", 
 
    pointHighlightFill: "#fff", 
 
    pointHighlightStroke: "rgba(120,120,120,1)", 
 
    data: [randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()] 
 
    }, { 
 
    fillColor: "rgba(220,220,220,0.2)", 
 
    strokeColor: "rgba(220,220,220,1)", 
 
    pointColor: "rgba(220,220,220,1)", 
 
    pointStrokeColor: "#fff", 
 
    pointHighlightFill: "#fff", 
 
    pointHighlightStroke: "rgba(220,220,220,1)", 
 
    data: [randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()] 
 
    }] 
 

 
} 
 
window.onload = function() { 
 
    var ctx = document.getElementById("canvas").getContext("2d"); 
 
    window.myBar = new Chart(ctx).MyLine(barChartData, { 
 
    overrideRotation: 90 
 
    }); 
 
}
<script src="http://www.chartjs.org/assets/Chart.min.js"></script> 
 

 
<canvas id="canvas" height="150" width="300"></canvas>

+0

Dzięki za rozwiązanie Pigwa. Czy zauważyłeś, że w swoim fragmencie, gdy wyświetlają się podpowiedzi, kolor tła legendy nie zmienia się na kolor obrysu? Jeśli dobrze to zrozumiem, powinny wyświetlić 'zbiory danych [i] .strokeColor'. Zauważyłem to podczas pracy z przykładami Chart.js. – Delcon

+0

@Delcon, przykro było, ponieważ korzystałem z poprzedniego przykładu, który miał dane ustawione dla wykresu słupkowego i pominął właściwości wykresu liniowego, zaktualizowany, aby mieć faktyczne ustawienia wykresu liniowego w danych – Quince

2

Oto nieco bardziej hackier wersja (odpowiedź pigwa jest lepiej - dodaje może pęknąć, gdyby przyszła realizacja Chart.js robi calculateXLabelRotation inaczej)

Obrót etykieta jest obliczana poprzez stopniowe obracanie etykiet tak, aby pasowały do ​​pionowych linii siatki - przestrzeń między nimi jest obliczana przy użyciu scale.calculateX(1) - scale.calculateX(0). Wskakujemy w odpowiednim momencie, aby wymusić wyniku tego obliczenia do 0 (poprzez scale.calculateX zwrotu tej samej wartości) - to z kolei wymusza rotację, aby przejść do jego maksimum (czyli 90 stopni)

Podgląd

enter image description here


Script

Chart.types.Line.extend({ 
    name: "LineAlt", 
    initialize: function() { 
     Chart.types.Line.prototype.initialize.apply(this, arguments); 

     var scale = this.scale; 
     var originalCalculateXLabelRotation = scale.calculateXLabelRotation; 
     var originalXScalePaddingLeft = scale.xScalePaddingLeft; 
     scale.calculateXLabelRotation = function() { 
      var originalCalculateX = scale.calculateX; 
      scale.calculateX = function() { 
       return 0; 
      } 
      originalCalculateXLabelRotation.apply(this, arguments); 
      scale.xScalePaddingLeft = originalXScalePaddingLeft; 
      scale.calculateX = originalCalculateX; 
     } 
     this.scale.fit(); 
    } 
}); 

a następnie

... 
new Chart(ctx).LineAlt(data); 

Fiddle - http://jsfiddle.net/gc5gdg7e/

27

Jeśli używasz chart.js 2.x, wystarczy ustawić maxRotation: 90 i minRotation: 90 w kleszcze opcje. Mi to pasuje! A jeśli chcesz wszystkie etykiety x, możesz ustawić autoSkip: false. Oto przykład.

var myChart = new Chart(ctx, { 
    type: 'bar', 
    data: chartData, 
    options: { 
     scales: { 
      xAxes: [{ 
       ticks: { 
        autoSkip: false, 
        maxRotation: 90, 
        minRotation: 90 
       } 
      }] 
     } 
    } 
}); 
Powiązane problemy