Comparar commits
143 Commits
| Autor | SHA1 | Data | |
|---|---|---|---|
| c074d3b7d4 | |||
| 6cce958548 | |||
| ccb1c68b65 | |||
| f609452727 | |||
| b2150b93a2 | |||
| b9fa20714f | |||
| e5ee242dc6 | |||
| 9dbc5650ed | |||
| 0052ceb7a1 | |||
| e91e6be851 | |||
| 349586e14c | |||
| c4b30a7b0e | |||
| f0555af8cc | |||
| e5244b7dba | |||
| bf2ca8bd0b | |||
| f4bcef13f5 | |||
| efdc23c567 | |||
| e84d27dde7 | |||
| 7aa2fd1af3 | |||
| 5a1c968105 | |||
| e87fd9e0cc | |||
| dae1e429b8 | |||
| 55670b0cf7 | |||
| 5f7507c324 | |||
| a90aac7b26 | |||
| cf1f772157 | |||
| 8e9fef27c2 | |||
| 75fb79f814 | |||
| f4ef56993d | |||
| 3bfbf10cff | |||
| e6ea34e453 | |||
| ae51789c32 | |||
| 4d48ab5109 | |||
| c75c21105a | |||
| 830cf33c1f | |||
| a0377362d7 | |||
| 420290969e | |||
| dc152f875f | |||
| a4a07df612 | |||
| a08f8b3015 | |||
| df13f819b5 | |||
| a888aba61e | |||
| 800246660a | |||
| ca2e017f80 | |||
| 1471a61609 | |||
| 1580d1ed4d | |||
| 34aaeac421 | |||
| 0c69c9a79c | |||
| 5400a61ff1 | |||
| 942cf5e718 | |||
| f32d62722a | |||
| 82a74701a7 | |||
| 09d2f1d900 | |||
| 7edcc0659b | |||
| 673e5d59a5 | |||
| ead6247cd8 | |||
| e00f9d5790 | |||
| fe77f07c07 | |||
| 5a80b9e501 | |||
| ae9db841f9 | |||
| 937d866bd3 | |||
| 592414330b | |||
| ac098b8b2f | |||
| 3a193e2117 | |||
| 0495e45ff7 | |||
| 045d8f6c2a | |||
| 9c78de10ba | |||
| 37249e4375 | |||
| d61745a311 | |||
| 55c7d6872a | |||
| 3bd9120a3a | |||
| 01fe535594 | |||
| f6ac7d9369 | |||
| 0e02d216aa | |||
| 108c4fcd56 | |||
| 05523b01b0 | |||
| be07f052d9 | |||
| 7f34d8dd2f | |||
| f85ffbc09c | |||
| 6d708a8f2c | |||
| 66bc1dc492 | |||
| 8e3ba9d88e | |||
| 1e4894d625 | |||
| 14b6fdd51e | |||
| 3099d967da | |||
| 471a5f5aaa | |||
| fff13f2692 | |||
| 234efc5267 | |||
| c4d02a8f96 | |||
| 21efd50fb7 | |||
| 972ceb24e6 | |||
| 679ac764b1 | |||
| 962b99e8d3 | |||
| 3d15e1ff54 | |||
| 178880bace | |||
| d5d63070c6 | |||
| 97da3347be | |||
| d6252df4cd | |||
| 33308616af | |||
| 68255893cf | |||
| 57d8155bb0 | |||
| 92841cd38a | |||
| 29c3bd3746 | |||
| b0380d4ede | |||
| 28bc80e439 | |||
| d46524aedc | |||
| 677c043a91 | |||
| 50d9389dce | |||
| 2c04a816d7 | |||
| f4a5a30451 | |||
| 4267d01bc2 | |||
| 8324b35506 | |||
| b823bae63e | |||
| 334ba44e95 | |||
| e4d308f329 | |||
| cf587122da | |||
| 93a79ec470 | |||
| 3d862962f7 | |||
| 69bff1183f | |||
| 93a923d38f | |||
| 22aabdbfab | |||
| 5ba1ec0d3b | |||
| 8398d26d10 | |||
| fa33f3158e | |||
| 0fa03fad24 | |||
| 91bacf8e51 | |||
| a848142274 | |||
| be50c63e72 | |||
| 0494d551b6 | |||
| ecf5801787 | |||
| 753fd79bf3 | |||
| 2845d39311 | |||
| 07b052cfab | |||
| 3aaa3e27f3 | |||
| c316f90999 | |||
| b8e57144cc | |||
| 1017934dce | |||
| 6716dbb7e5 | |||
| 9bebedd967 | |||
| 988034cef6 | |||
| 85572d7b67 | |||
| 74c04a354a | |||
| dac859ec1c |
@@ -4,6 +4,7 @@ node_js:
|
||||
- "0.10"
|
||||
|
||||
before_install:
|
||||
- "export CHROME_BIN=chromium-browser"
|
||||
- "export DISPLAY=:99.0"
|
||||
- "sh -e /etc/init.d/xvfb start"
|
||||
|
||||
|
||||
externo
+631
-438
Diferenças do arquivo suprimidas por serem muito extensas
Carregar Diff
externo
+11
-11
Diff do arquivo suprimido porque uma ou mais linhas são muito longas
+122
-148
@@ -34,9 +34,9 @@ bower install Chart.js --save
|
||||
npm install Chart.js --save
|
||||
```
|
||||
|
||||
https://cdnjs.com/libraries/chart.js
|
||||
https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.0.0-beta/Chart.js
|
||||
|
||||
###Creating a chart
|
||||
###Creating a Chart
|
||||
|
||||
To create a chart, we need to instantiate the `Chart` class. To do this, we need to pass in the node, jQuery instance, or 2d context of the canvas of where we want to draw the chart. Here's an example.
|
||||
|
||||
@@ -48,173 +48,147 @@ To create a chart, we need to instantiate the `Chart` class. To do this, we need
|
||||
// Any of the following formats may be used
|
||||
var ctx = document.getElementById("myChart");
|
||||
var ctx = document.getElementById("myChart").getContext("2d");
|
||||
var ctx = $("myChart");
|
||||
var ctx = $("#myChart");
|
||||
```
|
||||
|
||||
Once you have the element or context, you're ready to instantiate a pre-defined chart-type or create your own!
|
||||
|
||||
The following example instantiates a the pre-defined Polar Area chart type with a config object of data and options.
|
||||
```javascript
|
||||
var myNewChart = Chart.PolarArea(ctx, {
|
||||
data: data,
|
||||
options: options
|
||||
});
|
||||
```
|
||||
The following example instantiates a bar chart showing the number of votes for different colors and the y-axis starting at 0.
|
||||
|
||||
To create a scatter chart, which is a special configuration of a line chart, we use the following.
|
||||
```javascript
|
||||
var myScatterChart = Chart.Scatter(ctx, {
|
||||
data: data,
|
||||
options: options
|
||||
});
|
||||
```
|
||||
|
||||
Alternatively, we can use the more advanced API to create simple or advanced chart types. In the example below, we are creating a line chart.
|
||||
```javascript
|
||||
```html
|
||||
<canvas id="myChart" width="400" height="400"></canvas>
|
||||
<script>
|
||||
var ctx = document.getElementById("myChart");
|
||||
var myChart = new Chart(ctx, {
|
||||
type: 'line', // built in types are 'line', 'bar', 'radar', 'polarArea', 'doughnut', 'scatter'
|
||||
data: data,
|
||||
options: options
|
||||
type: 'bar',
|
||||
data: {
|
||||
labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
|
||||
datasets: [{
|
||||
label: '# of Votes',
|
||||
data: [12, 19, 3, 5, 2, 3]
|
||||
}]
|
||||
},
|
||||
options:{
|
||||
scales:{
|
||||
yAxes:[{
|
||||
ticks:{
|
||||
beginAtZero:true
|
||||
}
|
||||
}]
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
```
|
||||
|
||||
It's that easy to get started using Chart.js! From here you can explore the many options that can help you customise your charts with scales, tooltips, labels, colors, custom actions, and much more.
|
||||
|
||||
###Global chart configuration
|
||||
|
||||
This concept was introduced in Chart.js 1.0 to keep configuration DRY, and allow for changing options globally across chart types, avoiding the need to specify options for each instance, or the default for a particular chart type.
|
||||
|
||||
Chart.js merges configurations and options in a few places with the global defaults using chart type defaults and scales defaults. This way you can be as specific as you want in your individual chart configs, or change the defaults for Chart.js as a whole.
|
||||
|
||||
```javascript
|
||||
Chart.defaults.global = {
|
||||
responsive: true,
|
||||
responsiveAnimationDuration: 0,
|
||||
maintainAspectRatio: true,
|
||||
events: ["mousemove", "mouseout", "click", "touchstart", "touchmove", "touchend"],
|
||||
hover: {
|
||||
onHover: null,
|
||||
mode: 'single',
|
||||
animationDuration: 400,
|
||||
},
|
||||
onClick: null,
|
||||
defaultColor: 'rgba(0,0,0,0.1)',
|
||||
The global options are defined in `Chart.defaults.global`.
|
||||
|
||||
// Element defaults defined in element extensions
|
||||
elements: {},
|
||||
Name | Type | Default | Description
|
||||
--- | --- | --- | ---
|
||||
responsive | Boolean | true | Resizes when the canvas container does.
|
||||
responsiveAnimationDuration | Number | 0 | Duration in milliseconds it takes to animate to new size after a resize event.
|
||||
maintainAspectRatio | Boolean | true | Maintain the original canvas aspect ratio `(width / height)` when resizing
|
||||
events | Array[String] | `["mousemove", "mouseout", "click", "touchstart", "touchmove", "touchend"]` | Events that the chart should listen to for tooltips and hovering
|
||||
hover |-|-|-
|
||||
*hover*.onHover | Function | null | Called when any of the events fire. Called in the context of the chart and passed an array of active elements (bars, points, etc)
|
||||
*hover*.mode | String | 'single' | Sets which elements hover. Acceptable options are `'single'`, `'label'`, or `'dataset'`. `single` highlights the closest element. `label` highlights elements in all datasets at the same `X` value. `dataset` highlights the closest dataset.
|
||||
*hover*.animationDuration | Number | 400 | Duration in milliseconds it takes to animate hover style changes
|
||||
onClick | Function | null | Called if the event is of type 'mouseup' or 'click'. Called in the context of the chart and passed an array of active elements
|
||||
defaultColor | Color | 'rgba(0,0,0,0.1)' |
|
||||
legendCallback | Function | ` function (chart) { // the chart object to generate a legend from. }` | Function to generate a legend. Default implementation returns an HTML string.
|
||||
|
||||
// Legend callback function.
|
||||
// @param {Chart} chart : the chart object to generate a legend for
|
||||
legendCallback: legendCallback: function(chart) {
|
||||
var text = [];
|
||||
text.push('<ul class="' + chart.id + '-legend">');
|
||||
for (var i = 0; i < chart.data.datasets.length; i++) {
|
||||
text.push('<li><span style="background-color:' + chart.data.datasets[i].backgroundColor + '">');
|
||||
if (chart.data.datasets[i].label) {
|
||||
text.push(chart.data.datasets[i].label);
|
||||
}
|
||||
text.push('</span></li>');
|
||||
}
|
||||
text.push('</ul>');
|
||||
The global options for tooltips are defined in `Chart.defaults.global.tooltips`.
|
||||
|
||||
return text.join("");
|
||||
}
|
||||
Name | Type | Default | Description
|
||||
--- |:---:| --- | ---
|
||||
enabled | Boolean | true |
|
||||
custom | | null |
|
||||
mode | String | 'single' | Sets which elements appear in the tooltip. Acceptable options are `'single'` or `'label'`. `single` highlights the closest element. `label` highlights elements in all datasets at the same `X` value.
|
||||
backgroundColor | Color | 'rgba(0,0,0,0.8)' | Background color of the tooltip
|
||||
| | |
|
||||
Label | | | There are three labels you can control. `title`, `body`, `footer` the star (\*) represents one of these three. *(i.e. titleFontFamily, footerSpacing)*
|
||||
\*FontFamily | String | "'Helvetica Neue', 'Helvetica', 'Arial', sans-serif" |
|
||||
\*FontSize | Number | 12 |
|
||||
\*FontStyle | String | title - "bold", body - "normal", footer - "bold" |
|
||||
\*Spacing | Number | 2 |
|
||||
\*Color | Color | "#fff" |
|
||||
\*Align | String | "left" | text alignment. See [MDN Canvas Documentation](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/textAlign)
|
||||
titleMarginBottom | Number | 6 | Margin to add on bottom of title section
|
||||
footerMarginTop | Number | 6 | Margin to add before drawing the footer
|
||||
xPadding | Number | 6 | Padding to add on top and bottom of tooltip
|
||||
yPadding | Number | 6 | Padding to add on left and right of tooltip
|
||||
caretSize | Number | 5 | Size, in px, of the tooltip arrow
|
||||
cornerRadius | Number | 6 | Radius of tooltip corner curves
|
||||
xOffset | Number | 10 |
|
||||
multiKeyBackground | Color | "#fff" |
|
||||
| | |
|
||||
callbacks | - | - | V2.0 introduces callback functions as a replacement for the template engine in v1. The tooltip has the following callbacks for providing text. For all functions, 'this' will be the tooltip object create from the Chart.Tooltip constructor
|
||||
**Callback Functions** | | | All functions are called with the same arguments
|
||||
xLabel | String or Array[Strings] | | This is the xDataValue for each item to be displayed in the tooltip
|
||||
yLabel | String or Array[Strings] | | This is the yDataValue for each item to be displayed in the tooltip
|
||||
index | Number | | Data index.
|
||||
data | Object | | Data object passed to chart.
|
||||
`return`| String or Array[Strings] | | All functions must return either a string or an array of strings. Arrays of strings are treated as multiple lines of text.
|
||||
| | |
|
||||
*callbacks*.beforeTitle | Function | none | Text to render before the title
|
||||
*callbacks*.title | Function | `function(tooltipItems, data) { //Pick first xLabel }` | Text to render as the title
|
||||
*callbacks*.afterTitle | Function | none | Text to render after the ttiel
|
||||
*callbacks*.beforeBody | Function | none | Text to render before the body section
|
||||
*callbacks*.beforeLabel | Function | none | Text to render before an individual label
|
||||
*callbacks*.label | Function | `function(tooltipItem, data) { // Returns "datasetLabel: tooltipItem.yLabel" }` | Text to render as label
|
||||
*callbacks*.afterLabel | Function | none | Text to render after an individual label
|
||||
*callbacks*.afterBody | Function | none | Text to render after the body section
|
||||
*callbacks*.beforeFooter | Function | none | Text to render before the footer section
|
||||
*callbacks*.footer | Function | none | Text to render as the footer
|
||||
*callbacks*.afterFooter | Function | none | Text to render after the footer section
|
||||
|
||||
animation: {
|
||||
duration: 1000,
|
||||
easing: "easeOutQuart",
|
||||
onProgress: function() {},
|
||||
onComplete: function() {},
|
||||
},
|
||||
The global options for animations are defined in `Chart.defaults.global.animation`.
|
||||
|
||||
tooltips:{
|
||||
enabled: true,
|
||||
custom: null,
|
||||
backgroundColor: "rgba(0,0,0,0.8)",
|
||||
fontFamily: "'Helvetica Neue', 'Helvetica', 'Arial', sans-serif",
|
||||
fontSize: 10,
|
||||
fontStyle: "normal",
|
||||
fontColor: "#fff",
|
||||
titleFontFamily: "'Helvetica Neue', 'Helvetica', 'Arial', sans-serif",
|
||||
titleFontSize: 12,
|
||||
titleFontStyle: "bold",
|
||||
titleFontColor: "#fff",
|
||||
yPadding: 6,
|
||||
xPadding: 6,
|
||||
caretSize: 8,
|
||||
cornerRadius: 6,
|
||||
xOffset: 10,
|
||||
// V2.0 introduces callback functions as a replacement for the template engine in v1. The tooltip
|
||||
// has the following callbacks for providing text. For all functions, 'this' will be the tooltip object
|
||||
// create from the Chart.Tooltip constructor
|
||||
//
|
||||
// All functions are called with the same arguments
|
||||
// - xLabel : string or array of strings. This is the xDataValue for each item to be displayed in the tooltip
|
||||
// - yLabel : string or array of strings. This is the yDataValue for each item to be displayed in the tooltip
|
||||
// - index : number. Data index
|
||||
// - datasetIndex : number. Dataset index
|
||||
// - data : object. Data object passed to chart
|
||||
callbacks: {
|
||||
beforeTitle: helpers.noop,
|
||||
title: function(xLabel, yLabel, index, datasetIndex, data) {
|
||||
// If there are multiple items, use the xLabel of the
|
||||
return helpers.isArray(xLabel) ? xLabel[0] : xLabel;
|
||||
},
|
||||
afterTitle: helpers.noop,
|
||||
Name | Type | Default | Description
|
||||
--- |:---:| --- | ---
|
||||
duration | Number | 1000 | The number of milliseconds an animation takes.
|
||||
easing | String | "easeOutQuart" | Easing function to use.
|
||||
onProgress | Function | none |
|
||||
onComplete | Function |none |
|
||||
|
||||
beforeBody: helpers.noop,
|
||||
The global options for elements are defined in `Chart.defaults.global.elements`.
|
||||
|
||||
beforeLabel: helpers.noop,
|
||||
label: function(xLabel, yLabel, index, datasetIndex, data) {
|
||||
return this._data.datasets[datasetIndex].label + ': ' + yLabel;
|
||||
},
|
||||
afterLabel: helpers.noop,
|
||||
|
||||
afterBody: helpers.noop,
|
||||
|
||||
beforeFooter: helpers.noop,
|
||||
footer: helpers.noop,
|
||||
afterFooter: helpers.noop,
|
||||
},
|
||||
multiKeyBackground: '#fff',
|
||||
},
|
||||
|
||||
elements: {
|
||||
arc: {
|
||||
backgroundColor: Chart.defaults.global.defaultColor,
|
||||
borderColor: "#fff",
|
||||
borderWidth: 2
|
||||
},
|
||||
line: {
|
||||
tension: 0.4,
|
||||
backgroundColor: Chart.defaults.global.defaultColor,
|
||||
borderWidth: 3,
|
||||
borderColor: Chart.defaults.global.defaultColor,
|
||||
borderCapStyle: 'butt',
|
||||
borderDash: [],
|
||||
borderDashOffset: 0.0,
|
||||
borderJoinStyle: 'miter',
|
||||
fill: true, // do we fill in the area between the line and its base axis
|
||||
skipNull: true,
|
||||
drawNull: false,
|
||||
},
|
||||
point: {
|
||||
radius: 3,
|
||||
backgroundColor: Chart.defaults.global.defaultColor,
|
||||
borderWidth: 1,
|
||||
borderColor: Chart.defaults.global.defaultColor,
|
||||
// Hover
|
||||
hitRadius: 1,
|
||||
hoverRadius: 4,
|
||||
hoverBorderWidth: 1,
|
||||
},
|
||||
rectangle: {
|
||||
backgroundColor: Chart.defaults.global.defaultColor,
|
||||
borderWidth: 0,
|
||||
borderColor: Chart.defaults.global.defaultColor,
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
```
|
||||
Name | Type | Default | Description
|
||||
--- |:---:| --- | ---
|
||||
arc | - | - | -
|
||||
*arc*.backgroundColor | Color | `Chart.defaults.global.defaultColor` | Default fill color for arcs
|
||||
*arc*.borderColor | Color | "#fff" | Default stroke color for arcs
|
||||
*arc*.borderWidth | Number | 2 | Default stroke width for arcs
|
||||
line | - | - | -
|
||||
*line*.tension | Number | 0.4 | Default bezier curve tension. Set to `0` for no bezier curves.
|
||||
*line*.backgroundColor | Color | `Chart.defaults.global.defaultColor` | Default line fill color
|
||||
*line*.borderWidth | Number | 3 | Default line stroke width
|
||||
*line*.borderColor | Color | `Chart.defaults.global.defaultColor` | Default line stroke color
|
||||
*line*.borderCapStyle | String | 'butt' | Default line cap style. See [MDN](https://developer.mozilla.org/en/docs/Web/API/CanvasRenderingContext2D/lineCap)
|
||||
*line*.borderDash | Array | `[]` | Default line dash. See [MDN](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/setLineDash)
|
||||
*line*.borderDashOffset | Number | 0.0 | Default line dash offset. See [MDN](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/lineDashOffset)
|
||||
*line*.borderJoinStyle | String | 'miter' | Default line join style. See [MDN](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/lineJoin)
|
||||
*line*.fill | Boolean | true |
|
||||
point | - | - | -
|
||||
*point*.radius | Number | 3 | Default point radius
|
||||
*point*.backgroundColor | Color | `Chart.defaults.global.defaultColor` | Default point fill color
|
||||
*point*.borderWidth | Number | 1 | Default point stroke width
|
||||
*point*.borderColor | Color | `Chart.defaults.global.defaultColor` | Default point stroke color
|
||||
*point*.hitRadius | Number | 1 | Extra radius added to point radius for hit detection
|
||||
*point*.hoverRadius | Number | 4 | Default point radius when hovered
|
||||
*point*.hoverBorderWidth | Number | 1 | Default stroke width when hovered
|
||||
rectangle | - | - | -
|
||||
*rectangle*.backgroundColor | Color | `Chart.defaults.global.defaultColor` | Default bar fill color
|
||||
*rectangle*.borderWidth | Number | 0 | Default bar stroke width
|
||||
*rectangle*.borderColor | Color | `Chart.defaults.global.defaultColor` | Default bar stroke color
|
||||
|
||||
If for example, you wanted all charts created to be responsive, and resize when the browser window does, the following setting can be changed:
|
||||
|
||||
@@ -222,4 +196,4 @@ If for example, you wanted all charts created to be responsive, and resize when
|
||||
Chart.defaults.global.responsive = true;
|
||||
```
|
||||
|
||||
Now, every time we create a chart, `options.responsive` will be `true`.
|
||||
Now, every time we create a chart, `options.responsive` will be `true`.
|
||||
|
||||
@@ -1,227 +0,0 @@
|
||||
---
|
||||
title: Getting started
|
||||
anchor: getting-started
|
||||
---
|
||||
|
||||
###Scales
|
||||
|
||||
Scales in v2.0 of Chart.js are significantly more powerful, but also different than those of v1.0.
|
||||
- Multiple x & y axes are now supported.
|
||||
- A built-in label auto-skip feature now detects would-be overlapping ticks and labels and removes every nth label to keep things displaying normally.
|
||||
- Scale labels
|
||||
|
||||
Every scale extends a core scale class with the following options:
|
||||
|
||||
```javascript
|
||||
Chart.defaults.scale = {
|
||||
display: true,
|
||||
|
||||
// grid line settings
|
||||
gridLines: {
|
||||
show: true,
|
||||
color: "rgba(0, 0, 0, 0.1)",
|
||||
lineWidth: 1,
|
||||
drawOnChartArea: true,
|
||||
drawTicks: true,
|
||||
zeroLineWidth: 1,
|
||||
zeroLineColor: "rgba(0,0,0,0.25)",
|
||||
offsetGridLines: false,
|
||||
},
|
||||
|
||||
// scale label
|
||||
scaleLabel: {
|
||||
fontColor: '#666',
|
||||
fontFamily: 'Helvetica Neue',
|
||||
fontSize: 12,
|
||||
fontStyle: 'normal',
|
||||
|
||||
// actual label
|
||||
labelString: '',
|
||||
|
||||
// display property
|
||||
show: false,
|
||||
},
|
||||
|
||||
// label settings
|
||||
ticks: {
|
||||
beginAtZero: false,
|
||||
fontSize: 12,
|
||||
fontStyle: "normal",
|
||||
fontColor: "#666",
|
||||
fontFamily: "Helvetica Neue",
|
||||
maxRotation: 90,
|
||||
minRotation: 20,
|
||||
mirror: false,
|
||||
padding: 10,
|
||||
reverse: false,
|
||||
show: true,
|
||||
template: "<%=value%>",
|
||||
userCallback: false,
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
The `userCallback` method may be used for advanced tick customization. The following callback would display every label in scientific notation
|
||||
```javascript
|
||||
{
|
||||
scales: {
|
||||
xAxes: [{
|
||||
ticks: {
|
||||
// Return an empty string to draw the tick line but hide the tick label
|
||||
// Return `null` or `undefined` to hide the tick line entirely
|
||||
userCallback: function(value, index, values) {
|
||||
return value.toExponential();
|
||||
}
|
||||
}
|
||||
}]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### Category Scale
|
||||
The category scale will be familiar to those who have used v1.0. Labels are drawn in from the labels array included in the chart data.
|
||||
|
||||
The category scale extends the core scale class with the following tick template:
|
||||
|
||||
```javascript
|
||||
{
|
||||
position: "bottom",
|
||||
}
|
||||
```
|
||||
|
||||
#### Linear Scale
|
||||
The linear scale can be used to display numerical data. It can be placed on either the x or y axis. The scatter chart type automatically configures a line chart to use one of these scales for the x axis.
|
||||
|
||||
The linear scale extends the core scale class with the following tick template:
|
||||
|
||||
```javascript
|
||||
{
|
||||
position: "left",
|
||||
}
|
||||
```
|
||||
|
||||
#### Logarithmic Scale
|
||||
The logarithmic scale is used to display logarithmic data of course. It can be placed on either the x or y axis.
|
||||
|
||||
The log scale extends the core scale class with the following tick template:
|
||||
|
||||
```javascript
|
||||
{
|
||||
position: "left",
|
||||
ticks: {
|
||||
template: "<%var remain = value / (Math.pow(10, Math.floor(Chart.helpers.log10(value))));if (remain === 1 || remain === 2 || remain === 5) {%><%=value.toExponential()%><%} else {%><%= null %><%}%>",
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### Time Scale
|
||||
The time scale is used to display times and dates. It can be placed on the x axis. When building its ticks, it will automatically calculate the most comfortable unit base on the size of the scale.
|
||||
|
||||
The time scale extends the core scale class with the following tick template:
|
||||
|
||||
```javascript
|
||||
{
|
||||
position: "bottom",
|
||||
time: {
|
||||
// string/callback - By default, date objects are expected. You may use a pattern string from http://momentjs.com/docs/#/parsing/string-format/ to parse a time string format, or use a callback function that is passed the label, and must return a moment() instance.
|
||||
format: false,
|
||||
// string - By default, unit will automatically be detected. Override with 'week', 'month', 'year', etc. (see supported time measurements)
|
||||
unit: false,
|
||||
// string - By default, no rounding is applied. To round, set to a supported time unit eg. 'week', 'month', 'year', etc.
|
||||
round: false,
|
||||
// string - By default, is set to the detected (or manually overridden) time unit's `display` property (see supported time measurements). To override, use a pattern string from http://momentjs.com/docs/#/displaying/format/
|
||||
displayFormat: false
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
The following time measurements are supported:
|
||||
|
||||
```javascript
|
||||
{
|
||||
'millisecond': {
|
||||
display: 'SSS [ms]', // 002 ms
|
||||
maxStep: 1000,
|
||||
},
|
||||
'second': {
|
||||
display: 'h:mm:ss a', // 11:20:01 AM
|
||||
maxStep: 60,
|
||||
},
|
||||
'minute': {
|
||||
display: 'h:mm:ss a', // 11:20:01 AM
|
||||
maxStep: 60,
|
||||
},
|
||||
'hour': {
|
||||
display: 'MMM D, hA', // Sept 4, 5PM
|
||||
maxStep: 24,
|
||||
},
|
||||
'day': {
|
||||
display: 'll', // Sep 4 2015
|
||||
maxStep: 7,
|
||||
},
|
||||
'week': {
|
||||
display: 'll', // Week 46, or maybe "[W]WW - YYYY" ?
|
||||
maxStep: 4.3333,
|
||||
},
|
||||
'month': {
|
||||
display: 'MMM YYYY', // Sept 2015
|
||||
maxStep: 12,
|
||||
},
|
||||
'quarter': {
|
||||
display: '[Q]Q - YYYY', // Q3
|
||||
maxStep: 4,
|
||||
},
|
||||
'year': {
|
||||
display: 'YYYY', // 2015
|
||||
maxStep: false,
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
#### Radial Linear Scale
|
||||
The radial linear scale is used specifically for the radar chart type.
|
||||
|
||||
The radial linear scale extends the core scale class with the following tick template:
|
||||
|
||||
```javascript
|
||||
{
|
||||
animate: true,
|
||||
lineArc: false,
|
||||
position: "chartArea",
|
||||
|
||||
angleLines: {
|
||||
show: true,
|
||||
color: "rgba(0, 0, 0, 0.1)",
|
||||
lineWidth: 1
|
||||
},
|
||||
|
||||
// label settings
|
||||
ticks: {
|
||||
//Boolean - Show a backdrop to the scale label
|
||||
showLabelBackdrop: true,
|
||||
|
||||
//String - The colour of the label backdrop
|
||||
backdropColor: "rgba(255,255,255,0.75)",
|
||||
|
||||
//Number - The backdrop padding above & below the label in pixels
|
||||
backdropPaddingY: 2,
|
||||
|
||||
//Number - The backdrop padding to the side of the label in pixels
|
||||
backdropPaddingX: 2,
|
||||
},
|
||||
|
||||
pointLabels: {
|
||||
//String - Point label font declaration
|
||||
fontFamily: "'Arial'",
|
||||
|
||||
//String - Point label font weight
|
||||
fontStyle: "normal",
|
||||
|
||||
//Number - Point label font size in pixels
|
||||
fontSize: 10,
|
||||
|
||||
//String - Point label font colour
|
||||
fontColor: "#666",
|
||||
},
|
||||
}
|
||||
```
|
||||
@@ -0,0 +1,262 @@
|
||||
---
|
||||
title: Getting started
|
||||
anchor: scales
|
||||
---
|
||||
|
||||
###Scales
|
||||
|
||||
Scales in v2.0 of Chart.js are significantly more powerful, but also different than those of v1.0.
|
||||
- Multiple x & y axes are now supported.
|
||||
- A built-in label auto-skip feature now detects would-be overlapping ticks and labels and removes every nth label to keep things displaying normally.
|
||||
- Scale titles are now supported
|
||||
|
||||
Every scale extends a core scale class with the following options:
|
||||
|
||||
Name | Type | Default | Description
|
||||
--- |:---:| --- | ---
|
||||
type | String | Chart specific. | Type of scale being employed. Custom scales can be created and registered with a string key. Options: ["category"](#scales-category-scale), ["linear"](#scales-linear-scale), ["logarithmic"](#scales-logarithmic-scale), ["time"](#scales-time-scale), ["radialLinear"](#scales-radial-linear-scale)
|
||||
display | Boolean | true | If true, show the scale including gridlines, ticks, and labels. Overrides *gridLines.display*, *scaleLabel.display*, and *ticks.display*.
|
||||
**gridLines** | Array | - | Options for the grid lines that run perpendicular to the axis.
|
||||
*gridLines*.display | Boolean | true |
|
||||
*gridLines*.color | Color | "rgba(0, 0, 0, 0.1)" | Color of the grid lines.
|
||||
*gridLines*.lineWidth | Number | 1 | Stroke width of grid lines
|
||||
*gridLines*.drawOnChartArea | Boolean | true | If true, draw lines on the chart area inside the axis lines. This is useful when there are multiple axes and you need to control which grid lines are drawn
|
||||
*gridLines*.drawTicks | Boolean | true | If true, draw lines beside the ticks in the axis area beside the chart.
|
||||
*gridLines*.zeroLineWidth | Number | 1 | Stroke width of the grid line for the first index (index 0).
|
||||
*gridLines*.zeroLineColor | Color | "rgba(0, 0, 0, 0.25)" | Stroke color of the grid line for the first index (index 0).
|
||||
*gridLines*.offsetGridLines | Boolean | false | If true, offset labels from grid lines.
|
||||
**scaleLabel** | Array | | Title for the entire axis.
|
||||
*scaleLabel*.display | Boolean | false |
|
||||
*scaleLabel*.labelString | String | "" | The text for the title. (i.e. "# of People", "Response Choices")
|
||||
*scaleLabel*.fontColor | Color | "#666" | Font color for the scale title.
|
||||
*scaleLabel*.fontFamily| String | "Helvetica Neue" | Font family for the scale title, follows CSS font-family options.
|
||||
*scaleLabel*.fontSize | Number | 12 | Font size for the scale title.
|
||||
*scaleLabel*.fontStyle | String | "normal" | Font style for the scale title, follows CSS font-style options (i.e. normal, italic, oblique, initial, inherit).
|
||||
**ticks** | Array | | Settings for the labels that run along the axis.
|
||||
*ticks*.beginAtZero | Boolean | false | If true the scale will be begin at 0, if false the ticks will begin at your smallest data value.
|
||||
*ticks*.fontColor | Color | "#666" | Font color for the tick labels.
|
||||
*ticks*.fontFamily | String | "Helvetica Neue" | Font family for the tick labels, follows CSS font-family options.
|
||||
*ticks*.fontSize | Number | 12 | Font size for the tick labels.
|
||||
*ticks*.fontStyle | String | "normal" | Font style for the tick labels, follows CSS font-style options (i.e. normal, italic, oblique, initial, inherit).
|
||||
*ticks*.maxRotation | Number | 90 | Maximum rotation for tick labels when rotating to condense labels. Note: Rotation doesn't occur until necessary. *Note: Only applicable to horizontal scales.*
|
||||
*ticks*.minRotation | Number | 20 | *currently not-implemented* Minimum rotation for tick labels when condensing is necessary. *Note: Only applicable to horizontal scales.*
|
||||
*ticks*.padding | Number | 10 | Padding between the tick label and the axis. *Note: Only applicable to horizontal scales.*
|
||||
*ticks*.mirror | Boolean | false | Flips tick labels around axis, displaying the labels inside the chart instead of outside. *Note: Only applicable to vertical scales.*
|
||||
*ticks*.reverse | Boolean | false | Reverses order of tick labels.
|
||||
*ticks*.display | Boolean | true | If true, show the ticks.
|
||||
*ticks*.suggestedMin | Number | - | User defined minimum number for the scale, overrides minimum value *except for if* it is higher than the minimum value.
|
||||
*ticks*.suggestedMax | Number | - | User defined maximum number for the scale, overrides maximum value *except for if* it is lower than the maximum value.
|
||||
*ticks*.callback | Function | `function(value) { return '' + value; } ` | Returns the string representation of the tick value as it should be displayed on the chart.
|
||||
|
||||
The `callback` method may be used for advanced tick customization. The following callback would display every label in scientific notation
|
||||
```javascript
|
||||
{
|
||||
scales: {
|
||||
xAxes: [{
|
||||
ticks: {
|
||||
// Return an empty string to draw the tick line but hide the tick label
|
||||
// Return `null` or `undefined` to hide the tick line entirely
|
||||
userCallback: function(value, index, values) {
|
||||
return value.toExponential();
|
||||
}
|
||||
}
|
||||
}]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### Category Scale
|
||||
The category scale will be familiar to those who have used v1.0. Labels are drawn in from the labels array included in the chart data.
|
||||
|
||||
The category scale extends the core scale class with the following tick template:
|
||||
|
||||
```javascript
|
||||
{
|
||||
position: "bottom",
|
||||
}
|
||||
```
|
||||
|
||||
#### Linear Scale
|
||||
The linear scale can be used to display numerical data. It can be placed on either the x or y axis. The scatter chart type automatically configures a line chart to use one of these scales for the x axis.
|
||||
|
||||
The linear scale extends the core scale class with the following tick template:
|
||||
|
||||
```javascript
|
||||
{
|
||||
position: "left",
|
||||
ticks: {
|
||||
callback: function(tickValue, index, ticks) {
|
||||
var delta = ticks[1] - ticks[0];
|
||||
|
||||
// If we have a number like 2.5 as the delta, figure out how many decimal places we need
|
||||
if (Math.abs(delta) > 1) {
|
||||
if (tickValue !== Math.floor(tickValue)) {
|
||||
// not an integer
|
||||
delta = tickValue - Math.floor(tickValue);
|
||||
}
|
||||
}
|
||||
|
||||
var logDelta = helpers.log10(Math.abs(delta));
|
||||
var tickString = '';
|
||||
|
||||
if (tickValue !== 0) {
|
||||
var numDecimal = -1 * Math.floor(logDelta);
|
||||
numDecimal = Math.max(Math.min(numDecimal, 20), 0); // toFixed has a max of 20 decimal places
|
||||
tickString = tickValue.toFixed(numDecimal);
|
||||
} else {
|
||||
tickString = '0'; // never show decimal places for 0
|
||||
}
|
||||
|
||||
return tickString;
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### Logarithmic Scale
|
||||
The logarithmic scale is used to display logarithmic data of course. It can be placed on either the x or y axis.
|
||||
|
||||
The log scale extends the core scale class with the following tick template:
|
||||
|
||||
```javascript
|
||||
{
|
||||
position: "left",
|
||||
ticks: {
|
||||
callback: function(value) {
|
||||
var remain = value / (Math.pow(10, Math.floor(Chart.helpers.log10(value))));
|
||||
|
||||
if (remain === 1 || remain === 2 || remain === 5) {
|
||||
return value.toExponential();
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### Time Scale
|
||||
The time scale is used to display times and dates. It can be placed on the x axis. When building its ticks, it will automatically calculate the most comfortable unit base on the size of the scale.
|
||||
|
||||
The time scale extends the core scale class with the following tick template:
|
||||
|
||||
```javascript
|
||||
{
|
||||
position: "bottom",
|
||||
time: {
|
||||
// string/callback - By default, date objects are expected. You may use a pattern string from http://momentjs.com/docs/#/parsing/string-format/ to parse a time string format, or use a callback function that is passed the label, and must return a moment() instance.
|
||||
format: false,
|
||||
// string - By default, unit will automatically be detected. Override with 'week', 'month', 'year', etc. (see supported time measurements)
|
||||
unit: false,
|
||||
// string - By default, no rounding is applied. To round, set to a supported time unit eg. 'week', 'month', 'year', etc.
|
||||
round: false,
|
||||
// Moment js for each of the units. Replaces `displayFormat`
|
||||
// To override, use a pattern string from http://momentjs.com/docs/#/displaying/format/
|
||||
displayFormats: {
|
||||
'millisecond': 'SSS [ms]',
|
||||
'second': 'h:mm:ss a', // 11:20:01 AM
|
||||
'minute': 'h:mm:ss a', // 11:20:01 AM
|
||||
'hour': 'MMM D, hA', // Sept 4, 5PM
|
||||
'day': 'll', // Sep 4 2015
|
||||
'week': 'll', // Week 46, or maybe "[W]WW - YYYY" ?
|
||||
'month': 'MMM YYYY', // Sept 2015
|
||||
'quarter': '[Q]Q - YYYY', // Q3
|
||||
'year': 'YYYY', // 2015
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
The following time measurements are supported:
|
||||
|
||||
```javascript
|
||||
{
|
||||
'millisecond': {
|
||||
display: 'SSS [ms]', // 002 ms
|
||||
maxStep: 1000,
|
||||
},
|
||||
'second': {
|
||||
display: 'h:mm:ss a', // 11:20:01 AM
|
||||
maxStep: 60,
|
||||
},
|
||||
'minute': {
|
||||
display: 'h:mm:ss a', // 11:20:01 AM
|
||||
maxStep: 60,
|
||||
},
|
||||
'hour': {
|
||||
display: 'MMM D, hA', // Sept 4, 5PM
|
||||
maxStep: 24,
|
||||
},
|
||||
'day': {
|
||||
display: 'll', // Sep 4 2015
|
||||
maxStep: 7,
|
||||
},
|
||||
'week': {
|
||||
display: 'll', // Week 46, or maybe "[W]WW - YYYY" ?
|
||||
maxStep: 4.3333,
|
||||
},
|
||||
'month': {
|
||||
display: 'MMM YYYY', // Sept 2015
|
||||
maxStep: 12,
|
||||
},
|
||||
'quarter': {
|
||||
display: '[Q]Q - YYYY', // Q3
|
||||
maxStep: 4,
|
||||
},
|
||||
'year': {
|
||||
display: 'YYYY', // 2015
|
||||
maxStep: false,
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
#### Radial Linear Scale
|
||||
The radial linear scale is used specifically for the radar chart type.
|
||||
|
||||
The radial linear scale extends the core scale class with the following tick template:
|
||||
|
||||
```javascript
|
||||
{
|
||||
animate: true,
|
||||
lineArc: false,
|
||||
position: "chartArea",
|
||||
|
||||
angleLines: {
|
||||
display: true,
|
||||
color: "rgba(0, 0, 0, 0.1)",
|
||||
lineWidth: 1
|
||||
},
|
||||
|
||||
// label settings
|
||||
ticks: {
|
||||
//Boolean - Show a backdrop to the scale label
|
||||
showLabelBackdrop: true,
|
||||
|
||||
//String - The colour of the label backdrop
|
||||
backdropColor: "rgba(255,255,255,0.75)",
|
||||
|
||||
//Number - The backdrop padding above & below the label in pixels
|
||||
backdropPaddingY: 2,
|
||||
|
||||
//Number - The backdrop padding to the side of the label in pixels
|
||||
backdropPaddingX: 2,
|
||||
|
||||
//Number - Limit the maximum number of ticks
|
||||
maxTicksLimit: 11,
|
||||
},
|
||||
|
||||
pointLabels: {
|
||||
//String - Point label font declaration
|
||||
fontFamily: "'Arial'",
|
||||
|
||||
//String - Point label font weight
|
||||
fontStyle: "normal",
|
||||
|
||||
//Number - Point label font size in pixels
|
||||
fontSize: 10,
|
||||
|
||||
//String - Point label font colour
|
||||
fontColor: "#666",
|
||||
},
|
||||
}
|
||||
```
|
||||
+24
-55
@@ -15,7 +15,7 @@ Often, it is used to show trend data, and the comparison of two data sets.
|
||||
```javascript
|
||||
var myLineChart = new Chart(ctx, {
|
||||
type: 'line',
|
||||
data: data,
|
||||
data: data,
|
||||
options: options
|
||||
});
|
||||
```
|
||||
@@ -23,7 +23,7 @@ var myLineChart = new Chart(ctx, {
|
||||
Alternatively a line chart can be created using syntax similar to the v1.0 syntax
|
||||
```javascript
|
||||
var myLineChart = Chart.Line(ctx, {
|
||||
data: data,
|
||||
data: data,
|
||||
options: options
|
||||
});
|
||||
```
|
||||
@@ -113,37 +113,22 @@ The label key on each dataset is optional, and can be used when generating a sca
|
||||
|
||||
These are the customisation options specific to Line charts. These options are merged with the [global chart configuration options](#getting-started-global-chart-configuration), and form the options of the chart.
|
||||
|
||||
```javascript
|
||||
{
|
||||
// Boolean - if true, line stack on top of each other along the y axis
|
||||
stacked: false,
|
||||
The default options for line chart are defined in `Chart.defaults.Line`.
|
||||
|
||||
hover: {
|
||||
// String - We use a label hover mode since the x axis displays data by the index in the dataset
|
||||
mode: "label"
|
||||
},
|
||||
|
||||
scales: {
|
||||
// Defines all of the x axes used in the chart. See the [scale documentation](#getting-started-scales) for details on the available options
|
||||
xAxes: [{
|
||||
// String - type of scale. Built in types are 'category' and 'linear'
|
||||
type: 'category',
|
||||
|
||||
// String - id of the axis so that data can bind to it
|
||||
id: "x-axis-1", // need an ID so datasets can reference the scale
|
||||
}],
|
||||
|
||||
// Defines all of the y axes used in the chart.
|
||||
// By default, the line chart uses a linear scale along the y axis
|
||||
yAxes: [{
|
||||
type: 'linear',
|
||||
|
||||
// String - ID of the axis for data binding
|
||||
id: "y-axis-1",
|
||||
}],
|
||||
}
|
||||
};
|
||||
```
|
||||
Name | Type | Default | Description
|
||||
--- | --- | --- | ---
|
||||
stacked | Boolean | false | If true, lines stack on top of each other along the y axis.
|
||||
*hover*.mode | String | "label" | Label's hover mode. "label" is used since the x axis displays data by the index in the dataset.
|
||||
scales | - | - | -
|
||||
*scales*.xAxes | Array | `[{type:"category","id":"x-axis-1"}]` | Defines all of the x axes used in the chart. See the [scale documentation](#getting-started-scales) for details on the available options.
|
||||
*Options for xAxes* | | |
|
||||
type | String | "category" | As defined in ["Category"](#scales-category-scale).
|
||||
id | String | "x-axis-1" | Id of the axis so that data can bind to it.
|
||||
| | |
|
||||
*scales*.yAxes | Array | `[{type:"linear","id":"y-axis-1"}]` | Defines all of the x axes used in the chart. See the [scale documentation](#getting-started-scales) for details on the available options.
|
||||
*Options for yAxes* | | |
|
||||
type | String | "linear" | As defined in ["Linear"](#scales-linear-scale).
|
||||
id | String | "y-axis-1" | Id of the axis so that data can bind to it.
|
||||
|
||||
You can override these for your `Chart` instance by passing a member `options` into the `Line` method.
|
||||
|
||||
@@ -152,10 +137,10 @@ For example, we could have a line chart display without an x axis by doing the f
|
||||
```javascript
|
||||
new Chart(ctx, {
|
||||
type: 'line',
|
||||
data: data,
|
||||
data: data,
|
||||
options: {
|
||||
xAxes: [{
|
||||
show: false
|
||||
display: false
|
||||
}]
|
||||
}
|
||||
});
|
||||
@@ -181,32 +166,16 @@ canvas.onclick = function(evt){
|
||||
|
||||
This functionality may be useful for implementing DOM based tooltips, or triggering custom behaviour in your application.
|
||||
|
||||
#### .getElementAtEvent( event )
|
||||
Calling `getElementAtEvent(event)` on your Chart instance passing an argument of an event, or jQuery event, will return the single element at the event position. If there are multiple items within range, only the first is returned
|
||||
|
||||
#### .update( )
|
||||
|
||||
Calling `update()` on your Chart instance will re-render the chart with any updated values, allowing you to edit the value of multiple existing points, then render those in one animated render loop.
|
||||
Calling `update()` on your Chart instance will re-render the chart with any updated values, allowing you to edit the value of multiple existing points, then render those in one animated render loop. You can safely call `update()` after changing the entire data object on the chart.
|
||||
|
||||
```javascript
|
||||
myLineChart.datasets[0].points[2].value = 50;
|
||||
myLineChart.data.datasets[0].data[2] = 50;
|
||||
// Would update the first dataset's value of 'March' to be 50
|
||||
myLineChart.update();
|
||||
// Calling update now animates the position of March from 90 to 50.
|
||||
```
|
||||
|
||||
#### .addData( valuesArray, label )
|
||||
|
||||
Calling `addData(valuesArray, label)` on your Chart instance passing an array of values for each dataset, along with a label for those points.
|
||||
|
||||
```javascript
|
||||
// The values array passed into addData should be one for each dataset in the chart
|
||||
myLineChart.addData([40, 60], "August");
|
||||
// This new data will now animate at the end of the chart.
|
||||
```
|
||||
|
||||
#### .removeData( )
|
||||
|
||||
Calling `removeData()` on your Chart instance will remove the first value for all datasets on the chart.
|
||||
|
||||
```javascript
|
||||
myLineChart.removeData();
|
||||
// The chart will remove the first point and animate other points into place
|
||||
```
|
||||
|
||||
+77
-177
@@ -14,8 +14,9 @@ It is sometimes used to show trend data, and the comparison of multiple data set
|
||||
|
||||
### Example usage
|
||||
```javascript
|
||||
var myBarChart = new Chart(ctx).Bar({
|
||||
data: data,
|
||||
var myBarChart = new Chart(ctx,{
|
||||
type: 'bar',
|
||||
data: data,
|
||||
options: options
|
||||
});
|
||||
```
|
||||
@@ -72,212 +73,111 @@ The label key on each dataset is optional, and can be used when generating a sca
|
||||
|
||||
These are the customisation options specific to Bar charts. These options are merged with the [global chart configuration options](#getting-started-global-chart-configuration), and form the options of the chart.
|
||||
|
||||
```javascript
|
||||
{
|
||||
// Boolean - if true, bars stack on top of each other
|
||||
stacked: false,
|
||||
The default options for bar chart are defined in `Chart.defaults.Bar`.
|
||||
|
||||
hover: {
|
||||
// String - We use a label hover mode since the x axis displays data by the index in the dataset
|
||||
mode: "label"
|
||||
},
|
||||
|
||||
scales: {
|
||||
// The bar chart officially supports only 1 x-axis but uses an array to keep the API consistent. Use a scatter chart if you need multiple x axes.
|
||||
xAxes: [{
|
||||
// String - type of axis to use. Should not be changed from 'dataset'.
|
||||
scaleType: "dataset", // scatter should not use a dataset axis
|
||||
|
||||
// Boolean - if true, show the scale
|
||||
display: true,
|
||||
|
||||
// String - position of the scale. possible options are "top" and "bottom" for dataset scales
|
||||
position: "bottom",
|
||||
|
||||
// String - id of the axis so that data can bind to it
|
||||
id: "x-axis-1", // need an ID so datasets can reference the scale
|
||||
|
||||
// grid line settings
|
||||
gridLines: {
|
||||
// Boolean - if true, show the grid lines
|
||||
show: true,
|
||||
|
||||
// String - color of the grid lines
|
||||
color: "rgba(0, 0, 0, 0.05)",
|
||||
|
||||
// Number - width of the grid lines
|
||||
lineWidth: 1,
|
||||
|
||||
// Boolean - if true draw lines on the chart area
|
||||
drawOnChartArea: true,
|
||||
|
||||
// Boolean - if true draw ticks in the axis area
|
||||
drawTicks: true,
|
||||
|
||||
// Number - width of the grid line for the first index (index 0)
|
||||
zeroLineWidth: 1,
|
||||
|
||||
// String - color of the grid line for the first index
|
||||
zeroLineColor: "rgba(0,0,0,0.25)",
|
||||
|
||||
// Boolean - if true, offset labels from grid lines
|
||||
offsetGridLines: false,
|
||||
},
|
||||
|
||||
// label settings
|
||||
labels: {
|
||||
// Boolean - if true show labels
|
||||
show: true,
|
||||
|
||||
// String - template string for labels
|
||||
template: "<%=value%>",
|
||||
|
||||
// Number - label font size
|
||||
fontSize: 12,
|
||||
|
||||
// String - label font style
|
||||
fontStyle: "normal",
|
||||
|
||||
// String - label font color
|
||||
fontColor: "#666",
|
||||
|
||||
// String - label font family
|
||||
fontFamily: "Helvetica Neue",
|
||||
},
|
||||
}],
|
||||
yAxes: [{
|
||||
// String - type of axis. 'linear' is the default but extensions may provide other types such as logarithmic
|
||||
scaleType: "linear",
|
||||
|
||||
// Boolean - if true, show the scale
|
||||
display: true,
|
||||
|
||||
// String - position of axis. Vertical axes can have either "left" or "right"
|
||||
position: "left",
|
||||
|
||||
// ID of the axis for data binding
|
||||
id: "y-axis-1",
|
||||
|
||||
// grid line settings
|
||||
gridLines: {
|
||||
// Boolean - if true, show the grid lines
|
||||
show: true,
|
||||
|
||||
// String - color of the grid lines
|
||||
color: "rgba(0, 0, 0, 0.05)",
|
||||
|
||||
// Number - width of the grid lines
|
||||
lineWidth: 1,
|
||||
|
||||
// Boolean - if true draw lines on the chart area
|
||||
drawOnChartArea: true,
|
||||
|
||||
// Boolean - if true draw ticks in the axis area
|
||||
drawTicks: true,
|
||||
|
||||
// Number - width of the grid line representing a numerical value of 0
|
||||
zeroLineWidth: 1,
|
||||
|
||||
// String - color of the grid line representing a numerical value of 0
|
||||
zeroLineColor: "rgba(0,0,0,0.25)",
|
||||
},
|
||||
|
||||
// Boolean - if true ensures that the scale always has a 0 point
|
||||
beginAtZero: false,
|
||||
|
||||
// Object - if specified, allows the user to override the step generation algorithm.
|
||||
// Contains the following values
|
||||
// start: // number to start at
|
||||
// stepWidth: // size of step
|
||||
// steps: // number of steps
|
||||
override: null,
|
||||
|
||||
// label settings
|
||||
labels: {
|
||||
// Boolean - if true show labels
|
||||
show: true,
|
||||
|
||||
// String - template string for labels
|
||||
template: "<%=value%>",
|
||||
|
||||
// Function - if specified this is passed the tick value, index, and the array of all tick values. Returns a string that is used as the label for that value
|
||||
userCallback: null,
|
||||
|
||||
// Number - label font size
|
||||
fontSize: 12,
|
||||
|
||||
// String - label font style
|
||||
fontStyle: "normal",
|
||||
|
||||
// String - label font color
|
||||
fontColor: "#666",
|
||||
|
||||
// String - label font family
|
||||
fontFamily: "Helvetica Neue",
|
||||
},
|
||||
}],
|
||||
},
|
||||
};
|
||||
```
|
||||
Name | Type | Default | Description
|
||||
--- |:---:| --- | ---
|
||||
stacked | Boolean | false |
|
||||
*hover*.mode | String | "label" | Label's hover mode. "label" is used since the x axis displays data by the index in the dataset.
|
||||
scales | Array | - | -
|
||||
*scales*.xAxes | Array | | The bar chart officially supports only 1 x-axis but uses an array to keep the API consistent. Use a scatter chart if you need multiple x axes.
|
||||
*Options for xAxes* | | |
|
||||
type | String | "Category" | As defined in [Scales](#scales-category-scale).
|
||||
display | Boolean | true | If true, show the scale.
|
||||
position | String | "bottom" | Position of the scale. Options are "top" and "bottom" for dataset scales.
|
||||
id | String | "x-axis-1" | Id of the axis so that data can bind to it
|
||||
categoryPercentage | Number | 0.8 | Percent (0-1) of the available width (the space between the gridlines for small datasets) for each data-point to use for the bars. [Read More](#bar-chart-barpercentage-vs-categorypercentage)
|
||||
barPercentage | Number | 0.9 | Percent (0-1) of the available width each bar should be within the category percentage. 1.0 will take the whole category width and put the bars right next to each other. [Read More](#bar-chart-barpercentage-vs-categorypercentage)
|
||||
gridLines | Array | [See Scales](#scales) |
|
||||
*gridLines*.offsetGridLines | Boolean | true | If true, the bars for a particular data point fall between the grid lines. If false, the grid line will go right down the middle of the bars.
|
||||
scaleLabel | Array | [See Scales](#scales) |
|
||||
ticks | Array | [See Scales](#scales) |
|
||||
| | |
|
||||
*scales*.yAxes | Array | `[{ type: "linear" }]` |
|
||||
*Options for xAxes* | | |
|
||||
type | String | "linear" | As defined in [Scales](#scales-linear-scale).
|
||||
display | Boolean | true | If true, show the scale.
|
||||
position | String | "left" | Position of the scale. Options are "left" and "right" for dataset scales.
|
||||
id | String | "y-axis-1" | Id of the axis so that data can bind to it.
|
||||
gridLines | Array | [See Scales](#scales) |
|
||||
scaleLabel | Array | [See Scales](#scales) |
|
||||
ticks | Array | [See Scales](#scales) |
|
||||
|
||||
You can override these for your `Chart` instance by passing a second argument into the `Bar` method as an object with the keys you want to override.
|
||||
|
||||
For example, we could have a bar chart without a stroke on each bar by doing the following:
|
||||
|
||||
```javascript
|
||||
new Chart(ctx).Bar({
|
||||
data: data,
|
||||
new Chart(ctx,{
|
||||
type:"bar",
|
||||
data: data,
|
||||
options: {
|
||||
barShowStroke: false
|
||||
scales: {
|
||||
xAxes: [{
|
||||
stacked: true,
|
||||
}],
|
||||
yAxes: [{
|
||||
stacked: true
|
||||
}]
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
// This will create a chart with all of the default options, merged from the global config,
|
||||
// and the Bar chart defaults but this particular instance will have `barShowStroke` set to false.
|
||||
// and the Bar chart defaults but this particular instance will have `stacked` set to true
|
||||
// for both x and y axes.
|
||||
```
|
||||
|
||||
We can also change these defaults values for each Bar type that is created, this object is available at `Chart.defaults.Bar`.
|
||||
|
||||
#### barPercentage vs categoryPercentage
|
||||
|
||||
The following shows the relationship between the bar percentage option and the category percentage option.
|
||||
|
||||
```text
|
||||
// categoryPercentage: 1.0
|
||||
// barPercentage: 1.0
|
||||
Bar: | 1.0 | 1.0 |
|
||||
Category: | 1.0 |
|
||||
Sample: |===========|
|
||||
|
||||
// categoryPercentage: 1.0
|
||||
// barPercentage: 0.5
|
||||
Bar: |.5| |.5|
|
||||
Category: | 1.0 |
|
||||
Sample: |==============|
|
||||
|
||||
// categoryPercentage: 0.5
|
||||
// barPercentage: 1.0
|
||||
Bar: |1.||1.|
|
||||
Category: | .5 |
|
||||
Sample: |==============|
|
||||
```
|
||||
### Prototype methods
|
||||
|
||||
#### .getBarsAtEvent( event )
|
||||
#### .getElementsAtEvent( event )
|
||||
|
||||
Calling `getBarsAtEvent(event)` on your Chart instance passing an argument of an event, or jQuery event, will return the bar elements that are at that the same position of that event.
|
||||
Calling `getElementsAtEvent(event)` on your Chart instance passing an argument of an event, or jQuery event, will return the point elements that are at that the same position of that event.
|
||||
|
||||
```javascript
|
||||
canvas.onclick = function(evt){
|
||||
var activeBars = myBarChart.getBarsAtEvent(evt);
|
||||
// => activeBars is an array of bars on the canvas that are at the same position as the click event.
|
||||
var activePoints = myLineChart.getElementsAtEvent(evt);
|
||||
// => activePoints is an array of points on the canvas that are at the same position as the click event.
|
||||
};
|
||||
```
|
||||
|
||||
This functionality may be useful for implementing DOM based tooltips, or triggering custom behaviour in your application.
|
||||
|
||||
#### .getElementAtEvent( event )
|
||||
Calling `getElementAtEvent(event)` on your Chart instance passing an argument of an event, or jQuery event, will return the single element at the event position. If there are multiple items within range, only the first is returned
|
||||
|
||||
#### .update( )
|
||||
|
||||
Calling `update()` on your Chart instance will re-render the chart with any updated values, allowing you to edit the value of multiple existing points, then render those in one animated render loop.
|
||||
|
||||
```javascript
|
||||
myBarChart.datasets[0].bars[2].value = 50;
|
||||
myBarChart.data.datasets[0].data[2] = 50;
|
||||
// Would update the first dataset's value of 'March' to be 50
|
||||
myBarChart.update();
|
||||
// Calling update now animates the position of March from 90 to 50.
|
||||
```
|
||||
|
||||
#### .addData( valuesArray, label )
|
||||
|
||||
Calling `addData(valuesArray, label)` on your Chart instance passing an array of values for each dataset, along with a label for those bars.
|
||||
|
||||
```javascript
|
||||
// The values array passed into addData should be one for each dataset in the chart
|
||||
myBarChart.addData([40, 60], "August");
|
||||
// The new data will now animate at the end of the chart.
|
||||
```
|
||||
|
||||
#### .removeData( )
|
||||
|
||||
Calling `removeData()` on your Chart instance will remove the first value for all datasets on the chart.
|
||||
|
||||
```javascript
|
||||
myBarChart.removeData();
|
||||
// The chart will now animate and remove the first bar
|
||||
```
|
||||
```
|
||||
+38
-76
@@ -15,7 +15,11 @@ They are often useful for comparing the points of two or more different data set
|
||||
###Example usage
|
||||
|
||||
```javascript
|
||||
var myRadarChart = new Chart(ctx).Radar(data, options);
|
||||
var myRadarChart = new Chart(ctx,{
|
||||
type:'radar',
|
||||
data: data,
|
||||
options: options
|
||||
});
|
||||
```
|
||||
|
||||
###Data structure
|
||||
@@ -25,22 +29,22 @@ var data = {
|
||||
datasets: [
|
||||
{
|
||||
label: "My First dataset",
|
||||
fillColor: "rgba(220,220,220,0.2)",
|
||||
strokeColor: "rgba(220,220,220,1)",
|
||||
pointColor: "rgba(220,220,220,1)",
|
||||
pointStrokeColor: "#fff",
|
||||
pointHighlightFill: "#fff",
|
||||
pointHighlightStroke: "rgba(220,220,220,1)",
|
||||
backgroundColor: "rgba(220,220,220,0.2)",
|
||||
borderColor: "rgba(220,220,220,1)",
|
||||
pointBackgroundColor: "rgba(220,220,220,1)",
|
||||
pointBorderColor: "#fff",
|
||||
pointHoverBackgroundColor: "#fff",
|
||||
pointHoverBorderColor: "rgba(220,220,220,1)",
|
||||
data: [65, 59, 90, 81, 56, 55, 40]
|
||||
},
|
||||
{
|
||||
label: "My Second dataset",
|
||||
fillColor: "rgba(151,187,205,0.2)",
|
||||
strokeColor: "rgba(151,187,205,1)",
|
||||
pointColor: "rgba(151,187,205,1)",
|
||||
pointStrokeColor: "#fff",
|
||||
pointHighlightFill: "#fff",
|
||||
pointHighlightStroke: "rgba(151,187,205,1)",
|
||||
backgroundColor: "rgba(151,187,205,0.2)",
|
||||
borderColor: "rgba(151,187,205,1)",
|
||||
pointBackgroundColor: "rgba(151,187,205,1)",
|
||||
pointBorderColor: "#fff",
|
||||
pointHoverBackgroundColor: "#fff",
|
||||
pointHoverBorderColor: "rgba(151,187,205,1)",
|
||||
data: [28, 48, 40, 19, 96, 27, 100]
|
||||
}
|
||||
]
|
||||
@@ -55,77 +59,35 @@ The label key on each dataset is optional, and can be used when generating a sca
|
||||
|
||||
These are the customisation options specific to Radar charts. These options are merged with the [global chart configuration options](#getting-started-global-chart-configuration), and form the options of the chart.
|
||||
|
||||
The default options for radar chart are defined in `Chart.defaults.radar`.
|
||||
|
||||
```javascript
|
||||
{
|
||||
//Boolean - Whether to show lines for each scale point
|
||||
scaleShowLine : true,
|
||||
|
||||
//Boolean - Whether we show the angle lines out of the radar
|
||||
angleShowLineOut : true,
|
||||
|
||||
//Boolean - Whether to show labels on the scale
|
||||
scaleShowLabels : false,
|
||||
|
||||
// Boolean - Whether the scale should begin at zero
|
||||
scaleBeginAtZero : true,
|
||||
|
||||
//String - Colour of the angle line
|
||||
angleLineColor : "rgba(0,0,0,.1)",
|
||||
|
||||
//Number - Pixel width of the angle line
|
||||
angleLineWidth : 1,
|
||||
|
||||
//String - Point label font declaration
|
||||
pointLabelFontFamily : "'Arial'",
|
||||
|
||||
//String - Point label font weight
|
||||
pointLabelFontStyle : "normal",
|
||||
|
||||
//Number - Point label font size in pixels
|
||||
pointLabelFontSize : 10,
|
||||
|
||||
//String - Point label font colour
|
||||
pointLabelFontColor : "#666",
|
||||
|
||||
//Boolean - Whether to show a dot for each point
|
||||
pointDot : true,
|
||||
|
||||
//Number - Radius of each point dot in pixels
|
||||
pointDotRadius : 3,
|
||||
|
||||
//Number - Pixel width of point dot stroke
|
||||
pointDotStrokeWidth : 1,
|
||||
|
||||
//Number - amount extra to add to the radius to cater for hit detection outside the drawn point
|
||||
pointHitDetectionRadius : 20,
|
||||
|
||||
//Boolean - Whether to show a stroke for datasets
|
||||
datasetStroke : true,
|
||||
|
||||
//Number - Pixel width of dataset stroke
|
||||
datasetStrokeWidth : 2,
|
||||
|
||||
//Boolean - Whether to fill the dataset with a colour
|
||||
datasetFill : true,
|
||||
{% raw %}
|
||||
//String - A legend template
|
||||
legendTemplate : "<ul class=\"<%=name.toLowerCase()%>-legend\"><% for (var i=0; i<datasets.length; i++){%><li><span style=\"background-color:<%=datasets[i].strokeColor%>\"></span><%if(datasets[i].label){%><%=datasets[i].label%><%}%></li><%}%></ul>"
|
||||
{% endraw %}
|
||||
}
|
||||
```
|
||||
|
||||
Name | Type | Default | Description
|
||||
--- | --- | --- | ---
|
||||
scale | Array | [See Scales](#scales) and [Defaults for Radial Linear Scale](#scales-radial-linear-scale) | Options for the one scale used on the chart. Use this to style the ticks, labels, and grid lines.
|
||||
*scale*.type | String |"radialLinear" | As defined in ["Radial Linear"](#scales-radial-linear-scale).
|
||||
*elements*.line | Array | | Options for all line elements used on the chart, as defined in the global elements, duplicated here to show Radar chart specific defaults.
|
||||
*elements.line*.tension | Number | 0 | Tension exhibited by lines when calculating splineCurve.
|
||||
|
||||
You can override these for your `Chart` instance by passing a second argument into the `Radar` method as an object with the keys you want to override.
|
||||
|
||||
For example, we could have a radar chart without a point for each on piece of data by doing the following:
|
||||
|
||||
```javascript
|
||||
new Chart(ctx).Radar(data, {
|
||||
pointDot: false
|
||||
new Chart(ctx, {
|
||||
type:"radar",
|
||||
data: data,
|
||||
options: {
|
||||
scale: {
|
||||
reverse: true,
|
||||
ticks: {
|
||||
beginAtZero: true
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
// This will create a chart with all of the default options, merged from the global config,
|
||||
// and the Bar chart defaults but this particular instance will have `pointDot` set to false.
|
||||
// and the Radar chart defaults but this particular instance's scale will be reversed as
|
||||
// well as the ticks beginning at zero.
|
||||
```
|
||||
|
||||
We can also change these defaults values for each Radar type that is created, this object is available at `Chart.defaults.Radar`.
|
||||
@@ -174,4 +136,4 @@ Calling `removeData()` on your Chart instance will remove the first value for al
|
||||
```javascript
|
||||
myRadarChart.removeData();
|
||||
// Other points will now animate to their correct positions.
|
||||
```
|
||||
```
|
||||
|
||||
@@ -60,52 +60,13 @@ As you can see, for the chart data you pass in an array of objects, with a value
|
||||
|
||||
These are the customisation options specific to Polar Area charts. These options are merged with the [global chart configuration options](#getting-started-global-chart-configuration), and form the options of the chart.
|
||||
|
||||
```javascript
|
||||
{
|
||||
//Boolean - Show a backdrop to the scale label
|
||||
scaleShowLabelBackdrop : true,
|
||||
|
||||
//String - The colour of the label backdrop
|
||||
scaleBackdropColor : "rgba(255,255,255,0.75)",
|
||||
|
||||
// Boolean - Whether the scale should begin at zero
|
||||
scaleBeginAtZero : true,
|
||||
|
||||
//Number - The backdrop padding above & below the label in pixels
|
||||
scaleBackdropPaddingY : 2,
|
||||
|
||||
//Number - The backdrop padding to the side of the label in pixels
|
||||
scaleBackdropPaddingX : 2,
|
||||
|
||||
//Boolean - Show line for each value in the scale
|
||||
scaleShowLine : true,
|
||||
|
||||
//Boolean - Stroke a line around each segment in the chart
|
||||
segmentShowStroke : true,
|
||||
|
||||
//String - The colour of the stroke on each segment.
|
||||
segmentStrokeColor : "#fff",
|
||||
|
||||
//Number - The width of the stroke value in pixels
|
||||
segmentStrokeWidth : 2,
|
||||
|
||||
//Number - Amount of animation steps
|
||||
animationSteps : 100,
|
||||
|
||||
//String - Animation easing effect.
|
||||
animationEasing : "easeOutBounce",
|
||||
|
||||
//Boolean - Whether to animate the rotation of the chart
|
||||
animateRotate : true,
|
||||
|
||||
//Boolean - Whether to animate scaling the chart from the centre
|
||||
animateScale : false,
|
||||
{% raw %}
|
||||
//String - A legend template
|
||||
legendTemplate : "<ul class=\"<%=name.toLowerCase()%>-legend\"><% for (var i=0; i<segments.length; i++){%><li><span style=\"background-color:<%=segments[i].fillColor%>\"></span><%if(segments[i].label){%><%=segments[i].label%><%}%></li><%}%></ul>"
|
||||
{% endraw %}
|
||||
}
|
||||
```
|
||||
Name | Type | Default | Description
|
||||
--- | --- | --- | ---
|
||||
scale | Array | [See Scales](#scales) and [Defaults for Radial Linear Scale](#getting-started-radial-linear-scale) | Options for the one scale used on the chart. Use this to style the ticks, labels, and grid.
|
||||
*scale*.type | String |"radialLinear" | As defined in ["Radial Linear"](#scales-radial-linear-scale).
|
||||
*scale*.lineArc | Boolean | true | When true, lines are circular.
|
||||
*animation*.animateRotate | Boolean |true | If true, will animate the rotation of the chart.
|
||||
*animation*.animateScale | Boolean | true | If true, will animate scaling the chart.
|
||||
|
||||
You can override these for your `Chart` instance by passing a second argument into the `PolarArea` method as an object with the keys you want to override.
|
||||
|
||||
|
||||
@@ -24,35 +24,44 @@ They are also registered under two aliases in the `Chart` core. Other than their
|
||||
|
||||
```javascript
|
||||
// For a pie chart
|
||||
var myPieChart = new Chart(ctx[0]).Pie(data,options);
|
||||
var myPieChart = new Chart(ctx[0],{
|
||||
type:'pie',
|
||||
data: data,
|
||||
options: options
|
||||
});
|
||||
|
||||
// And for a doughnut chart
|
||||
var myDoughnutChart = new Chart(ctx[1]).Doughnut(data,options);
|
||||
var myDoughnutChart = new Chart(ctx[1], {
|
||||
type:'doughnut',
|
||||
data: data,
|
||||
options: options
|
||||
});
|
||||
```
|
||||
|
||||
### Data structure
|
||||
|
||||
```javascript
|
||||
var data = [
|
||||
{
|
||||
value: 300,
|
||||
color:"#F7464A",
|
||||
highlight: "#FF5A5E",
|
||||
label: "Red"
|
||||
},
|
||||
{
|
||||
value: 50,
|
||||
color: "#46BFBD",
|
||||
highlight: "#5AD3D1",
|
||||
label: "Green"
|
||||
},
|
||||
{
|
||||
value: 100,
|
||||
color: "#FDB45C",
|
||||
highlight: "#FFC870",
|
||||
label: "Yellow"
|
||||
}
|
||||
]
|
||||
var data = {
|
||||
labels: [
|
||||
"Red",
|
||||
"Green",
|
||||
"Yellow"
|
||||
],
|
||||
datasets: [
|
||||
{
|
||||
data: [300, 50, 100],
|
||||
backgroundColor: [
|
||||
"#F7464A",
|
||||
"#46BFBD",
|
||||
"#FDB45C"
|
||||
],
|
||||
hoverBackgroundColor: [
|
||||
"#FF5A5E",
|
||||
"#5AD3D1",
|
||||
"#FFC870"
|
||||
]
|
||||
}]
|
||||
};
|
||||
```
|
||||
|
||||
For a pie chart, you must pass in an array of objects with a value and an optional color property. The value attribute should be a number, Chart.js will total all of the numbers and calculate the relative proportion of each. The color attribute should be a string. Similar to CSS, for this string you can use HEX notation, RGB, RGBA or HSL.
|
||||
@@ -61,44 +70,25 @@ For a pie chart, you must pass in an array of objects with a value and an option
|
||||
|
||||
These are the customisation options specific to Pie & Doughnut charts. These options are merged with the [global chart configuration options](#getting-started-global-chart-configuration), and form the options of the chart.
|
||||
|
||||
```javascript
|
||||
{
|
||||
//Boolean - Whether we should show a stroke on each segment
|
||||
segmentShowStroke : true,
|
||||
Name | Type | Default | Description
|
||||
--- | --- | --- | ---
|
||||
cutoutPercentage | Number | 50 - for doughnut, 0 - for pie | The percentage of the chart that is cut out of the middle.
|
||||
scale | Array | [See Scales](#scales) and [Defaults for Radial Linear Scale](#getting-started-radial-linear-scale) | Options for the one scale used on the chart. Use this to style the ticks, labels, and grid.
|
||||
*scale*.type | String |"radialLinear" | As defined in ["Radial Linear"](#scales-radial-linear-scale).
|
||||
*scale*.lineArc | Boolean | true | When true, lines are arced compared to straight when false.
|
||||
*animation*.animateRotate | Boolean |true | If true, will animate the rotation of the chart.
|
||||
*animation*.animateScale | Boolean | false | If true, will animate scaling the Doughnut from the centre.
|
||||
|
||||
//String - The colour of each segment stroke
|
||||
segmentStrokeColor : "#fff",
|
||||
|
||||
//Number - The width of each segment stroke
|
||||
segmentStrokeWidth : 2,
|
||||
|
||||
//Number - The percentage of the chart that we cut out of the middle
|
||||
percentageInnerCutout : 50, // This is 0 for Pie charts
|
||||
|
||||
//Number - Amount of animation steps
|
||||
animationSteps : 100,
|
||||
|
||||
//String - Animation easing effect
|
||||
animationEasing : "easeOutBounce",
|
||||
|
||||
//Boolean - Whether we animate the rotation of the Doughnut
|
||||
animateRotate : true,
|
||||
|
||||
//Boolean - Whether we animate scaling the Doughnut from the centre
|
||||
animateScale : false,
|
||||
{% raw %}
|
||||
//String - A legend template
|
||||
legendTemplate : "<ul class=\"<%=name.toLowerCase()%>-legend\"><% for (var i=0; i<segments.length; i++){%><li><span style=\"background-color:<%=segments[i].fillColor%>\"></span><%if(segments[i].label){%><%=segments[i].label%><%}%></li><%}%></ul>"
|
||||
{% endraw %}
|
||||
}
|
||||
```
|
||||
You can override these for your `Chart` instance by passing a second argument into the `Doughnut` method as an object with the keys you want to override.
|
||||
|
||||
For example, we could have a doughnut chart that animates by scaling out from the centre like so:
|
||||
|
||||
```javascript
|
||||
new Chart(ctx).Doughnut(data, {
|
||||
animateScale: true
|
||||
new Chart(ctx,{
|
||||
type:"doughnut",
|
||||
animation:{
|
||||
animateScale:true
|
||||
}
|
||||
});
|
||||
// This will create a chart with all of the default options, merged from the global config,
|
||||
// and the Doughnut chart defaults but this particular instance will have `animateScale` set to `true`.
|
||||
|
||||
@@ -27,7 +27,6 @@ var srcFiles = [
|
||||
'./node_modules/color/dist/color.min.js',
|
||||
'./src/core/core.js',
|
||||
'./src/core/core.helpers.js',
|
||||
'./src/core/core.chart.js',
|
||||
'./src/core/core.element.js',
|
||||
'./src/core/**',
|
||||
'./src/controllers/**',
|
||||
|
||||
+14
-2
@@ -1,7 +1,19 @@
|
||||
module.exports = function(config) {
|
||||
config.set({
|
||||
var configuration = {
|
||||
browsers: ['Firefox'],
|
||||
customLaunchers: {
|
||||
Chrome_travis_ci: {
|
||||
base: 'Chrome',
|
||||
flags: ['--no-sandbox']
|
||||
}
|
||||
},
|
||||
frameworks: ['jasmine'],
|
||||
reporters: ['progress', 'html'],
|
||||
});
|
||||
};
|
||||
|
||||
if (process.env.TRAVIS) {
|
||||
configuration.browsers.push('Chrome_travis_ci');
|
||||
}
|
||||
|
||||
config.set(configuration);
|
||||
};
|
||||
@@ -43,6 +43,9 @@
|
||||
type: 'bar',
|
||||
data: barChartData,
|
||||
options: {
|
||||
tooltips: {
|
||||
mode: 'label'
|
||||
},
|
||||
responsive: true,
|
||||
scales: {
|
||||
xAxes: [{
|
||||
|
||||
@@ -18,8 +18,8 @@
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="canvas-holder" style="width:50%">
|
||||
<canvas id="chart-area" width="500" height="500" />
|
||||
<div id="canvas-holder" style="width:100%">
|
||||
<canvas id="chart-area" />
|
||||
</div>
|
||||
<button id="randomizeData">Randomize Data</button>
|
||||
<button id="addDataset">Add Dataset</button>
|
||||
|
||||
+110
-116
@@ -2,149 +2,143 @@
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>Line Chart with Custom Tooltips</title>
|
||||
<script src="../Chart.js"></script>
|
||||
<script src="http://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
|
||||
<style>
|
||||
<title>Line Chart with Custom Tooltips</title>
|
||||
<script src="../Chart.js"></script>
|
||||
<script src="http://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
|
||||
<style>
|
||||
#canvas-holder1 {
|
||||
width: 300px;
|
||||
margin: 20px auto;
|
||||
width: 300px;
|
||||
margin: 20px auto;
|
||||
}
|
||||
|
||||
|
||||
#canvas-holder2 {
|
||||
width: 50%;
|
||||
margin: 20px 25%;
|
||||
width: 50%;
|
||||
margin: 20px 25%;
|
||||
}
|
||||
|
||||
|
||||
#chartjs-tooltip {
|
||||
opacity: 1;
|
||||
position: absolute;
|
||||
background: rgba(0, 0, 0, .7);
|
||||
color: white;
|
||||
border-radius: 3px;
|
||||
-webkit-transition: all .1s ease;
|
||||
transition: all .1s ease;
|
||||
pointer-events: none;
|
||||
-webkit-transform: translate(-50%, 0);
|
||||
transform: translate(-50%, 0);
|
||||
opacity: 1;
|
||||
position: absolute;
|
||||
background: rgba(0, 0, 0, .7);
|
||||
color: white;
|
||||
border-radius: 3px;
|
||||
-webkit-transition: all .1s ease;
|
||||
transition: all .1s ease;
|
||||
pointer-events: none;
|
||||
-webkit-transform: translate(-50%, 0);
|
||||
transform: translate(-50%, 0);
|
||||
}
|
||||
|
||||
|
||||
.chartjs-tooltip-key {
|
||||
display: inline-block;
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
display: inline-block;
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="canvas-holder1">
|
||||
<canvas id="chart1" width="300" height="30" />
|
||||
</div>
|
||||
<script>
|
||||
<div id="canvas-holder1">
|
||||
<canvas id="chart1" width="300" height="100" />
|
||||
</div>
|
||||
<script>
|
||||
window.count = 0;
|
||||
Chart.defaults.global.pointHitDetectionRadius = 1;
|
||||
var customTooltips = function(tooltip) {
|
||||
|
||||
console.log(tooltip._view);
|
||||
console.log(window.count++, tooltip);
|
||||
|
||||
// Tooltip Element
|
||||
var tooltipEl = $('#chartjs-tooltip');
|
||||
// Tooltip Element
|
||||
var tooltipEl = $('#chartjs-tooltip');
|
||||
|
||||
if (!tooltipEl[0]) {
|
||||
$('body').append('<div id="chartjs-tooltip"></div>');
|
||||
tooltipEl = $('#chartjs-tooltip');
|
||||
}
|
||||
if (!tooltipEl[0]) {
|
||||
$('body').append('<div id="chartjs-tooltip"></div>');
|
||||
tooltipEl = $('#chartjs-tooltip');
|
||||
}
|
||||
|
||||
// Hide if no tooltip
|
||||
if (!tooltip._view.opacity) {
|
||||
tooltipEl.css({
|
||||
opacity: 0
|
||||
});
|
||||
$('.chartjs-wrap canvas')
|
||||
.each(function(index, el) {
|
||||
$(el).css('cursor', 'default');
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
$(tooltip._chart.canvas).css('cursor', 'pointer');
|
||||
|
||||
// Set caret Position
|
||||
tooltipEl.removeClass('above below no-transform');
|
||||
if (tooltip._view.yAlign) {
|
||||
tooltipEl.addClass(tooltip._view.yAlign);
|
||||
} else {
|
||||
tooltipEl.addClass('no-transform');
|
||||
}
|
||||
|
||||
// Set Text
|
||||
if (tooltip._view.text) {
|
||||
tooltipEl.html(tooltip._view.text);
|
||||
} else if (tooltip._view.labels) {
|
||||
var innerHtml = '<div class="title">' + tooltip._view.title + '</div>';
|
||||
for (var i = 0; i < tooltip._view.labels.length; i++) {
|
||||
innerHtml += [
|
||||
'<div class="section">',
|
||||
' <span class="key" style="background-color:' + tooltip._view.legendColors[i].fill + '"></span>',
|
||||
' <span class="value">' + tooltip._view.labels[i] + '</span>',
|
||||
'</div>'
|
||||
].join('');
|
||||
}
|
||||
tooltipEl.html(innerHtml);
|
||||
}
|
||||
|
||||
// Find Y Location on page
|
||||
var top = 0;
|
||||
if (tooltip._view.yAlign) {
|
||||
if (tooltip._view.yAlign == 'above') {
|
||||
top = tooltip._view.y - tooltip._view.caretHeight - tooltip._view.caretPadding;
|
||||
} else {
|
||||
top = tooltip._view.y + tooltip._view.caretHeight + tooltip._view.caretPadding;
|
||||
}
|
||||
}
|
||||
|
||||
var offset = $(tooltip._chart.canvas).offset();
|
||||
|
||||
// Display, position, and set styles for font
|
||||
// Hide if no tooltip
|
||||
if (!tooltip.opacity) {
|
||||
tooltipEl.css({
|
||||
opacity: 1,
|
||||
width: tooltip._view.width ? (tooltip._view.width + 'px') : 'auto',
|
||||
left: offset.left + tooltip._view.x + 'px',
|
||||
top: offset.top + top + 'px',
|
||||
fontFamily: tooltip._view._fontFamily,
|
||||
fontSize: tooltip._view.fontSize,
|
||||
fontStyle: tooltip._view._fontStyle,
|
||||
padding: tooltip._view.yPadding + 'px ' + tooltip._view.xPadding + 'px',
|
||||
opacity: 0
|
||||
});
|
||||
$('.chartjs-wrap canvas')
|
||||
.each(function(index, el) {
|
||||
$(el).css('cursor', 'default');
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
$(this._chart.canvas).css('cursor', 'pointer');
|
||||
|
||||
// Set caret Position
|
||||
tooltipEl.removeClass('above below no-transform');
|
||||
if (tooltip.yAlign) {
|
||||
tooltipEl.addClass(tooltip.yAlign);
|
||||
} else {
|
||||
tooltipEl.addClass('no-transform');
|
||||
}
|
||||
|
||||
// Set Text
|
||||
if (tooltip.body) {
|
||||
var innerHtml = [
|
||||
(tooltip.beforeTitle || []).join('\n'), (tooltip.title || []).join('\n'), (tooltip.afterTitle || []).join('\n'), (tooltip.beforeBody || []).join('\n'), (tooltip.body || []).join('\n'), (tooltip.afterBody || []).join('\n'), (tooltip.beforeFooter || [])
|
||||
.join('\n'), (tooltip.footer || []).join('\n'), (tooltip.afterFooter || []).join('\n')
|
||||
];
|
||||
tooltipEl.html(innerHtml.join('\n'));
|
||||
}
|
||||
|
||||
// Find Y Location on page
|
||||
var top = 0;
|
||||
if (tooltip.yAlign) {
|
||||
if (tooltip.yAlign == 'above') {
|
||||
top = tooltip.y - tooltip.caretHeight - tooltip.caretPadding;
|
||||
} else {
|
||||
top = tooltip.y + tooltip.caretHeight + tooltip.caretPadding;
|
||||
}
|
||||
}
|
||||
|
||||
var offset = $(this._chart.canvas).offset();
|
||||
|
||||
// Display, position, and set styles for font
|
||||
tooltipEl.css({
|
||||
opacity: 1,
|
||||
width: tooltip.width ? (tooltip.width + 'px') : 'auto',
|
||||
left: offset.left + tooltip.x + 'px',
|
||||
top: offset.top + top + 'px',
|
||||
fontFamily: tooltip._fontFamily,
|
||||
fontSize: tooltip.fontSize,
|
||||
fontStyle: tooltip._fontStyle,
|
||||
padding: tooltip.yPadding + 'px ' + tooltip.xPadding + 'px',
|
||||
});
|
||||
};
|
||||
var randomScalingFactor = function() {
|
||||
return Math.round(Math.random() * 100);
|
||||
return Math.round(Math.random() * 100);
|
||||
};
|
||||
var lineChartData = {
|
||||
labels: ["January", "February", "March", "April", "May", "June", "July"],
|
||||
datasets: [{
|
||||
label: "My First dataset",
|
||||
data: [randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()]
|
||||
}, {
|
||||
label: "My Second dataset",
|
||||
data: [randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()]
|
||||
}]
|
||||
labels: ["January", "February", "March", "April", "May", "June", "July"],
|
||||
datasets: [{
|
||||
label: "My First dataset",
|
||||
data: [randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()]
|
||||
}, {
|
||||
label: "My Second dataset",
|
||||
data: [randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()]
|
||||
}]
|
||||
};
|
||||
|
||||
window.onload = function() {
|
||||
var chartEl = document.getElementById("chart1");
|
||||
window.myLine = new Chart(chartEl, {
|
||||
type: 'line',
|
||||
data: lineChartData,
|
||||
options: {
|
||||
tooltips: {
|
||||
enabled: false,
|
||||
custom: customTooltips
|
||||
}
|
||||
}
|
||||
});
|
||||
var chartEl = document.getElementById("chart1");
|
||||
window.myLine = new Chart(chartEl, {
|
||||
type: 'line',
|
||||
data: lineChartData,
|
||||
options: {
|
||||
tooltips: {
|
||||
enabled: false,
|
||||
custom: customTooltips
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
</script>
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
|
||||
@@ -60,7 +60,7 @@
|
||||
xAxes: [{
|
||||
display: true,
|
||||
scaleLabel: {
|
||||
show: true,
|
||||
display: true,
|
||||
labelString: 'x axis'
|
||||
}
|
||||
}],
|
||||
@@ -68,7 +68,7 @@
|
||||
display: true,
|
||||
type: 'logarithmic',
|
||||
scaleLabel: {
|
||||
show: true,
|
||||
display: true,
|
||||
labelString: 'y axis'
|
||||
}
|
||||
}]
|
||||
|
||||
@@ -0,0 +1,175 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>Line Chart</title>
|
||||
<script src="../Chart.js"></script>
|
||||
<script src="../node_modules/jquery/dist/jquery.min.js"></script>
|
||||
<style>
|
||||
canvas {
|
||||
-webkit-box-shadow: 0 0 20px 0 rgba(0, 0, 0, .5);
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div style="width:100%;">
|
||||
<canvas id="canvas" style="width:100%;height:100%"></canvas>
|
||||
</div>
|
||||
<br>
|
||||
<br>
|
||||
<button id="randomizeData">Randomize Data</button>
|
||||
<button id="addDataset">Add Dataset</button>
|
||||
<button id="removeDataset">Remove Dataset</button>
|
||||
<button id="addData">Add Data</button>
|
||||
<button id="removeData">Remove Data</button>
|
||||
<div>
|
||||
<h3>Legend</h3>
|
||||
<div id="legendContainer">
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
var randomScalingFactor = function() {
|
||||
return Math.round(Math.random() * 100);
|
||||
//return 0;
|
||||
};
|
||||
var randomColorFactor = function() {
|
||||
return Math.round(Math.random() * 255);
|
||||
};
|
||||
var randomColor = function(opacity) {
|
||||
return 'rgba(' + randomColorFactor() + ',' + randomColorFactor() + ',' + randomColorFactor() + ',' + (opacity || '.3') + ')';
|
||||
};
|
||||
|
||||
var config = {
|
||||
type: 'line',
|
||||
data: {
|
||||
labels: ["January", "February", "March", "April", "May", "June", "July"],
|
||||
datasets: [{
|
||||
label: "My First dataset",
|
||||
|
||||
// Skip a point in the middle
|
||||
data: [randomScalingFactor(), randomScalingFactor(), NaN, randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()],
|
||||
fill: true,
|
||||
borderDash: [5, 5],
|
||||
}, {
|
||||
label: "My Second dataset",
|
||||
|
||||
// Skip first and last points
|
||||
data: [NaN, randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), NaN],
|
||||
}]
|
||||
},
|
||||
options: {
|
||||
responsive: true,
|
||||
tooltips: {
|
||||
mode: 'label',
|
||||
},
|
||||
hover: {
|
||||
mode: 'label'
|
||||
},
|
||||
scales: {
|
||||
xAxes: [{
|
||||
display: true,
|
||||
scaleLabel: {
|
||||
display: true,
|
||||
labelString: 'Month'
|
||||
}
|
||||
}],
|
||||
yAxes: [{
|
||||
display: true,
|
||||
scaleLabel: {
|
||||
display: true,
|
||||
labelString: 'Value'
|
||||
},
|
||||
}]
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
$.each(config.data.datasets, function(i, dataset) {
|
||||
dataset.borderColor = randomColor(0.4);
|
||||
dataset.backgroundColor = randomColor(0.5);
|
||||
dataset.pointBorderColor = randomColor(0.7);
|
||||
dataset.pointBackgroundColor = randomColor(0.5);
|
||||
dataset.pointBorderWidth = 1;
|
||||
});
|
||||
|
||||
console.log(config.data);
|
||||
|
||||
window.onload = function() {
|
||||
var ctx = document.getElementById("canvas").getContext("2d");
|
||||
window.myLine = new Chart(ctx, config);
|
||||
|
||||
updateLegend();
|
||||
};
|
||||
|
||||
function updateLegend() {
|
||||
$legendContainer = $('#legendContainer');
|
||||
$legendContainer.empty();
|
||||
$legendContainer.append(window.myLine.generateLegend());
|
||||
}
|
||||
|
||||
$('#randomizeData').click(function() {
|
||||
$.each(config.data.datasets, function(i, dataset) {
|
||||
dataset.data = dataset.data.map(function() {
|
||||
return randomScalingFactor();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
window.myLine.update();
|
||||
updateLegend();
|
||||
});
|
||||
|
||||
$('#addDataset').click(function() {
|
||||
var newDataset = {
|
||||
label: 'Dataset ' + config.data.datasets.length,
|
||||
borderColor: randomColor(0.4),
|
||||
backgroundColor: randomColor(0.5),
|
||||
pointBorderColor: randomColor(0.7),
|
||||
pointBackgroundColor: randomColor(0.5),
|
||||
pointBorderWidth: 1,
|
||||
data: [],
|
||||
};
|
||||
|
||||
for (var index = 0; index < config.data.labels.length; ++index) {
|
||||
newDataset.data.push(randomScalingFactor());
|
||||
}
|
||||
|
||||
config.data.datasets.push(newDataset);
|
||||
window.myLine.update();
|
||||
updateLegend();
|
||||
});
|
||||
|
||||
$('#addData').click(function() {
|
||||
if (config.data.datasets.length > 0) {
|
||||
config.data.labels.push('dataset #' + config.data.labels.length);
|
||||
|
||||
$.each(config.data.datasets, function(i, dataset) {
|
||||
dataset.data.push(randomScalingFactor());
|
||||
});
|
||||
|
||||
window.myLine.update();
|
||||
updateLegend();
|
||||
}
|
||||
});
|
||||
|
||||
$('#removeDataset').click(function() {
|
||||
config.data.datasets.splice(0, 1);
|
||||
window.myLine.update();
|
||||
updateLegend();
|
||||
});
|
||||
|
||||
$('#removeData').click(function() {
|
||||
config.data.labels.splice(-1, 1); // remove the label first
|
||||
|
||||
config.data.datasets.forEach(function(dataset, datasetIndex) {
|
||||
dataset.data.pop();
|
||||
});
|
||||
|
||||
window.myLine.update();
|
||||
updateLegend();
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -0,0 +1,174 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>Line Chart</title>
|
||||
<script src="../Chart.js"></script>
|
||||
<script src="../node_modules/jquery/dist/jquery.min.js"></script>
|
||||
<style>
|
||||
canvas {
|
||||
-webkit-box-shadow: 0 0 20px 0 rgba(0, 0, 0, .5);
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div style="width:100%;">
|
||||
<canvas id="canvas" style="width:100%;height:100%"></canvas>
|
||||
</div>
|
||||
<br>
|
||||
<br>
|
||||
<button id="randomizeData">Randomize Data</button>
|
||||
<button id="addDataset">Add Dataset</button>
|
||||
<button id="removeDataset">Remove Dataset</button>
|
||||
<button id="addData">Add Data</button>
|
||||
<button id="removeData">Remove Data</button>
|
||||
<div>
|
||||
<h3>Legend</h3>
|
||||
<div id="legendContainer">
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
var randomScalingFactor = function() {
|
||||
return Math.round(Math.random() * 100 * (Math.random() > 0.5 ? -1 : 1));
|
||||
};
|
||||
var randomColorFactor = function() {
|
||||
return Math.round(Math.random() * 255);
|
||||
};
|
||||
var randomColor = function(opacity) {
|
||||
return 'rgba(' + randomColorFactor() + ',' + randomColorFactor() + ',' + randomColorFactor() + ',' + (opacity || '1') + ')';
|
||||
};
|
||||
|
||||
var config = {
|
||||
type: 'line',
|
||||
data: {
|
||||
labels: ["January", "February", "March", "April", "May", "June", "July"],
|
||||
datasets: [{
|
||||
label: "My First dataset",
|
||||
data: [randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()],
|
||||
}, {
|
||||
label: "My Second dataset",
|
||||
data: [randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()],
|
||||
}, {
|
||||
label: "My Third dataset",
|
||||
data: [randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()],
|
||||
}, {
|
||||
label: "My Third dataset",
|
||||
data: [randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()],
|
||||
}]
|
||||
},
|
||||
options: {
|
||||
responsive: true,
|
||||
tooltips: {
|
||||
mode: 'label',
|
||||
},
|
||||
hover: {
|
||||
mode: 'label'
|
||||
},
|
||||
scales: {
|
||||
xAxes: [{
|
||||
scaleLabel: {
|
||||
display: true,
|
||||
labelString: 'Month'
|
||||
}
|
||||
}],
|
||||
yAxes: [{
|
||||
stacked: true,
|
||||
scaleLabel: {
|
||||
display: true,
|
||||
labelString: 'Value'
|
||||
}
|
||||
}]
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
$.each(config.data.datasets, function(i, dataset) {
|
||||
var color = randomColor(1);
|
||||
dataset.borderColor = color;
|
||||
dataset.backgroundColor = color;
|
||||
dataset.pointBorderColor = color;
|
||||
dataset.pointBackgroundColor = color;
|
||||
dataset.pointBorderWidth = 1;
|
||||
});
|
||||
|
||||
console.log(config.data);
|
||||
|
||||
window.onload = function() {
|
||||
var ctx = document.getElementById("canvas").getContext("2d");
|
||||
window.myLine = new Chart(ctx, config);
|
||||
|
||||
updateLegend();
|
||||
};
|
||||
|
||||
function updateLegend() {
|
||||
$legendContainer = $('#legendContainer');
|
||||
$legendContainer.empty();
|
||||
$legendContainer.append(window.myLine.generateLegend());
|
||||
}
|
||||
|
||||
$('#randomizeData').click(function() {
|
||||
$.each(config.data.datasets, function(i, dataset) {
|
||||
dataset.data = dataset.data.map(function() {
|
||||
return randomScalingFactor();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
window.myLine.update();
|
||||
updateLegend();
|
||||
});
|
||||
|
||||
$('#addDataset').click(function() {
|
||||
var newDataset = {
|
||||
label: 'Dataset ' + config.data.datasets.length,
|
||||
borderColor: randomColor(0.4),
|
||||
backgroundColor: randomColor(0.5),
|
||||
pointBorderColor: randomColor(0.7),
|
||||
pointBackgroundColor: randomColor(0.5),
|
||||
pointBorderWidth: 1,
|
||||
data: [],
|
||||
};
|
||||
|
||||
for (var index = 0; index < config.data.labels.length; ++index) {
|
||||
newDataset.data.push(randomScalingFactor());
|
||||
}
|
||||
|
||||
config.data.datasets.push(newDataset);
|
||||
window.myLine.update();
|
||||
updateLegend();
|
||||
});
|
||||
|
||||
$('#addData').click(function() {
|
||||
if (config.data.datasets.length > 0) {
|
||||
config.data.labels.push('dataset #' + config.data.labels.length);
|
||||
|
||||
$.each(config.data.datasets, function(i, dataset) {
|
||||
dataset.data.push(randomScalingFactor());
|
||||
});
|
||||
|
||||
window.myLine.update();
|
||||
updateLegend();
|
||||
}
|
||||
});
|
||||
|
||||
$('#removeDataset').click(function() {
|
||||
config.data.datasets.splice(0, 1);
|
||||
window.myLine.update();
|
||||
updateLegend();
|
||||
});
|
||||
|
||||
$('#removeData').click(function() {
|
||||
config.data.labels.splice(-1, 1); // remove the label first
|
||||
|
||||
config.data.datasets.forEach(function(dataset, datasetIndex) {
|
||||
dataset.data.pop();
|
||||
});
|
||||
|
||||
window.myLine.update();
|
||||
updateLegend();
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -77,14 +77,14 @@
|
||||
// round: 'day'
|
||||
},
|
||||
scaleLabel: {
|
||||
show: true,
|
||||
display: true,
|
||||
labelString: 'Date'
|
||||
}
|
||||
}, ],
|
||||
yAxes: [{
|
||||
display: true,
|
||||
scaleLabel: {
|
||||
show: true,
|
||||
display: true,
|
||||
labelString: 'value'
|
||||
}
|
||||
}]
|
||||
|
||||
@@ -92,14 +92,14 @@
|
||||
// round: 'day'
|
||||
},
|
||||
scaleLabel: {
|
||||
show: true,
|
||||
display: true,
|
||||
labelString: 'Date'
|
||||
}
|
||||
}, ],
|
||||
yAxes: [{
|
||||
display: true,
|
||||
scaleLabel: {
|
||||
show: true,
|
||||
display: true,
|
||||
labelString: 'value'
|
||||
}
|
||||
}]
|
||||
|
||||
+33
-1
@@ -19,6 +19,7 @@
|
||||
<br>
|
||||
<br>
|
||||
<button id="randomizeData">Randomize Data</button>
|
||||
<button id="changeDataObject">Change Data Object</button>
|
||||
<button id="addDataset">Add Dataset</button>
|
||||
<button id="removeDataset">Remove Dataset</button>
|
||||
<button id="addData">Add Data</button>
|
||||
@@ -30,7 +31,8 @@
|
||||
</div>
|
||||
<script>
|
||||
var randomScalingFactor = function() {
|
||||
return Math.round(Math.random() * 100 * (Math.random() > 0.5 ? -1 : 1));
|
||||
return Math.round(Math.random() * 100);
|
||||
//return 0;
|
||||
};
|
||||
var randomColorFactor = function() {
|
||||
return Math.round(Math.random() * 255);
|
||||
@@ -101,6 +103,10 @@
|
||||
scaleLabel: {
|
||||
show: true,
|
||||
labelString: 'Value'
|
||||
},
|
||||
ticks: {
|
||||
suggestedMin: -10,
|
||||
suggestedMax: 250,
|
||||
}
|
||||
}]
|
||||
}
|
||||
@@ -142,6 +148,32 @@
|
||||
updateLegend();
|
||||
});
|
||||
|
||||
$('#changeDataObject').click(function() {
|
||||
config.data = {
|
||||
labels: ["July", "August", "September", "October", "November", "December"],
|
||||
datasets: [{
|
||||
label: "My First dataset",
|
||||
data: [randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()],
|
||||
fill: false,
|
||||
}, {
|
||||
label: "My Second dataset",
|
||||
fill: false,
|
||||
data: [randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()],
|
||||
}]
|
||||
};
|
||||
|
||||
$.each(config.data.datasets, function(i, dataset) {
|
||||
dataset.borderColor = randomColor(0.4);
|
||||
dataset.backgroundColor = randomColor(0.5);
|
||||
dataset.pointBorderColor = randomColor(0.7);
|
||||
dataset.pointBackgroundColor = randomColor(0.5);
|
||||
dataset.pointBorderWidth = 1;
|
||||
});
|
||||
|
||||
// Update the chart
|
||||
window.myLine.update();
|
||||
});
|
||||
|
||||
$('#addDataset').click(function() {
|
||||
var newDataset = {
|
||||
label: 'Dataset ' + config.data.datasets.length,
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="canvas-holder" style="width:50%" width="50%">
|
||||
<div id="canvas-holder" style="width:100%">
|
||||
<canvas id="chart-area"></canvas>
|
||||
</div>
|
||||
<button id="randomizeData">Randomize Data</button>
|
||||
@@ -17,7 +17,7 @@
|
||||
<div>
|
||||
<h3>Legend</h3>
|
||||
<div id="legendContainer">
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
@@ -60,9 +60,12 @@
|
||||
options: {
|
||||
responsive: true,
|
||||
scale: {
|
||||
beginAtZero: true,
|
||||
reverse: false
|
||||
}
|
||||
ticks: {
|
||||
beginAtZero: true
|
||||
},
|
||||
reverse: false
|
||||
},
|
||||
animateRotate:false
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,152 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>Radar Chart</title>
|
||||
<script src="../Chart.js"></script>
|
||||
<script src="http://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div style="width:50%">
|
||||
<canvas id="canvas" height="450" width="450"></canvas>
|
||||
</div>
|
||||
<button id="randomizeData">Randomize Data</button>
|
||||
<button id="addDataset">Add Dataset</button>
|
||||
<button id="removeDataset">Remove Dataset</button>
|
||||
<button id="addData">Add Data</button>
|
||||
<button id="removeData">Remove Data</button>
|
||||
<div>
|
||||
<h3>Legend</h3>
|
||||
<div id="legendContainer">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
var randomScalingFactor = function() {
|
||||
return Math.round(Math.random() * 100);
|
||||
};
|
||||
var randomColorFactor = function() {
|
||||
return Math.round(Math.random() * 255);
|
||||
};
|
||||
var randomColor = function(opacity) {
|
||||
return 'rgba(' + randomColorFactor() + ',' + randomColorFactor() + ',' + randomColorFactor() + ',' + (opacity || '.3') + ')';
|
||||
};
|
||||
|
||||
var config = {
|
||||
type: 'radar',
|
||||
data: {
|
||||
labels: ["Eating", "Drinking", "Sleeping", "Designing", "Coding", "Cycling", "Running"],
|
||||
datasets: [{
|
||||
label: "Skip first dataset",
|
||||
borderColor: 'rgb(255, 0, 0)',
|
||||
backgroundColor: "rgba(255,255,0,0.5)",
|
||||
pointBackgroundColor: "rgba(220,220,220,1)",
|
||||
data: [NaN, randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()]
|
||||
}, {
|
||||
label: "Skip mid dataset",
|
||||
borderColor: 'rgb(255, 0, 255)',
|
||||
backgroundColor: "rgba(0, 255, 0, 0.5)",
|
||||
pointBackgroundColor: "rgba(151,187,205,1)",
|
||||
hoverPointBackgroundColor: "#fff",
|
||||
pointHighlightStroke: "rgba(151,187,205,1)",
|
||||
data: [randomScalingFactor(), randomScalingFactor(), NaN, randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()]
|
||||
},{
|
||||
label: "Skip last dataset",
|
||||
borderColor: 'rgb(0, 255, 255)',
|
||||
backgroundColor: "rgba(0, 0, 255, 0.5)",
|
||||
pointBackgroundColor: "rgba(151,187,205,1)",
|
||||
hoverPointBackgroundColor: "#fff",
|
||||
pointHighlightStroke: "rgba(151,187,205,1)",
|
||||
data: [randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), NaN]
|
||||
}]
|
||||
},
|
||||
options: {
|
||||
elements: {
|
||||
line: {
|
||||
tension: 0.0,
|
||||
}
|
||||
},
|
||||
scale: {
|
||||
beginAtZero: true,
|
||||
reverse: false
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
function updateLegend() {
|
||||
$legendContainer = $('#legendContainer');
|
||||
$legendContainer.empty();
|
||||
$legendContainer.append(window.myRadar.generateLegend());
|
||||
}
|
||||
|
||||
window.onload = function() {
|
||||
window.myRadar = new Chart(document.getElementById("canvas"), config);
|
||||
updateLegend();
|
||||
};
|
||||
|
||||
$('#randomizeData').click(function() {
|
||||
$.each(config.data.datasets, function(i, dataset) {
|
||||
dataset.data = dataset.data.map(function() {
|
||||
return randomScalingFactor();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
window.myRadar.update();
|
||||
updateLegend();
|
||||
});
|
||||
|
||||
$('#addDataset').click(function() {
|
||||
var newDataset = {
|
||||
label: 'Dataset ' + config.data.datasets.length,
|
||||
borderColor: randomColor(0.4),
|
||||
backgroundColor: randomColor(0.5),
|
||||
pointBorderColor: randomColor(0.7),
|
||||
pointBackgroundColor: randomColor(0.5),
|
||||
pointBorderWidth: 1,
|
||||
data: [],
|
||||
};
|
||||
|
||||
for (var index = 0; index < config.data.labels.length; ++index) {
|
||||
newDataset.data.push(randomScalingFactor());
|
||||
}
|
||||
|
||||
config.data.datasets.push(newDataset);
|
||||
window.myRadar.update();
|
||||
updateLegend();
|
||||
});
|
||||
|
||||
$('#addData').click(function() {
|
||||
if (config.data.datasets.length > 0) {
|
||||
config.data.labels.push('dataset #' + config.data.labels.length);
|
||||
|
||||
$.each(config.data.datasets, function (i, dataset) {
|
||||
dataset.data.push(randomScalingFactor());
|
||||
});
|
||||
|
||||
window.myRadar.update();
|
||||
updateLegend();
|
||||
}
|
||||
});
|
||||
|
||||
$('#removeDataset').click(function() {
|
||||
config.data.datasets.splice(0, 1);
|
||||
window.myRadar.update();
|
||||
updateLegend();
|
||||
});
|
||||
|
||||
$('#removeData').click(function() {
|
||||
config.data.labels.pop(); // remove the label first
|
||||
|
||||
$.each(config.data.datasets, function(i, dataset) {
|
||||
dataset.data.pop();
|
||||
});
|
||||
|
||||
window.myRadar.update();
|
||||
updateLegend();
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -8,8 +8,8 @@
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div style="width:50%">
|
||||
<canvas id="canvas" height="450" width="450"></canvas>
|
||||
<div style="width:100%">
|
||||
<canvas id="canvas"></canvas>
|
||||
</div>
|
||||
<button id="randomizeData">Randomize Data</button>
|
||||
<button id="addDataset">Add Dataset</button>
|
||||
@@ -19,7 +19,7 @@
|
||||
<div>
|
||||
<h3>Legend</h3>
|
||||
<div id="legendContainer">
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
@@ -41,7 +41,7 @@
|
||||
label: "My First dataset",
|
||||
backgroundColor: "rgba(220,220,220,0.2)",
|
||||
pointBackgroundColor: "rgba(220,220,220,1)",
|
||||
data: [null, randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()]
|
||||
data: [randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()]
|
||||
}, {
|
||||
label: 'Hidden dataset',
|
||||
hidden: true,
|
||||
@@ -52,13 +52,15 @@
|
||||
pointBackgroundColor: "rgba(151,187,205,1)",
|
||||
hoverPointBackgroundColor: "#fff",
|
||||
pointHighlightStroke: "rgba(151,187,205,1)",
|
||||
data: [null, randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()]
|
||||
data: [randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()]
|
||||
},]
|
||||
},
|
||||
options: {
|
||||
scale: {
|
||||
beginAtZero: true,
|
||||
reverse: false
|
||||
reverse: true,
|
||||
ticks: {
|
||||
beginAtZero: true
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -149,7 +149,7 @@
|
||||
},
|
||||
scaleLabel: {
|
||||
labelString: 'Frequency',
|
||||
show: true,
|
||||
display: true,
|
||||
}
|
||||
}],
|
||||
yAxes: [{
|
||||
@@ -161,7 +161,7 @@
|
||||
},
|
||||
scaleLabel: {
|
||||
labelString: 'Voltage',
|
||||
show: true
|
||||
display: true
|
||||
}
|
||||
}]
|
||||
}
|
||||
|
||||
@@ -96,7 +96,7 @@
|
||||
zeroLineColor: "rgba(0,255,0,1)"
|
||||
},
|
||||
scaleLabel: {
|
||||
show: true,
|
||||
display: true,
|
||||
labelString: 'x axis'
|
||||
}
|
||||
}],
|
||||
@@ -106,7 +106,7 @@
|
||||
zeroLineColor: "rgba(0,255,0,1)"
|
||||
},
|
||||
scaleLabel: {
|
||||
show: true,
|
||||
display: true,
|
||||
labelString: 'y axis'
|
||||
}
|
||||
}]
|
||||
|
||||
@@ -24,14 +24,23 @@
|
||||
},
|
||||
|
||||
tooltips: {
|
||||
template: "(<%= value.x %>, <%= value.y %>)",
|
||||
multiTemplate: "<%if (datasetLabel){%><%=datasetLabel%>: <%}%>(<%= value.x %>, <%= value.y %>)",
|
||||
callbacks: {
|
||||
title: function(tooltipItems, data) {
|
||||
// Title doesn't make sense for scatter since we format the data as a point
|
||||
return '';
|
||||
},
|
||||
label: function(tooltipItem, data) {
|
||||
return '(' + tooltipItem.xLabel + ', ' + tooltipItem.yLabel + ')';
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
// Register the default config for this type
|
||||
Chart.defaults.bubble = defaultConfig;
|
||||
|
||||
Chart.Bubble = function(context, config) {
|
||||
config.options = helpers.configMerge(defaultConfig, config.options);
|
||||
config.type = 'bubble';
|
||||
return new Chart(context, config);
|
||||
};
|
||||
|
||||
@@ -7,7 +7,23 @@
|
||||
|
||||
var defaultConfig = {
|
||||
aspectRatio: 1,
|
||||
legendTemplate: "<ul class=\"<%=name.toLowerCase()%>-legend\"><% for (var i = 0; i < data.datasets[0].data.length; i++){%><li><span style=\"background-color:<%=data.datasets[0].backgroundColor[i]%>\"><%if(data.labels && i < data.labels.length){%><%=data.labels[i]%><%}%></span></li><%}%></ul>",
|
||||
legendCallback: function(chart) {
|
||||
var text = [];
|
||||
text.push('<ul class="' + chart.id + '-legend">');
|
||||
|
||||
if (chart.data.datasets.length) {
|
||||
for (var i = 0; i < chart.data.datasets[0].data.length; ++i) {
|
||||
text.push('<li><span style="background-color:' + chart.data.datasets[0].backgroundColor[i] + '">');
|
||||
if (chart.data.labels[i]) {
|
||||
text.push(chart.data.labels[i]);
|
||||
}
|
||||
text.push('</span></li>');
|
||||
}
|
||||
}
|
||||
|
||||
text.push('</ul>');
|
||||
return text.join("");
|
||||
}
|
||||
};
|
||||
|
||||
Chart.Doughnut = function(context, config) {
|
||||
|
||||
@@ -7,7 +7,23 @@
|
||||
|
||||
var defaultConfig = {
|
||||
aspectRatio: 1,
|
||||
legendTemplate: "<ul class=\"<%=name.toLowerCase()%>-legend\"><% for (var i = 0; i < data.datasets[0].data.length; i++){%><li><span style=\"background-color:<%=data.datasets[0].backgroundColor[i]%>\"><%if(data.labels && i < data.labels.length){%><%=data.labels[i]%><%}%></span></li><%}%></ul>",
|
||||
legendCallback: function(chart) {
|
||||
var text = [];
|
||||
text.push('<ul class="' + chart.id + '-legend">');
|
||||
|
||||
if (chart.data.datasets.length) {
|
||||
for (var i = 0; i < chart.data.datasets[0].data.length; ++i) {
|
||||
text.push('<li><span style="background-color:' + chart.data.datasets[0].backgroundColor[i] + '">');
|
||||
if (chart.data.labels[i]) {
|
||||
text.push(chart.data.labels[i]);
|
||||
}
|
||||
text.push('</span></li>');
|
||||
}
|
||||
}
|
||||
|
||||
text.push('</ul>');
|
||||
return text.join("");
|
||||
}
|
||||
};
|
||||
|
||||
Chart.PolarArea = function(context, config) {
|
||||
|
||||
@@ -24,15 +24,26 @@
|
||||
},
|
||||
|
||||
tooltips: {
|
||||
template: "(<%= value.x %>, <%= value.y %>)",
|
||||
multiTemplate: "<%if (datasetLabel){%><%=datasetLabel%>: <%}%>(<%= value.x %>, <%= value.y %>)",
|
||||
callbacks: {
|
||||
title: function(tooltipItems, data) {
|
||||
// Title doesn't make sense for scatter since we format the data as a point
|
||||
return '';
|
||||
},
|
||||
label: function(tooltipItem, data) {
|
||||
return '(' + tooltipItem.xLabel + ', ' + tooltipItem.yLabel + ')';
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
// Register the default config for this type
|
||||
Chart.defaults.scatter = defaultConfig;
|
||||
|
||||
// Scatter charts use line controllers
|
||||
Chart.controllers.scatter = Chart.controllers.line;
|
||||
|
||||
Chart.Scatter = function(context, config) {
|
||||
config.options = helpers.configMerge(defaultConfig, config.options);
|
||||
config.type = 'line';
|
||||
config.type = 'scatter';
|
||||
return new Chart(context, config);
|
||||
};
|
||||
|
||||
|
||||
@@ -293,7 +293,7 @@
|
||||
var leftTick = xScale.getPixelForValue(null, index, barIndex, this.chart.isCombo);
|
||||
leftTick -= this.chart.isCombo ? (ruler.tickWidth / 2) : 0;
|
||||
|
||||
if (yScale.options.stacked) {
|
||||
if (xScale.options.stacked) {
|
||||
return leftTick + (ruler.categoryWidth / 2) + ruler.categorySpacing;
|
||||
}
|
||||
|
||||
|
||||
@@ -18,6 +18,16 @@
|
||||
},
|
||||
//The percentage of the chart that we cut out of the middle.
|
||||
cutoutPercentage: 50,
|
||||
|
||||
// Need to override these to give a nice default
|
||||
tooltips: {
|
||||
callbacks: {
|
||||
title: function() { return '';},
|
||||
label: function(tooltipItem, data) {
|
||||
return data.labels[tooltipItem.index] + ': ' + data.datasets[tooltipItem.datasetIndex].data[tooltipItem.index];
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Chart.defaults.pie = helpers.clone(Chart.defaults.doughnut);
|
||||
|
||||
@@ -169,6 +169,49 @@
|
||||
this.updateBezierControlPoints();
|
||||
},
|
||||
|
||||
getPointBackgroundColor: function(point, index) {
|
||||
var backgroundColor = this.chart.options.elements.point.backgroundColor;
|
||||
var dataset = this.getDataset();
|
||||
|
||||
if (point.custom && point.custom.backgroundColor) {
|
||||
backgroundColor = point.custom.backgroundColor;
|
||||
} else if (dataset.pointBackgroundColor) {
|
||||
backgroundColor = helpers.getValueAtIndexOrDefault(dataset.pointBackgroundColor, index, backgroundColor);
|
||||
} else if (dataset.backgroundColor) {
|
||||
backgroundColor = dataset.backgroundColor;
|
||||
}
|
||||
|
||||
return backgroundColor;
|
||||
},
|
||||
getPointBorderColor: function(point, index) {
|
||||
var borderColor = this.chart.options.elements.point.borderColor;
|
||||
var dataset = this.getDataset();
|
||||
|
||||
if (point.custom && point.custom.borderColor) {
|
||||
borderColor = point.custom.borderColor;
|
||||
} else if (dataset.pointBorderColor) {
|
||||
borderColor = helpers.getValueAtIndexOrDefault(this.getDataset().pointBorderColor, index, borderColor);
|
||||
} else if (dataset.borderColor) {
|
||||
borderColor = dataset.borderColor;
|
||||
}
|
||||
|
||||
return borderColor;
|
||||
},
|
||||
getPointBorderWidth: function(point, index) {
|
||||
var borderWidth = this.chart.options.elements.point.borderWidth;
|
||||
var dataset = this.getDataset();
|
||||
|
||||
if (point.custom && point.custom.borderWidth !== undefined) {
|
||||
borderWidth = point.custom.borderWidth;
|
||||
} else if (dataset.pointBorderWidth !== undefined) {
|
||||
borderWidth = helpers.getValueAtIndexOrDefault(dataset.pointBorderWidth, index, borderWidth);
|
||||
} else if (dataset.borderWidth !== undefined) {
|
||||
borderWidth = dataset.borderWidth;
|
||||
}
|
||||
|
||||
return borderWidth;
|
||||
},
|
||||
|
||||
updateElement: function(point, index, reset) {
|
||||
var yScale = this.getScaleForId(this.getDataset().yAxisID);
|
||||
var xScale = this.getScaleForId(this.getDataset().xAxisID);
|
||||
@@ -193,13 +236,13 @@
|
||||
// Desired view properties
|
||||
_model: {
|
||||
x: xScale.getPixelForValue(this.getDataset().data[index], index, this.index, this.chart.isCombo),
|
||||
y: reset ? scaleBase : yScale.getPixelForValue(this.getDataset().data[index], index, this.index),
|
||||
y: reset ? scaleBase : this.calculatePointY(this.getDataset().data[index], index, this.index, this.chart.isCombo),
|
||||
// Appearance
|
||||
tension: point.custom && point.custom.tension ? point.custom.tension : (this.getDataset().tension || this.chart.options.elements.line.tension),
|
||||
radius: point.custom && point.custom.radius ? point.custom.radius : helpers.getValueAtIndexOrDefault(this.getDataset().radius, index, this.chart.options.elements.point.radius),
|
||||
backgroundColor: point.custom && point.custom.backgroundColor ? point.custom.backgroundColor : helpers.getValueAtIndexOrDefault(this.getDataset().pointBackgroundColor, index, this.chart.options.elements.point.backgroundColor),
|
||||
borderColor: point.custom && point.custom.borderColor ? point.custom.borderColor : helpers.getValueAtIndexOrDefault(this.getDataset().pointBorderColor, index, this.chart.options.elements.point.borderColor),
|
||||
borderWidth: point.custom && point.custom.borderWidth ? point.custom.borderWidth : helpers.getValueAtIndexOrDefault(this.getDataset().pointBorderWidth, index, this.chart.options.elements.point.borderWidth),
|
||||
backgroundColor: this.getPointBackgroundColor(point, index),
|
||||
borderColor: this.getPointBorderColor(point, index),
|
||||
borderWidth: this.getPointBorderWidth(point, index),
|
||||
// Tooltip
|
||||
hitRadius: point.custom && point.custom.hitRadius ? point.custom.hitRadius : helpers.getValueAtIndexOrDefault(this.getDataset().hitRadius, index, this.chart.options.elements.point.hitRadius),
|
||||
},
|
||||
@@ -208,6 +251,39 @@
|
||||
point._model.skip = point.custom && point.custom.skip ? point.custom.skip : (isNaN(point._model.x) || isNaN(point._model.y));
|
||||
},
|
||||
|
||||
calculatePointY: function(value, index, datasetIndex, isCombo) {
|
||||
|
||||
var xScale = this.getScaleForId(this.getDataset().xAxisID);
|
||||
var yScale = this.getScaleForId(this.getDataset().yAxisID);
|
||||
|
||||
if (yScale.options.stacked) {
|
||||
|
||||
var sumPos = 0,
|
||||
sumNeg = 0;
|
||||
|
||||
for (var i = this.chart.data.datasets.length - 1; i > datasetIndex; i--) {
|
||||
var ds = this.chart.data.datasets[i];
|
||||
if (helpers.isDatasetVisible(ds)) {
|
||||
if (ds.data[index] < 0) {
|
||||
sumNeg += ds.data[index] || 0;
|
||||
} else {
|
||||
sumPos += ds.data[index] || 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (value < 0) {
|
||||
return yScale.getPixelForValue(sumNeg + value);
|
||||
} else {
|
||||
return yScale.getPixelForValue(sumPos + value);
|
||||
}
|
||||
|
||||
return yScale.getPixelForValue(value);
|
||||
}
|
||||
|
||||
return yScale.getPixelForValue(value);
|
||||
},
|
||||
|
||||
updateBezierControlPoints: function() {
|
||||
// Update bezier control points
|
||||
helpers.each(this.getDataset().metaData, function(point, index) {
|
||||
@@ -218,28 +294,12 @@
|
||||
point._model.tension
|
||||
);
|
||||
|
||||
point._model.controlPointPreviousX = controlPoints.previous.x;
|
||||
point._model.controlPointNextX = controlPoints.next.x;
|
||||
|
||||
// Prevent the bezier going outside of the bounds of the graph
|
||||
point._model.controlPointPreviousX = Math.max(Math.min(controlPoints.previous.x, this.chart.chartArea.right), this.chart.chartArea.left);
|
||||
point._model.controlPointPreviousY = Math.max(Math.min(controlPoints.previous.y, this.chart.chartArea.bottom), this.chart.chartArea.top);
|
||||
|
||||
// Cap outer bezier handles to the upper/lower scale bounds
|
||||
if (controlPoints.next.y > this.chart.chartArea.bottom) {
|
||||
point._model.controlPointNextY = this.chart.chartArea.bottom;
|
||||
} else if (controlPoints.next.y < this.chart.chartArea.top) {
|
||||
point._model.controlPointNextY = this.chart.chartArea.top;
|
||||
} else {
|
||||
point._model.controlPointNextY = controlPoints.next.y;
|
||||
}
|
||||
|
||||
// Cap inner bezier handles to the upper/lower scale bounds
|
||||
if (controlPoints.previous.y > this.chart.chartArea.bottom) {
|
||||
point._model.controlPointPreviousY = this.chart.chartArea.bottom;
|
||||
} else if (controlPoints.previous.y < this.chart.chartArea.top) {
|
||||
point._model.controlPointPreviousY = this.chart.chartArea.top;
|
||||
} else {
|
||||
point._model.controlPointPreviousY = controlPoints.previous.y;
|
||||
}
|
||||
point._model.controlPointNextX = Math.max(Math.min(controlPoints.next.x, this.chart.chartArea.right), this.chart.chartArea.left);
|
||||
point._model.controlPointNextY = Math.max(Math.min(controlPoints.next.y, this.chart.chartArea.bottom), this.chart.chartArea.top);
|
||||
|
||||
// Now pivot the point for animation
|
||||
point.pivot();
|
||||
@@ -279,9 +339,9 @@
|
||||
var index = point._index;
|
||||
|
||||
point._model.radius = point.custom && point.custom.radius ? point.custom.radius : helpers.getValueAtIndexOrDefault(this.getDataset().radius, index, this.chart.options.elements.point.radius);
|
||||
point._model.backgroundColor = point.custom && point.custom.backgroundColor ? point.custom.backgroundColor : helpers.getValueAtIndexOrDefault(this.getDataset().pointBackgroundColor, index, this.chart.options.elements.point.backgroundColor);
|
||||
point._model.borderColor = point.custom && point.custom.borderColor ? point.custom.borderColor : helpers.getValueAtIndexOrDefault(this.getDataset().pointBorderColor, index, this.chart.options.elements.point.borderColor);
|
||||
point._model.borderWidth = point.custom && point.custom.borderWidth ? point.custom.borderWidth : helpers.getValueAtIndexOrDefault(this.getDataset().pointBorderWidth, index, this.chart.options.elements.point.borderWidth);
|
||||
point._model.backgroundColor = this.getPointBackgroundColor(point, index);
|
||||
point._model.borderColor = this.getPointBorderColor(point, index);
|
||||
point._model.borderWidth = this.getPointBorderWidth(point, index);
|
||||
}
|
||||
});
|
||||
}).call(this);
|
||||
|
||||
@@ -17,6 +17,16 @@
|
||||
//Boolean - Whether to animate the rotation of the chart
|
||||
animateRotate: true,
|
||||
animateScale: true,
|
||||
|
||||
// Need to override these to give a nice default
|
||||
tooltips: {
|
||||
callbacks: {
|
||||
title: function() { return ''; },
|
||||
label: function(tooltipItem, data) {
|
||||
return data.labels[tooltipItem.index] + ': ' + tooltipItem.yLabel;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Chart.controllers.polarArea = function(chart, datasetIndex) {
|
||||
@@ -143,6 +153,7 @@
|
||||
_chart: this.chart.chart,
|
||||
_datasetIndex: this.index,
|
||||
_index: index,
|
||||
_scale: this.chart.scale,
|
||||
|
||||
// Desired view properties
|
||||
_model: reset ? resetModel : {
|
||||
|
||||
@@ -167,6 +167,7 @@
|
||||
// Utility
|
||||
_datasetIndex: this.index,
|
||||
_index: index,
|
||||
_scale: this.chart.scale,
|
||||
|
||||
// Desired view properties
|
||||
_model: {
|
||||
@@ -196,28 +197,12 @@
|
||||
point._model.tension
|
||||
);
|
||||
|
||||
point._model.controlPointPreviousX = controlPoints.previous.x;
|
||||
point._model.controlPointNextX = controlPoints.next.x;
|
||||
|
||||
// Prevent the bezier going outside of the bounds of the graph
|
||||
point._model.controlPointPreviousX = Math.max(Math.min(controlPoints.previous.x, this.chart.chartArea.right), this.chart.chartArea.left);
|
||||
point._model.controlPointPreviousY = Math.max(Math.min(controlPoints.previous.y, this.chart.chartArea.bottom), this.chart.chartArea.top);
|
||||
|
||||
// Cap outer bezier handles to the upper/lower scale bounds
|
||||
if (controlPoints.next.y > this.chart.chartArea.bottom) {
|
||||
point._model.controlPointNextY = this.chart.chartArea.bottom;
|
||||
} else if (controlPoints.next.y < this.chart.chartArea.top) {
|
||||
point._model.controlPointNextY = this.chart.chartArea.top;
|
||||
} else {
|
||||
point._model.controlPointNextY = controlPoints.next.y;
|
||||
}
|
||||
|
||||
// Cap inner bezier handles to the upper/lower scale bounds
|
||||
if (controlPoints.previous.y > this.chart.chartArea.bottom) {
|
||||
point._model.controlPointPreviousY = this.chart.chartArea.bottom;
|
||||
} else if (controlPoints.previous.y < this.chart.chartArea.top) {
|
||||
point._model.controlPointPreviousY = this.chart.chartArea.top;
|
||||
} else {
|
||||
point._model.controlPointPreviousY = controlPoints.previous.y;
|
||||
}
|
||||
point._model.controlPointNextX = Math.max(Math.min(controlPoints.next.x, this.chart.chartArea.right), this.chart.chartArea.left);
|
||||
point._model.controlPointNextY = Math.max(Math.min(controlPoints.next.y, this.chart.chartArea.bottom), this.chart.chartArea.top);
|
||||
|
||||
// Now pivot the point for animation
|
||||
point.pivot();
|
||||
|
||||
@@ -23,10 +23,15 @@
|
||||
|
||||
this.chart = instance;
|
||||
this.config = instance.config;
|
||||
this.data = this.config.data;
|
||||
this.options = this.config.options = helpers.configMerge(Chart.defaults.global, Chart.defaults[this.config.type], this.config.options || {});
|
||||
this.id = helpers.uid();
|
||||
|
||||
Object.defineProperty(this, 'data', {
|
||||
get: function() {
|
||||
return this.config.data;
|
||||
},
|
||||
});
|
||||
|
||||
//Add the chart instance to the global namespace
|
||||
Chart.instances[this.id] = this;
|
||||
|
||||
@@ -112,7 +117,7 @@
|
||||
}
|
||||
},
|
||||
buildScales: function buildScales() {
|
||||
// Map of scale ID to scale object so we can lookup later
|
||||
// Map of scale ID to scale object so we can lookup later
|
||||
this.scales = {};
|
||||
|
||||
// Build the x axes
|
||||
@@ -123,7 +128,7 @@
|
||||
var scale = new ScaleClass({
|
||||
ctx: this.chart.ctx,
|
||||
options: xAxisOptions,
|
||||
data: this.data,
|
||||
chart: this,
|
||||
id: xAxisOptions.id,
|
||||
});
|
||||
|
||||
@@ -138,7 +143,7 @@
|
||||
var scale = new ScaleClass({
|
||||
ctx: this.chart.ctx,
|
||||
options: yAxisOptions,
|
||||
data: this.data,
|
||||
chart: this,
|
||||
id: yAxisOptions.id,
|
||||
});
|
||||
|
||||
@@ -152,8 +157,7 @@
|
||||
var scale = new ScaleClass({
|
||||
ctx: this.chart.ctx,
|
||||
options: this.options.scale,
|
||||
data: this.data,
|
||||
chart: this.chart,
|
||||
chart: this,
|
||||
});
|
||||
|
||||
this.scale = scale;
|
||||
@@ -170,18 +174,22 @@
|
||||
if (!dataset.type) {
|
||||
dataset.type = this.config.type;
|
||||
}
|
||||
|
||||
var type = dataset.type;
|
||||
types.push(type);
|
||||
|
||||
if (dataset.controller) {
|
||||
dataset.controller.updateIndex(datasetIndex);
|
||||
return;
|
||||
}
|
||||
|
||||
dataset.controller = new Chart.controllers[type](this, datasetIndex);
|
||||
|
||||
if (resetNewControllers) {
|
||||
dataset.controller.reset();
|
||||
}
|
||||
}, this);
|
||||
|
||||
if (types.length > 1) {
|
||||
for (var i = 1; i < types.length; i++) {
|
||||
if (types[i] != types[i - 1]) {
|
||||
@@ -199,6 +207,9 @@
|
||||
},
|
||||
|
||||
update: function update(animationDuration, lazy) {
|
||||
// In case the entire data object changed
|
||||
this.tooltip._data = this.data;
|
||||
|
||||
Chart.scaleService.update(this, this.chart.width, this.chart.height);
|
||||
|
||||
// Make sure dataset controllers are updated and new controllers are reset
|
||||
@@ -294,13 +305,25 @@
|
||||
var eventPosition = helpers.getRelativePosition(e, this.chart);
|
||||
var elementsArray = [];
|
||||
|
||||
helpers.each(this.data.datasets, function(dataset, datasetIndex) {
|
||||
if (helpers.isDatasetVisible(dataset)) {
|
||||
helpers.each(dataset.metaData, function(element, index) {
|
||||
if (element.inLabelRange(eventPosition.x, eventPosition.y)) {
|
||||
elementsArray.push(element);
|
||||
var found = (function(){
|
||||
for (var i = 0; i < this.data.datasets.length; i++) {
|
||||
if (helpers.isDatasetVisible(this.data.datasets[i])) {
|
||||
for (var j = 0; j < this.data.datasets[i].metaData.length; j++) {
|
||||
if (this.data.datasets[i].metaData[j].inRange(eventPosition.x, eventPosition.y)) {
|
||||
return this.data.datasets[i].metaData[j];
|
||||
}
|
||||
}
|
||||
}, this);
|
||||
}
|
||||
}
|
||||
}).call(this);
|
||||
|
||||
if(!found){
|
||||
return elementsArray;
|
||||
}
|
||||
|
||||
helpers.each(this.data.datasets, function(dataset, dsIndex){
|
||||
if(helpers.isDatasetVisible(dataset)){
|
||||
elementsArray.push(dataset.metaData[found._index]);
|
||||
}
|
||||
}, this);
|
||||
|
||||
@@ -375,7 +398,8 @@
|
||||
|
||||
// Find Active Elements for hover and tooltips
|
||||
if (e.type == 'mouseout') {
|
||||
this.active = this.tooltipActive = [];
|
||||
this.active = [];
|
||||
this.tooltipActive = [];
|
||||
} else {
|
||||
this.active = function() {
|
||||
switch (this.options.hover.mode) {
|
||||
@@ -426,7 +450,8 @@
|
||||
case 'label':
|
||||
case 'dataset':
|
||||
for (var i = 0; i < this.lastActive.length; i++) {
|
||||
this.data.datasets[this.lastActive[i]._datasetIndex].controller.removeHoverStyle(this.lastActive[i], this.lastActive[i]._datasetIndex, this.lastActive[i]._index);
|
||||
if (this.lastActive[i])
|
||||
this.data.datasets[this.lastActive[i]._datasetIndex].controller.removeHoverStyle(this.lastActive[i], this.lastActive[i]._datasetIndex, this.lastActive[i]._index);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@@ -443,7 +468,8 @@
|
||||
case 'label':
|
||||
case 'dataset':
|
||||
for (var j = 0; j < this.active.length; j++) {
|
||||
this.data.datasets[this.active[j]._datasetIndex].controller.setHoverStyle(this.active[j]);
|
||||
if (this.active[j])
|
||||
this.data.datasets[this.active[j]._datasetIndex].controller.setHoverStyle(this.active[j]);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@@ -457,20 +483,8 @@
|
||||
|
||||
// The usual updates
|
||||
this.tooltip.initialize();
|
||||
|
||||
// Active
|
||||
if (this.tooltipActive.length) {
|
||||
this.tooltip._model.opacity = 1;
|
||||
|
||||
helpers.extend(this.tooltip, {
|
||||
_active: this.tooltipActive,
|
||||
});
|
||||
|
||||
this.tooltip.update();
|
||||
} else {
|
||||
// Inactive
|
||||
this.tooltip._model.opacity = 0;
|
||||
}
|
||||
this.tooltip._active = this.tooltipActive;
|
||||
this.tooltip.update();
|
||||
}
|
||||
|
||||
// Hover animations
|
||||
@@ -492,16 +506,17 @@
|
||||
}, this);
|
||||
|
||||
// If entering, leaving, or changing elements, animate the change via pivot
|
||||
if ((!this.lastActive.length && this.active.length) ||
|
||||
(this.lastActive.length && !this.active.length) ||
|
||||
(this.lastActive.length && this.active.length && changed) ||
|
||||
(!this.lastTooltipActive.length && this.tooltipActive.length) ||
|
||||
(this.lastTooltipActive.length && !this.tooltipActive.length) ||
|
||||
(this.lastTooltipActive.length && this.tooltipActive.length && changed)) {
|
||||
if ((this.lastActive.length !== this.active.length) ||
|
||||
(this.lastTooltipActive.length !== this.tooltipActive.length) ||
|
||||
changed) {
|
||||
|
||||
this.stop();
|
||||
|
||||
// We only need to render at this point. Updating will cause scales to be recomputed generating flicker & using more
|
||||
if (this.options.tooltips.enabled || this.options.tooltips.custom) {
|
||||
this.tooltip.update(true);
|
||||
}
|
||||
|
||||
// We only need to render at this point. Updating will cause scales to be recomputed generating flicker & using more
|
||||
// memory than necessary.
|
||||
this.render(this.options.hover.animationDuration, true);
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
|
||||
// Init if doesn't exist
|
||||
else if (!this._view[key]) {
|
||||
if (typeof value === 'number') {
|
||||
if (typeof value === 'number' && isNaN(this._view[key]) === false) {
|
||||
this._view[key] = value * ease;
|
||||
} else {
|
||||
this._view[key] = value || null;
|
||||
@@ -61,14 +61,13 @@
|
||||
}
|
||||
// Number transitions
|
||||
else if (typeof value === 'number') {
|
||||
var startVal = this._start[key] !== undefined ? this._start[key] : 0;
|
||||
var startVal = this._start[key] !== undefined && isNaN(this._start[key]) === false ? this._start[key] : 0;
|
||||
this._view[key] = ((this._model[key] - startVal) * ease) + startVal;
|
||||
}
|
||||
// Everything else
|
||||
else {
|
||||
this._view[key] = value;
|
||||
}
|
||||
|
||||
}, this);
|
||||
|
||||
if (ease === 1) {
|
||||
|
||||
+24
-22
@@ -321,27 +321,29 @@
|
||||
aliasPixel = helpers.aliasPixel = function(pixelWidth) {
|
||||
return (pixelWidth % 2 === 0) ? 0 : 0.5;
|
||||
},
|
||||
splineCurve = helpers.splineCurve = function(FirstPoint, MiddlePoint, AfterPoint, t) {
|
||||
splineCurve = helpers.splineCurve = function(firstPoint, middlePoint, afterPoint, t) {
|
||||
//Props to Rob Spencer at scaled innovation for his post on splining between points
|
||||
//http://scaledinnovation.com/analytics/splines/aboutSplines.html
|
||||
|
||||
// This function must also respect "skipped" points
|
||||
|
||||
var previous = FirstPoint,
|
||||
current = MiddlePoint,
|
||||
next = AfterPoint;
|
||||
var previous = firstPoint.skip ? middlePoint : firstPoint,
|
||||
current = middlePoint,
|
||||
next = afterPoint.skip ? middlePoint : afterPoint;
|
||||
|
||||
if (previous.skip) {
|
||||
previous = current;
|
||||
}
|
||||
if (next.skip) {
|
||||
next = current;
|
||||
}
|
||||
var d01 = Math.sqrt(Math.pow(current.x - previous.x, 2) + Math.pow(current.y - previous.y, 2));
|
||||
var d12 = Math.sqrt(Math.pow(next.x - current.x, 2) + Math.pow(next.y - current.y, 2));
|
||||
|
||||
var s01 = d01 / (d01 + d12);
|
||||
var s12 = d12 / (d01 + d12);
|
||||
|
||||
// If all points are the same, s01 & s02 will be inf
|
||||
s01 = isNaN(s01) ? 0 : s01;
|
||||
s12 = isNaN(s12) ? 0 : s12;
|
||||
|
||||
var fa = t * s01; // scaling factor for triangle Ta
|
||||
var fb = t * s12;
|
||||
|
||||
var d01 = Math.sqrt(Math.pow(current.x - previous.x, 2) + Math.pow(current.y - previous.y, 2)),
|
||||
d12 = Math.sqrt(Math.pow(next.x - current.x, 2) + Math.pow(next.y - current.y, 2)),
|
||||
fa = t * d01 / (d01 + d12), // scaling factor for triangle Ta
|
||||
fb = t * d12 / (d01 + d12);
|
||||
return {
|
||||
previous: {
|
||||
x: current.x - fa * (next.x - previous.x),
|
||||
@@ -622,7 +624,7 @@
|
||||
canvas = evt.currentTarget || evt.srcElement,
|
||||
boundingRect = canvas.getBoundingClientRect();
|
||||
|
||||
if (e.touches) {
|
||||
if (e.touches && e.touches.length > 0) {
|
||||
mouseX = e.touches[0].clientX;
|
||||
mouseY = e.touches[0].clientY;
|
||||
|
||||
@@ -632,7 +634,7 @@
|
||||
}
|
||||
|
||||
// Scale mouse coordinates into canvas coordinates
|
||||
// by following the pattern laid out by 'jerryj' in the comments of
|
||||
// by following the pattern laid out by 'jerryj' in the comments of
|
||||
// http://www.html5canvastutorials.com/advanced/html5-canvas-mouse-coordinates/
|
||||
|
||||
// We divide by the current device pixel ratio, because the canvas is scaled up by that amount in each direction. However
|
||||
@@ -739,12 +741,12 @@
|
||||
var ctx = chart.ctx;
|
||||
var width = chart.canvas.width;
|
||||
var height = chart.canvas.height;
|
||||
chart.currentDevicePixelRatio = window.devicePixelRatio || 1;
|
||||
var pixelRatio = chart.currentDevicePixelRatio = window.devicePixelRatio || 1;
|
||||
|
||||
if (window.devicePixelRatio !== 1) {
|
||||
ctx.canvas.height = height * window.devicePixelRatio;
|
||||
ctx.canvas.width = width * window.devicePixelRatio;
|
||||
ctx.scale(window.devicePixelRatio, window.devicePixelRatio);
|
||||
if (pixelRatio !== 1) {
|
||||
ctx.canvas.height = height * pixelRatio;
|
||||
ctx.canvas.width = width * pixelRatio;
|
||||
ctx.scale(pixelRatio, pixelRatio);
|
||||
|
||||
ctx.canvas.style.width = width + 'px';
|
||||
ctx.canvas.style.height = height + 'px';
|
||||
@@ -752,7 +754,7 @@
|
||||
// Store the device pixel ratio so that we can go backwards in `destroy`.
|
||||
// The devicePixelRatio changes with zoom, so there are no guarantees that it is the same
|
||||
// when destroy is called
|
||||
chart.originalDevicePixelRatio = chart.originalDevicePixelRatio || window.devicePixelRatio;
|
||||
chart.originalDevicePixelRatio = chart.originalDevicePixelRatio || pixelRatio;
|
||||
}
|
||||
},
|
||||
//-- Canvas methods
|
||||
|
||||
+1
-1
@@ -79,7 +79,7 @@
|
||||
responsive: true,
|
||||
responsiveAnimationDuration: 0,
|
||||
maintainAspectRatio: true,
|
||||
events: ["mousemove", "mouseout", "click", "touchstart", "touchmove", "touchend"],
|
||||
events: ["mousemove", "mouseout", "click", "touchstart", "touchmove"],
|
||||
hover: {
|
||||
onHover: null,
|
||||
mode: 'single',
|
||||
|
||||
+25
-13
@@ -10,7 +10,7 @@
|
||||
|
||||
// grid line settings
|
||||
gridLines: {
|
||||
show: true,
|
||||
display: true,
|
||||
color: "rgba(0, 0, 0, 0.1)",
|
||||
lineWidth: 1,
|
||||
drawOnChartArea: true,
|
||||
@@ -31,7 +31,7 @@
|
||||
labelString: '',
|
||||
|
||||
// display property
|
||||
show: false,
|
||||
display: false,
|
||||
},
|
||||
|
||||
// label settings
|
||||
@@ -46,7 +46,7 @@
|
||||
mirror: false,
|
||||
padding: 10,
|
||||
reverse: false,
|
||||
show: true,
|
||||
display: true,
|
||||
callback: function(value) {
|
||||
return '' + value;
|
||||
},
|
||||
@@ -231,18 +231,18 @@
|
||||
if (this.isHorizontal()) {
|
||||
this.minSize.width = this.maxWidth; // fill all the width
|
||||
} else {
|
||||
this.minSize.width = this.options.gridLines.show && this.options.display ? 10 : 0;
|
||||
this.minSize.width = this.options.gridLines.display && this.options.display ? 10 : 0;
|
||||
}
|
||||
|
||||
// height
|
||||
if (this.isHorizontal()) {
|
||||
this.minSize.height = this.options.gridLines.show && this.options.display ? 10 : 0;
|
||||
this.minSize.height = this.options.gridLines.display && this.options.display ? 10 : 0;
|
||||
} else {
|
||||
this.minSize.height = this.maxHeight; // fill all the height
|
||||
}
|
||||
|
||||
// Are we showing a title for the scale?
|
||||
if (this.options.scaleLabel.show) {
|
||||
if (this.options.scaleLabel.display) {
|
||||
if (this.isHorizontal()) {
|
||||
this.minSize.height += (this.options.scaleLabel.fontSize * 1.5);
|
||||
} else {
|
||||
@@ -250,7 +250,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
if (this.options.ticks.show && this.options.display) {
|
||||
if (this.options.ticks.display && this.options.display) {
|
||||
// Don't bother fitting the ticks if we are not showing them
|
||||
var labelFont = helpers.fontString(this.options.ticks.fontSize,
|
||||
this.options.ticks.fontStyle, this.options.ticks.fontFamily);
|
||||
@@ -259,6 +259,8 @@
|
||||
// A horizontal axis is more constrained by the height.
|
||||
var maxLabelHeight = this.maxHeight - this.minSize.height;
|
||||
var longestLabelWidth = helpers.longestText(this.ctx, labelFont, this.ticks);
|
||||
|
||||
// TODO - improve this calculation
|
||||
var labelHeight = (Math.sin(helpers.toRadians(this.labelRotation)) * longestLabelWidth) + 1.5 * this.options.ticks.fontSize;
|
||||
|
||||
this.minSize.height = Math.min(this.maxHeight, this.minSize.height + labelHeight);
|
||||
@@ -280,6 +282,11 @@
|
||||
var maxLabelWidth = this.maxWidth - this.minSize.width;
|
||||
var largestTextWidth = helpers.longestText(this.ctx, labelFont, this.ticks);
|
||||
|
||||
// Account for padding
|
||||
if (!this.options.ticks.mirror) {
|
||||
largestTextWidth += this.options.ticks.padding;
|
||||
}
|
||||
|
||||
if (largestTextWidth < maxLabelWidth) {
|
||||
// We don't need all the room
|
||||
this.minSize.width += largestTextWidth;
|
||||
@@ -404,7 +411,7 @@
|
||||
var xLineValue = this.getPixelForTick(index); // xvalues for grid lines
|
||||
var xLabelValue = this.getPixelForTick(index, this.options.gridLines.offsetGridLines); // x values for ticks (need to consider offsetLabel option)
|
||||
|
||||
if (this.options.gridLines.show) {
|
||||
if (this.options.gridLines.display) {
|
||||
if (index === (typeof this.zeroLineIndex !== 'undefined' ? this.zeroLineIndex : 0)) {
|
||||
// Draw the first index specially
|
||||
this.ctx.lineWidth = this.options.gridLines.zeroLineWidth;
|
||||
@@ -436,7 +443,7 @@
|
||||
this.ctx.stroke();
|
||||
}
|
||||
|
||||
if (this.options.ticks.show) {
|
||||
if (this.options.ticks.display) {
|
||||
this.ctx.save();
|
||||
this.ctx.translate(xLabelValue, (isRotated) ? this.top + 12 : this.options.position === "top" ? this.bottom - 10 : this.top + 10);
|
||||
this.ctx.rotate(helpers.toRadians(this.labelRotation) * -1);
|
||||
@@ -448,7 +455,7 @@
|
||||
}
|
||||
}, this);
|
||||
|
||||
if (this.options.scaleLabel.show) {
|
||||
if (this.options.scaleLabel.display) {
|
||||
// Draw the scale label
|
||||
this.ctx.textAlign = "center";
|
||||
this.ctx.textBaseline = 'middle';
|
||||
@@ -467,9 +474,14 @@
|
||||
var xTickEnd = this.options.position == "right" ? this.left + 5 : this.right;
|
||||
|
||||
helpers.each(this.ticks, function(label, index) {
|
||||
// If the callback returned a null or undefined value, do not draw this line
|
||||
if (label === undefined || label === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
var yLineValue = this.getPixelForTick(index); // xvalues for grid lines
|
||||
|
||||
if (this.options.gridLines.show) {
|
||||
if (this.options.gridLines.display) {
|
||||
if (index === (typeof this.zeroLineIndex !== 'undefined' ? this.zeroLineIndex : 0)) {
|
||||
// Draw the first index specially
|
||||
this.ctx.lineWidth = this.options.gridLines.zeroLineWidth;
|
||||
@@ -501,7 +513,7 @@
|
||||
this.ctx.stroke();
|
||||
}
|
||||
|
||||
if (this.options.ticks.show) {
|
||||
if (this.options.ticks.display) {
|
||||
var xLabelValue;
|
||||
var yLabelValue = this.getPixelForTick(index, this.options.gridLines.offsetGridLines); // x values for ticks (need to consider offsetLabel option)
|
||||
|
||||
@@ -536,7 +548,7 @@
|
||||
}
|
||||
}, this);
|
||||
|
||||
if (this.options.scaleLabel.show) {
|
||||
if (this.options.scaleLabel.display) {
|
||||
// Draw the scale label
|
||||
scaleLabelX = this.options.position == 'left' ? this.left + (this.options.scaleLabel.fontSize / 2) : this.right - (this.options.scaleLabel.fontSize / 2);
|
||||
scaleLabelY = this.top + ((this.bottom - this.top) / 2);
|
||||
|
||||
+151
-99
@@ -38,23 +38,39 @@
|
||||
xOffset: 10,
|
||||
multiKeyBackground: '#fff',
|
||||
callbacks: {
|
||||
// Args are: (tooltipItems, data)
|
||||
beforeTitle: helpers.noop,
|
||||
title: function(xLabel, yLabel, index, datasetIndex, data) {
|
||||
// Pick first label for now
|
||||
return helpers.isArray(xLabel) ? xLabel[0] : xLabel;
|
||||
title: function(tooltipItems, data) {
|
||||
// Pick first xLabel for now
|
||||
var title = '';
|
||||
|
||||
if (tooltipItems.length > 0) {
|
||||
if (tooltipItems[0].xLabel) {
|
||||
title = tooltipItems[0].xLabel;
|
||||
} else if (data.labels.length > 0 && tooltipItems[0].index < data.labels.length) {
|
||||
title = data.labels[tooltipItems[0].index];
|
||||
}
|
||||
}
|
||||
|
||||
return title;
|
||||
},
|
||||
afterTitle: helpers.noop,
|
||||
|
||||
// Args are: (tooltipItems, data)
|
||||
beforeBody: helpers.noop,
|
||||
|
||||
// Args are: (tooltipItem, data)
|
||||
beforeLabel: helpers.noop,
|
||||
label: function(xLabel, yLabel, index, datasetIndex, data) {
|
||||
return this._data.datasets[datasetIndex].label + ': ' + yLabel;
|
||||
label: function(tooltipItem, data) {
|
||||
var datasetLabel = data.datasets[tooltipItem.datasetIndex].label || '';
|
||||
return datasetLabel + ': ' + tooltipItem.yLabel;
|
||||
},
|
||||
afterLabel: helpers.noop,
|
||||
|
||||
// Args are: (tooltipItems, data)
|
||||
afterBody: helpers.noop,
|
||||
|
||||
// Args are: (tooltipItems, data)
|
||||
beforeFooter: helpers.noop,
|
||||
footer: helpers.noop,
|
||||
afterFooter: helpers.noop,
|
||||
@@ -88,9 +104,9 @@
|
||||
bodyColor: options.tooltips.bodyColor,
|
||||
_bodyFontFamily: options.tooltips.bodyFontFamily,
|
||||
_bodyFontStyle: options.tooltips.bodyFontStyle,
|
||||
_bodyAlign: options.tooltips.bodyAlign,
|
||||
bodyFontSize: options.tooltips.bodyFontSize,
|
||||
bodySpacing: options.tooltips.bodySpacing,
|
||||
_bodposition: options.tooltips.bodposition,
|
||||
|
||||
// Title
|
||||
titleColor: options.tooltips.titleColor,
|
||||
@@ -120,7 +136,8 @@
|
||||
});
|
||||
},
|
||||
|
||||
// Get the title
|
||||
// Get the title
|
||||
// Args are: (tooltipItem, data)
|
||||
getTitle: function() {
|
||||
var beforeTitle = this._options.tooltips.callbacks.beforeTitle.apply(this, arguments),
|
||||
title = this._options.tooltips.callbacks.title.apply(this, arguments),
|
||||
@@ -134,59 +151,35 @@
|
||||
return lines;
|
||||
},
|
||||
|
||||
getBeforeBody: function(xLabel, yLabel, index, datasetIndex, data) {
|
||||
var lines = this._options.tooltips.callbacks.beforeBody.call(this, xLabel, yLabel, index, datasetIndex, data);
|
||||
// Args are: (tooltipItem, data)
|
||||
getBeforeBody: function() {
|
||||
var lines = this._options.tooltips.callbacks.beforeBody.call(this, arguments);
|
||||
return helpers.isArray(lines) ? lines : [lines];
|
||||
},
|
||||
|
||||
getBody: function(xLabel, yLabel, index, datasetIndex) {
|
||||
|
||||
// Args are: (tooltipItem, data)
|
||||
getBody: function(tooltipItems, data) {
|
||||
var lines = [];
|
||||
|
||||
var beforeLabel,
|
||||
afterLabel,
|
||||
label;
|
||||
helpers.each(tooltipItems, function(bodyItem) {
|
||||
var beforeLabel = this._options.tooltips.callbacks.beforeLabel.call(this, bodyItem, data) || '';
|
||||
var bodyLabel = this._options.tooltips.callbacks.label.call(this, bodyItem, data) || '';
|
||||
var afterLabel = this._options.tooltips.callbacks.afterLabel.call(this, bodyItem, data) || '';
|
||||
|
||||
if (helpers.isArray(xLabel)) {
|
||||
|
||||
var labels = [];
|
||||
|
||||
// Run EACH label pair through the label callback this time.
|
||||
for (var i = 0; i < xLabel.length; i++) {
|
||||
|
||||
beforeLabel = this._options.tooltips.callbacks.beforeLabel.call(this, xLabel[i], yLabel[i], index, datasetIndex);
|
||||
afterLabel = this._options.tooltips.callbacks.afterLabel.call(this, xLabel[i], yLabel[i], index, datasetIndex);
|
||||
|
||||
labels.push((beforeLabel ? beforeLabel : '') + this._options.tooltips.callbacks.label.call(this, xLabel[i], yLabel[i], index, datasetIndex) + (afterLabel ? afterLabel : ''));
|
||||
|
||||
}
|
||||
|
||||
if (labels.length) {
|
||||
lines = lines.concat(labels);
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
// Run the single label through the callback
|
||||
|
||||
beforeLabel = this._options.tooltips.callbacks.beforeLabel.apply(this, arguments);
|
||||
label = this._options.tooltips.callbacks.label.apply(this, arguments);
|
||||
afterLabel = this._options.tooltips.callbacks.afterLabel.apply(this, arguments);
|
||||
|
||||
if (beforeLabel || label || afterLabel) {
|
||||
lines.push((beforeLabel ? afterLabel : '') + label + (afterLabel ? afterLabel : ''));
|
||||
}
|
||||
}
|
||||
lines.push(beforeLabel + bodyLabel + afterLabel);
|
||||
}, this);
|
||||
|
||||
return lines;
|
||||
},
|
||||
|
||||
getAfterBody: function(xLabel, yLabel, index, datasetIndex, data) {
|
||||
var lines = this._options.tooltips.callbacks.afterBody.call(this, xLabel, yLabel, index, datasetIndex, data);
|
||||
// Args are: (tooltipItem, data)
|
||||
getAfterBody: function() {
|
||||
var lines = this._options.tooltips.callbacks.afterBody.call(this, arguments);
|
||||
return helpers.isArray(lines) ? lines : [lines];
|
||||
},
|
||||
|
||||
// Get the footer and beforeFooter and afterFooter lines
|
||||
// Args are: (tooltipItem, data)
|
||||
getFooter: function() {
|
||||
var beforeFooter = this._options.tooltips.callbacks.beforeFooter.apply(this, arguments);
|
||||
var footer = this._options.tooltips.callbacks.footer.apply(this, arguments);
|
||||
@@ -200,68 +193,118 @@
|
||||
return lines;
|
||||
},
|
||||
|
||||
update: function() {
|
||||
getAveragePosition: function(elements){
|
||||
|
||||
if(!elements.length){
|
||||
return false;
|
||||
}
|
||||
|
||||
var xPositions = [];
|
||||
var yPositions = [];
|
||||
|
||||
helpers.each(elements, function(el){
|
||||
if(el) {
|
||||
var pos = el.tooltipPosition();
|
||||
xPositions.push(pos.x);
|
||||
yPositions.push(pos.y);
|
||||
}
|
||||
});
|
||||
|
||||
var x = 0, y = 0;
|
||||
for (var i = 0; i < xPositions.length; i++) {
|
||||
x += xPositions[i];
|
||||
y += yPositions[i];
|
||||
}
|
||||
|
||||
return {
|
||||
x: Math.round(x / xPositions.length),
|
||||
y: Math.round(y / xPositions.length)
|
||||
};
|
||||
|
||||
},
|
||||
|
||||
update: function(changed) {
|
||||
|
||||
var ctx = this._chart.ctx;
|
||||
|
||||
var element = this._active[0],
|
||||
xLabel,
|
||||
yLabel,
|
||||
labelColors = [],
|
||||
tooltipPosition;
|
||||
if(this._active.length){
|
||||
this._model.opacity = 1;
|
||||
|
||||
if (this._options.tooltips.mode == 'single') {
|
||||
var element = this._active[0],
|
||||
labelColors = [],
|
||||
tooltipPosition;
|
||||
|
||||
xLabel = element._xScale.getLabelForIndex(element._index, element._datasetIndex);
|
||||
yLabel = element._yScale.getLabelForIndex(element._index, element._datasetIndex);
|
||||
tooltipPosition = this._active[0].tooltipPosition();
|
||||
var tooltipItems = [];
|
||||
|
||||
} else {
|
||||
if (this._options.tooltips.mode == 'single') {
|
||||
var yScale = element._yScale || element._scale; // handle radar || polarArea charts
|
||||
tooltipItems.push({
|
||||
xLabel: element._xScale ? element._xScale.getLabelForIndex(element._index, element._datasetIndex) : '',
|
||||
yLabel: yScale ? yScale.getLabelForIndex(element._index, element._datasetIndex) : '',
|
||||
index: element._index,
|
||||
datasetIndex: element._datasetIndex,
|
||||
});
|
||||
tooltipPosition = this.getAveragePosition(this._active);
|
||||
} else {
|
||||
helpers.each(this._data.datasets, function(dataset, datasetIndex) {
|
||||
if (!helpers.isDatasetVisible(dataset)) {
|
||||
return;
|
||||
}
|
||||
var currentElement = dataset.metaData[element._index];
|
||||
if (currentElement) {
|
||||
var yScale = element._yScale || element._scale; // handle radar || polarArea charts
|
||||
|
||||
xLabel = [];
|
||||
yLabel = [];
|
||||
tooltipItems.push({
|
||||
xLabel: currentElement._xScale ? currentElement._xScale.getLabelForIndex(currentElement._index, currentElement._datasetIndex) : '',
|
||||
yLabel: yScale ? yScale.getLabelForIndex(currentElement._index, currentElement._datasetIndex) : '',
|
||||
index: element._index,
|
||||
datasetIndex: datasetIndex,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
helpers.each(this._data.datasets, function(dataset, datasetIndex) {
|
||||
if (!helpers.isDatasetVisible(dataset)) {
|
||||
return;
|
||||
}
|
||||
xLabel.push(element._xScale.getLabelForIndex(element._index, datasetIndex));
|
||||
yLabel.push(element._yScale.getLabelForIndex(element._index, datasetIndex));
|
||||
helpers.each(this._active, function(active, i) {
|
||||
if (active) {
|
||||
labelColors.push({
|
||||
borderColor: active._view.borderColor,
|
||||
backgroundColor: active._view.backgroundColor
|
||||
});
|
||||
}
|
||||
}, this);
|
||||
|
||||
tooltipPosition = this.getAveragePosition(this._active);
|
||||
tooltipPosition.y = this._active[0]._yScale.getPixelForDecimal(0.5);
|
||||
}
|
||||
|
||||
// Build the Text Lines
|
||||
helpers.extend(this._model, {
|
||||
title: this.getTitle(tooltipItems, this._data),
|
||||
beforeBody: this.getBeforeBody(tooltipItems, this._data),
|
||||
body: this.getBody(tooltipItems, this._data),
|
||||
afterBody: this.getAfterBody(tooltipItems, this._data),
|
||||
footer: this.getFooter(tooltipItems, this._data),
|
||||
});
|
||||
|
||||
helpers.each(this._active, function(active, i) {
|
||||
labelColors.push({
|
||||
borderColor: active._view.borderColor,
|
||||
backgroundColor: active._view.backgroundColor
|
||||
});
|
||||
}, this);
|
||||
|
||||
tooltipPosition = this._active[0].tooltipPosition();
|
||||
tooltipPosition.y = this._active[0]._yScale.getPixelForDecimal(0.5);
|
||||
|
||||
helpers.extend(this._model, {
|
||||
x: Math.round(tooltipPosition.x),
|
||||
y: Math.round(tooltipPosition.y),
|
||||
caretPadding: tooltipPosition.padding,
|
||||
labelColors: labelColors,
|
||||
});
|
||||
}
|
||||
else{
|
||||
this._model.opacity = 0;
|
||||
}
|
||||
|
||||
|
||||
// Build the Text Lines
|
||||
helpers.extend(this._model, {
|
||||
title: this.getTitle(xLabel, yLabel, element._index, element._datasetIndex, this._data),
|
||||
beforeBody: this.getBeforeBody(xLabel, yLabel, element._index, element._datasetIndex, this._data),
|
||||
body: this.getBody(xLabel, yLabel, element._index, element._datasetIndex, this._data),
|
||||
afterBody: this.getAfterBody(xLabel, yLabel, element._index, element._datasetIndex, this._data),
|
||||
footer: this.getFooter(xLabel, yLabel, element._index, element._datasetIndex, this._data),
|
||||
});
|
||||
|
||||
helpers.extend(this._model, {
|
||||
x: Math.round(tooltipPosition.x),
|
||||
y: Math.round(tooltipPosition.y),
|
||||
caretPadding: tooltipPosition.padding,
|
||||
labelColors: labelColors,
|
||||
});
|
||||
if (changed && this._options.tooltips.custom) {
|
||||
this._options.tooltips.custom.call(this, this._model);
|
||||
}
|
||||
|
||||
return this;
|
||||
},
|
||||
draw: function() {
|
||||
|
||||
|
||||
var ctx = this._chart.ctx;
|
||||
var vm = this._view;
|
||||
|
||||
@@ -349,8 +392,11 @@
|
||||
|
||||
// Draw Background
|
||||
|
||||
// IE11/Edge does not like very small opacities, so snap to 0
|
||||
var opacity = Math.abs(vm.opacity < 1e-3) ? 0 : vm.opacity;
|
||||
|
||||
if (this._options.tooltips.enabled) {
|
||||
ctx.fillStyle = helpers.color(vm.backgroundColor).alpha(vm.opacity).rgbString();
|
||||
ctx.fillStyle = helpers.color(vm.backgroundColor).alpha(opacity).rgbString();
|
||||
helpers.drawRoundedRectangle(ctx, tooltipX, tooltipY, tooltipWidth, tooltipHeight, vm.cornerRadius);
|
||||
ctx.fill();
|
||||
}
|
||||
@@ -358,7 +404,7 @@
|
||||
|
||||
// Draw Caret
|
||||
if (this._options.tooltips.enabled) {
|
||||
ctx.fillStyle = helpers.color(vm.backgroundColor).alpha(vm.opacity).rgbString();
|
||||
ctx.fillStyle = helpers.color(vm.backgroundColor).alpha(opacity).rgbString();
|
||||
|
||||
if (vm.xAlign == 'left') {
|
||||
|
||||
@@ -390,7 +436,7 @@
|
||||
if (vm.title.length) {
|
||||
ctx.textAlign = vm._titleAlign;
|
||||
ctx.textBaseline = "top";
|
||||
ctx.fillStyle = helpers.color(vm.titleColor).alpha(vm.opacity).rgbString();
|
||||
ctx.fillStyle = helpers.color(vm.titleColor).alpha(opacity).rgbString();
|
||||
ctx.font = helpers.fontString(vm.titleFontSize, vm._titleFontStyle, vm._titleFontFamily);
|
||||
|
||||
helpers.each(vm.title, function(title, i) {
|
||||
@@ -406,7 +452,7 @@
|
||||
// Body
|
||||
ctx.textAlign = vm._bodyAlign;
|
||||
ctx.textBaseline = "top";
|
||||
ctx.fillStyle = helpers.color(vm.bodyColor).alpha(vm.opacity).rgbString();
|
||||
ctx.fillStyle = helpers.color(vm.bodyColor).alpha(opacity).rgbString();
|
||||
ctx.font = helpers.fontString(vm.bodyFontSize, vm._bodyFontStyle, vm._bodyFontFamily);
|
||||
|
||||
// Before Body
|
||||
@@ -420,13 +466,19 @@
|
||||
|
||||
// Draw Legend-like boxes if needed
|
||||
if (this._options.tooltips.mode != 'single') {
|
||||
ctx.fillStyle = helpers.color(vm.labelColors[i].borderColor).alpha(vm.opacity).rgbString();
|
||||
// Fill a white rect so that colours merge nicely if the opacity is < 1
|
||||
ctx.fillStyle = helpers.color('#FFFFFF').alpha(opacity).rgbaString();
|
||||
ctx.fillRect(xBase, yBase, vm.bodyFontSize, vm.bodyFontSize);
|
||||
|
||||
ctx.fillStyle = helpers.color(vm.labelColors[i].backgroundColor).alpha(vm.opacity).rgbString();
|
||||
// Border
|
||||
ctx.strokeStyle = helpers.color(vm.labelColors[i].borderColor).alpha(opacity).rgbaString();
|
||||
ctx.strokeRect(xBase, yBase, vm.bodyFontSize, vm.bodyFontSize);
|
||||
|
||||
// Inner square
|
||||
ctx.fillStyle = helpers.color(vm.labelColors[i].backgroundColor).alpha(opacity).rgbaString();
|
||||
ctx.fillRect(xBase + 1, yBase + 1, vm.bodyFontSize - 2, vm.bodyFontSize - 2);
|
||||
|
||||
ctx.fillStyle = helpers.color(vm.bodyColor).alpha(vm.opacity).rgbString(); // Return fill style for text
|
||||
ctx.fillStyle = helpers.color(vm.bodyColor).alpha(opacity).rgbaString(); // Return fill style for text
|
||||
}
|
||||
|
||||
// Body Line
|
||||
@@ -452,7 +504,7 @@
|
||||
|
||||
ctx.textAlign = vm._footerAlign;
|
||||
ctx.textBaseline = "top";
|
||||
ctx.fillStyle = helpers.color(vm.footerColor).alpha(vm.opacity).rgbString();
|
||||
ctx.fillStyle = helpers.color(vm.footerColor).alpha(opacity).rgbString();
|
||||
ctx.font = helpers.fontString(vm.footerFontSize, vm._footerFontStyle, vm._footerFontFamily);
|
||||
|
||||
helpers.each(vm.footer, function(footer, i) {
|
||||
|
||||
+86
-104
@@ -29,64 +29,38 @@
|
||||
fill: true, // do we fill in the area between the line and its base axis
|
||||
};
|
||||
|
||||
|
||||
Chart.elements.Line = Chart.Element.extend({
|
||||
lineToNextPoint: function(previousPoint, point, nextPoint, skipHandler, previousSkipHandler) {
|
||||
var ctx = this._chart.ctx;
|
||||
|
||||
if (point._view.skip) {
|
||||
skipHandler.call(this, previousPoint, point, nextPoint);
|
||||
} else if (previousPoint._view.skip) {
|
||||
previousSkipHandler.call(this, previousPoint, point, nextPoint);
|
||||
} else {
|
||||
// Line between points
|
||||
ctx.bezierCurveTo(
|
||||
previousPoint._view.controlPointNextX,
|
||||
previousPoint._view.controlPointNextY,
|
||||
point._view.controlPointPreviousX,
|
||||
point._view.controlPointPreviousY,
|
||||
point._view.x,
|
||||
point._view.y
|
||||
);
|
||||
}
|
||||
},
|
||||
|
||||
draw: function() {
|
||||
var _this = this;
|
||||
|
||||
var vm = this._view;
|
||||
var ctx = this._chart.ctx;
|
||||
var first = this._children[0];
|
||||
var last = this._children[this._children.length - 1];
|
||||
|
||||
ctx.save();
|
||||
|
||||
// Draw the background first (so the border is always on top)
|
||||
helpers.each(this._children, function(point, index) {
|
||||
|
||||
var previous = helpers.previousItem(this._children, index);
|
||||
var next = helpers.nextItem(this._children, index);
|
||||
|
||||
// First point moves to it's starting position no matter what
|
||||
if (!index) {
|
||||
ctx.moveTo(point._view.x, vm.scaleZero);
|
||||
}
|
||||
|
||||
// Skip this point, draw to scaleZero, move to next point, and draw to next point
|
||||
if (point._view.skip && !this.loop) {
|
||||
ctx.lineTo(previous._view.x, vm.scaleZero);
|
||||
ctx.moveTo(next._view.x, vm.scaleZero);
|
||||
return;
|
||||
}
|
||||
|
||||
// The previous line was skipped, so just draw a normal straight line to the point
|
||||
if (previous._view.skip) {
|
||||
ctx.lineTo(point._view.x, point._view.y);
|
||||
return;
|
||||
}
|
||||
|
||||
// Draw a bezier to point
|
||||
if (vm.tension > 0 && index) {
|
||||
//ctx.lineTo(point._view.x, point._view.y);
|
||||
ctx.bezierCurveTo(
|
||||
previous._view.controlPointNextX,
|
||||
previous._view.controlPointNextY,
|
||||
point._view.controlPointPreviousX,
|
||||
point._view.controlPointPreviousY,
|
||||
point._view.x,
|
||||
point._view.y
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
// Draw a straight line to the point
|
||||
ctx.lineTo(point._view.x, point._view.y);
|
||||
|
||||
}, this);
|
||||
|
||||
// For radial scales, loop back around to the first point
|
||||
if (this._loop) {
|
||||
// Draw a bezier line
|
||||
if (vm.tension > 0 && !first._view.skip) {
|
||||
function loopBackToStart(drawLineToCenter) {
|
||||
if (!first._view.skip && !last._view.skip) {
|
||||
// Draw a bezier line from last to first
|
||||
ctx.bezierCurveTo(
|
||||
last._view.controlPointNextX,
|
||||
last._view.controlPointNextY,
|
||||
@@ -95,23 +69,68 @@
|
||||
first._view.x,
|
||||
first._view.y
|
||||
);
|
||||
return;
|
||||
} else if (drawLineToCenter) {
|
||||
// Go to center
|
||||
ctx.lineTo(_this._view.scaleZero.x, _this._view.scaleZero.y);
|
||||
}
|
||||
// Draw a straight line
|
||||
ctx.lineTo(first._view.x, first._view.y);
|
||||
}
|
||||
|
||||
ctx.save();
|
||||
|
||||
// If we had points and want to fill this line, do so.
|
||||
if (this._children.length > 0 && vm.fill) {
|
||||
//Round off the line by going to the base of the chart, back to the start, then fill.
|
||||
ctx.lineTo(this._children[this._children.length - 1]._view.x, vm.scaleZero);
|
||||
ctx.lineTo(this._children[0]._view.x, vm.scaleZero);
|
||||
// Draw the background first (so the border is always on top)
|
||||
ctx.beginPath();
|
||||
|
||||
helpers.each(this._children, function(point, index) {
|
||||
var previous = helpers.previousItem(this._children, index);
|
||||
var next = helpers.nextItem(this._children, index);
|
||||
|
||||
// First point moves to it's starting position no matter what
|
||||
if (index === 0) {
|
||||
if (this._loop) {
|
||||
ctx.moveTo(vm.scaleZero.x, vm.scaleZero.y);
|
||||
} else {
|
||||
ctx.moveTo(point._view.x, vm.scaleZero);
|
||||
}
|
||||
|
||||
if (point._view.skip) {
|
||||
if (!this._loop) {
|
||||
ctx.moveTo(next._view.x, this._view.scaleZero);
|
||||
}
|
||||
} else {
|
||||
ctx.lineTo(point._view.x, point._view.y);
|
||||
}
|
||||
} else {
|
||||
this.lineToNextPoint(previous, point, next, function(previousPoint, point, nextPoint) {
|
||||
if (this._loop) {
|
||||
// Go to center
|
||||
ctx.lineTo(this._view.scaleZero.x, this._view.scaleZero.y);
|
||||
} else {
|
||||
ctx.lineTo(previousPoint._view.x, this._view.scaleZero);
|
||||
ctx.moveTo(nextPoint._view.x, this._view.scaleZero);
|
||||
}
|
||||
}, function(previousPoint, point, nextPoint) {
|
||||
// If we skipped the last point, draw a line to ourselves so that the fill is nice
|
||||
ctx.lineTo(point._view.x, point._view.y);
|
||||
});
|
||||
}
|
||||
}, this);
|
||||
|
||||
// For radial scales, loop back around to the first point
|
||||
if (this._loop) {
|
||||
loopBackToStart(true);
|
||||
} else {
|
||||
//Round off the line by going to the base of the chart, back to the start, then fill.
|
||||
ctx.lineTo(this._children[this._children.length - 1]._view.x, vm.scaleZero);
|
||||
ctx.lineTo(this._children[0]._view.x, vm.scaleZero);
|
||||
}
|
||||
|
||||
ctx.fillStyle = vm.backgroundColor || Chart.defaults.global.defaultColor;
|
||||
ctx.closePath();
|
||||
ctx.fill();
|
||||
}
|
||||
|
||||
|
||||
// Now draw the line between all the points with any borders
|
||||
ctx.lineCap = vm.borderCapStyle || Chart.defaults.global.elements.line.borderCapStyle;
|
||||
|
||||
@@ -130,57 +149,20 @@
|
||||
var previous = helpers.previousItem(this._children, index);
|
||||
var next = helpers.nextItem(this._children, index);
|
||||
|
||||
if (!index) {
|
||||
ctx.moveTo(point._view.x, vm.scaleZero);
|
||||
}
|
||||
|
||||
// Skip this point and move to the next points zeroPoint
|
||||
if (point._view.skip && !this.loop) {
|
||||
ctx.moveTo(next._view.x, vm.scaleZero);
|
||||
return;
|
||||
}
|
||||
|
||||
// Previous point was skipped, just move to the point
|
||||
if (previous._view.skip) {
|
||||
if (index === 0) {
|
||||
ctx.moveTo(point._view.x, point._view.y);
|
||||
return;
|
||||
} else {
|
||||
this.lineToNextPoint(previous, point, next, function(previousPoint, point, nextPoint) {
|
||||
ctx.moveTo(nextPoint._view.x, nextPoint._view.y);
|
||||
}, function(previousPoint, point, nextPoint) {
|
||||
// If we skipped the last point, move up to our point preventing a line from being drawn
|
||||
ctx.moveTo(point._view.x, point._view.y);
|
||||
});
|
||||
}
|
||||
|
||||
// Draw a bezier line to the point
|
||||
if (vm.tension > 0 && index) {
|
||||
ctx.bezierCurveTo(
|
||||
previous._view.controlPointNextX,
|
||||
previous._view.controlPointNextY,
|
||||
point._view.controlPointPreviousX,
|
||||
point._view.controlPointPreviousY,
|
||||
point._view.x,
|
||||
point._view.y
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
// Draw a straight line to the point
|
||||
ctx.lineTo(point._view.x, point._view.y);
|
||||
|
||||
}, this);
|
||||
|
||||
if (this._loop && !first._view.skip) {
|
||||
|
||||
// Draw a bezier line to the first point
|
||||
if (vm.tension > 0) {
|
||||
ctx.bezierCurveTo(
|
||||
last._view.controlPointNextX,
|
||||
last._view.controlPointNextY,
|
||||
first._view.controlPointPreviousX,
|
||||
first._view.controlPointPreviousY,
|
||||
first._view.x,
|
||||
first._view.y
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
// Draw a straight line to the first point
|
||||
ctx.lineTo(first._view.x, first._view.y);
|
||||
if (this._loop) {
|
||||
loopBackToStart();
|
||||
}
|
||||
|
||||
ctx.stroke();
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
var DatasetScale = Chart.Scale.extend({
|
||||
buildTicks: function(index) {
|
||||
this.ticks = this.data.labels;
|
||||
this.ticks = this.chart.data.labels;
|
||||
},
|
||||
|
||||
getLabelForIndex: function(index, datasetIndex) {
|
||||
@@ -23,7 +23,7 @@
|
||||
getPixelForValue: function(value, index, datasetIndex, includeOffset) {
|
||||
if (this.isHorizontal()) {
|
||||
var innerWidth = this.width - (this.paddingLeft + this.paddingRight);
|
||||
var valueWidth = innerWidth / Math.max((this.data.labels.length - ((this.options.gridLines.offsetGridLines) ? 0 : 1)), 1);
|
||||
var valueWidth = innerWidth / Math.max((this.chart.data.labels.length - ((this.options.gridLines.offsetGridLines) ? 0 : 1)), 1);
|
||||
var widthOffset = (valueWidth * index) + this.paddingLeft;
|
||||
|
||||
if (this.options.gridLines.offsetGridLines && includeOffset) {
|
||||
@@ -33,7 +33,7 @@
|
||||
return this.left + Math.round(widthOffset);
|
||||
} else {
|
||||
var innerHeight = this.height - (this.paddingTop + this.paddingBottom);
|
||||
var valueHeight = innerHeight / Math.max((this.data.labels.length - ((this.options.gridLines.offsetGridLines) ? 0 : 1)), 1);
|
||||
var valueHeight = innerHeight / Math.max((this.chart.data.labels.length - ((this.options.gridLines.offsetGridLines) ? 0 : 1)), 1);
|
||||
var heightOffset = (valueHeight * index) + this.paddingTop;
|
||||
|
||||
if (this.options.gridLines.offsetGridLines && includeOffset) {
|
||||
|
||||
@@ -42,15 +42,25 @@
|
||||
this.min = null;
|
||||
this.max = null;
|
||||
|
||||
var positiveValues = [];
|
||||
var negativeValues = [];
|
||||
|
||||
if (this.options.stacked) {
|
||||
helpers.each(this.data.datasets, function(dataset) {
|
||||
var valuesPerType = {};
|
||||
|
||||
helpers.each(this.chart.data.datasets, function(dataset) {
|
||||
if (valuesPerType[dataset.type] === undefined) {
|
||||
valuesPerType[dataset.type] = {
|
||||
positiveValues: [],
|
||||
negativeValues: [],
|
||||
};
|
||||
}
|
||||
|
||||
// Store these per type
|
||||
var positiveValues = valuesPerType[dataset.type].positiveValues;
|
||||
var negativeValues = valuesPerType[dataset.type].negativeValues;
|
||||
|
||||
if (helpers.isDatasetVisible(dataset) && (this.isHorizontal() ? dataset.xAxisID === this.id : dataset.yAxisID === this.id)) {
|
||||
helpers.each(dataset.data, function(rawValue, index) {
|
||||
|
||||
var value = this.getRightValue(rawValue);
|
||||
var value = +this.getRightValue(rawValue);
|
||||
if (isNaN(value)) {
|
||||
return;
|
||||
}
|
||||
@@ -71,15 +81,19 @@
|
||||
}
|
||||
}, this);
|
||||
|
||||
var values = positiveValues.concat(negativeValues);
|
||||
this.min = helpers.min(values);
|
||||
this.max = helpers.max(values);
|
||||
helpers.each(valuesPerType, function(valuesForType) {
|
||||
var values = valuesForType.positiveValues.concat(valuesForType.negativeValues);
|
||||
var minVal = helpers.min(values);
|
||||
var maxVal = helpers.max(values);
|
||||
this.min = this.min === null ? minVal : Math.min(this.min, minVal);
|
||||
this.max = this.max === null ? maxVal : Math.max(this.max, maxVal);
|
||||
}, this);
|
||||
|
||||
} else {
|
||||
helpers.each(this.data.datasets, function(dataset) {
|
||||
helpers.each(this.chart.data.datasets, function(dataset) {
|
||||
if (helpers.isDatasetVisible(dataset) && (this.isHorizontal() ? dataset.xAxisID === this.id : dataset.yAxisID === this.id)) {
|
||||
helpers.each(dataset.data, function(rawValue, index) {
|
||||
var value = this.getRightValue(rawValue);
|
||||
var value = +this.getRightValue(rawValue);
|
||||
if (isNaN(value)) {
|
||||
return;
|
||||
}
|
||||
@@ -100,12 +114,6 @@
|
||||
}, this);
|
||||
}
|
||||
|
||||
if (this.min === this.max) {
|
||||
this.min--;
|
||||
this.max++;
|
||||
}
|
||||
|
||||
|
||||
// Then calulate the ticks
|
||||
this.ticks = [];
|
||||
|
||||
@@ -117,10 +125,12 @@
|
||||
var maxTicks;
|
||||
|
||||
if (this.isHorizontal()) {
|
||||
maxTicks = Math.min(11, Math.ceil(this.width / 50));
|
||||
maxTicks = Math.min(this.options.ticks.maxTicksLimit ? this.options.ticks.maxTicksLimit : 11,
|
||||
Math.ceil(this.width / 50));
|
||||
} else {
|
||||
// The factor of 2 used to scale the font size has been experimentally determined.
|
||||
maxTicks = Math.min(11, Math.ceil(this.height / (2 * this.options.ticks.fontSize)));
|
||||
maxTicks = Math.min(this.options.ticks.maxTicksLimit ? this.options.ticks.maxTicksLimit : 11,
|
||||
Math.ceil(this.height / (2 * this.options.ticks.fontSize)));
|
||||
}
|
||||
|
||||
// Make sure we always have at least 2 ticks
|
||||
@@ -146,6 +156,19 @@
|
||||
}
|
||||
}
|
||||
|
||||
if (this.options.ticks.suggestedMin) {
|
||||
this.min = Math.min(this.min, this.options.ticks.suggestedMin);
|
||||
}
|
||||
|
||||
if (this.options.ticks.suggestedMax) {
|
||||
this.max = Math.max(this.max, this.options.ticks.suggestedMax);
|
||||
}
|
||||
|
||||
if (this.min === this.max) {
|
||||
this.min--;
|
||||
this.max++;
|
||||
}
|
||||
|
||||
var niceRange = helpers.niceNum(this.max - this.min, false);
|
||||
var spacing = helpers.niceNum(niceRange / (maxTicks - 1), true);
|
||||
var niceMin = Math.floor(this.min / spacing) * spacing;
|
||||
@@ -182,14 +205,14 @@
|
||||
},
|
||||
|
||||
getLabelForIndex: function(index, datasetIndex) {
|
||||
return this.getRightValue(this.data.datasets[datasetIndex].data[index]);
|
||||
return +this.getRightValue(this.chart.data.datasets[datasetIndex].data[index]);
|
||||
},
|
||||
|
||||
// Utils
|
||||
getPixelForValue: function(value, index, datasetIndex, includeOffset) {
|
||||
// This must be called after fit has been run so that
|
||||
// this.left, this.top, this.right, and this.bottom have been defined
|
||||
var rightValue = this.getRightValue(value);
|
||||
var rightValue = +this.getRightValue(value);
|
||||
var pixel;
|
||||
var range = this.end - this.start;
|
||||
|
||||
|
||||
@@ -30,14 +30,18 @@
|
||||
this.min = null;
|
||||
this.max = null;
|
||||
|
||||
var values = [];
|
||||
|
||||
if (this.options.stacked) {
|
||||
helpers.each(this.data.datasets, function(dataset) {
|
||||
if (helpers.isDatasetVisible(dataset) && (this.isHorizontal() ? dataset.xAxisID === this.id : dataset.yAxisID === this.id)) {
|
||||
helpers.each(dataset.data, function(rawValue, index) {
|
||||
var valuesPerType = {};
|
||||
|
||||
var value = this.getRightValue(rawValue);
|
||||
helpers.each(this.chart.data.datasets, function(dataset) {
|
||||
if (helpers.isDatasetVisible(dataset) && (this.isHorizontal() ? dataset.xAxisID === this.id : dataset.yAxisID === this.id)) {
|
||||
if (valuesPerType[dataset.type] === undefined) {
|
||||
valuesPerType[dataset.type] = [];
|
||||
}
|
||||
|
||||
helpers.each(dataset.data, function(rawValue, index) {
|
||||
var values = valuesPerType[dataset.type];
|
||||
var value = +this.getRightValue(rawValue);
|
||||
if (isNaN(value)) {
|
||||
return;
|
||||
}
|
||||
@@ -54,14 +58,18 @@
|
||||
}
|
||||
}, this);
|
||||
|
||||
this.min = helpers.min(values);
|
||||
this.max = helpers.max(values);
|
||||
helpers.each(valuesPerType, function(valuesForType) {
|
||||
var minVal = helpers.min(valuesForType);
|
||||
var maxVal = helpers.max(valuesForType);
|
||||
this.min = this.min === null ? minVal : Math.min(this.min, minVal);
|
||||
this.max = this.max === null ? maxVal : Math.max(this.max, maxVal);
|
||||
}, this);
|
||||
|
||||
} else {
|
||||
helpers.each(this.data.datasets, function(dataset) {
|
||||
helpers.each(this.chart.data.datasets, function(dataset) {
|
||||
if (helpers.isDatasetVisible(dataset) && (this.isHorizontal() ? dataset.xAxisID === this.id : dataset.yAxisID === this.id)) {
|
||||
helpers.each(dataset.data, function(rawValue, index) {
|
||||
var value = this.getRightValue(rawValue);
|
||||
var value = +this.getRightValue(rawValue);
|
||||
if (isNaN(value)) {
|
||||
return;
|
||||
}
|
||||
@@ -137,7 +145,7 @@
|
||||
},
|
||||
// Get the correct tooltip label
|
||||
getLabelForIndex: function(index, datasetIndex) {
|
||||
return this.getRightValue(this.data.datasets[datasetIndex].data[index]);
|
||||
return +this.getRightValue(this.chart.data.datasets[datasetIndex].data[index]);
|
||||
},
|
||||
getPixelForTick: function(index, includeOffset) {
|
||||
return this.getPixelForValue(this.tickValues[index], null, null, includeOffset);
|
||||
@@ -145,7 +153,7 @@
|
||||
getPixelForValue: function(value, index, datasetIndex, includeOffset) {
|
||||
var pixel;
|
||||
|
||||
var newVal = this.getRightValue(value);
|
||||
var newVal = +this.getRightValue(value);
|
||||
var range = helpers.log10(this.end) - helpers.log10(this.start);
|
||||
|
||||
if (this.isHorizontal()) {
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
position: "chartArea",
|
||||
|
||||
angleLines: {
|
||||
show: true,
|
||||
display: true,
|
||||
color: "rgba(0, 0, 0, 0.1)",
|
||||
lineWidth: 1
|
||||
},
|
||||
@@ -51,7 +51,7 @@
|
||||
|
||||
var LinearRadialScale = Chart.Scale.extend({
|
||||
getValueCount: function() {
|
||||
return this.data.labels.length;
|
||||
return this.chart.data.labels.length;
|
||||
},
|
||||
setDimensions: function() {
|
||||
// Set the unconstrained dimension before label rotation
|
||||
@@ -67,10 +67,10 @@
|
||||
this.min = null;
|
||||
this.max = null;
|
||||
|
||||
helpers.each(this.data.datasets, function(dataset) {
|
||||
helpers.each(this.chart.data.datasets, function(dataset) {
|
||||
if (helpers.isDatasetVisible(dataset)) {
|
||||
helpers.each(dataset.data, function(rawValue, index) {
|
||||
var value = this.getRightValue(rawValue);
|
||||
var value = +this.getRightValue(rawValue);
|
||||
if (isNaN(value)) {
|
||||
return;
|
||||
}
|
||||
@@ -101,7 +101,8 @@
|
||||
// the axis area. For now, we say that the minimum tick spacing in pixels must be 50
|
||||
// We also limit the maximum number of ticks to 11 which gives a nice 10 squares on
|
||||
// the graph
|
||||
var maxTicks = Math.min(11, Math.ceil(this.drawingArea / (1.5 * this.options.ticks.fontSize)));
|
||||
var maxTicks = Math.min(this.options.ticks.maxTicksLimit ? this.options.ticks.maxTicksLimit : 11,
|
||||
Math.ceil(this.drawingArea / (1.5 * this.options.ticks.fontSize)));
|
||||
maxTicks = Math.max(2, maxTicks); // Make sure we always have at least 2 ticks
|
||||
|
||||
// To get a "nice" value for the tick spacing, we will use the appropriately named
|
||||
@@ -151,6 +152,9 @@
|
||||
|
||||
this.zeroLineIndex = this.ticks.indexOf(0);
|
||||
},
|
||||
getLabelForIndex: function(index, datasetIndex) {
|
||||
return +this.getRightValue(this.chart.data.datasets[datasetIndex].data[index]);
|
||||
},
|
||||
getCircumference: function() {
|
||||
return ((Math.PI * 2) / this.getValueCount());
|
||||
},
|
||||
@@ -206,7 +210,7 @@
|
||||
for (i = 0; i < this.getValueCount(); i++) {
|
||||
// 5px to space the text slightly out - similar to what we do in the draw function.
|
||||
pointPosition = this.getPointPosition(i, largestPossibleRadius);
|
||||
textWidth = this.ctx.measureText(this.options.ticks.callback(this.data.labels[i])).width + 5;
|
||||
textWidth = this.ctx.measureText(this.options.ticks.callback(this.chart.data.labels[i])).width + 5;
|
||||
if (i === 0 || i === this.getValueCount() / 2) {
|
||||
// If we're at index zero, or exactly the middle, we're at exactly the top/bottom
|
||||
// of the radar chart, so text will be aligned centrally, so we'll half it and compare
|
||||
@@ -268,7 +272,10 @@
|
||||
return index * angleMultiplier - (Math.PI / 2);
|
||||
},
|
||||
getDistanceFromCenterForValue: function(value) {
|
||||
if (value === null) return 0; // null always in center
|
||||
if (value === null) {
|
||||
return 0; // null always in center
|
||||
}
|
||||
|
||||
// Take into account half font size + the yPadding of the top value
|
||||
var scalingFactor = this.drawingArea / (this.max - this.min);
|
||||
if (this.options.reverse) {
|
||||
@@ -297,7 +304,7 @@
|
||||
var yHeight = this.yCenter - yCenterOffset;
|
||||
|
||||
// Draw circular lines around the scale
|
||||
if (this.options.gridLines.show) {
|
||||
if (this.options.gridLines.display) {
|
||||
ctx.strokeStyle = this.options.gridLines.color;
|
||||
ctx.lineWidth = this.options.gridLines.lineWidth;
|
||||
|
||||
@@ -323,7 +330,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
if (this.options.ticks.show) {
|
||||
if (this.options.ticks.display) {
|
||||
ctx.font = helpers.fontString(this.options.ticks.fontSize, this.options.ticks.fontStyle, this.options.ticks.fontFamily);
|
||||
|
||||
if (this.options.ticks.showLabelBackdrop) {
|
||||
@@ -350,7 +357,7 @@
|
||||
ctx.strokeStyle = this.options.angleLines.color;
|
||||
|
||||
for (var i = this.getValueCount() - 1; i >= 0; i--) {
|
||||
if (this.options.angleLines.show) {
|
||||
if (this.options.angleLines.display) {
|
||||
var outerPosition = this.getPointPosition(i, this.getDistanceFromCenterForValue(this.options.reverse ? this.min : this.max));
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(this.xCenter, this.yCenter);
|
||||
@@ -363,8 +370,8 @@
|
||||
ctx.font = helpers.fontString(this.options.pointLabels.fontSize, this.options.pointLabels.fontStyle, this.options.pointLabels.fontFamily);
|
||||
ctx.fillStyle = this.options.pointLabels.fontColor;
|
||||
|
||||
var labelsCount = this.data.labels.length,
|
||||
halfLabelsCount = this.data.labels.length / 2,
|
||||
var labelsCount = this.chart.data.labels.length,
|
||||
halfLabelsCount = this.chart.data.labels.length / 2,
|
||||
quarterLabelsCount = halfLabelsCount / 2,
|
||||
upperHalf = (i < quarterLabelsCount || i > labelsCount - quarterLabelsCount),
|
||||
exactQuarter = (i === quarterLabelsCount || i === labelsCount - quarterLabelsCount);
|
||||
@@ -387,7 +394,7 @@
|
||||
ctx.textBaseline = 'top';
|
||||
}
|
||||
|
||||
ctx.fillText(this.data.labels[i], pointLabelPosition.x, pointLabelPosition.y);
|
||||
ctx.fillText(this.chart.data.labels[i], pointLabelPosition.x, pointLabelPosition.y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+25
-50
@@ -22,44 +22,6 @@
|
||||
'quarter',
|
||||
'year',
|
||||
],
|
||||
unit: {
|
||||
'millisecond': {
|
||||
display: 'SSS [ms]', // 002 ms
|
||||
maxStep: 1000,
|
||||
},
|
||||
'second': {
|
||||
display: 'h:mm:ss a', // 11:20:01 AM
|
||||
maxStep: 60,
|
||||
},
|
||||
'minute': {
|
||||
display: 'h:mm:ss a', // 11:20:01 AM
|
||||
maxStep: 60,
|
||||
},
|
||||
'hour': {
|
||||
display: 'MMM D, hA', // Sept 4, 5PM
|
||||
maxStep: 24,
|
||||
},
|
||||
'day': {
|
||||
display: 'll', // Sep 4 2015
|
||||
maxStep: 7,
|
||||
},
|
||||
'week': {
|
||||
display: 'll', // Week 46, or maybe "[W]WW - YYYY" ?
|
||||
maxStep: 4.3333,
|
||||
},
|
||||
'month': {
|
||||
display: 'MMM YYYY', // Sept 2015
|
||||
maxStep: 12,
|
||||
},
|
||||
'quarter': {
|
||||
display: '[Q]Q - YYYY', // Q3
|
||||
maxStep: 4,
|
||||
},
|
||||
'year': {
|
||||
display: 'YYYY', // 2015
|
||||
maxStep: false,
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
var defaultConfig = {
|
||||
@@ -69,7 +31,20 @@
|
||||
format: false, // false == date objects or use pattern string from http://momentjs.com/docs/#/parsing/string-format/
|
||||
unit: false, // false == automatic or override with week, month, year, etc.
|
||||
round: false, // none, or override with week, month, year, etc.
|
||||
displayFormat: false, // defaults to unit's corresponding unitFormat below or override using pattern string from http://momentjs.com/docs/#/displaying/format/
|
||||
displayFormat: false, // DEPRECATED
|
||||
|
||||
// defaults to unit's corresponding unitFormat below or override using pattern string from http://momentjs.com/docs/#/displaying/format/
|
||||
displayFormats: {
|
||||
'millisecond': 'SSS [ms]',
|
||||
'second': 'h:mm:ss a', // 11:20:01 AM
|
||||
'minute': 'h:mm:ss a', // 11:20:01 AM
|
||||
'hour': 'MMM D, hA', // Sept 4, 5PM
|
||||
'day': 'll', // Sep 4 2015
|
||||
'week': 'll', // Week 46, or maybe "[W]WW - YYYY" ?
|
||||
'month': 'MMM YYYY', // Sept 2015
|
||||
'quarter': '[Q]Q - YYYY', // Q3
|
||||
'year': 'YYYY', // 2015
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@@ -82,8 +57,8 @@
|
||||
// Only parse these once. If the dataset does not have data as x,y pairs, we will use
|
||||
// these
|
||||
var scaleLabelMoments = [];
|
||||
if (this.data.labels && this.data.labels.length > 0) {
|
||||
helpers.each(this.data.labels, function(label, index) {
|
||||
if (this.chart.data.labels && this.chart.data.labels.length > 0) {
|
||||
helpers.each(this.chart.data.labels, function(label, index) {
|
||||
var labelMoment = this.parseTime(label);
|
||||
if (this.options.time.round) {
|
||||
labelMoment.startOf(this.options.time.round);
|
||||
@@ -107,7 +82,7 @@
|
||||
this.lastTick = null;
|
||||
}
|
||||
|
||||
helpers.each(this.data.datasets, function(dataset, datasetIndex) {
|
||||
helpers.each(this.chart.data.datasets, function(dataset, datasetIndex) {
|
||||
var momentsForDataset = [];
|
||||
|
||||
if (typeof dataset.data[0] === 'object') {
|
||||
@@ -145,7 +120,7 @@
|
||||
// Set unit override if applicable
|
||||
if (this.options.time.unit) {
|
||||
this.tickUnit = this.options.time.unit || 'day';
|
||||
this.displayFormat = time.unit[this.tickUnit].display;
|
||||
this.displayFormat = this.options.time.displayFormats[this.tickUnit];
|
||||
this.tickRange = Math.ceil(this.lastTick.diff(this.firstTick, this.tickUnit, true));
|
||||
} else {
|
||||
// Determine the smallest needed unit of the time
|
||||
@@ -156,7 +131,7 @@
|
||||
// Start as small as possible
|
||||
this.tickUnit = 'millisecond';
|
||||
this.tickRange = Math.ceil(this.lastTick.diff(this.firstTick, this.tickUnit, true) + buffer);
|
||||
this.displayFormat = time.unit[this.tickUnit].display;
|
||||
this.displayFormat = this.options.time.displayFormats[this.tickUnit];
|
||||
|
||||
// Work our way up to comfort
|
||||
helpers.each(time.units, function(format) {
|
||||
@@ -165,7 +140,7 @@
|
||||
}
|
||||
this.tickUnit = format;
|
||||
this.tickRange = Math.ceil(this.lastTick.diff(this.firstTick, this.tickUnit) + buffer);
|
||||
this.displayFormat = time.unit[format].display;
|
||||
this.displayFormat = this.options.time.displayFormats[format];
|
||||
|
||||
}, this);
|
||||
}
|
||||
@@ -174,7 +149,7 @@
|
||||
this.lastTick.endOf(this.tickUnit);
|
||||
this.smallestLabelSeparation = this.width;
|
||||
|
||||
helpers.each(this.data.datasets, function(dataset, datasetIndex) {
|
||||
helpers.each(this.chart.data.datasets, function(dataset, datasetIndex) {
|
||||
for (var i = 1; i < this.labelMoments[datasetIndex].length; i++) {
|
||||
this.smallestLabelSeparation = Math.min(this.smallestLabelSeparation, this.labelMoments[datasetIndex][i].diff(this.labelMoments[datasetIndex][i - 1], this.tickUnit, true));
|
||||
}
|
||||
@@ -192,17 +167,17 @@
|
||||
},
|
||||
// Get tooltip label
|
||||
getLabelForIndex: function(index, datasetIndex) {
|
||||
var label = this.data.labels && index < this.data.labels.length ? this.data.labels[index] : '';
|
||||
var label = this.chart.data.labels && index < this.chart.data.labels.length ? this.chart.data.labels[index] : '';
|
||||
|
||||
if (typeof this.data.datasets[datasetIndex].data[0] === 'object') {
|
||||
label = this.getRightValue(this.data.datasets[datasetIndex].data[index]);
|
||||
if (typeof this.chart.data.datasets[datasetIndex].data[0] === 'object') {
|
||||
label = this.getRightValue(this.chart.data.datasets[datasetIndex].data[index]);
|
||||
}
|
||||
|
||||
return label;
|
||||
},
|
||||
convertTicksToLabels: function() {
|
||||
this.ticks = this.ticks.map(function(tick, index, ticks) {
|
||||
var formattedTick = tick.format(this.options.time.displayFormat ? this.options.time.displayFormat : time.unit[this.tickUnit].display);
|
||||
var formattedTick = tick.format(this.options.time.displayFormat ? this.options.time.displayFormat : this.options.time.displayFormats[this.tickUnit]);
|
||||
|
||||
if (this.options.ticks.userCallback) {
|
||||
return this.options.ticks.userCallback(formattedTick, index, ticks);
|
||||
|
||||
@@ -190,7 +190,9 @@ describe('Bar controller tests', function() {
|
||||
var yScale = new VerticalScaleConstructor({
|
||||
ctx: mockContext,
|
||||
options: verticalScaleConfig,
|
||||
data: data,
|
||||
chart: {
|
||||
data: data
|
||||
},
|
||||
id: 'firstYScaleID'
|
||||
});
|
||||
|
||||
@@ -207,7 +209,9 @@ describe('Bar controller tests', function() {
|
||||
var xScale = new HorizontalScaleConstructor({
|
||||
ctx: mockContext,
|
||||
options: horizontalScaleConfig,
|
||||
data: data,
|
||||
chart: {
|
||||
data: data
|
||||
},
|
||||
id: 'firstXScaleID'
|
||||
});
|
||||
|
||||
@@ -262,7 +266,7 @@ describe('Bar controller tests', function() {
|
||||
expect(bar1._xScale).toBe(chart.scales.firstXScaleID);
|
||||
expect(bar1._yScale).toBe(chart.scales.firstYScaleID);
|
||||
expect(bar1._model).toEqual({
|
||||
x: 103.60000000000001,
|
||||
x: 113.60000000000001,
|
||||
y: 194,
|
||||
label: 'label1',
|
||||
datasetLabel: 'dataset2',
|
||||
@@ -279,7 +283,7 @@ describe('Bar controller tests', function() {
|
||||
expect(bar2._xScale).toBe(chart.scales.firstXScaleID);
|
||||
expect(bar2._yScale).toBe(chart.scales.firstYScaleID);
|
||||
expect(bar2._model).toEqual({
|
||||
x: 141.6,
|
||||
x: 151.60000000000002,
|
||||
y: 6,
|
||||
label: 'label2',
|
||||
datasetLabel: 'dataset2',
|
||||
@@ -316,7 +320,9 @@ describe('Bar controller tests', function() {
|
||||
var yScale = new VerticalScaleConstructor({
|
||||
ctx: mockContext,
|
||||
options: verticalScaleConfig,
|
||||
data: data,
|
||||
chart: {
|
||||
data: data
|
||||
},
|
||||
id: 'firstYScaleID'
|
||||
});
|
||||
|
||||
@@ -333,7 +339,9 @@ describe('Bar controller tests', function() {
|
||||
var xScale = new HorizontalScaleConstructor({
|
||||
ctx: mockContext,
|
||||
options: horizontalScaleConfig,
|
||||
data: data,
|
||||
chart: {
|
||||
data: data
|
||||
},
|
||||
id: 'firstXScaleID'
|
||||
});
|
||||
|
||||
@@ -399,7 +407,9 @@ describe('Bar controller tests', function() {
|
||||
var yScale = new VerticalScaleConstructor({
|
||||
ctx: mockContext,
|
||||
options: verticalScaleConfig,
|
||||
data: data,
|
||||
chart: {
|
||||
data: data
|
||||
},
|
||||
id: 'firstYScaleID'
|
||||
});
|
||||
|
||||
@@ -416,7 +426,9 @@ describe('Bar controller tests', function() {
|
||||
var xScale = new HorizontalScaleConstructor({
|
||||
ctx: mockContext,
|
||||
options: horizontalScaleConfig,
|
||||
data: data,
|
||||
chart: {
|
||||
data: data
|
||||
},
|
||||
id: 'firstXScaleID'
|
||||
});
|
||||
|
||||
@@ -519,7 +531,9 @@ describe('Bar controller tests', function() {
|
||||
var yScale = new VerticalScaleConstructor({
|
||||
ctx: mockContext,
|
||||
options: verticalScaleConfig,
|
||||
data: data,
|
||||
chart: {
|
||||
data: data
|
||||
},
|
||||
id: 'firstYScaleID'
|
||||
});
|
||||
|
||||
@@ -536,7 +550,9 @@ describe('Bar controller tests', function() {
|
||||
var xScale = new HorizontalScaleConstructor({
|
||||
ctx: mockContext,
|
||||
options: horizontalScaleConfig,
|
||||
data: data,
|
||||
chart: {
|
||||
data: data
|
||||
},
|
||||
id: 'firstXScaleID'
|
||||
});
|
||||
|
||||
|
||||
+164
-36
@@ -159,7 +159,9 @@ describe('Line controller tests', function() {
|
||||
var yScale = new VerticalScaleConstructor({
|
||||
ctx: mockContext,
|
||||
options: verticalScaleConfig,
|
||||
data: data,
|
||||
chart: {
|
||||
data: data
|
||||
},
|
||||
id: 'firstYScaleID'
|
||||
});
|
||||
|
||||
@@ -176,7 +178,9 @@ describe('Line controller tests', function() {
|
||||
var xScale = new HorizontalScaleConstructor({
|
||||
ctx: mockContext,
|
||||
options: horizontalScaleConfig,
|
||||
data: data,
|
||||
chart: {
|
||||
data: data
|
||||
},
|
||||
id: 'firstXScaleID'
|
||||
});
|
||||
|
||||
@@ -192,7 +196,7 @@ describe('Line controller tests', function() {
|
||||
chartArea: {
|
||||
bottom: 200,
|
||||
left: xScale.left,
|
||||
right: 200,
|
||||
right: xScale.left + 200,
|
||||
top: 0
|
||||
},
|
||||
data: data,
|
||||
@@ -267,13 +271,13 @@ describe('Line controller tests', function() {
|
||||
tension: 0.1,
|
||||
|
||||
// Point
|
||||
x: 71,
|
||||
x: 81,
|
||||
y: 62,
|
||||
|
||||
// Control points
|
||||
controlPointPreviousX: 71,
|
||||
controlPointPreviousX: 81,
|
||||
controlPointPreviousY: 62,
|
||||
controlPointNextX: 76,
|
||||
controlPointNextX: 86,
|
||||
controlPointNextY: 57.3,
|
||||
});
|
||||
|
||||
@@ -287,13 +291,13 @@ describe('Line controller tests', function() {
|
||||
tension: 0.1,
|
||||
|
||||
// Point
|
||||
x: 121,
|
||||
x: 131,
|
||||
y: 15,
|
||||
|
||||
// Control points
|
||||
controlPointPreviousX: 117.82889384189087,
|
||||
controlPointPreviousX: 127.82889384189087,
|
||||
controlPointPreviousY: 12.04867347661131,
|
||||
controlPointNextX: 127.92889384189088,
|
||||
controlPointNextX: 137.92889384189088,
|
||||
controlPointNextY: 21.44867347661131,
|
||||
});
|
||||
|
||||
@@ -307,13 +311,13 @@ describe('Line controller tests', function() {
|
||||
tension: 0.1,
|
||||
|
||||
// Point
|
||||
x: 172,
|
||||
x: 182,
|
||||
y: 156,
|
||||
|
||||
// Control points
|
||||
controlPointPreviousX: 164.8815225337256,
|
||||
controlPointPreviousX: 174.8815225337256,
|
||||
controlPointPreviousY: 143.38408449046415,
|
||||
controlPointNextX: 174.98152253372558,
|
||||
controlPointNextX: 184.98152253372558,
|
||||
controlPointNextY: 161.28408449046415,
|
||||
});
|
||||
|
||||
@@ -327,13 +331,13 @@ describe('Line controller tests', function() {
|
||||
tension: 0.1,
|
||||
|
||||
// Point
|
||||
x: 222,
|
||||
x: 232,
|
||||
y: 194,
|
||||
|
||||
// Control points
|
||||
controlPointPreviousX: 217,
|
||||
controlPointPreviousX: 227,
|
||||
controlPointPreviousY: 190.2,
|
||||
controlPointNextX: 222,
|
||||
controlPointNextX: 232,
|
||||
controlPointNextY: 194,
|
||||
});
|
||||
|
||||
@@ -383,13 +387,13 @@ describe('Line controller tests', function() {
|
||||
tension: 0.2,
|
||||
|
||||
// Point
|
||||
x: 71,
|
||||
x: 81,
|
||||
y: 62,
|
||||
|
||||
// Control points
|
||||
controlPointPreviousX: 71,
|
||||
controlPointPreviousX: 81,
|
||||
controlPointPreviousY: 62,
|
||||
controlPointNextX: 81,
|
||||
controlPointNextX: 91,
|
||||
controlPointNextY: 52.6,
|
||||
});
|
||||
|
||||
@@ -403,13 +407,13 @@ describe('Line controller tests', function() {
|
||||
tension: 0.2,
|
||||
|
||||
// Point
|
||||
x: 121,
|
||||
x: 131,
|
||||
y: 15,
|
||||
|
||||
// Control points
|
||||
controlPointPreviousX: 114.65778768378175,
|
||||
controlPointPreviousX: 124.65778768378175,
|
||||
controlPointPreviousY: 9.097346953222619,
|
||||
controlPointNextX: 134.85778768378177,
|
||||
controlPointNextX: 144.85778768378177,
|
||||
controlPointNextY: 27.897346953222623,
|
||||
});
|
||||
|
||||
@@ -423,13 +427,13 @@ describe('Line controller tests', function() {
|
||||
tension: 0.2,
|
||||
|
||||
// Point
|
||||
x: 172,
|
||||
x: 182,
|
||||
y: 156,
|
||||
|
||||
// Control points
|
||||
controlPointPreviousX: 157.76304506745115,
|
||||
controlPointPreviousX: 167.76304506745115,
|
||||
controlPointPreviousY: 130.76816898092827,
|
||||
controlPointNextX: 177.96304506745116,
|
||||
controlPointNextX: 187.96304506745116,
|
||||
controlPointNextY: 166.56816898092828,
|
||||
});
|
||||
|
||||
@@ -443,13 +447,13 @@ describe('Line controller tests', function() {
|
||||
tension: 0.2,
|
||||
|
||||
// Point
|
||||
x: 222,
|
||||
x: 232,
|
||||
y: 194,
|
||||
|
||||
// Control points
|
||||
controlPointPreviousX: 212,
|
||||
controlPointPreviousX: 222,
|
||||
controlPointPreviousY: 186.4,
|
||||
controlPointNextX: 222,
|
||||
controlPointNextX: 232,
|
||||
controlPointNextY: 194,
|
||||
});
|
||||
|
||||
@@ -505,17 +509,129 @@ describe('Line controller tests', function() {
|
||||
tension: 0.15,
|
||||
|
||||
// Point
|
||||
x: 71,
|
||||
x: 81,
|
||||
y: 62,
|
||||
|
||||
// Control points
|
||||
controlPointPreviousX: 71,
|
||||
controlPointPreviousX: 81,
|
||||
controlPointPreviousY: 62,
|
||||
controlPointNextX: 78.5,
|
||||
controlPointNextX: 88.5,
|
||||
controlPointNextY: 54.95,
|
||||
});
|
||||
});
|
||||
|
||||
it ('should fall back to the line styles for points', function() {
|
||||
var data = {
|
||||
datasets: [{
|
||||
data: [0, 0],
|
||||
label: 'dataset2',
|
||||
xAxisID: 'firstXScaleID',
|
||||
yAxisID: 'firstYScaleID',
|
||||
|
||||
// line styles
|
||||
backgroundColor: 'rgb(98, 98, 98)',
|
||||
borderColor: 'rgb(8, 8, 8)',
|
||||
borderWidth: 0.55,
|
||||
}],
|
||||
labels: ['label1', 'label2']
|
||||
};
|
||||
var mockContext = window.createMockContext();
|
||||
|
||||
var VerticalScaleConstructor = Chart.scaleService.getScaleConstructor('linear');
|
||||
var verticalScaleConfig = Chart.helpers.clone(Chart.scaleService.getScaleDefaults('linear'));
|
||||
verticalScaleConfig = Chart.helpers.scaleMerge(verticalScaleConfig, Chart.defaults.line.scales.yAxes[0]);
|
||||
var yScale = new VerticalScaleConstructor({
|
||||
ctx: mockContext,
|
||||
options: verticalScaleConfig,
|
||||
chart: {
|
||||
data: data
|
||||
},
|
||||
id: 'firstYScaleID'
|
||||
});
|
||||
|
||||
// Update ticks & set physical dimensions
|
||||
var verticalSize = yScale.update(50, 200);
|
||||
yScale.top = 0;
|
||||
yScale.left = 0;
|
||||
yScale.right = verticalSize.width;
|
||||
yScale.bottom = verticalSize.height;
|
||||
|
||||
var HorizontalScaleConstructor = Chart.scaleService.getScaleConstructor('category');
|
||||
var horizontalScaleConfig = Chart.helpers.clone(Chart.scaleService.getScaleDefaults('category'));
|
||||
horizontalScaleConfig = Chart.helpers.scaleMerge(horizontalScaleConfig, Chart.defaults.line.scales.xAxes[0]);
|
||||
var xScale = new HorizontalScaleConstructor({
|
||||
ctx: mockContext,
|
||||
options: horizontalScaleConfig,
|
||||
chart: {
|
||||
data: data
|
||||
},
|
||||
id: 'firstXScaleID'
|
||||
});
|
||||
|
||||
// Update ticks & set physical dimensions
|
||||
var horizontalSize = xScale.update(200, 50);
|
||||
xScale.left = yScale.right;
|
||||
xScale.top = yScale.bottom;
|
||||
xScale.right = horizontalSize.width + xScale.left;
|
||||
xScale.bottom = horizontalSize.height + xScale.top;
|
||||
|
||||
var chart = {
|
||||
chartArea: {
|
||||
bottom: 200,
|
||||
left: xScale.left,
|
||||
right: 200,
|
||||
top: 0
|
||||
},
|
||||
data: data,
|
||||
config: {
|
||||
type: 'line'
|
||||
},
|
||||
options: {
|
||||
elements: {
|
||||
line: {
|
||||
backgroundColor: 'rgb(255, 0, 0)',
|
||||
borderCapStyle: 'round',
|
||||
borderColor: 'rgb(0, 255, 0)',
|
||||
borderDash: [],
|
||||
borderDashOffset: 0.1,
|
||||
borderJoinStyle: 'bevel',
|
||||
borderWidth: 1.2,
|
||||
fill: true,
|
||||
tension: 0.1,
|
||||
},
|
||||
point: {
|
||||
backgroundColor: Chart.defaults.global.defaultColor,
|
||||
borderWidth: 1,
|
||||
borderColor: Chart.defaults.global.defaultColor,
|
||||
hitRadius: 1,
|
||||
hoverRadius: 4,
|
||||
hoverBorderWidth: 1,
|
||||
radius: 3,
|
||||
}
|
||||
},
|
||||
scales: {
|
||||
xAxes: [{
|
||||
id: 'firstXScaleID'
|
||||
}],
|
||||
yAxes: [{
|
||||
id: 'firstYScaleID'
|
||||
}]
|
||||
}
|
||||
},
|
||||
scales: {
|
||||
firstXScaleID: xScale,
|
||||
firstYScaleID: yScale,
|
||||
}
|
||||
};
|
||||
|
||||
var controller = new Chart.controllers.line(chart, 0);
|
||||
controller.update();
|
||||
|
||||
expect(chart.data.datasets[0].metaData[0]._model.backgroundColor).toBe('rgb(98, 98, 98)');
|
||||
expect(chart.data.datasets[0].metaData[0]._model.borderColor).toBe('rgb(8, 8, 8)');
|
||||
expect(chart.data.datasets[0].metaData[0]._model.borderWidth).toBe(0.55);
|
||||
});
|
||||
|
||||
it('should handle number of data point changes in update', function() {
|
||||
var data = {
|
||||
datasets: [{
|
||||
@@ -534,7 +650,9 @@ describe('Line controller tests', function() {
|
||||
var yScale = new VerticalScaleConstructor({
|
||||
ctx: mockContext,
|
||||
options: verticalScaleConfig,
|
||||
data: data,
|
||||
chart: {
|
||||
data: data
|
||||
},
|
||||
id: 'firstYScaleID'
|
||||
});
|
||||
|
||||
@@ -551,7 +669,9 @@ describe('Line controller tests', function() {
|
||||
var xScale = new HorizontalScaleConstructor({
|
||||
ctx: mockContext,
|
||||
options: horizontalScaleConfig,
|
||||
data: data,
|
||||
chart: {
|
||||
data: data
|
||||
},
|
||||
id: 'firstXScaleID'
|
||||
});
|
||||
|
||||
@@ -649,7 +769,9 @@ describe('Line controller tests', function() {
|
||||
var yScale = new VerticalScaleConstructor({
|
||||
ctx: mockContext,
|
||||
options: verticalScaleConfig,
|
||||
data: data,
|
||||
chart: {
|
||||
data: data
|
||||
},
|
||||
id: 'firstYScaleID'
|
||||
});
|
||||
|
||||
@@ -666,7 +788,9 @@ describe('Line controller tests', function() {
|
||||
var xScale = new HorizontalScaleConstructor({
|
||||
ctx: mockContext,
|
||||
options: horizontalScaleConfig,
|
||||
data: data,
|
||||
chart: {
|
||||
data: data
|
||||
},
|
||||
id: 'firstXScaleID'
|
||||
});
|
||||
|
||||
@@ -783,7 +907,9 @@ describe('Line controller tests', function() {
|
||||
var yScale = new VerticalScaleConstructor({
|
||||
ctx: mockContext,
|
||||
options: verticalScaleConfig,
|
||||
data: data,
|
||||
chart: {
|
||||
data: data
|
||||
},
|
||||
id: 'firstYScaleID'
|
||||
});
|
||||
|
||||
@@ -800,7 +926,9 @@ describe('Line controller tests', function() {
|
||||
var xScale = new HorizontalScaleConstructor({
|
||||
ctx: mockContext,
|
||||
options: horizontalScaleConfig,
|
||||
data: data,
|
||||
chart: {
|
||||
data: data
|
||||
},
|
||||
id: 'firstXScaleID'
|
||||
});
|
||||
|
||||
|
||||
@@ -219,7 +219,7 @@ describe('Core helper tests', function() {
|
||||
drawTicks: true, // draw ticks extending towards the label
|
||||
lineWidth: 1,
|
||||
offsetGridLines: false,
|
||||
show: true,
|
||||
display: true,
|
||||
zeroLineColor: "rgba(0,0,0,0.25)",
|
||||
zeroLineWidth: 1,
|
||||
},
|
||||
@@ -230,7 +230,7 @@ describe('Core helper tests', function() {
|
||||
fontSize: 12,
|
||||
fontStyle: 'normal',
|
||||
labelString: '',
|
||||
show: false,
|
||||
display: false,
|
||||
},
|
||||
ticks: {
|
||||
beginAtZero: false,
|
||||
@@ -243,7 +243,7 @@ describe('Core helper tests', function() {
|
||||
mirror: false,
|
||||
padding: 10,
|
||||
reverse: false,
|
||||
show: true,
|
||||
display: true,
|
||||
callback: merged.scales.yAxes[1].ticks.callback, // make it nicer, then check explicitly below
|
||||
},
|
||||
type: 'linear'
|
||||
@@ -256,7 +256,7 @@ describe('Core helper tests', function() {
|
||||
drawTicks: true, // draw ticks extending towards the label
|
||||
lineWidth: 1,
|
||||
offsetGridLines: false,
|
||||
show: true,
|
||||
display: true,
|
||||
zeroLineColor: "rgba(0,0,0,0.25)",
|
||||
zeroLineWidth: 1,
|
||||
},
|
||||
@@ -267,7 +267,7 @@ describe('Core helper tests', function() {
|
||||
fontSize: 12,
|
||||
fontStyle: 'normal',
|
||||
labelString: '',
|
||||
show: false,
|
||||
display: false,
|
||||
},
|
||||
ticks: {
|
||||
beginAtZero: false,
|
||||
@@ -280,7 +280,7 @@ describe('Core helper tests', function() {
|
||||
mirror: false,
|
||||
padding: 10,
|
||||
reverse: false,
|
||||
show: true,
|
||||
display: true,
|
||||
callback: merged.scales.yAxes[2].ticks.callback, // make it nicer, then check explicitly below
|
||||
},
|
||||
type: 'linear'
|
||||
@@ -324,7 +324,7 @@ describe('Core helper tests', function() {
|
||||
it('should do a log10 operation', function() {
|
||||
expect(helpers.log10(0)).toBe(-Infinity);
|
||||
expect(helpers.log10(1)).toBe(0);
|
||||
expect(helpers.log10(1000)).toBe(3);
|
||||
expect(helpers.log10(1000)).toBeCloseTo(3, 1e-9);
|
||||
});
|
||||
|
||||
it('Should generate ids', function() {
|
||||
|
||||
@@ -21,7 +21,9 @@ describe('Test the scale service', function() {
|
||||
var xScale = new XConstructor({
|
||||
ctx: mockContext,
|
||||
options: xScaleConfig,
|
||||
data: mockData,
|
||||
chart: {
|
||||
data: mockData
|
||||
},
|
||||
id: xScaleID
|
||||
});
|
||||
|
||||
@@ -30,7 +32,9 @@ describe('Test the scale service', function() {
|
||||
var yScale = new YConstructor({
|
||||
ctx: mockContext,
|
||||
options: yScaleConfig,
|
||||
data: mockData,
|
||||
chart: {
|
||||
data: mockData
|
||||
},
|
||||
id: yScaleID
|
||||
});
|
||||
|
||||
@@ -42,24 +46,24 @@ describe('Test the scale service', function() {
|
||||
Chart.scaleService.update(chartInstance, canvasWidth, canvasHeight);
|
||||
|
||||
expect(chartInstance.chartArea).toEqual({
|
||||
left: 45,
|
||||
left: 55,
|
||||
right: 245,
|
||||
top: 5,
|
||||
bottom: 76.0423977855504,
|
||||
bottom: 75.0664716027288,
|
||||
});
|
||||
|
||||
// Is xScale at the right spot
|
||||
expect(xScale.left).toBe(45);
|
||||
expect(xScale.left).toBe(55);
|
||||
expect(xScale.right).toBe(245);
|
||||
expect(xScale.top).toBe(76.0423977855504);
|
||||
expect(xScale.top).toBe(75.0664716027288);
|
||||
expect(xScale.bottom).toBe(145);
|
||||
expect(xScale.labelRotation).toBe(55);
|
||||
expect(xScale.labelRotation).toBe(57);
|
||||
|
||||
// Is yScale at the right spot
|
||||
expect(yScale.left).toBe(5);
|
||||
expect(yScale.right).toBe(45);
|
||||
expect(yScale.right).toBe(55);
|
||||
expect(yScale.top).toBe(5);
|
||||
expect(yScale.bottom).toBe(76.0423977855504);
|
||||
expect(yScale.bottom).toBe(75.0664716027288);
|
||||
});
|
||||
|
||||
it('should fit scales that are in the top and right positions', function() {
|
||||
@@ -84,7 +88,9 @@ describe('Test the scale service', function() {
|
||||
var xScale = new XConstructor({
|
||||
ctx: mockContext,
|
||||
options: xScaleConfig,
|
||||
data: mockData,
|
||||
chart: {
|
||||
data: mockData
|
||||
},
|
||||
id: xScaleID
|
||||
});
|
||||
|
||||
@@ -94,7 +100,9 @@ describe('Test the scale service', function() {
|
||||
var yScale = new YConstructor({
|
||||
ctx: mockContext,
|
||||
options: yScaleConfig,
|
||||
data: mockData,
|
||||
chart: {
|
||||
data: mockData
|
||||
},
|
||||
id: yScaleID
|
||||
});
|
||||
|
||||
@@ -107,22 +115,22 @@ describe('Test the scale service', function() {
|
||||
|
||||
expect(chartInstance.chartArea).toEqual({
|
||||
left: 5,
|
||||
right: 205,
|
||||
top: 73.9576022144496,
|
||||
right: 195,
|
||||
top: 74.9335283972712,
|
||||
bottom: 145,
|
||||
});
|
||||
|
||||
// Is xScale at the right spot
|
||||
expect(xScale.left).toBe(5);
|
||||
expect(xScale.right).toBe(205);
|
||||
expect(xScale.right).toBe(195);
|
||||
expect(xScale.top).toBe(5);
|
||||
expect(xScale.bottom).toBe(73.9576022144496);
|
||||
expect(xScale.labelRotation).toBe(55);
|
||||
expect(xScale.bottom).toBe(74.9335283972712);
|
||||
expect(xScale.labelRotation).toBe(57);
|
||||
|
||||
// Is yScale at the right spot
|
||||
expect(yScale.left).toBe(205);
|
||||
expect(yScale.left).toBe(195);
|
||||
expect(yScale.right).toBe(245);
|
||||
expect(yScale.top).toBe(73.9576022144496);
|
||||
expect(yScale.top).toBe(74.9335283972712);
|
||||
expect(yScale.bottom).toBe(145);
|
||||
});
|
||||
|
||||
@@ -151,7 +159,9 @@ describe('Test the scale service', function() {
|
||||
var xScale = new XConstructor({
|
||||
ctx: mockContext,
|
||||
options: xScaleConfig,
|
||||
data: mockData,
|
||||
chart: {
|
||||
data: mockData
|
||||
},
|
||||
id: xScaleID
|
||||
});
|
||||
|
||||
@@ -160,13 +170,17 @@ describe('Test the scale service', function() {
|
||||
var yScale1 = new YConstructor({
|
||||
ctx: mockContext,
|
||||
options: yScaleConfig,
|
||||
data: mockData,
|
||||
chart: {
|
||||
data: mockData
|
||||
},
|
||||
id: yScaleID1
|
||||
});
|
||||
var yScale2 = new YConstructor({
|
||||
ctx: mockContext,
|
||||
options: yScaleConfig,
|
||||
data: mockData,
|
||||
chart: {
|
||||
data: mockData
|
||||
},
|
||||
id: yScaleID2
|
||||
});
|
||||
|
||||
@@ -179,28 +193,28 @@ describe('Test the scale service', function() {
|
||||
Chart.scaleService.update(chartInstance, canvasWidth, canvasHeight);
|
||||
|
||||
expect(chartInstance.chartArea).toEqual({
|
||||
left: 95,
|
||||
left: 115,
|
||||
right: 245,
|
||||
top: 5,
|
||||
bottom: 70.01536896070459,
|
||||
bottom: 68.48521368620018,
|
||||
});
|
||||
|
||||
// Is xScale at the right spot
|
||||
expect(xScale.left).toBe(95);
|
||||
expect(xScale.left).toBe(115);
|
||||
expect(xScale.right).toBe(245);
|
||||
expect(xScale.top).toBe(70.01536896070459);
|
||||
expect(xScale.top).toBe(68.48521368620018);
|
||||
expect(xScale.bottom).toBe(145);
|
||||
|
||||
// Are yScales at the right spot
|
||||
expect(yScale1.left).toBe(5);
|
||||
expect(yScale1.right).toBe(45);
|
||||
expect(yScale1.right).toBe(55);
|
||||
expect(yScale1.top).toBe(5);
|
||||
expect(yScale1.bottom).toBe(70.01536896070459);
|
||||
expect(yScale1.bottom).toBe(68.48521368620018);
|
||||
|
||||
expect(yScale2.left).toBe(45);
|
||||
expect(yScale2.right).toBe(95);
|
||||
expect(yScale2.left).toBe(55);
|
||||
expect(yScale2.right).toBe(115);
|
||||
expect(yScale2.top).toBe(5);
|
||||
expect(yScale2.bottom).toBe(70.01536896070459);
|
||||
expect(yScale2.bottom).toBe(68.48521368620018);
|
||||
});
|
||||
|
||||
// This is an oddball case. What happens is, when the scales are fit the first time they must fit within the assigned size. In this case,
|
||||
@@ -230,7 +244,9 @@ describe('Test the scale service', function() {
|
||||
var scale = new ScaleConstructor({
|
||||
ctx: mockContext,
|
||||
options: scaleConfig,
|
||||
data: mockData,
|
||||
chart: {
|
||||
data: mockData
|
||||
},
|
||||
id: scaleID
|
||||
});
|
||||
|
||||
|
||||
+609
-121
@@ -22,6 +22,8 @@ describe('Line element tests', function() {
|
||||
_view: {
|
||||
x: 0,
|
||||
y: 10,
|
||||
controlPointNextX: 0,
|
||||
controlPointNextY: 10
|
||||
}
|
||||
}));
|
||||
points.push(new Chart.elements.Point({
|
||||
@@ -30,6 +32,10 @@ describe('Line element tests', function() {
|
||||
_view: {
|
||||
x: 5,
|
||||
y: 0,
|
||||
controlPointPreviousX: 5,
|
||||
controlPointPreviousY: 0,
|
||||
controlPointNextX: 5,
|
||||
controlPointNextY: 0
|
||||
}
|
||||
}));
|
||||
points.push(new Chart.elements.Point({
|
||||
@@ -38,6 +44,10 @@ describe('Line element tests', function() {
|
||||
_view: {
|
||||
x: 15,
|
||||
y: -10,
|
||||
controlPointPreviousX: 15,
|
||||
controlPointPreviousY: -10,
|
||||
controlPointNextX: 15,
|
||||
controlPointNextY: -10
|
||||
}
|
||||
}));
|
||||
points.push(new Chart.elements.Point({
|
||||
@@ -46,6 +56,10 @@ describe('Line element tests', function() {
|
||||
_view: {
|
||||
x: 19,
|
||||
y: -5,
|
||||
controlPointPreviousX: 19,
|
||||
controlPointPreviousY: -5,
|
||||
controlPointNextX: 19,
|
||||
controlPointNextY: -5
|
||||
}
|
||||
}));
|
||||
|
||||
@@ -68,21 +82,6 @@ describe('Line element tests', function() {
|
||||
expect(mockContext.getCalls()).toEqual([{
|
||||
name: 'save',
|
||||
args: [],
|
||||
}, {
|
||||
name: 'moveTo',
|
||||
args: [0, 0]
|
||||
}, {
|
||||
name: 'lineTo',
|
||||
args: [0, 10]
|
||||
}, {
|
||||
name: 'lineTo',
|
||||
args: [5, 0]
|
||||
}, {
|
||||
name: 'lineTo',
|
||||
args: [15, -10]
|
||||
}, {
|
||||
name: 'lineTo',
|
||||
args: [19, -5]
|
||||
}, {
|
||||
name: 'setLineCap',
|
||||
args: ['butt']
|
||||
@@ -108,19 +107,16 @@ describe('Line element tests', function() {
|
||||
args: []
|
||||
}, {
|
||||
name: 'moveTo',
|
||||
args: [0, 0]
|
||||
}, {
|
||||
name: 'lineTo',
|
||||
args: [0, 10]
|
||||
}, {
|
||||
name: 'lineTo',
|
||||
args: [5, 0]
|
||||
name: 'bezierCurveTo',
|
||||
args: [0, 10, 5, 0, 5, 0]
|
||||
}, {
|
||||
name: 'lineTo',
|
||||
args: [15, -10]
|
||||
name: 'bezierCurveTo',
|
||||
args: [5, 0, 15, -10, 15, -10]
|
||||
}, {
|
||||
name: 'lineTo',
|
||||
args: [19, -5]
|
||||
name: 'bezierCurveTo',
|
||||
args: [15, -10, 19, -5, 19, -5]
|
||||
}, {
|
||||
name: 'stroke',
|
||||
args: [],
|
||||
@@ -140,7 +136,9 @@ describe('Line element tests', function() {
|
||||
_index: 0,
|
||||
_view: {
|
||||
x: 0,
|
||||
y: 10
|
||||
y: 10,
|
||||
controlPointNextX: 0,
|
||||
controlPointNextY: 10
|
||||
}
|
||||
}));
|
||||
points.push(new Chart.elements.Point({
|
||||
@@ -148,7 +146,11 @@ describe('Line element tests', function() {
|
||||
_index: 1,
|
||||
_view: {
|
||||
x: 5,
|
||||
y: 0
|
||||
y: 0,
|
||||
controlPointPreviousX: 5,
|
||||
controlPointPreviousY: 0,
|
||||
controlPointNextX: 5,
|
||||
controlPointNextY: 0
|
||||
}
|
||||
}));
|
||||
points.push(new Chart.elements.Point({
|
||||
@@ -156,7 +158,11 @@ describe('Line element tests', function() {
|
||||
_index: 2,
|
||||
_view: {
|
||||
x: 15,
|
||||
y: -10
|
||||
y: -10,
|
||||
controlPointPreviousX: 15,
|
||||
controlPointPreviousY: -10,
|
||||
controlPointNextX: 15,
|
||||
controlPointNextY: -10
|
||||
}
|
||||
}));
|
||||
points.push(new Chart.elements.Point({
|
||||
@@ -164,7 +170,11 @@ describe('Line element tests', function() {
|
||||
_index: 3,
|
||||
_view: {
|
||||
x: 19,
|
||||
y: -5
|
||||
y: -5,
|
||||
controlPointPreviousX: 19,
|
||||
controlPointPreviousY: -5,
|
||||
controlPointNextX: 19,
|
||||
controlPointNextY: -5
|
||||
}
|
||||
}));
|
||||
|
||||
@@ -195,6 +205,9 @@ describe('Line element tests', function() {
|
||||
var expected = [{
|
||||
name: 'save',
|
||||
args: [],
|
||||
}, {
|
||||
name: 'beginPath',
|
||||
args: []
|
||||
}, {
|
||||
name: 'moveTo',
|
||||
args: [0, 2]
|
||||
@@ -202,14 +215,14 @@ describe('Line element tests', function() {
|
||||
name: 'lineTo',
|
||||
args: [0, 10]
|
||||
}, {
|
||||
name: 'lineTo',
|
||||
args: [5, 0]
|
||||
name: 'bezierCurveTo',
|
||||
args: [0, 10, 5, 0, 5, 0]
|
||||
}, {
|
||||
name: 'lineTo',
|
||||
args: [15, -10]
|
||||
name: 'bezierCurveTo',
|
||||
args: [5, 0, 15, -10, 15, -10]
|
||||
}, {
|
||||
name: 'lineTo',
|
||||
args: [19, -5]
|
||||
name: 'bezierCurveTo',
|
||||
args: [15, -10, 19, -5, 19, -5]
|
||||
}, {
|
||||
name: 'lineTo',
|
||||
args: [19, 2]
|
||||
@@ -248,6 +261,103 @@ describe('Line element tests', function() {
|
||||
}, {
|
||||
name: 'beginPath',
|
||||
args: []
|
||||
}, {
|
||||
name: 'moveTo',
|
||||
args: [0, 10]
|
||||
}, {
|
||||
name: 'bezierCurveTo',
|
||||
args: [0, 10, 5, 0, 5, 0]
|
||||
}, {
|
||||
name: 'bezierCurveTo',
|
||||
args: [5, 0, 15, -10, 15, -10]
|
||||
}, {
|
||||
name: 'bezierCurveTo',
|
||||
args: [15, -10, 19, -5, 19, -5]
|
||||
}, {
|
||||
name: 'stroke',
|
||||
args: [],
|
||||
}, {
|
||||
name: 'restore',
|
||||
args: []
|
||||
}];
|
||||
expect(mockContext.getCalls()).toEqual(expected);
|
||||
});
|
||||
|
||||
it ('should skip points correctly', function() {
|
||||
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
|
||||
}
|
||||
}));
|
||||
points.push(new Chart.elements.Point({
|
||||
_datasetindex: 2,
|
||||
_index: 1,
|
||||
_view: {
|
||||
x: 5,
|
||||
y: 0,
|
||||
controlPointPreviousX: 5,
|
||||
controlPointPreviousY: 0,
|
||||
controlPointNextX: 5,
|
||||
controlPointNextY: 0
|
||||
}
|
||||
}));
|
||||
points.push(new Chart.elements.Point({
|
||||
_datasetindex: 2,
|
||||
_index: 2,
|
||||
_view: {
|
||||
x: 15,
|
||||
y: -10,
|
||||
controlPointPreviousX: 15,
|
||||
controlPointPreviousY: -10,
|
||||
controlPointNextX: 15,
|
||||
controlPointNextY: -10,
|
||||
skip: true
|
||||
}
|
||||
}));
|
||||
points.push(new Chart.elements.Point({
|
||||
_datasetindex: 2,
|
||||
_index: 3,
|
||||
_view: {
|
||||
x: 19,
|
||||
y: -5,
|
||||
controlPointPreviousX: 19,
|
||||
controlPointPreviousY: -5,
|
||||
controlPointNextX: 19,
|
||||
controlPointNextY: -5
|
||||
}
|
||||
}));
|
||||
|
||||
var line = new Chart.elements.Line({
|
||||
_datasetindex: 2,
|
||||
_chart: {
|
||||
ctx: mockContext,
|
||||
},
|
||||
_children: points,
|
||||
// Need to provide some settings
|
||||
_view: {
|
||||
fill: true,
|
||||
scaleZero: 2, // for filling lines
|
||||
tension: 0.0, // no bezier curve for now
|
||||
}
|
||||
});
|
||||
|
||||
line.draw();
|
||||
|
||||
var expected = [{
|
||||
name: 'save',
|
||||
args: []
|
||||
}, {
|
||||
name: 'beginPath',
|
||||
args: []
|
||||
}, {
|
||||
name: 'moveTo',
|
||||
args: [0, 2]
|
||||
@@ -255,14 +365,67 @@ describe('Line element tests', function() {
|
||||
name: 'lineTo',
|
||||
args: [0, 10]
|
||||
}, {
|
||||
name: 'lineTo',
|
||||
args: [5, 0]
|
||||
name: 'bezierCurveTo',
|
||||
args: [0, 10, 5, 0, 5, 0]
|
||||
}, {
|
||||
name: 'lineTo',
|
||||
args: [5, 2]
|
||||
}, {
|
||||
name: 'moveTo',
|
||||
args: [19, 2]
|
||||
}, {
|
||||
name: 'lineTo',
|
||||
args: [19, -5]
|
||||
}, {
|
||||
name: 'lineTo',
|
||||
args: [19, 2]
|
||||
}, {
|
||||
name: 'lineTo',
|
||||
args: [15, -10]
|
||||
args: [0, 2]
|
||||
}, {
|
||||
name: 'lineTo',
|
||||
args: [19, -5]
|
||||
name: 'setFillStyle',
|
||||
args: ['rgba(0,0,0,0.1)']
|
||||
}, {
|
||||
name: 'closePath',
|
||||
args: []
|
||||
}, {
|
||||
name: 'fill',
|
||||
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: 'bezierCurveTo',
|
||||
args: [0, 10, 5, 0, 5, 0]
|
||||
}, {
|
||||
name: 'moveTo',
|
||||
args: [19, -5]
|
||||
}, {
|
||||
name: 'moveTo',
|
||||
args: [19, -5]
|
||||
}, {
|
||||
name: 'stroke',
|
||||
args: [],
|
||||
@@ -283,7 +446,11 @@ describe('Line element tests', function() {
|
||||
_index: 0,
|
||||
_view: {
|
||||
x: 0,
|
||||
y: 10
|
||||
y: 10,
|
||||
controlPointPreviousX: 0,
|
||||
controlPointPreviousY: 10,
|
||||
controlPointNextX: 0,
|
||||
controlPointNextY: 10
|
||||
}
|
||||
}));
|
||||
points.push(new Chart.elements.Point({
|
||||
@@ -291,7 +458,11 @@ describe('Line element tests', function() {
|
||||
_index: 1,
|
||||
_view: {
|
||||
x: 5,
|
||||
y: 0
|
||||
y: 0,
|
||||
controlPointPreviousX: 5,
|
||||
controlPointPreviousY: 0,
|
||||
controlPointNextX: 5,
|
||||
controlPointNextY: 0
|
||||
}
|
||||
}));
|
||||
points.push(new Chart.elements.Point({
|
||||
@@ -299,7 +470,11 @@ describe('Line element tests', function() {
|
||||
_index: 2,
|
||||
_view: {
|
||||
x: 15,
|
||||
y: -10
|
||||
y: -10,
|
||||
controlPointPreviousX: 15,
|
||||
controlPointPreviousY: -10,
|
||||
controlPointNextX: 15,
|
||||
controlPointNextY: -10
|
||||
}
|
||||
}));
|
||||
points.push(new Chart.elements.Point({
|
||||
@@ -307,7 +482,11 @@ describe('Line element tests', function() {
|
||||
_index: 3,
|
||||
_view: {
|
||||
x: 19,
|
||||
y: -5
|
||||
y: -5,
|
||||
controlPointPreviousX: 19,
|
||||
controlPointPreviousY: -5,
|
||||
controlPointNextX: 19,
|
||||
controlPointNextY: -5
|
||||
}
|
||||
}));
|
||||
|
||||
@@ -320,9 +499,12 @@ describe('Line element tests', function() {
|
||||
_loop: true, // want the line to loop back to the first point
|
||||
// Need to provide some settings
|
||||
_view: {
|
||||
fill: false, // don't want to fill
|
||||
fill: true, // don't want to fill
|
||||
tension: 0.0, // no bezier curve for now
|
||||
scaleZero: 0,
|
||||
scaleZero: {
|
||||
x: 3,
|
||||
y: 2
|
||||
},
|
||||
}
|
||||
});
|
||||
|
||||
@@ -331,24 +513,36 @@ describe('Line element tests', function() {
|
||||
expect(mockContext.getCalls()).toEqual([{
|
||||
name: 'save',
|
||||
args: [],
|
||||
}, {
|
||||
name: 'beginPath',
|
||||
args: []
|
||||
}, {
|
||||
name: 'moveTo',
|
||||
args: [0, 0]
|
||||
args: [3, 2]
|
||||
}, {
|
||||
name: 'lineTo',
|
||||
args: [0, 10]
|
||||
}, {
|
||||
name: 'lineTo',
|
||||
args: [5, 0]
|
||||
name: 'bezierCurveTo',
|
||||
args: [0, 10, 5, 0, 5, 0]
|
||||
}, {
|
||||
name: 'lineTo',
|
||||
args: [15, -10]
|
||||
name: 'bezierCurveTo',
|
||||
args: [5, 0, 15, -10, 15, -10]
|
||||
}, {
|
||||
name: 'lineTo',
|
||||
args: [19, -5]
|
||||
name: 'bezierCurveTo',
|
||||
args: [15, -10, 19, -5, 19, -5]
|
||||
}, {
|
||||
name: 'lineTo',
|
||||
args: [0, 10]
|
||||
name: 'bezierCurveTo',
|
||||
args: [19, -5, 0, 10, 0, 10]
|
||||
}, {
|
||||
name: 'setFillStyle',
|
||||
args: ['rgba(0,0,0,0.1)']
|
||||
}, {
|
||||
name: 'closePath',
|
||||
args: []
|
||||
}, {
|
||||
name: 'fill',
|
||||
args: []
|
||||
}, {
|
||||
name: 'setLineCap',
|
||||
args: ['butt']
|
||||
@@ -374,22 +568,19 @@ describe('Line element tests', function() {
|
||||
args: []
|
||||
}, {
|
||||
name: 'moveTo',
|
||||
args: [0, 0]
|
||||
}, {
|
||||
name: 'lineTo',
|
||||
args: [0, 10]
|
||||
}, {
|
||||
name: 'lineTo',
|
||||
args: [5, 0]
|
||||
name: 'bezierCurveTo',
|
||||
args: [0, 10, 5, 0, 5, 0]
|
||||
}, {
|
||||
name: 'lineTo',
|
||||
args: [15, -10]
|
||||
name: 'bezierCurveTo',
|
||||
args: [5, 0, 15, -10, 15, -10]
|
||||
}, {
|
||||
name: 'lineTo',
|
||||
args: [19, -5]
|
||||
name: 'bezierCurveTo',
|
||||
args: [15, -10, 19, -5, 19, -5]
|
||||
}, {
|
||||
name: 'lineTo',
|
||||
args: [0, 10]
|
||||
name: 'bezierCurveTo',
|
||||
args: [19, -5, 0, 10, 0, 10]
|
||||
}, {
|
||||
name: 'stroke',
|
||||
args: [],
|
||||
@@ -399,7 +590,7 @@ describe('Line element tests', function() {
|
||||
}]);
|
||||
});
|
||||
|
||||
it('should draw with bezier curves if tension > 0', function() {
|
||||
it('should be able to draw with a loop back to the beginning point when there is a skip in the middle of the dataset', function() {
|
||||
var mockContext = window.createMockContext();
|
||||
|
||||
// Create our points
|
||||
@@ -410,10 +601,10 @@ describe('Line element tests', function() {
|
||||
_view: {
|
||||
x: 0,
|
||||
y: 10,
|
||||
controlPointNextX: 1,
|
||||
controlPointNextY: 1,
|
||||
controlPointPreviousX: 0,
|
||||
controlPointPreviousY: 0,
|
||||
controlPointPreviousY: 10,
|
||||
controlPointNextX: 0,
|
||||
controlPointNextY: 10
|
||||
}
|
||||
}));
|
||||
points.push(new Chart.elements.Point({
|
||||
@@ -422,10 +613,11 @@ describe('Line element tests', function() {
|
||||
_view: {
|
||||
x: 5,
|
||||
y: 0,
|
||||
controlPointNextX: 6,
|
||||
controlPointNextY: 7,
|
||||
controlPointPreviousX: 4,
|
||||
controlPointPreviousY: 3,
|
||||
controlPointPreviousX: 5,
|
||||
controlPointPreviousY: 0,
|
||||
controlPointNextX: 5,
|
||||
controlPointNextY: 0,
|
||||
skip: true
|
||||
}
|
||||
}));
|
||||
points.push(new Chart.elements.Point({
|
||||
@@ -434,10 +626,10 @@ describe('Line element tests', function() {
|
||||
_view: {
|
||||
x: 15,
|
||||
y: -10,
|
||||
controlPointNextX: 16,
|
||||
controlPointNextY: 17,
|
||||
controlPointPreviousX: 14,
|
||||
controlPointPreviousY: 13,
|
||||
controlPointPreviousX: 15,
|
||||
controlPointPreviousY: -10,
|
||||
controlPointNextX: 15,
|
||||
controlPointNextY: -10
|
||||
}
|
||||
}));
|
||||
points.push(new Chart.elements.Point({
|
||||
@@ -446,10 +638,10 @@ describe('Line element tests', function() {
|
||||
_view: {
|
||||
x: 19,
|
||||
y: -5,
|
||||
controlPointNextX: 20,
|
||||
controlPointNextY: 21,
|
||||
controlPointPreviousX: 18,
|
||||
controlPointPreviousY: 17,
|
||||
controlPointPreviousX: 19,
|
||||
controlPointPreviousY: -5,
|
||||
controlPointNextX: 19,
|
||||
controlPointNextY: -5
|
||||
}
|
||||
}));
|
||||
|
||||
@@ -459,51 +651,47 @@ describe('Line element tests', function() {
|
||||
ctx: mockContext,
|
||||
},
|
||||
_children: points,
|
||||
_loop: true, // want the line to loop back to the first point
|
||||
// Need to provide some settings
|
||||
_view: {
|
||||
fill: true,
|
||||
scaleZero: 2, // for filling lines
|
||||
tension: 0.5, // have bezier curves
|
||||
|
||||
borderCapStyle: 'round',
|
||||
borderColor: 'rgb(255, 255, 0)',
|
||||
borderDash: [2, 2],
|
||||
borderDashOffset: 1.5,
|
||||
borderJoinStyle: 'bevel',
|
||||
borderWidth: 4,
|
||||
backgroundColor: 'rgb(0, 0, 0)'
|
||||
fill: true, // don't want to fill
|
||||
tension: 0.0, // no bezier curve for now
|
||||
scaleZero: {
|
||||
x: 3,
|
||||
y: 2
|
||||
},
|
||||
}
|
||||
});
|
||||
|
||||
line.draw();
|
||||
|
||||
var expected = [{
|
||||
expect(mockContext.getCalls()).toEqual([{
|
||||
name: 'save',
|
||||
args: [],
|
||||
}, {
|
||||
name: 'beginPath',
|
||||
args: []
|
||||
}, {
|
||||
name: 'moveTo',
|
||||
args: [0, 2]
|
||||
args: [3, 2]
|
||||
}, {
|
||||
name: 'lineTo',
|
||||
args: [0, 10]
|
||||
}, {
|
||||
name: 'bezierCurveTo',
|
||||
args: [1, 1, 4, 3, 5, 0]
|
||||
}, {
|
||||
name: 'bezierCurveTo',
|
||||
args: [6, 7, 14, 13, 15, -10]
|
||||
}, {
|
||||
name: 'bezierCurveTo',
|
||||
args: [16, 17, 18, 17, 19, -5]
|
||||
name: 'lineTo',
|
||||
args: [3, 2]
|
||||
}, {
|
||||
name: 'lineTo',
|
||||
args: [19, 2]
|
||||
args: [15, -10]
|
||||
}, {
|
||||
name: 'lineTo',
|
||||
args: [0, 2]
|
||||
name: 'bezierCurveTo',
|
||||
args: [15, -10, 19, -5, 19, -5]
|
||||
}, {
|
||||
name: 'bezierCurveTo',
|
||||
args: [19, -5, 0, 10, 0, 10]
|
||||
}, {
|
||||
name: 'setFillStyle',
|
||||
args: ['rgb(0, 0, 0)']
|
||||
args: ['rgba(0,0,0,0.1)']
|
||||
}, {
|
||||
name: 'closePath',
|
||||
args: []
|
||||
@@ -512,49 +700,349 @@ describe('Line element tests', function() {
|
||||
args: []
|
||||
}, {
|
||||
name: 'setLineCap',
|
||||
args: ['round']
|
||||
args: ['butt']
|
||||
}, {
|
||||
name: 'setLineDash',
|
||||
args: [
|
||||
[2, 2]
|
||||
[]
|
||||
]
|
||||
}, {
|
||||
name: 'setLineDashOffset',
|
||||
args: [1.5]
|
||||
args: [0.0]
|
||||
}, {
|
||||
name: 'setLineJoin',
|
||||
args: ['bevel']
|
||||
args: ['miter']
|
||||
}, {
|
||||
name: 'setLineWidth',
|
||||
args: [4]
|
||||
args: [3]
|
||||
}, {
|
||||
name: 'setStrokeStyle',
|
||||
args: ['rgb(255, 255, 0)']
|
||||
args: ['rgba(0,0,0,0.1)']
|
||||
}, {
|
||||
name: 'beginPath',
|
||||
args: []
|
||||
}, {
|
||||
name: 'moveTo',
|
||||
args: [0, 2]
|
||||
}, {
|
||||
name: 'lineTo',
|
||||
args: [0, 10]
|
||||
}, {
|
||||
name: 'bezierCurveTo',
|
||||
args: [1, 1, 4, 3, 5, 0]
|
||||
name: 'moveTo',
|
||||
args: [15, -10]
|
||||
}, {
|
||||
name: 'moveTo',
|
||||
args: [15, -10]
|
||||
}, {
|
||||
name: 'bezierCurveTo',
|
||||
args: [6, 7, 14, 13, 15, -10]
|
||||
args: [15, -10, 19, -5, 19, -5]
|
||||
}, {
|
||||
name: 'bezierCurveTo',
|
||||
args: [16, 17, 18, 17, 19, -5]
|
||||
args: [19, -5, 0, 10, 0, 10]
|
||||
}, {
|
||||
name: 'stroke',
|
||||
args: [],
|
||||
}, {
|
||||
name: 'restore',
|
||||
args: []
|
||||
}];
|
||||
expect(mockContext.getCalls()).toEqual(expected);
|
||||
}]);
|
||||
});
|
||||
|
||||
it('should be able to draw with a loop back to the beginning point when the first point is skipped', function() {
|
||||
var mockContext = window.createMockContext();
|
||||
|
||||
// Create our points
|
||||
var points = [];
|
||||
points.push(new Chart.elements.Point({
|
||||
_datasetindex: 2,
|
||||
_index: 0,
|
||||
_view: {
|
||||
x: 0,
|
||||
y: 10,
|
||||
controlPointPreviousX: 0,
|
||||
controlPointPreviousY: 10,
|
||||
controlPointNextX: 0,
|
||||
controlPointNextY: 10,
|
||||
skip: true
|
||||
}
|
||||
}));
|
||||
points.push(new Chart.elements.Point({
|
||||
_datasetindex: 2,
|
||||
_index: 1,
|
||||
_view: {
|
||||
x: 5,
|
||||
y: 0,
|
||||
controlPointPreviousX: 5,
|
||||
controlPointPreviousY: 0,
|
||||
controlPointNextX: 5,
|
||||
controlPointNextY: 0,
|
||||
}
|
||||
}));
|
||||
points.push(new Chart.elements.Point({
|
||||
_datasetindex: 2,
|
||||
_index: 2,
|
||||
_view: {
|
||||
x: 15,
|
||||
y: -10,
|
||||
controlPointPreviousX: 15,
|
||||
controlPointPreviousY: -10,
|
||||
controlPointNextX: 15,
|
||||
controlPointNextY: -10
|
||||
}
|
||||
}));
|
||||
points.push(new Chart.elements.Point({
|
||||
_datasetindex: 2,
|
||||
_index: 3,
|
||||
_view: {
|
||||
x: 19,
|
||||
y: -5,
|
||||
controlPointPreviousX: 19,
|
||||
controlPointPreviousY: -5,
|
||||
controlPointNextX: 19,
|
||||
controlPointNextY: -5
|
||||
}
|
||||
}));
|
||||
|
||||
var line = new Chart.elements.Line({
|
||||
_datasetindex: 2,
|
||||
_chart: {
|
||||
ctx: mockContext,
|
||||
},
|
||||
_children: points,
|
||||
_loop: true, // want the line to loop back to the first point
|
||||
// Need to provide some settings
|
||||
_view: {
|
||||
fill: true, // don't want to fill
|
||||
tension: 0.0, // no bezier curve for now
|
||||
scaleZero: {
|
||||
x: 3,
|
||||
y: 2
|
||||
},
|
||||
}
|
||||
});
|
||||
|
||||
line.draw();
|
||||
|
||||
expect(mockContext.getCalls()).toEqual([{
|
||||
name: 'save',
|
||||
args: [],
|
||||
}, {
|
||||
name: 'beginPath',
|
||||
args: []
|
||||
}, {
|
||||
name: 'moveTo',
|
||||
args: [3, 2]
|
||||
}, {
|
||||
name: 'lineTo',
|
||||
args: [5, 0]
|
||||
}, {
|
||||
name: 'bezierCurveTo',
|
||||
args: [5, 0, 15, -10, 15, -10]
|
||||
}, {
|
||||
name: 'bezierCurveTo',
|
||||
args: [15, -10, 19, -5, 19, -5]
|
||||
}, {
|
||||
name: 'lineTo',
|
||||
args: [3, 2]
|
||||
}, {
|
||||
name: 'setFillStyle',
|
||||
args: ['rgba(0,0,0,0.1)']
|
||||
}, {
|
||||
name: 'closePath',
|
||||
args: []
|
||||
}, {
|
||||
name: 'fill',
|
||||
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: 'moveTo',
|
||||
args: [5, 0]
|
||||
}, {
|
||||
name: 'bezierCurveTo',
|
||||
args: [5, 0, 15, -10, 15, -10]
|
||||
}, {
|
||||
name: 'bezierCurveTo',
|
||||
args: [15, -10, 19, -5, 19, -5]
|
||||
}, {
|
||||
name: 'stroke',
|
||||
args: [],
|
||||
}, {
|
||||
name: 'restore',
|
||||
args: []
|
||||
}]);
|
||||
});
|
||||
|
||||
it('should be able to draw with a loop back to the beginning point when the last point is skipped', function() {
|
||||
var mockContext = window.createMockContext();
|
||||
|
||||
// Create our points
|
||||
var points = [];
|
||||
points.push(new Chart.elements.Point({
|
||||
_datasetindex: 2,
|
||||
_index: 0,
|
||||
_view: {
|
||||
x: 0,
|
||||
y: 10,
|
||||
controlPointPreviousX: 0,
|
||||
controlPointPreviousY: 10,
|
||||
controlPointNextX: 0,
|
||||
controlPointNextY: 10
|
||||
}
|
||||
}));
|
||||
points.push(new Chart.elements.Point({
|
||||
_datasetindex: 2,
|
||||
_index: 1,
|
||||
_view: {
|
||||
x: 5,
|
||||
y: 0,
|
||||
controlPointPreviousX: 5,
|
||||
controlPointPreviousY: 0,
|
||||
controlPointNextX: 5,
|
||||
controlPointNextY: 0,
|
||||
}
|
||||
}));
|
||||
points.push(new Chart.elements.Point({
|
||||
_datasetindex: 2,
|
||||
_index: 2,
|
||||
_view: {
|
||||
x: 15,
|
||||
y: -10,
|
||||
controlPointPreviousX: 15,
|
||||
controlPointPreviousY: -10,
|
||||
controlPointNextX: 15,
|
||||
controlPointNextY: -10
|
||||
}
|
||||
}));
|
||||
points.push(new Chart.elements.Point({
|
||||
_datasetindex: 2,
|
||||
_index: 3,
|
||||
_view: {
|
||||
x: 19,
|
||||
y: -5,
|
||||
controlPointPreviousX: 19,
|
||||
controlPointPreviousY: -5,
|
||||
controlPointNextX: 19,
|
||||
controlPointNextY: -5,
|
||||
skip: true
|
||||
}
|
||||
}));
|
||||
|
||||
var line = new Chart.elements.Line({
|
||||
_datasetindex: 2,
|
||||
_chart: {
|
||||
ctx: mockContext,
|
||||
},
|
||||
_children: points,
|
||||
_loop: true, // want the line to loop back to the first point
|
||||
// Need to provide some settings
|
||||
_view: {
|
||||
fill: true, // don't want to fill
|
||||
tension: 0.0, // no bezier curve for now
|
||||
scaleZero: {
|
||||
x: 3,
|
||||
y: 2
|
||||
},
|
||||
}
|
||||
});
|
||||
|
||||
line.draw();
|
||||
|
||||
expect(mockContext.getCalls()).toEqual([{
|
||||
name: 'save',
|
||||
args: [],
|
||||
}, {
|
||||
name: 'beginPath',
|
||||
args: []
|
||||
}, {
|
||||
name: 'moveTo',
|
||||
args: [3, 2]
|
||||
}, {
|
||||
name: 'lineTo',
|
||||
args: [0, 10]
|
||||
}, {
|
||||
name: 'bezierCurveTo',
|
||||
args: [0, 10, 5, 0, 5, 0]
|
||||
}, {
|
||||
name: 'bezierCurveTo',
|
||||
args: [5, 0, 15, -10, 15, -10]
|
||||
}, {
|
||||
name: 'lineTo',
|
||||
args: [3, 2]
|
||||
}, {
|
||||
name: 'lineTo',
|
||||
args: [3, 2]
|
||||
}, {
|
||||
name: 'setFillStyle',
|
||||
args: ['rgba(0,0,0,0.1)']
|
||||
}, {
|
||||
name: 'closePath',
|
||||
args: []
|
||||
}, {
|
||||
name: 'fill',
|
||||
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: 'bezierCurveTo',
|
||||
args: [0, 10, 5, 0, 5, 0]
|
||||
}, {
|
||||
name: 'bezierCurveTo',
|
||||
args: [5, 0, 15, -10, 15, -10]
|
||||
}, {
|
||||
name: 'moveTo',
|
||||
args: [19, -5]
|
||||
}, {
|
||||
name: 'stroke',
|
||||
args: [],
|
||||
}, {
|
||||
name: 'restore',
|
||||
args: []
|
||||
}]);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -18,7 +18,7 @@ describe('Category scale tests', function() {
|
||||
drawTicks: true, // draw ticks extending towards the label
|
||||
lineWidth: 1,
|
||||
offsetGridLines: false,
|
||||
show: true,
|
||||
display: true,
|
||||
zeroLineColor: "rgba(0,0,0,0.25)",
|
||||
zeroLineWidth: 1,
|
||||
},
|
||||
@@ -29,7 +29,7 @@ describe('Category scale tests', function() {
|
||||
fontSize: 12,
|
||||
fontStyle: 'normal',
|
||||
labelString: '',
|
||||
show: false,
|
||||
display: false,
|
||||
},
|
||||
ticks: {
|
||||
beginAtZero: false,
|
||||
@@ -42,7 +42,7 @@ describe('Category scale tests', function() {
|
||||
mirror: false,
|
||||
padding: 10,
|
||||
reverse: false,
|
||||
show: true,
|
||||
display: true,
|
||||
callback: defaultConfig.ticks.callback, // make this nicer, then check explicitly below
|
||||
}
|
||||
});
|
||||
@@ -67,7 +67,9 @@ describe('Category scale tests', function() {
|
||||
var scale = new Constructor({
|
||||
ctx: {},
|
||||
options: config,
|
||||
data: mockData,
|
||||
chart: {
|
||||
data: mockData
|
||||
},
|
||||
id: scaleID
|
||||
});
|
||||
|
||||
@@ -93,7 +95,9 @@ describe('Category scale tests', function() {
|
||||
var scale = new Constructor({
|
||||
ctx: mockContext,
|
||||
options: config,
|
||||
data: mockData,
|
||||
chart: {
|
||||
data: mockData
|
||||
},
|
||||
id: scaleID
|
||||
});
|
||||
|
||||
@@ -151,7 +155,9 @@ describe('Category scale tests', function() {
|
||||
var scale = new Constructor({
|
||||
ctx: mockContext,
|
||||
options: config,
|
||||
data: mockData,
|
||||
chart: {
|
||||
data: mockData
|
||||
},
|
||||
id: scaleID
|
||||
});
|
||||
|
||||
|
||||
+393
-35
@@ -17,7 +17,7 @@ describe('Linear Scale', function() {
|
||||
drawTicks: true, // draw ticks extending towards the label
|
||||
lineWidth: 1,
|
||||
offsetGridLines: false,
|
||||
show: true,
|
||||
display: true,
|
||||
zeroLineColor: "rgba(0,0,0,0.25)",
|
||||
zeroLineWidth: 1,
|
||||
},
|
||||
@@ -28,7 +28,7 @@ describe('Linear Scale', function() {
|
||||
fontSize: 12,
|
||||
fontStyle: 'normal',
|
||||
labelString: '',
|
||||
show: false,
|
||||
display: false,
|
||||
},
|
||||
ticks: {
|
||||
beginAtZero: false,
|
||||
@@ -41,7 +41,7 @@ describe('Linear Scale', function() {
|
||||
mirror: false,
|
||||
padding: 10,
|
||||
reverse: false,
|
||||
show: true,
|
||||
display: true,
|
||||
callback: defaultConfig.ticks.callback, // make this work nicer, then check below
|
||||
}
|
||||
});
|
||||
@@ -69,7 +69,48 @@ describe('Linear Scale', function() {
|
||||
var scale = new Constructor({
|
||||
ctx: {},
|
||||
options: Chart.scaleService.getScaleDefaults('linear'), // use default config for scale
|
||||
data: mockData,
|
||||
chart: {
|
||||
data: mockData
|
||||
},
|
||||
id: scaleID
|
||||
});
|
||||
|
||||
expect(scale).not.toEqual(undefined); // must construct
|
||||
expect(scale.min).toBe(undefined); // not yet set
|
||||
expect(scale.max).toBe(undefined);
|
||||
|
||||
// Set arbitrary width and height for now
|
||||
scale.width = 50;
|
||||
scale.height = 400;
|
||||
|
||||
scale.buildTicks();
|
||||
expect(scale.min).toBe(-100);
|
||||
expect(scale.max).toBe(150);
|
||||
});
|
||||
|
||||
it('Should correctly determine the max & min of string data values', function() {
|
||||
var scaleID = 'myScale';
|
||||
|
||||
var mockData = {
|
||||
datasets: [{
|
||||
yAxisID: scaleID,
|
||||
data: ['10', '5', '0', '-5', '78', '-100']
|
||||
}, {
|
||||
yAxisID: 'second scale',
|
||||
data: ['-1000', '1000'],
|
||||
}, {
|
||||
yAxisID: scaleID,
|
||||
data: ['150']
|
||||
}]
|
||||
};
|
||||
|
||||
var Constructor = Chart.scaleService.getScaleConstructor('linear');
|
||||
var scale = new Constructor({
|
||||
ctx: {},
|
||||
options: Chart.scaleService.getScaleDefaults('linear'), // use default config for scale
|
||||
chart: {
|
||||
data: mockData
|
||||
},
|
||||
id: scaleID
|
||||
});
|
||||
|
||||
@@ -107,7 +148,9 @@ describe('Linear Scale', function() {
|
||||
var scale = new Constructor({
|
||||
ctx: {},
|
||||
options: Chart.scaleService.getScaleDefaults('linear'), // use default config for scale
|
||||
data: mockData,
|
||||
chart: {
|
||||
data: mockData
|
||||
},
|
||||
id: scaleID
|
||||
});
|
||||
|
||||
@@ -152,7 +195,9 @@ describe('Linear Scale', function() {
|
||||
var verticalScale = new Constructor({
|
||||
ctx: {},
|
||||
options: config,
|
||||
data: mockData,
|
||||
chart: {
|
||||
data: mockData
|
||||
},
|
||||
id: scaleID
|
||||
});
|
||||
|
||||
@@ -169,7 +214,9 @@ describe('Linear Scale', function() {
|
||||
var horizontalScale = new Constructor({
|
||||
ctx: {},
|
||||
options: horizontalConfig,
|
||||
data: mockData,
|
||||
chart: {
|
||||
data: mockData
|
||||
},
|
||||
id: scaleID,
|
||||
});
|
||||
|
||||
@@ -188,13 +235,19 @@ describe('Linear Scale', function() {
|
||||
var mockData = {
|
||||
datasets: [{
|
||||
yAxisID: scaleID,
|
||||
data: [10, 5, 0, -5, 78, -100]
|
||||
data: [10, 5, 0, -5, 78, -100],
|
||||
type: 'bar'
|
||||
}, {
|
||||
yAxisID: 'second scale',
|
||||
data: [-1000, 1000],
|
||||
}, {
|
||||
yAxisID: scaleID,
|
||||
data: [150, 0, 0, -100, -10, 9]
|
||||
data: [150, 0, 0, -100, -10, 9],
|
||||
type: 'bar'
|
||||
}, {
|
||||
yAxisID: scaleID,
|
||||
data: [10, 10, 10, 10, 10, 10],
|
||||
type: 'line'
|
||||
}]
|
||||
};
|
||||
|
||||
@@ -205,7 +258,9 @@ describe('Linear Scale', function() {
|
||||
var scale = new Constructor({
|
||||
ctx: {},
|
||||
options: config,
|
||||
data: mockData,
|
||||
chart: {
|
||||
data: mockData
|
||||
},
|
||||
id: scaleID
|
||||
});
|
||||
|
||||
@@ -245,7 +300,9 @@ describe('Linear Scale', function() {
|
||||
var scale = new Constructor({
|
||||
ctx: {},
|
||||
options: config,
|
||||
data: mockData,
|
||||
chart: {
|
||||
data: mockData
|
||||
},
|
||||
id: scaleID
|
||||
});
|
||||
|
||||
@@ -270,7 +327,9 @@ describe('Linear Scale', function() {
|
||||
var scale = new Constructor({
|
||||
ctx: {},
|
||||
options: config,
|
||||
data: mockData,
|
||||
chart: {
|
||||
data: mockData
|
||||
},
|
||||
id: scaleID
|
||||
});
|
||||
|
||||
@@ -283,6 +342,39 @@ describe('Linear Scale', function() {
|
||||
expect(scale.max).toBe(1);
|
||||
});
|
||||
|
||||
it('Should use the suggestedMin and suggestedMax options', function() {
|
||||
var scaleID = 'myScale';
|
||||
|
||||
var mockData = {
|
||||
datasets: [{
|
||||
yAxisID: scaleID,
|
||||
data: [1, 1, 1, 2, 1, 0]
|
||||
}]
|
||||
};
|
||||
|
||||
var config = Chart.helpers.clone(Chart.scaleService.getScaleDefaults('linear'));
|
||||
config.ticks.suggestedMin = -10;
|
||||
config.ticks.suggestedMax = 10;
|
||||
|
||||
var Constructor = Chart.scaleService.getScaleConstructor('linear');
|
||||
var scale = new Constructor({
|
||||
ctx: {},
|
||||
options: config,
|
||||
chart: {
|
||||
data: mockData
|
||||
},
|
||||
id: scaleID
|
||||
});
|
||||
|
||||
// Set arbitrary width and height for now
|
||||
scale.width = 50;
|
||||
scale.height = 400;
|
||||
|
||||
scale.buildTicks();
|
||||
expect(scale.min).toBe(-10);
|
||||
expect(scale.max).toBe(10);
|
||||
});
|
||||
|
||||
it('should forcibly include 0 in the range if the beginAtZero option is used', function() {
|
||||
var scaleID = 'myScale';
|
||||
|
||||
@@ -300,7 +392,9 @@ describe('Linear Scale', function() {
|
||||
var scale = new Constructor({
|
||||
ctx: {},
|
||||
options: config,
|
||||
data: mockData,
|
||||
chart: {
|
||||
data: mockData
|
||||
},
|
||||
id: scaleID
|
||||
});
|
||||
|
||||
@@ -339,7 +433,9 @@ describe('Linear Scale', function() {
|
||||
var scale = new Constructor({
|
||||
ctx: {},
|
||||
options: config,
|
||||
data: mockData,
|
||||
chart: {
|
||||
data: mockData
|
||||
},
|
||||
id: scaleID
|
||||
});
|
||||
|
||||
@@ -371,7 +467,9 @@ describe('Linear Scale', function() {
|
||||
var scale = new Constructor({
|
||||
ctx: {},
|
||||
options: config,
|
||||
data: mockData,
|
||||
chart: {
|
||||
data: mockData
|
||||
},
|
||||
id: scaleID
|
||||
});
|
||||
|
||||
@@ -403,7 +501,9 @@ describe('Linear Scale', function() {
|
||||
var scale = new Constructor({
|
||||
ctx: mockContext,
|
||||
options: config,
|
||||
data: mockData,
|
||||
chart: {
|
||||
data: mockData
|
||||
},
|
||||
id: scaleID
|
||||
});
|
||||
|
||||
@@ -428,7 +528,9 @@ describe('Linear Scale', function() {
|
||||
var scale = new Constructor({
|
||||
ctx: mockContext,
|
||||
options: config,
|
||||
data: mockData,
|
||||
chart: {
|
||||
data: mockData
|
||||
},
|
||||
id: scaleID
|
||||
});
|
||||
|
||||
@@ -457,7 +559,9 @@ describe('Linear Scale', function() {
|
||||
var scale = new Constructor({
|
||||
ctx: mockContext,
|
||||
options: config,
|
||||
data: mockData,
|
||||
chart: {
|
||||
data: mockData
|
||||
},
|
||||
id: scaleID
|
||||
});
|
||||
|
||||
@@ -484,7 +588,9 @@ describe('Linear Scale', function() {
|
||||
var verticalScale = new Constructor({
|
||||
ctx: mockContext,
|
||||
options: config,
|
||||
data: mockData,
|
||||
chart: {
|
||||
data: mockData
|
||||
},
|
||||
id: scaleID
|
||||
});
|
||||
|
||||
@@ -510,7 +616,9 @@ describe('Linear Scale', function() {
|
||||
var horizontalScale = new Constructor({
|
||||
ctx: mockContext,
|
||||
options: horizontalConfig,
|
||||
data: mockData,
|
||||
chart: {
|
||||
data: mockData
|
||||
},
|
||||
id: scaleID,
|
||||
});
|
||||
|
||||
@@ -549,16 +657,18 @@ describe('Linear Scale', function() {
|
||||
var verticalScale = new Constructor({
|
||||
ctx: mockContext,
|
||||
options: config,
|
||||
data: mockData,
|
||||
chart: {
|
||||
data: mockData
|
||||
},
|
||||
id: scaleID
|
||||
});
|
||||
|
||||
var minSize = verticalScale.update(100, 300);
|
||||
expect(minSize).toEqual({
|
||||
width: 30,
|
||||
width: 40,
|
||||
height: 300,
|
||||
});
|
||||
expect(verticalScale.width).toBe(30);
|
||||
expect(verticalScale.width).toBe(40);
|
||||
expect(verticalScale.height).toBe(300);
|
||||
expect(verticalScale.paddingTop).toBe(6);
|
||||
expect(verticalScale.paddingBottom).toBe(6);
|
||||
@@ -582,10 +692,10 @@ describe('Linear Scale', function() {
|
||||
expect(verticalScale.paddingRight).toBe(0);
|
||||
|
||||
// Extra size when scale label showing
|
||||
config.scaleLabel.show = true;
|
||||
config.scaleLabel.display = true;
|
||||
minSize = verticalScale.update(100, 300);
|
||||
expect(minSize).toEqual({
|
||||
width: 48,
|
||||
width: 58,
|
||||
height: 300,
|
||||
});
|
||||
});
|
||||
@@ -608,7 +718,9 @@ describe('Linear Scale', function() {
|
||||
var horizontalScale = new Constructor({
|
||||
ctx: mockContext,
|
||||
options: config,
|
||||
data: mockData,
|
||||
chart: {
|
||||
data: mockData
|
||||
},
|
||||
id: scaleID
|
||||
});
|
||||
|
||||
@@ -642,7 +754,7 @@ describe('Linear Scale', function() {
|
||||
expect(horizontalScale.paddingRight).toBe(2);
|
||||
|
||||
// Extra size when scale label showing
|
||||
config.scaleLabel.show = true;
|
||||
config.scaleLabel.display = true;
|
||||
minSize = horizontalScale.update(200, 300);
|
||||
expect(minSize).toEqual({
|
||||
width: 200,
|
||||
@@ -668,7 +780,9 @@ describe('Linear Scale', function() {
|
||||
var horizontalScale = new Constructor({
|
||||
ctx: mockContext,
|
||||
options: config,
|
||||
data: mockData,
|
||||
chart: {
|
||||
data: mockData
|
||||
},
|
||||
id: scaleID
|
||||
});
|
||||
|
||||
@@ -820,8 +934,8 @@ describe('Linear Scale', function() {
|
||||
// Turn off some drawing
|
||||
config.gridLines.drawTicks = false;
|
||||
config.gridLines.drawOnChartArea = false;
|
||||
config.ticks.show = false;
|
||||
config.scaleLabel.show = true;
|
||||
config.ticks.display = false;
|
||||
config.scaleLabel.display = true;
|
||||
config.scaleLabel.labelString = 'myLabel';
|
||||
|
||||
mockContext.resetCalls();
|
||||
@@ -899,7 +1013,9 @@ describe('Linear Scale', function() {
|
||||
var verticalScale = new Constructor({
|
||||
ctx: mockContext,
|
||||
options: config,
|
||||
data: mockData,
|
||||
chart: {
|
||||
data: mockData
|
||||
},
|
||||
id: scaleID
|
||||
});
|
||||
|
||||
@@ -1319,8 +1435,8 @@ describe('Linear Scale', function() {
|
||||
// Turn off some drawing
|
||||
config.gridLines.drawTicks = false;
|
||||
config.gridLines.drawOnChartArea = false;
|
||||
config.ticks.show = false;
|
||||
config.scaleLabel.show = true;
|
||||
config.ticks.display = false;
|
||||
config.scaleLabel.display = true;
|
||||
|
||||
mockContext.resetCalls();
|
||||
|
||||
@@ -1421,7 +1537,7 @@ describe('Linear Scale', function() {
|
||||
}, {
|
||||
"name": "rotate",
|
||||
"args": [-1.5707963267948966]
|
||||
}, {
|
||||
}, {
|
||||
"name": "setFillStyle",
|
||||
"args": ["#666"]
|
||||
}, {
|
||||
@@ -1432,4 +1548,246 @@ describe('Linear Scale', function() {
|
||||
"args": []
|
||||
}]);
|
||||
});
|
||||
});
|
||||
|
||||
it("should not draw lines where the callback function returned null or undefined", function() {
|
||||
var scaleID = 'myScale';
|
||||
|
||||
var mockData = {
|
||||
datasets: [{
|
||||
xAxisID: scaleID, // for the horizontal scale
|
||||
yAxisID: scaleID,
|
||||
data: [-5, 0, 2, -3, 5]
|
||||
}]
|
||||
};
|
||||
var mockContext = window.createMockContext();
|
||||
|
||||
var config = Chart.helpers.clone(Chart.scaleService.getScaleDefaults('linear'));
|
||||
config.ticks.callback = function(tickValue, index) {
|
||||
return index % 2 === 0 ? null : tickValue.toString();
|
||||
};
|
||||
var Constructor = Chart.scaleService.getScaleConstructor('linear');
|
||||
var verticalScale = new Constructor({
|
||||
ctx: mockContext,
|
||||
options: config,
|
||||
chart: {
|
||||
data: mockData
|
||||
},
|
||||
id: scaleID
|
||||
});
|
||||
|
||||
var minSize = verticalScale.update(100, 300);
|
||||
minSize = verticalScale.update(30, 300, {
|
||||
left: 0,
|
||||
right: 0,
|
||||
top: 15,
|
||||
bottom: 3
|
||||
});
|
||||
expect(minSize).toEqual({
|
||||
width: 30,
|
||||
height: 300,
|
||||
});
|
||||
|
||||
verticalScale.left = 0;
|
||||
verticalScale.right = minSize.width;
|
||||
verticalScale.top = 0;
|
||||
verticalScale.bottom = minSize.height;
|
||||
|
||||
var chartArea = {
|
||||
top: 0,
|
||||
bottom: minSize.height,
|
||||
left: minSize.width,
|
||||
right: minSize.width + 100
|
||||
};
|
||||
|
||||
mockContext.resetCalls();
|
||||
verticalScale.draw(chartArea);
|
||||
|
||||
expect(mockContext.getCalls()).toEqual([{
|
||||
"name": "setFillStyle",
|
||||
"args": ["#666"]
|
||||
}, {
|
||||
"name": "setLineWidth",
|
||||
"args": [1]
|
||||
}, {
|
||||
"name": "setStrokeStyle",
|
||||
"args": ["rgba(0, 0, 0, 0.1)"]
|
||||
}, {
|
||||
"name": "beginPath",
|
||||
"args": []
|
||||
}, {
|
||||
"name": "moveTo",
|
||||
"args": [25, 30.2]
|
||||
}, {
|
||||
"name": "lineTo",
|
||||
"args": [30, 30.2]
|
||||
}, {
|
||||
"name": "moveTo",
|
||||
"args": [30, 30.2]
|
||||
}, {
|
||||
"name": "lineTo",
|
||||
"args": [130, 30.2]
|
||||
}, {
|
||||
"name": "stroke",
|
||||
"args": []
|
||||
}, {
|
||||
"name": "save",
|
||||
"args": []
|
||||
}, {
|
||||
"name": "translate",
|
||||
"args": [20, 29.7]
|
||||
}, {
|
||||
"name": "rotate",
|
||||
"args": [-0]
|
||||
}, {
|
||||
"name": "fillText",
|
||||
"args": ["4", 0, 0]
|
||||
}, {
|
||||
"name": "restore",
|
||||
"args": []
|
||||
}, {
|
||||
"name": "beginPath",
|
||||
"args": []
|
||||
}, {
|
||||
"name": "moveTo",
|
||||
"args": [25, 89.6]
|
||||
}, {
|
||||
"name": "lineTo",
|
||||
"args": [30, 89.6]
|
||||
}, {
|
||||
"name": "moveTo",
|
||||
"args": [30, 89.6]
|
||||
}, {
|
||||
"name": "lineTo",
|
||||
"args": [130, 89.6]
|
||||
}, {
|
||||
"name": "stroke",
|
||||
"args": []
|
||||
}, {
|
||||
"name": "save",
|
||||
"args": []
|
||||
}, {
|
||||
"name": "translate",
|
||||
"args": [20, 89.1]
|
||||
}, {
|
||||
"name": "rotate",
|
||||
"args": [-0]
|
||||
}, {
|
||||
"name": "fillText",
|
||||
"args": ["2", 0, 0]
|
||||
}, {
|
||||
"name": "restore",
|
||||
"args": []
|
||||
}, {
|
||||
"name": "setLineWidth",
|
||||
"args": [1]
|
||||
}, {
|
||||
"name": "setStrokeStyle",
|
||||
"args": ["rgba(0,0,0,0.25)"]
|
||||
}, {
|
||||
"name": "beginPath",
|
||||
"args": []
|
||||
}, {
|
||||
"name": "moveTo",
|
||||
"args": [25, 149]
|
||||
}, {
|
||||
"name": "lineTo",
|
||||
"args": [30, 149]
|
||||
}, {
|
||||
"name": "moveTo",
|
||||
"args": [30, 149]
|
||||
}, {
|
||||
"name": "lineTo",
|
||||
"args": [130, 149]
|
||||
}, {
|
||||
"name": "stroke",
|
||||
"args": []
|
||||
}, {
|
||||
"name": "save",
|
||||
"args": []
|
||||
}, {
|
||||
"name": "translate",
|
||||
"args": [20, 148.5]
|
||||
}, {
|
||||
"name": "rotate",
|
||||
"args": [-0]
|
||||
}, {
|
||||
"name": "fillText",
|
||||
"args": ["0", 0, 0]
|
||||
}, {
|
||||
"name": "restore",
|
||||
"args": []
|
||||
}, {
|
||||
"name": "setLineWidth",
|
||||
"args": [1]
|
||||
}, {
|
||||
"name": "setStrokeStyle",
|
||||
"args": ["rgba(0, 0, 0, 0.1)"]
|
||||
}, {
|
||||
"name": "beginPath",
|
||||
"args": []
|
||||
}, {
|
||||
"name": "moveTo",
|
||||
"args": [25, 208.4]
|
||||
}, {
|
||||
"name": "lineTo",
|
||||
"args": [30, 208.4]
|
||||
}, {
|
||||
"name": "moveTo",
|
||||
"args": [30, 208.4]
|
||||
}, {
|
||||
"name": "lineTo",
|
||||
"args": [130, 208.4]
|
||||
}, {
|
||||
"name": "stroke",
|
||||
"args": []
|
||||
}, {
|
||||
"name": "save",
|
||||
"args": []
|
||||
}, {
|
||||
"name": "translate",
|
||||
"args": [20, 207.9]
|
||||
}, {
|
||||
"name": "rotate",
|
||||
"args": [-0]
|
||||
}, {
|
||||
"name": "fillText",
|
||||
"args": ["-2", 0, 0]
|
||||
}, {
|
||||
"name": "restore",
|
||||
"args": []
|
||||
}, {
|
||||
"name": "beginPath",
|
||||
"args": []
|
||||
}, {
|
||||
"name": "moveTo",
|
||||
"args": [25, 267.8]
|
||||
}, {
|
||||
"name": "lineTo",
|
||||
"args": [30, 267.8]
|
||||
}, {
|
||||
"name": "moveTo",
|
||||
"args": [30, 267.8]
|
||||
}, {
|
||||
"name": "lineTo",
|
||||
"args": [130, 267.8]
|
||||
}, {
|
||||
"name": "stroke",
|
||||
"args": []
|
||||
}, {
|
||||
"name": "save",
|
||||
"args": []
|
||||
}, {
|
||||
"name": "translate",
|
||||
"args": [20, 267.3]
|
||||
}, {
|
||||
"name": "rotate",
|
||||
"args": [-0]
|
||||
}, {
|
||||
"name": "fillText",
|
||||
"args": ["-4", 0, 0]
|
||||
}, {
|
||||
"name": "restore",
|
||||
"args": []
|
||||
}])
|
||||
});
|
||||
});
|
||||
@@ -16,7 +16,7 @@ describe('Logarithmic Scale tests', function() {
|
||||
drawTicks: true,
|
||||
lineWidth: 1,
|
||||
offsetGridLines: false,
|
||||
show: true,
|
||||
display: true,
|
||||
zeroLineColor: "rgba(0,0,0,0.25)",
|
||||
zeroLineWidth: 1,
|
||||
},
|
||||
@@ -27,7 +27,7 @@ describe('Logarithmic Scale tests', function() {
|
||||
fontSize: 12,
|
||||
fontStyle: 'normal',
|
||||
labelString: '',
|
||||
show: false,
|
||||
display: false,
|
||||
},
|
||||
ticks: {
|
||||
beginAtZero: false,
|
||||
@@ -40,7 +40,7 @@ describe('Logarithmic Scale tests', function() {
|
||||
mirror: false,
|
||||
padding: 10,
|
||||
reverse: false,
|
||||
show: true,
|
||||
display: true,
|
||||
callback: defaultConfig.ticks.callback, // make this nicer, then check explicitly below
|
||||
},
|
||||
});
|
||||
@@ -70,7 +70,45 @@ describe('Logarithmic Scale tests', function() {
|
||||
var scale = new Constructor({
|
||||
ctx: mockContext,
|
||||
options: Chart.scaleService.getScaleDefaults('logarithmic'), // use default config for scale
|
||||
data: mockData,
|
||||
chart: {
|
||||
data: mockData,
|
||||
},
|
||||
id: scaleID
|
||||
});
|
||||
|
||||
expect(scale).not.toEqual(undefined); // must construct
|
||||
expect(scale.min).toBe(undefined); // not yet set
|
||||
expect(scale.max).toBe(undefined);
|
||||
|
||||
scale.update(400, 400);
|
||||
expect(scale.min).toBe(1);
|
||||
expect(scale.max).toBe(10000);
|
||||
});
|
||||
|
||||
it('Should correctly determine the max & min of string data values', function() {
|
||||
var scaleID = 'myScale';
|
||||
|
||||
var mockData = {
|
||||
datasets: [{
|
||||
yAxisID: scaleID,
|
||||
data: ['10', '5', '5000', '78', '450']
|
||||
}, {
|
||||
yAxisID: 'second scale',
|
||||
data: ['1', '1000', '10', '100'],
|
||||
}, {
|
||||
yAxisID: scaleID,
|
||||
data: ['150']
|
||||
}]
|
||||
};
|
||||
|
||||
var mockContext = window.createMockContext();
|
||||
var Constructor = Chart.scaleService.getScaleConstructor('logarithmic');
|
||||
var scale = new Constructor({
|
||||
ctx: mockContext,
|
||||
options: Chart.scaleService.getScaleDefaults('logarithmic'), // use default config for scale
|
||||
chart: {
|
||||
data: mockData,
|
||||
},
|
||||
id: scaleID
|
||||
});
|
||||
|
||||
@@ -105,7 +143,9 @@ describe('Logarithmic Scale tests', function() {
|
||||
var scale = new Constructor({
|
||||
ctx: mockContext,
|
||||
options: Chart.scaleService.getScaleDefaults('logarithmic'), // use default config for scale
|
||||
data: mockData,
|
||||
chart: {
|
||||
data: mockData
|
||||
},
|
||||
id: scaleID
|
||||
});
|
||||
|
||||
@@ -147,7 +187,9 @@ describe('Logarithmic Scale tests', function() {
|
||||
var verticalScale = new Constructor({
|
||||
ctx: mockContext,
|
||||
options: config,
|
||||
data: mockData,
|
||||
chart: {
|
||||
data: mockData
|
||||
},
|
||||
id: scaleID
|
||||
});
|
||||
|
||||
@@ -160,7 +202,9 @@ describe('Logarithmic Scale tests', function() {
|
||||
var horizontalScale = new Constructor({
|
||||
ctx: mockContext,
|
||||
options: horizontalConfig,
|
||||
data: mockData,
|
||||
chart: {
|
||||
data: mockData
|
||||
},
|
||||
id: scaleID,
|
||||
});
|
||||
|
||||
@@ -175,13 +219,19 @@ describe('Logarithmic Scale tests', function() {
|
||||
var mockData = {
|
||||
datasets: [{
|
||||
yAxisID: scaleID,
|
||||
data: [10, 5, 1, 5, 78, 100]
|
||||
data: [10, 5, 1, 5, 78, 100],
|
||||
type: 'bar'
|
||||
}, {
|
||||
yAxisID: 'second scale',
|
||||
data: [-1000, 1000],
|
||||
}, {
|
||||
yAxisID: scaleID,
|
||||
data: [150, 10, 10, 100, 10, 9]
|
||||
data: [150, 10, 10, 100, 10, 9],
|
||||
type: 'bar'
|
||||
}, {
|
||||
yAxisID: scaleID,
|
||||
data: [100, 100, 100, 100, 100, 100],
|
||||
type: 'line'
|
||||
}]
|
||||
};
|
||||
|
||||
@@ -193,7 +243,9 @@ describe('Logarithmic Scale tests', function() {
|
||||
var scale = new Constructor({
|
||||
ctx: mockContext,
|
||||
options: config,
|
||||
data: mockData,
|
||||
chart: {
|
||||
data: mockData
|
||||
},
|
||||
id: scaleID
|
||||
});
|
||||
|
||||
@@ -208,17 +260,21 @@ describe('Logarithmic Scale tests', function() {
|
||||
var mockData = {
|
||||
datasets: [{
|
||||
yAxisID: scaleID,
|
||||
data: [10, 5, 1, 5, 78, 100]
|
||||
data: [10, 5, 1, 5, 78, 100],
|
||||
type: 'bar'
|
||||
}, {
|
||||
yAxisID: 'second scale',
|
||||
data: [-1000, 1000],
|
||||
type: 'bar'
|
||||
}, {
|
||||
yAxisID: scaleID,
|
||||
data: [150, 10, 10, 100, 10, 9]
|
||||
data: [150, 10, 10, 100, 10, 9],
|
||||
type: 'bar'
|
||||
}, {
|
||||
yAxisID: scaleID,
|
||||
data: [10000, 10000, 10000, 10000, 10000, 10000],
|
||||
hidden: true
|
||||
hidden: true,
|
||||
type: 'bar'
|
||||
}]
|
||||
};
|
||||
|
||||
@@ -230,7 +286,9 @@ describe('Logarithmic Scale tests', function() {
|
||||
var scale = new Constructor({
|
||||
ctx: mockContext,
|
||||
options: config,
|
||||
data: mockData,
|
||||
chart: {
|
||||
data: mockData
|
||||
},
|
||||
id: scaleID
|
||||
});
|
||||
|
||||
@@ -252,7 +310,9 @@ describe('Logarithmic Scale tests', function() {
|
||||
var scale = new Constructor({
|
||||
ctx: mockContext,
|
||||
options: config,
|
||||
data: mockData,
|
||||
chart: {
|
||||
data: mockData
|
||||
},
|
||||
id: scaleID
|
||||
});
|
||||
|
||||
@@ -285,7 +345,9 @@ describe('Logarithmic Scale tests', function() {
|
||||
var scale = new Constructor({
|
||||
ctx: {},
|
||||
options: config,
|
||||
data: mockData,
|
||||
chart: {
|
||||
data: mockData
|
||||
},
|
||||
id: scaleID
|
||||
});
|
||||
|
||||
@@ -318,7 +380,9 @@ describe('Logarithmic Scale tests', function() {
|
||||
var scale = new Constructor({
|
||||
ctx: {},
|
||||
options: config,
|
||||
data: mockData,
|
||||
chart: {
|
||||
data: mockData
|
||||
},
|
||||
id: scaleID
|
||||
});
|
||||
|
||||
@@ -350,7 +414,9 @@ describe('Logarithmic Scale tests', function() {
|
||||
var scale = new Constructor({
|
||||
ctx: mockContext,
|
||||
options: config,
|
||||
data: mockData,
|
||||
chart: {
|
||||
data: mockData
|
||||
},
|
||||
id: scaleID
|
||||
});
|
||||
|
||||
@@ -379,7 +445,9 @@ describe('Logarithmic Scale tests', function() {
|
||||
var scale = new Constructor({
|
||||
ctx: mockContext,
|
||||
options: config,
|
||||
data: mockData,
|
||||
chart: {
|
||||
data: mockData
|
||||
},
|
||||
id: scaleID
|
||||
});
|
||||
|
||||
@@ -406,7 +474,9 @@ describe('Logarithmic Scale tests', function() {
|
||||
var verticalScale = new Constructor({
|
||||
ctx: mockContext,
|
||||
options: config,
|
||||
data: mockData,
|
||||
chart: {
|
||||
data: mockData
|
||||
},
|
||||
id: scaleID
|
||||
});
|
||||
|
||||
@@ -431,7 +501,9 @@ describe('Logarithmic Scale tests', function() {
|
||||
var horizontalScale = new Constructor({
|
||||
ctx: mockContext,
|
||||
options: horizontalConfig,
|
||||
data: mockData,
|
||||
chart: {
|
||||
data: mockData
|
||||
},
|
||||
id: scaleID,
|
||||
});
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ describe('Test the radial linear scale', function() {
|
||||
var defaultConfig = Chart.scaleService.getScaleDefaults('radialLinear');
|
||||
expect(defaultConfig).toEqual({
|
||||
angleLines: {
|
||||
show: true,
|
||||
display: true,
|
||||
color: "rgba(0, 0, 0, 0.1)",
|
||||
lineWidth: 1
|
||||
},
|
||||
@@ -22,7 +22,7 @@ describe('Test the radial linear scale', function() {
|
||||
drawTicks: true,
|
||||
lineWidth: 1,
|
||||
offsetGridLines: false,
|
||||
show: true,
|
||||
display: true,
|
||||
zeroLineColor: "rgba(0,0,0,0.25)",
|
||||
zeroLineWidth: 1,
|
||||
},
|
||||
@@ -40,7 +40,7 @@ describe('Test the radial linear scale', function() {
|
||||
fontSize: 12,
|
||||
fontStyle: 'normal',
|
||||
labelString: '',
|
||||
show: false,
|
||||
display: false,
|
||||
},
|
||||
ticks: {
|
||||
backdropColor: "rgba(255,255,255,0.75)",
|
||||
@@ -57,7 +57,7 @@ describe('Test the radial linear scale', function() {
|
||||
padding: 10,
|
||||
reverse: false,
|
||||
showLabelBackdrop: true,
|
||||
show: true,
|
||||
display: true,
|
||||
callback: defaultConfig.ticks.callback, // make this nicer, then check explicitly below
|
||||
|
||||
},
|
||||
@@ -86,7 +86,39 @@ describe('Test the radial linear scale', function() {
|
||||
var scale = new Constructor({
|
||||
ctx: mockContext,
|
||||
options: Chart.scaleService.getScaleDefaults('radialLinear'), // use default config for scale
|
||||
data: mockData,
|
||||
chart: {
|
||||
data: mockData
|
||||
},
|
||||
id: scaleID,
|
||||
});
|
||||
|
||||
scale.update(200, 300);
|
||||
expect(scale.min).toBe(-100);
|
||||
expect(scale.max).toBe(200);
|
||||
});
|
||||
|
||||
it('Should correctly determine the max & min of string data values', function() {
|
||||
var scaleID = 'myScale';
|
||||
|
||||
var mockData = {
|
||||
datasets: [{
|
||||
yAxisID: scaleID,
|
||||
data: ['10', '5', '0', '-5', '78', '-100']
|
||||
}, {
|
||||
yAxisID: scaleID,
|
||||
data: ['150']
|
||||
}],
|
||||
labels: ['lablel1', 'label2', 'label3', 'label4', 'label5', 'label6']
|
||||
};
|
||||
|
||||
var mockContext = window.createMockContext();
|
||||
var Constructor = Chart.scaleService.getScaleConstructor('radialLinear');
|
||||
var scale = new Constructor({
|
||||
ctx: mockContext,
|
||||
options: Chart.scaleService.getScaleDefaults('radialLinear'), // use default config for scale
|
||||
chart: {
|
||||
data: mockData
|
||||
},
|
||||
id: scaleID,
|
||||
});
|
||||
|
||||
@@ -118,7 +150,9 @@ describe('Test the radial linear scale', function() {
|
||||
var scale = new Constructor({
|
||||
ctx: mockContext,
|
||||
options: Chart.scaleService.getScaleDefaults('radialLinear'), // use default config for scale
|
||||
data: mockData,
|
||||
chart: {
|
||||
data: mockData
|
||||
},
|
||||
id: scaleID,
|
||||
});
|
||||
|
||||
@@ -140,7 +174,9 @@ describe('Test the radial linear scale', function() {
|
||||
var scale = new Constructor({
|
||||
ctx: mockContext,
|
||||
options: Chart.scaleService.getScaleDefaults('radialLinear'), // use default config for scale
|
||||
data: mockData,
|
||||
chart: {
|
||||
data: mockData
|
||||
},
|
||||
id: scaleID,
|
||||
});
|
||||
|
||||
@@ -166,7 +202,9 @@ describe('Test the radial linear scale', function() {
|
||||
var scale = new Constructor({
|
||||
ctx: mockContext,
|
||||
options: config,
|
||||
data: mockData,
|
||||
chart: {
|
||||
data: mockData
|
||||
},
|
||||
id: scaleID,
|
||||
});
|
||||
|
||||
@@ -205,7 +243,9 @@ describe('Test the radial linear scale', function() {
|
||||
var scale = new Constructor({
|
||||
ctx: mockContext,
|
||||
options: config,
|
||||
data: mockData,
|
||||
chart: {
|
||||
data: mockData
|
||||
},
|
||||
id: scaleID,
|
||||
});
|
||||
|
||||
@@ -238,7 +278,9 @@ describe('Test the radial linear scale', function() {
|
||||
var scale = new Constructor({
|
||||
ctx: mockContext,
|
||||
options: config,
|
||||
data: mockData,
|
||||
chart: {
|
||||
data: mockData
|
||||
},
|
||||
id: scaleID,
|
||||
});
|
||||
|
||||
@@ -265,7 +307,9 @@ describe('Test the radial linear scale', function() {
|
||||
var scale = new Constructor({
|
||||
ctx: mockContext,
|
||||
options: config,
|
||||
data: mockData,
|
||||
chart: {
|
||||
data: mockData
|
||||
},
|
||||
id: scaleID,
|
||||
});
|
||||
|
||||
@@ -297,7 +341,9 @@ describe('Test the radial linear scale', function() {
|
||||
var scale = new Constructor({
|
||||
ctx: mockContext,
|
||||
options: config,
|
||||
data: mockData,
|
||||
chart: {
|
||||
data: mockData
|
||||
},
|
||||
id: scaleID,
|
||||
});
|
||||
|
||||
@@ -340,7 +386,9 @@ describe('Test the radial linear scale', function() {
|
||||
var scale = new Constructor({
|
||||
ctx: mockContext,
|
||||
options: config,
|
||||
data: mockData,
|
||||
chart: {
|
||||
data: mockData
|
||||
},
|
||||
id: scaleID,
|
||||
});
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ describe('Time scale tests', function() {
|
||||
drawTicks: true,
|
||||
lineWidth: 1,
|
||||
offsetGridLines: false,
|
||||
show: true,
|
||||
display: true,
|
||||
zeroLineColor: "rgba(0,0,0,0.25)",
|
||||
zeroLineWidth: 1,
|
||||
},
|
||||
@@ -32,7 +32,7 @@ describe('Time scale tests', function() {
|
||||
fontSize: 12,
|
||||
fontStyle: 'normal',
|
||||
labelString: '',
|
||||
show: false,
|
||||
display: false,
|
||||
},
|
||||
ticks: {
|
||||
beginAtZero: false,
|
||||
@@ -45,7 +45,7 @@ describe('Time scale tests', function() {
|
||||
mirror: false,
|
||||
padding: 10,
|
||||
reverse: false,
|
||||
show: true,
|
||||
display: true,
|
||||
callback: defaultConfig.ticks.callback, // make this nicer, then check explicitly below
|
||||
},
|
||||
time: {
|
||||
@@ -53,6 +53,17 @@ describe('Time scale tests', function() {
|
||||
unit: false,
|
||||
round: false,
|
||||
displayFormat: false,
|
||||
displayFormats: {
|
||||
'millisecond': 'SSS [ms]',
|
||||
'second': 'h:mm:ss a', // 11:20:01 AM
|
||||
'minute': 'h:mm:ss a', // 11:20:01 AM
|
||||
'hour': 'MMM D, hA', // Sept 4, 5PM
|
||||
'day': 'll', // Sep 4 2015
|
||||
'week': 'll', // Week 46, or maybe "[W]WW - YYYY" ?
|
||||
'month': 'MMM YYYY', // Sept 2015
|
||||
'quarter': '[Q]Q - YYYY', // Q3
|
||||
'year': 'YYYY', // 2015
|
||||
},
|
||||
}
|
||||
});
|
||||
|
||||
@@ -72,7 +83,9 @@ describe('Time scale tests', function() {
|
||||
var scale = new Constructor({
|
||||
ctx: mockContext,
|
||||
options: Chart.scaleService.getScaleDefaults('time'), // use default config for scale
|
||||
data: mockData,
|
||||
chart: {
|
||||
data: mockData
|
||||
},
|
||||
id: scaleID
|
||||
});
|
||||
|
||||
@@ -97,7 +110,9 @@ describe('Time scale tests', function() {
|
||||
var scale = new Constructor({
|
||||
ctx: mockContext,
|
||||
options: config, // use default config for scale
|
||||
data: mockData,
|
||||
chart: {
|
||||
data: mockData
|
||||
},
|
||||
id: scaleID
|
||||
});
|
||||
|
||||
@@ -121,7 +136,9 @@ describe('Time scale tests', function() {
|
||||
var scale = new Constructor({
|
||||
ctx: mockContext,
|
||||
options: config, // use default config for scale
|
||||
data: mockData,
|
||||
chart: {
|
||||
data: mockData
|
||||
},
|
||||
id: scaleID
|
||||
});
|
||||
|
||||
@@ -145,7 +162,9 @@ describe('Time scale tests', function() {
|
||||
var scale = new Constructor({
|
||||
ctx: mockContext,
|
||||
options: Chart.scaleService.getScaleDefaults('time'), // use default config for scale
|
||||
data: mockData,
|
||||
chart: {
|
||||
data: mockData
|
||||
},
|
||||
id: scaleID
|
||||
});
|
||||
|
||||
@@ -168,7 +187,9 @@ describe('Time scale tests', function() {
|
||||
var verticalScale = new Constructor({
|
||||
ctx: mockContext,
|
||||
options: verticalScaleConfig,
|
||||
data: mockData,
|
||||
chart: {
|
||||
data: mockData
|
||||
},
|
||||
id: scaleID
|
||||
});
|
||||
verticalScale.update(50, 400);
|
||||
|
||||
Referência em uma Nova Issue
Bloquear um usuário