mirror of
https://github.com/chartjs/Chart.js.git
synced 2026-03-09 09:46:51 +01:00
Enhancement: adds step-after functionality, true defaults to step-before (#4065)
* Adds step-after functionality, true defaults to step-before * Update stepped line sample to include all variations of steppedLine configurations * Update documentation on steppedLine values * Add tests for new steppedLine values 'before' and 'after'
This commit is contained in:
committed by
Evert Timberg
parent
19d6df21e3
commit
205cedc0ef
@@ -70,7 +70,7 @@ All point* properties can be specified as an array. If these are set to an array
|
||||
| `pointHoverRadius` | `Number/Number[]` | The radius of the point when hovered.
|
||||
| `showLine` | `Boolean` | If false, the line is not drawn for this dataset.
|
||||
| `spanGaps` | `Boolean` | If true, lines will be drawn between points with no or null data. If false, points with `NaN` data will create a break in the line
|
||||
| `steppedLine` | `Boolean` | If true, the line is shown as a stepped line and 'lineTension' will be ignored.
|
||||
| `steppedLine` | `Boolean/String` | If the line is shown as a stepped line. [more...](#stepped-line)
|
||||
|
||||
### cubicInterpolationMode
|
||||
The following interpolation modes are supported:
|
||||
@@ -106,6 +106,15 @@ The style of point. Options are:
|
||||
|
||||
If the option is an image, that image is drawn on the canvas using [drawImage](https://developer.mozilla.org/en/docs/Web/API/CanvasRenderingContext2D/drawImage).
|
||||
|
||||
### Stepped Line
|
||||
The following values are supported for `steppedLine`:
|
||||
* `false`: No Step Interpolation (default)
|
||||
* `true`: Step-before Interpolation (eq. 'before')
|
||||
* `'before'`: Step-before Interpolation
|
||||
* `'after'`: Step-after Interpolation
|
||||
|
||||
If the `steppedLine` value is set to anything other than false, `lineTension` will be ignored.
|
||||
|
||||
## Configuration Options
|
||||
|
||||
The line chart defines the following configuration options. These options are merged with the global chart configuration options, `Chart.defaults.global`, to form the options passed to the chart.
|
||||
|
||||
@@ -5,88 +5,98 @@
|
||||
<title>Stepped Line Chart</title>
|
||||
<script src="../../../dist/Chart.bundle.js"></script>
|
||||
<script src="../../utils.js"></script>
|
||||
<style>
|
||||
canvas{
|
||||
-moz-user-select: none;
|
||||
-webkit-user-select: none;
|
||||
-ms-user-select: none;
|
||||
}
|
||||
</style>
|
||||
<style>
|
||||
canvas {
|
||||
-moz-user-select: none;
|
||||
-webkit-user-select: none;
|
||||
-ms-user-select: none;
|
||||
}
|
||||
.chart-container {
|
||||
width: 500px;
|
||||
margin-left: 40px;
|
||||
margin-right: 40px;
|
||||
margin-bottom: 40px;
|
||||
}
|
||||
.container {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
justify-content: center;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div style="width:75%;">
|
||||
<canvas id="canvas"></canvas>
|
||||
</div>
|
||||
<div class="container">
|
||||
</div>
|
||||
<script>
|
||||
var config = {
|
||||
type: 'line',
|
||||
data: {
|
||||
labels: ["January", "February", "March", "April", "May", "June", "July"],
|
||||
datasets: [{
|
||||
label: "My First dataset",
|
||||
borderColor: window.chartColors.red,
|
||||
backgroundColor: window.chartColors.red,
|
||||
data: [
|
||||
randomScalingFactor(),
|
||||
randomScalingFactor(),
|
||||
randomScalingFactor(),
|
||||
randomScalingFactor(),
|
||||
randomScalingFactor(),
|
||||
randomScalingFactor(),
|
||||
randomScalingFactor()
|
||||
],
|
||||
fill: false,
|
||||
steppedLine: true,
|
||||
}, {
|
||||
label: "My Second dataset",
|
||||
steppedLine: true,
|
||||
borderColor: window.chartColors.blue,
|
||||
backgroundColor: window.chartColors.blue,
|
||||
data: [
|
||||
randomScalingFactor(),
|
||||
randomScalingFactor(),
|
||||
randomScalingFactor(),
|
||||
randomScalingFactor(),
|
||||
randomScalingFactor(),
|
||||
randomScalingFactor(),
|
||||
randomScalingFactor()
|
||||
],
|
||||
fill: false,
|
||||
}]
|
||||
},
|
||||
options: {
|
||||
responsive: true,
|
||||
title:{
|
||||
display:true,
|
||||
text:'Chart.js Line Chart'
|
||||
},
|
||||
tooltips: {
|
||||
mode: 'index',
|
||||
},
|
||||
scales: {
|
||||
xAxes: [{
|
||||
display: true,
|
||||
scaleLabel: {
|
||||
display: true,
|
||||
labelString: 'Month'
|
||||
}
|
||||
}],
|
||||
yAxes: [{
|
||||
display: true,
|
||||
scaleLabel: {
|
||||
display: true,
|
||||
labelString: 'Value'
|
||||
},
|
||||
}]
|
||||
}
|
||||
}
|
||||
};
|
||||
function createConfig(details, data) {
|
||||
return {
|
||||
type: 'line',
|
||||
data: {
|
||||
labels: ['Day 1', 'Day 2', 'Day 3', 'Day 4', 'Day 5', 'Day 6'],
|
||||
datasets: [{
|
||||
label: 'steppedLine: ' + ((typeof(details.steppedLine) === 'boolean') ? details.steppedLine : `'${details.steppedLine}'`),
|
||||
steppedLine: details.steppedLine,
|
||||
data: data,
|
||||
borderColor: details.color,
|
||||
fill: false,
|
||||
}]
|
||||
},
|
||||
options: {
|
||||
responsive: true,
|
||||
title: {
|
||||
display: true,
|
||||
text: details.label,
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
window.onload = function() {
|
||||
var ctx = document.getElementById("canvas").getContext("2d");
|
||||
window.myLine = new Chart(ctx, config);
|
||||
};
|
||||
|
||||
window.onload = function() {
|
||||
var container = document.querySelector('.container');
|
||||
|
||||
var data = [
|
||||
randomScalingFactor(),
|
||||
randomScalingFactor(),
|
||||
randomScalingFactor(),
|
||||
randomScalingFactor(),
|
||||
randomScalingFactor(),
|
||||
randomScalingFactor()
|
||||
];
|
||||
|
||||
var steppedLineSettings = [{
|
||||
steppedLine: false,
|
||||
label: 'No Step Interpolation',
|
||||
color: window.chartColors.red
|
||||
}, {
|
||||
steppedLine: true,
|
||||
label: 'Step Before Interpolation',
|
||||
color: window.chartColors.green
|
||||
}, {
|
||||
steppedLine: 'before',
|
||||
label: 'Step Before Interpolation',
|
||||
color: window.chartColors.green
|
||||
}, {
|
||||
steppedLine: 'after',
|
||||
label: 'Step After Interpolation',
|
||||
color: window.chartColors.purple
|
||||
}];
|
||||
|
||||
steppedLineSettings.forEach(function(details) {
|
||||
var div = document.createElement('div');
|
||||
div.classList.add('chart-container');
|
||||
|
||||
var canvas = document.createElement('canvas');
|
||||
div.appendChild(canvas);
|
||||
container.appendChild(div);
|
||||
|
||||
var ctx = canvas.getContext('2d');
|
||||
var config = createConfig(details, data);
|
||||
new Chart(ctx, config);
|
||||
});
|
||||
};
|
||||
</script>
|
||||
</body>
|
||||
|
||||
|
||||
@@ -123,7 +123,11 @@ module.exports = function(Chart) {
|
||||
|
||||
helpers.lineTo = function(ctx, previous, target, flip) {
|
||||
if (target.steppedLine) {
|
||||
ctx.lineTo(target.x, previous.y);
|
||||
if (target.steppedLine === 'after') {
|
||||
ctx.lineTo(previous.x, target.y);
|
||||
} else {
|
||||
ctx.lineTo(target.x, previous.y);
|
||||
}
|
||||
ctx.lineTo(target.x, target.y);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -243,7 +243,141 @@ describe('Chart.elements.Line', function() {
|
||||
}]);
|
||||
});
|
||||
|
||||
it('should draw stepped lines', function() {
|
||||
it('should draw stepped lines, with "before" interpolation', function() {
|
||||
|
||||
// Both `true` and `'before'` should draw the same steppedLine
|
||||
var beforeInterpolations = [true, 'before'];
|
||||
|
||||
beforeInterpolations.forEach(function(mode) {
|
||||
var mockContext = window.createMockContext();
|
||||
|
||||
// Create our points
|
||||
var points = [];
|
||||
points.push(new Chart.elements.Point({
|
||||
_datasetindex: 2,
|
||||
_index: 0,
|
||||
_view: {
|
||||
x: 0,
|
||||
y: 10,
|
||||
controlPointNextX: 0,
|
||||
controlPointNextY: 10,
|
||||
steppedLine: mode
|
||||
}
|
||||
}));
|
||||
points.push(new Chart.elements.Point({
|
||||
_datasetindex: 2,
|
||||
_index: 1,
|
||||
_view: {
|
||||
x: 5,
|
||||
y: 0,
|
||||
controlPointPreviousX: 5,
|
||||
controlPointPreviousY: 0,
|
||||
controlPointNextX: 5,
|
||||
controlPointNextY: 0,
|
||||
steppedLine: mode
|
||||
}
|
||||
}));
|
||||
points.push(new Chart.elements.Point({
|
||||
_datasetindex: 2,
|
||||
_index: 2,
|
||||
_view: {
|
||||
x: 15,
|
||||
y: -10,
|
||||
controlPointPreviousX: 15,
|
||||
controlPointPreviousY: -10,
|
||||
controlPointNextX: 15,
|
||||
controlPointNextY: -10,
|
||||
steppedLine: mode
|
||||
}
|
||||
}));
|
||||
points.push(new Chart.elements.Point({
|
||||
_datasetindex: 2,
|
||||
_index: 3,
|
||||
_view: {
|
||||
x: 19,
|
||||
y: -5,
|
||||
controlPointPreviousX: 19,
|
||||
controlPointPreviousY: -5,
|
||||
controlPointNextX: 19,
|
||||
controlPointNextY: -5,
|
||||
steppedLine: mode
|
||||
}
|
||||
}));
|
||||
|
||||
var line = new Chart.elements.Line({
|
||||
_datasetindex: 2,
|
||||
_chart: {
|
||||
ctx: mockContext,
|
||||
},
|
||||
_children: points,
|
||||
// Need to provide some settings
|
||||
_view: {
|
||||
fill: false, // don't want to fill
|
||||
tension: 0, // no bezier curve for now
|
||||
}
|
||||
});
|
||||
|
||||
line.draw();
|
||||
|
||||
expect(mockContext.getCalls()).toEqual([{
|
||||
name: 'save',
|
||||
args: [],
|
||||
}, {
|
||||
name: 'setLineCap',
|
||||
args: ['butt']
|
||||
}, {
|
||||
name: 'setLineDash',
|
||||
args: [
|
||||
[]
|
||||
]
|
||||
}, {
|
||||
name: 'setLineDashOffset',
|
||||
args: [0.0]
|
||||
}, {
|
||||
name: 'setLineJoin',
|
||||
args: ['miter']
|
||||
}, {
|
||||
name: 'setLineWidth',
|
||||
args: [3]
|
||||
}, {
|
||||
name: 'setStrokeStyle',
|
||||
args: ['rgba(0,0,0,0.1)']
|
||||
}, {
|
||||
name: 'beginPath',
|
||||
args: []
|
||||
}, {
|
||||
name: 'moveTo',
|
||||
args: [0, 10]
|
||||
}, {
|
||||
name: 'lineTo',
|
||||
args: [5, 10]
|
||||
}, {
|
||||
name: 'lineTo',
|
||||
args: [5, 0]
|
||||
}, {
|
||||
name: 'lineTo',
|
||||
args: [15, 0]
|
||||
}, {
|
||||
name: 'lineTo',
|
||||
args: [15, -10]
|
||||
}, {
|
||||
name: 'lineTo',
|
||||
args: [19, -10]
|
||||
}, {
|
||||
name: 'lineTo',
|
||||
args: [19, -5]
|
||||
}, {
|
||||
name: 'stroke',
|
||||
args: [],
|
||||
}, {
|
||||
name: 'restore',
|
||||
args: []
|
||||
}]);
|
||||
});
|
||||
});
|
||||
|
||||
it('should draw stepped lines, with "after" interpolation', function() {
|
||||
|
||||
var mockContext = window.createMockContext();
|
||||
|
||||
// Create our points
|
||||
@@ -256,7 +390,7 @@ describe('Chart.elements.Line', function() {
|
||||
y: 10,
|
||||
controlPointNextX: 0,
|
||||
controlPointNextY: 10,
|
||||
steppedLine: true
|
||||
steppedLine: 'after'
|
||||
}
|
||||
}));
|
||||
points.push(new Chart.elements.Point({
|
||||
@@ -269,7 +403,7 @@ describe('Chart.elements.Line', function() {
|
||||
controlPointPreviousY: 0,
|
||||
controlPointNextX: 5,
|
||||
controlPointNextY: 0,
|
||||
steppedLine: true
|
||||
steppedLine: 'after'
|
||||
}
|
||||
}));
|
||||
points.push(new Chart.elements.Point({
|
||||
@@ -282,7 +416,7 @@ describe('Chart.elements.Line', function() {
|
||||
controlPointPreviousY: -10,
|
||||
controlPointNextX: 15,
|
||||
controlPointNextY: -10,
|
||||
steppedLine: true
|
||||
steppedLine: 'after'
|
||||
}
|
||||
}));
|
||||
points.push(new Chart.elements.Point({
|
||||
@@ -295,7 +429,7 @@ describe('Chart.elements.Line', function() {
|
||||
controlPointPreviousY: -5,
|
||||
controlPointNextX: 19,
|
||||
controlPointNextY: -5,
|
||||
steppedLine: true
|
||||
steppedLine: 'after'
|
||||
}
|
||||
}));
|
||||
|
||||
@@ -345,19 +479,19 @@ describe('Chart.elements.Line', function() {
|
||||
args: [0, 10]
|
||||
}, {
|
||||
name: 'lineTo',
|
||||
args: [5, 10]
|
||||
args: [0, 0]
|
||||
}, {
|
||||
name: 'lineTo',
|
||||
args: [5, 0]
|
||||
}, {
|
||||
name: 'lineTo',
|
||||
args: [15, 0]
|
||||
args: [5, -10]
|
||||
}, {
|
||||
name: 'lineTo',
|
||||
args: [15, -10]
|
||||
}, {
|
||||
name: 'lineTo',
|
||||
args: [19, -10]
|
||||
args: [15, -5]
|
||||
}, {
|
||||
name: 'lineTo',
|
||||
args: [19, -5]
|
||||
|
||||
Reference in New Issue
Block a user