我正在使用ionic framework制作应用,我使用chart.js在图表中显示一些数据...
我基本上试图制作一个条形图,其中我只有一个水平条,模拟多年来的活动状态,如下图所示:
我找不到任何可以帮助我的东西,我开始用线条制作它,但我需要使用像grandient
,Chart.controllers.line.extend
这样的几个工具,它开始看起来更像是解决方法......它并没有真正起作用,并且没有多大意义来制作它......
有没有办法可以做到这一点?或者你知道我应该调查什么来实现这个目标吗?
答案 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();
});
};
同样,这不是一个理想的解决方案。它需要的处理能力比我预期的要多一些,但是它起作用了,至少它对我有用......
如果有人有更好的解决方案,请分享