Chart.js - 创建状态为

时间:2016-09-29 17:13:27

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

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

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

enter image description here

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

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

1 个答案:

答案 0 :(得分:0)

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

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

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

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

            });

        };

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

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