【问题标题】:Chart.js - Creating a single bar chart with statesChart.js - 创建带有状态的单个条形图
【发布时间】:2016-09-29 17:13:27
【问题描述】:

我正在使用ionic framework 制作应用程序,其中我使用chart.js 在图表中显示一些数据...

我基本上是在尝试制作一个条形图,其中我只有一个水平条,模拟多年来的活动状态,如下图所示:

我找不到任何可以帮助我的东西,我开始用线条制作这个,但我需要使用几个工具,如grandientChart.controllers.line.extend,它开始看起来更像是一种解决方法......它并没有那么好用,也没有多大意义……

有什么办法可以做到这一点吗?或者您知道我应该调查什么来实现这一目标吗?

【问题讨论】:

    标签: javascript bar-chart chart.js chart.js2


    【解决方案1】:

    好吧,我没有想出一个好的解决方案,但我找到了一个。

    所以基本上,正如我在问题中所描述的那样,我想创建一个条形图,但我也希望图表随着时间的推移会有不同的颜色......

    这是我解决这个问题的方法。

    首先我创建一个颜色数组,并计算颜色可见的时间百分比。然后我把它放在一个颜色数组中,称为“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});
    
            };
    

    然后我扩展Chart.controllers.line,并使用activityGradientArray 将渐变应用到chart.chart.ctx,使用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;
                    }
                });
    
            };
    

    这是我定义数据集的地方:

     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,
    
                        }]
            }
    
    
            };
    

    最后我用上述所有方法初始化图表:

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

    同样,这不是一个理想的解决方案。它比我预期的需要更多的处理,但它有效,至少它对我有用......

    如果有人有更好的解决方案,请分享

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-07-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多