2016-09-29 4 views
0

Ich mache eine App ionic framework verwenden, wo ich einige Daten in einem Diagramm zeigen, mit der chart.js ...Chart.js - Erstellen einer einzelnen Balkendiagramm mit den Zuständen

Ich versuche im Grunde ein machen Balkendiagramm, wo ich nur 1 horizontale Leiste haben, dass simuliert einen Zustand einer Tätigkeit im Laufe der Jahre, wie Sie im nächsten Bild sehen können:

enter image description here

ich nichts finden können, die mir helfen können , und ich fing an, dies mit Linien zu machen, aber ich muss mehrere Werkzeuge wie grandient,verwenden 10, und es fängt an, eher wie ein Workaround zu aussehen ... es funktioniert nicht wirklich so gut und macht nicht viel Sinn es zu machen ...

Gibt es eine Möglichkeit, dass ich das tun kann? oder haben Sie eine Idee, was ich untersuchen sollte, um dies zu erreichen?

Antwort

0

Nun, ich habe keine gute Lösung gefunden, aber ich habe eine gefunden.

Also im Grunde, wie ich auf der Frage beschrieben wollte ich ein Balkendiagramm erstellen, aber ich wollte auch, dass das Diagramm verschiedene Farben entlang der Zeit haben würde ...

Hier ist, wie ich dieses Problem gelöst.

Zuerst erstelle ich und Array von Farben, und berechnen Sie den Prozentsatz der Zeit, die eine Farbe sichtbar wäre. Und dann habe ich es in einer Reihe von Farben, die so genannten „activityGradientArray“

var generateFilteredActivityGradientArray = function(){ 
      var filteredActivityColorWithSpaces = $scope.filteredActivityColorWithSpaces; 

      //define ratio length 
      var ratioActivity = (1.0)/filteredActivityColorWithSpaces.length; 

      var newRatio = 0.0; 
      var oldRatio = 0.0; 
      var ratioCounter = 0.0; 
      var oldColor = ""; 
      var newColor = ""; 

      var colorScheme = []; 

      for (var i = 0; i < filteredActivityColorWithSpaces.length; i++) { 

       newColor = filteredActivityColorWithSpaces[i].color; 

       if (oldColor != newColor) { 
        colorScheme.push({ratio: ratioCounter, color: newColor}); 

        oldColor = newColor; 
        oldRatio = newRatio; 
       } 

       ratioCounter = ratioCounter + ratioActivity; 
      } 

      $scope.activityGradientArray = []; 

      for (var i = 1; i < colorScheme.length; i++) { 
       $scope.activityGradientArray.push({ratio: colorScheme[i-1].ratio, color: colorScheme[i-1].color}); 
       $scope.activityGradientArray.push({ratio: colorScheme[i].ratio, color: colorScheme[i-1].color}); 
      } 

      var lastPosition = colorScheme.length-1; 
      $scope.activityGradientArray.push({ratio: colorScheme[lastPosition].ratio, color: colorScheme[lastPosition].color}); 
      $scope.activityGradientArray.push({ratio: 1, color: colorScheme[lastPosition].color}); 

     }; 

Dann erweitere ich die Chart.controllers.line und die activityGradientArray verwenden, um einen Gradienten auf die chart.chart.ctx anzuwenden, mit addColorStop

var chartControllersLine = function(){ 

      return Chart.controllers.line.extend({ 
       update: function() { 

        if(($scope.filteredChart.temperature.isNull()) && ($scope.filteredChart.activity.isNull())) { 
         return; 
        } 

        // get the min and max values 
        var minY = Math.min.apply(null, this.chart.data.datasets[$scope.CHART_DATASET_TEMPERATURE].data); 
        var maxY = Math.max.apply(null, this.chart.data.datasets[$scope.CHART_DATASET_TEMPERATURE].data); 

        $scope.minYValue = minY; 

        var yScale = this.getScaleForId(this.getDataset().yAxisID); 
        var xAxis = this.chart.scales['x-axis-0']; 


        if((undefined == yScale) || (undefined == xAxis)){ 
         return; 
        } 

        var ctx = this.chart.chart.ctx; 
        // figure out the pixels for these and the value 0 
        var top = yScale.getPixelForValue(maxY)+5; //add 
        var bottom = yScale.getPixelForValue(minY)+5; 
        var left = xAxis.chart.chartArea.left; 
        var right = xAxis.chart.chartArea.right; 

        var minimumPixelPosition; 
        var maximumPixelPosition; 
        var minimumMarginPixelPosition; 
        var maximumMarginPixelPosition; 

        if(($scope.homeConfig.rangeChartMin > minY)){ 
         minimumPixelPosition = yScale.getPixelForValue($scope.homeConfig.rangeChartMin); 

        } else { 
         minimumPixelPosition = yScale.getPixelForValue(minY); 
        } 

        if(($scope.homeConfig.rangeChartMax < maxY)) { 
         maximumPixelPosition = yScale.getPixelForValue($scope.homeConfig.rangeChartMax); 
        } else { 
         maximumPixelPosition = yScale.getPixelForValue(maxY); 
        } 

        var isAllOutside = false; 
        if((($scope.homeConfig.rangeChartMax > maxY) && ($scope.homeConfig.rangeChartMin > maxY)) || 
         (($scope.homeConfig.rangeChartMax < minY) && ($scope.homeConfig.rangeChartMin < minY))) { 
         isAllOutside = true; 
        } 

        var ratioMinimumTemperature = Math.abs(Math.min((minimumPixelPosition - top)/(bottom - top), 1)); 
        var ratioMaximumTemperature = Math.abs(Math.min((maximumPixelPosition - top)/(bottom - top), 1)); 

        var ratioMinimumMarginTemperature = Math.abs(Math.min(((minimumPixelPosition+5) - top)/(bottom - top), 1)); 
        var ratioMaximumMarginTemperature = Math.abs(Math.min(((maximumPixelPosition+5) - top)/(bottom - top), 1)); 


        if(ratioMinimumTemperature < 0) 
         ratioMinimumTemperature = 0; 
        if(ratioMinimumTemperature > 1) 
         ratioMinimumTemperature = 1; 

        if(ratioMaximumTemperature < 0) 
         ratioMaximumTemperature = 0; 
        if(ratioMaximumTemperature > 1) 
         ratioMaximumTemperature = 1; 

        if(!$scope.filteredChart.activity.isNull()) { 

         var gradientActivity = ctx.createLinearGradient(left, 0, right, 0); 

         for(var i = 0; i<$scope.activityGradientArray.length; i++){ 
          gradientActivity.addColorStop($scope.activityGradientArray[i].ratio, $scope.activityGradientArray[i].color); 
         } 
         this.chart.data.datasets[$scope.CHART_DATASET_ACTIVITY].borderColor = gradientActivity; 

        } 

        var auxApply = Chart.controllers.line.prototype.update.apply(this, arguments); 

        return auxApply; 
       } 
      }); 

     }; 

Hier ist, wo ich den Datensatz definieren:

var lineChartData = function() { 
      return { 
       xAxisID: "x-axis-0", 
       labels: angular.isDefined($scope.filteredChart.labels) ? $scope.filteredChart.labels : [], 
       datasets: [ 
        { 
         yAxisID: "y-axis-activity", 
         label: "Activity", 
         fill: false, 
         data: angular.isDefined($scope.filteredChart.activity) ? $scope.filteredChart.activity : [], 
         borderWidth: 20, 
         pointRadius: 0, 
         borderColor: $scope.lineActivityColors, 
         borderCapStyle: 'butt', 
         borderDash: [], 
         borderDashOffset: 0.0, 
         borderJoinStyle: 'miter', 
         pointBorderWidth: 0, 
         pointHoverRadius: 5, 
         pointHitRadius: 10, 

        }] 
     } 


     }; 

Und schließlich, wo ich das Diagramm mit allen ab initialisieren ove Methoden:

$(document).ready(function() { 
       var ctx = resetHomeChart(); 

       if(null == ctx) 
        return; 

       $scope.pointTemperatureColors = []; 
       $scope.lineActivityColors = []; 

       Chart.defaults.NegativeTransparentLine = Chart.helpers.clone(Chart.defaults.line); 
       Chart.controllers.NegativeTransparentLine = chartControllersLine(); 

       $scope.lineChart = new Chart(ctx, { 
        data: lineChartData(), 
        type: 'NegativeTransparentLine', 
        pointDotRadius: 10, 
        bezierCurve: false, 
        scaleShowVerticalLines: false, 
        scaleGridLineColor: "black", 
        options: options() 
       }); 

       var maxTemperature = Math.max.apply(Math, $scope.lineChart.data.datasets[$scope.CHART_DATASET_TEMPERATURE].data.map(function(o) { 
        return o == null ? -Infinity : o; 
       })); 
       var minTemperature = Math.min.apply(Math, $scope.lineChart.data.datasets[$scope.CHART_DATASET_TEMPERATURE].data.map(function(o) { 
        return o == null ? Infinity : o; 
       })); 

       if((Infinity == maxTemperature || -Infinity == maxTemperature) && (Infinity == minTemperature || -Infinity == minTemperature)){ 
        maxTemperature = 0; 
        minTemperature = 0; 
       } 

       var yScaleMaxValue = maxTemperature + 2; 
       var yScaleMinValue = minTemperature - 4; 
       $scope.lineChart.options.scales.yAxes[0].ticks.max = Math.floor(yScaleMaxValue); 
       $scope.lineChart.options.scales.yAxes[1].ticks.max = Math.floor(yScaleMaxValue); 

       $scope.lineChart.options.scales.yAxes[0].ticks.min = Math.round(yScaleMinValue); 
       $scope.lineChart.options.scales.yAxes[1].ticks.min = Math.round(yScaleMinValue); 


       //adjust bar position on the chart 
       for (var i = 0; i < $scope.lineChart.data.datasets[$scope.CHART_DATASET_ACTIVITY].data.length; i++) { 
        if(null != $scope.lineChart.data.datasets[$scope.CHART_DATASET_ACTIVITY].data[i]) { 
         $scope.lineChart.data.datasets[$scope.CHART_DATASET_ACTIVITY].data[i] = yScaleMinValue + 2; 
        } 
       } 

       $scope.lineChart.update(); 

      }); 

     }; 

Auch dies ist keine ideale Lösung. Es dauert ein bisschen mehr Verarbeitung, als ich erwartet hätte, aber es funktioniert, zumindest hat es für mich getan ...

Wenn jemand eine bessere Lösung hätte, teilen Sie es bitte

Verwandte Themen