Comparar commits
323 Commits
| Autor | SHA1 | Data | |
|---|---|---|---|
| 669499ef1e | |||
| d46a174080 | |||
| 0c91bb96e0 | |||
| 9e9f436454 | |||
| cbd2fef80f | |||
| 996e471171 | |||
| 70f7dd4c7d | |||
| 9c106aa8ff | |||
| 7dcee4b40e | |||
| f12d1bcb56 | |||
| b9ab70f21b | |||
| c2d6e4c31f | |||
| a6c712323f | |||
| b93306788b | |||
| 2a62e0e04d | |||
| 8e5d8b8861 | |||
| 8b0b6194b2 | |||
| 675a9f827e | |||
| 235247eb12 | |||
| b3b5896329 | |||
| ecb1cde3fc | |||
| 9be48a73ea | |||
| 7e791e02f2 | |||
| 06d55e3501 | |||
| 37cfbdb802 | |||
| 8d1a857e75 | |||
| 42e2c237d4 | |||
| b22e1e3e9c | |||
| 635ec58616 | |||
| f44dd06826 | |||
| 02d7442e4f | |||
| 4ded634d75 | |||
| 80a25af502 | |||
| 9b2d2efc7a | |||
| 6b0e609935 | |||
| 74d3890ba9 | |||
| df4d2d2594 | |||
| b7dc2339f4 | |||
| edbb235668 | |||
| 92776ce0ac | |||
| e48c7f168b | |||
| 8a550852da | |||
| 6af94298ec | |||
| 1163efbcca | |||
| 3a32144d89 | |||
| e3519f5bd4 | |||
| 7d8b1712a7 | |||
| 54b51038ca | |||
| e774a893da | |||
| b03a057a76 | |||
| 48dd1cf024 | |||
| a2d477ac5e | |||
| 1352dfeb0f | |||
| d4e7765a50 | |||
| 73b579c962 | |||
| b67afcd727 | |||
| a10e245e5a | |||
| 181e866175 | |||
| d998c803d3 | |||
| a559ab85cd | |||
| c66edc9169 | |||
| b7606c7a8d | |||
| 12e2ace039 | |||
| ed4b9945f8 | |||
| 951e714e77 | |||
| 008bb1aab3 | |||
| 4cc24d475a | |||
| 4b8c9bc30d | |||
| 978ed1bc1e | |||
| 676765e808 | |||
| f2065265c8 | |||
| a6e2eec9e0 | |||
| 2e383da0d8 | |||
| e30a9d2a94 | |||
| 492292e94b | |||
| 454f519b6d | |||
| 56d53e3ad4 | |||
| 67b3d32218 | |||
| d7ad5b6340 | |||
| db1365c8ce | |||
| b5b0081108 | |||
| fff81c455d | |||
| ad972a0c5c | |||
| 872c92cd4b | |||
| 1d8d19d404 | |||
| ed6f234205 | |||
| 09c11440dd | |||
| e58421a08a | |||
| fb580a6e48 | |||
| f79ebdaa88 | |||
| b432a3d6db | |||
| ef4c46f2be | |||
| 69b1239aa1 | |||
| 4ef57315da | |||
| d26f37236d | |||
| 63e115e7a8 | |||
| 9f98334d6f | |||
| 15f724f146 | |||
| afb22d15ae | |||
| e709b13e77 | |||
| 460399f651 | |||
| 132272d140 | |||
| 9e4d90e110 | |||
| df91739b77 | |||
| d3f7071983 | |||
| d287a01b44 | |||
| 0eadc86d24 | |||
| c7b117631b | |||
| 0e29cfdfda | |||
| cf07df07d6 | |||
| 4e3dd8ae3f | |||
| 4b34bbadf9 | |||
| cc57b9e581 | |||
| aad966820e | |||
| 5443886ec3 | |||
| a8063de6b8 | |||
| e13ada2b43 | |||
| 62b29282fd | |||
| 2814c8e44c | |||
| 7f513b87ee | |||
| a3d4bc0bfe | |||
| e67d198e69 | |||
| b5692c8534 | |||
| 2e311896ad | |||
| 8cc5be1212 | |||
| b0a780822a | |||
| a932442d26 | |||
| 889c9de779 | |||
| e69aa04918 | |||
| c7f52f516c | |||
| 8c641d21d8 | |||
| 9605409838 | |||
| 604d6bd4e3 | |||
| 14f4fae786 | |||
| c476db0dd7 | |||
| 0a5f92a854 | |||
| b1cbf04f25 | |||
| 70b8bf106c | |||
| 99bf85e913 | |||
| e0c208be58 | |||
| 26eca23706 | |||
| 98253fea5d | |||
| 9a13dd78fc | |||
| 3e59438646 | |||
| 7a6f2b4f06 | |||
| a417dd00c5 | |||
| eee5af5924 | |||
| d3579334b2 | |||
| 0b8fd966ff | |||
| 972bc5636d | |||
| 44ed661e3b | |||
| 4009dbd6a0 | |||
| 2677360f4b | |||
| e461788b2b | |||
| f7ed97a33e | |||
| fc0434b3da | |||
| 1408c68205 | |||
| 53bc8e769f | |||
| b5f73e2087 | |||
| cb113c6452 | |||
| 8e5f1d9667 | |||
| 47d23601b1 | |||
| 212d513746 | |||
| 3e6883bdc0 | |||
| ae7552a916 | |||
| 930b16a0af | |||
| 78d9627e4d | |||
| 785f0b64b7 | |||
| d2b73bdc5b | |||
| 4b120ccbe9 | |||
| 1fd52e702c | |||
| de564326b0 | |||
| 154ce016cc | |||
| 5d8df20b0d | |||
| 24248120a9 | |||
| 019e985c8f | |||
| ff493738a2 | |||
| 5ea265983e | |||
| c09cac1cdd | |||
| afd2631728 | |||
| 4b09072c2a | |||
| b865fd317a | |||
| bb6237a15e | |||
| b8b7c85c5e | |||
| 5ec66308e4 | |||
| 9c6a7397b5 | |||
| 87b7f8070a | |||
| 2d28075cde | |||
| 2e0211320b | |||
| 8244dd1271 | |||
| 654e02763f | |||
| 0c1c9824b2 | |||
| 63b14dde15 | |||
| 6f6f80e6d7 | |||
| 13396c72b3 | |||
| a5550cef6b | |||
| 0f49be56a4 | |||
| b9776736d4 | |||
| 9ab36291a9 | |||
| 657e53c117 | |||
| dc2ebab883 | |||
| 82571710c6 | |||
| 06adbb0c54 | |||
| d051dfe47f | |||
| 06b02e9c33 | |||
| 8b3a98f242 | |||
| 026611110a | |||
| 092b011f9b | |||
| 8a027f49a4 | |||
| 359e94151c | |||
| 02f858b264 | |||
| bdb49e6396 | |||
| 05dbcd3a72 | |||
| 64de3eb711 | |||
| 854cebc59c | |||
| 74c9ef50c2 | |||
| 85f3755f9a | |||
| 7aa867cf24 | |||
| 5d4e7cebea | |||
| ed3e47f560 | |||
| d48979526f | |||
| 329ad3cdce | |||
| 84e859b6c5 | |||
| 81d4f97abc | |||
| 2e4bb1899f | |||
| c9878b8434 | |||
| 453310a338 | |||
| 9af5d0c9d6 | |||
| 7626dcf14e | |||
| b4df89fcd1 | |||
| 8c41c5c1b7 | |||
| cfc4599a30 | |||
| 8c1e9588a1 | |||
| 70c3672963 | |||
| f4a5f67f7c | |||
| 80e972c351 | |||
| d320ce6eaf | |||
| 7e97aa3300 | |||
| 102c069d74 | |||
| d8353c2b9a | |||
| 932908532c | |||
| 718dcd1a2b | |||
| f81d6f45e1 | |||
| 8522d4e60e | |||
| 211850add2 | |||
| aa96a3f33a | |||
| ac05a62000 | |||
| f18b7ebd57 | |||
| a7712e8c71 | |||
| 71bf3c8ee5 | |||
| 1900c3b0f3 | |||
| 73faf3413b | |||
| fdc9be3e23 | |||
| 7e21cb4e04 | |||
| 8984e8c2c4 | |||
| 686ea49953 | |||
| ae9eaa95c7 | |||
| e21147cbb9 | |||
| 98c1ac439d | |||
| 337511110c | |||
| 5ab5e8400a | |||
| 7eabb70130 | |||
| ae65fde3e9 | |||
| 27a121c6b2 | |||
| 1cfa42bc24 | |||
| 401ff95867 | |||
| ccc85c80d1 | |||
| 61b525a645 | |||
| a406fdae58 | |||
| a3daf1ca24 | |||
| 2ef91b1c78 | |||
| 5282c63ec3 | |||
| 0a59a3c4df | |||
| 47cf4f4814 | |||
| e6cbd9dc7f | |||
| f825a31ce4 | |||
| 53c4cd5ce1 | |||
| 8b840ce56b | |||
| 7eec283d70 | |||
| 10a9ef46cb | |||
| 179d80a93b | |||
| 48f10196f6 | |||
| bd25b5c7fd | |||
| 09c0f3308c | |||
| 30777e4a87 | |||
| 14e72759ee | |||
| d47e600f1a | |||
| 5bd10297fb | |||
| 55a115179e | |||
| 92e73bd28a | |||
| ebc955f562 | |||
| 5683c11ebd | |||
| 61467e107f | |||
| adf6f3abb2 | |||
| 22c50b0aba | |||
| edb245b649 | |||
| 16cf465575 | |||
| 997a216b50 | |||
| d193951dc5 | |||
| c37c58ad39 | |||
| 529d582f03 | |||
| aa7975e4f7 | |||
| fdfa9912e8 | |||
| 2f59921f7a | |||
| e25fd5e37c | |||
| 5d0171e8ed | |||
| 55fc0cfd49 | |||
| cdfdc3c3e2 | |||
| ef5081184f | |||
| 02e535cdad | |||
| 3e1b120cbe | |||
| 95844701bd | |||
| 403b6751ab | |||
| 2b81ac832a | |||
| 3f9e5ab7a2 | |||
| 23deaa9307 | |||
| 2183d09b58 | |||
| ea9d144c71 | |||
| 7a23131366 | |||
| d7632efe65 | |||
| 477e09f1d4 | |||
| 0a6c892766 | |||
| 51032692f3 |
@@ -5,3 +5,5 @@ node_modules/*
|
||||
custom/*
|
||||
|
||||
docs/index.md
|
||||
|
||||
bower_components/
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
language: node_js
|
||||
node_js:
|
||||
- "0.11"
|
||||
- "0.10"
|
||||
|
||||
before_script:
|
||||
- npm install
|
||||
|
||||
script:
|
||||
- gulp test
|
||||
|
||||
notifications:
|
||||
slack: chartjs:pcfCZR6ugg5TEcaLtmIfQYuA
|
||||
@@ -0,0 +1,55 @@
|
||||
Contributing to Chart.js
|
||||
========================
|
||||
|
||||
Contributions to Chart.js are welcome and encouraged, but please have a look through the guidelines in this document before raising an issue, or writing code for the project.
|
||||
|
||||
|
||||
Using issues
|
||||
------------
|
||||
|
||||
The [issue tracker](https://github.com/nnnick/Chart.js/issues) is the preferred channel for reporting bugs, requesting new features and submitting pull requests.
|
||||
|
||||
If you're suggesting a new chart type, please take a look at [writing new chart types](https://github.com/nnnick/Chart.js/blob/master/docs/06-Advanced.md#writing-new-chart-types) in the documentation, and some of the [community extensions](https://github.com/nnnick/Chart.js/blob/master/docs/06-Advanced.md#community-extensions) that have been created already.
|
||||
|
||||
To keep the library lightweight for everyone, it's unlikely we'll add many more chart types to the core of Chart.js, but issues are a good medium to design and spec out how new chart types could work and look.
|
||||
|
||||
Please do not use issues for support requests. For help using Chart.js, please take a look at the [`chartjs`](http://stackoverflow.com/questions/tagged/chartjs) tag on Stack Overflow.
|
||||
|
||||
|
||||
Reporting bugs
|
||||
--------------
|
||||
|
||||
Well structured, detailed bug reports are hugely valuable for the project.
|
||||
|
||||
Guidlines for reporting bugs:
|
||||
|
||||
- Check the issue search to see if it has already been reported
|
||||
- Isolate the problem to a simple test case
|
||||
- Provide a demonstration of the problem on [JS Bin](http://jsbin.com) or similar
|
||||
|
||||
Please provide any additional details associated with the bug, if it's browser or screen density specific, or only happens with a certain configuration or data.
|
||||
|
||||
|
||||
Pull requests
|
||||
-------------
|
||||
|
||||
Clear, concise pull requests are excellent at continuing the project's community driven growth. But please review [these guidelines](https://github.com/blog/1943-how-to-write-the-perfect-pull-request) and the guidelines below before starting work on the project.
|
||||
|
||||
Guidlines:
|
||||
|
||||
- Please create an issue first:
|
||||
- For bugs, we can discuss the fixing approach
|
||||
- For enhancements, we can discuss if it is within the project scope and avoid duplicate effort
|
||||
- Please make changes to the files in [`/src`](https://github.com/nnnick/Chart.js/tree/master/src), not `Chart.js` or `Chart.min.js` in the repo root directory, this avoids merge conflicts
|
||||
- Tabs for indentation, not spaces please
|
||||
- If adding new functionality, please also update the relevant `.md` file in [`/docs`](https://github.com/nnnick/Chart.js/tree/master/docs)
|
||||
- Please make your commits in logical sections with clear commit messages
|
||||
|
||||
Joining the Project
|
||||
-------------
|
||||
- Active committers and contributors are invited to introduce yourself and request commit access to this project. Please send an email to hello@nickdownie.com or file an issue.
|
||||
|
||||
License
|
||||
-------
|
||||
|
||||
By contributing your code, you agree to license your contribution under the [MIT license](https://github.com/nnnick/Chart.js/blob/master/LICENSE.md).
|
||||
externo
+5974
-3077
Diff do arquivo suprimido porque uma ou mais linhas são muito longas
externo
+7
-3
Diff do arquivo suprimido porque uma ou mais linhas são muito longas
+1
-1
@@ -1,4 +1,4 @@
|
||||
Copyright (c) 2013 Nick Downie
|
||||
Copyright (c) 2013-2015 Nick Downie
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
# Chart.js
|
||||
|
||||
[](https://travis-ci.org/nnnick/Chart.js) [](https://codeclimate.com/github/nnnick/Chart.js)
|
||||
|
||||
# Version 2.0 is in early alpha. We are changing the internal data model to reduce copying, increase performance and expose a more flexible API.
|
||||
|
||||
*Simple HTML5 Charts using the canvas element* [chartjs.org](http://www.chartjs.org)
|
||||
|
||||
## Documentation
|
||||
|
||||
You can find documentation at [chartjs.org/docs](http://www.chartjs.org/docs/). The markdown files that build the site are available under `/docs`. Please note - in some of the json examples of configuration you might notice some liquid tags - this is just for the generating the site html, please disregard.
|
||||
|
||||
## Bugs, issues and contributing
|
||||
|
||||
Before submitting an issue or a pull request to the project, please take a moment to look over the [contributing guidelines](https://github.com/nnnick/Chart.js/blob/master/CONTRIBUTING.md) first.
|
||||
|
||||
For support using Chart.js, please post questions with the [`chartjs` tag on Stack Overflow](http://stackoverflow.com/questions/tagged/chartjs).
|
||||
|
||||
## License
|
||||
|
||||
Chart.js is available under the [MIT license](http://opensource.org/licenses/MIT).
|
||||
+12
-9
@@ -1,10 +1,13 @@
|
||||
{
|
||||
"name": "Chart.js",
|
||||
"version": "1.0.1-beta",
|
||||
"description": "Simple HTML5 Charts using the canvas element",
|
||||
"homepage": "https://github.com/nnnick/Chart.js",
|
||||
"author": "nnnick",
|
||||
"main": ["Chart.min.js"],
|
||||
"dependencies": {
|
||||
}
|
||||
}
|
||||
"name": "Chart.js",
|
||||
"version": "2.0.0-alpha",
|
||||
"description": "Simple HTML5 Charts using the canvas element",
|
||||
"homepage": "https://github.com/nnnick/Chart.js",
|
||||
"author": "nnnick",
|
||||
"main": [
|
||||
"Chart.js"
|
||||
],
|
||||
"devDependencies": {
|
||||
"jquery": "~2.1.4"
|
||||
}
|
||||
}
|
||||
|
||||
+172
-82
@@ -28,9 +28,13 @@ require(['path/to/Chartjs'], function(Chart){
|
||||
You can also grab Chart.js using bower:
|
||||
|
||||
```bash
|
||||
bower install chartjs --save
|
||||
bower install Chart.js --save
|
||||
```
|
||||
|
||||
Also, Chart.js is available from CDN:
|
||||
|
||||
https://cdnjs.com/libraries/chart.js
|
||||
|
||||
###Creating a chart
|
||||
|
||||
To create a chart, we need to instantiate the `Chart` class. To do this, we need to pass in the 2d context of where we want to draw the chart. Here's an example.
|
||||
@@ -70,121 +74,207 @@ This concept was introduced in Chart.js 1.0 to keep configuration DRY, and allow
|
||||
|
||||
```javascript
|
||||
Chart.defaults.global = {
|
||||
// Boolean - Whether to animate the chart
|
||||
animation: true,
|
||||
// Animation settings
|
||||
animation: {
|
||||
// Length that animation should take in ms assuming 60fps.
|
||||
// Set to 0 to disable animation
|
||||
duration: 1000,
|
||||
|
||||
// Number - Number of animation steps
|
||||
animationSteps: 60,
|
||||
// Easing type. Possible values are:
|
||||
// [easeInOutQuart, linear, easeOutBounce, easeInBack, easeInOutQuad,
|
||||
// easeOutQuart, easeOutQuad, easeInOutBounce, easeOutSine, easeInOutCubic,
|
||||
// easeInExpo, easeInOutBack, easeInCirc, easeInOutElastic, easeOutBack,
|
||||
// easeInQuad, easeInOutExpo, easeInQuart, easeOutQuint, easeInOutCirc,
|
||||
// easeInSine, easeOutExpo, easeOutCirc, easeOutCubic, easeInQuint,
|
||||
// easeInElastic, easeInOutSine, easeInOutQuint, easeInBounce,
|
||||
// easeOutElastic, easeInCubic]
|
||||
easing: "easeOutQuart",
|
||||
|
||||
// String - Animation easing effect
|
||||
animationEasing: "easeOutQuart",
|
||||
// Function - function to call each time an animation step occurs
|
||||
onProgress: function() {},
|
||||
|
||||
// Boolean - If we should show the scale at all
|
||||
showScale: true,
|
||||
// Function - function to call when animations finish
|
||||
onComplete: function() {},
|
||||
},
|
||||
|
||||
// Boolean - If we want to override with a hard coded scale
|
||||
scaleOverride: false,
|
||||
// Boolean - if true, resize the charts when the page resizes
|
||||
responsive: false,
|
||||
|
||||
// ** Required if scaleOverride is true **
|
||||
// Number - The number of steps in a hard coded scale
|
||||
scaleSteps: null,
|
||||
// Number - The value jump in the hard coded scale
|
||||
scaleStepWidth: null,
|
||||
// Number - The scale starting value
|
||||
scaleStartValue: null,
|
||||
// Boolean - if true, try to maintain the screen aspect ratio
|
||||
maintainAspectRatio: true,
|
||||
|
||||
// String - Colour of the scale line
|
||||
scaleLineColor: "rgba(0,0,0,.1)",
|
||||
// Array - events to bind tooltips to
|
||||
events: ["mousemove", "mouseout", "click", "touchstart", "touchmove", "touchend"],
|
||||
|
||||
// Number - Pixel width of the scale line
|
||||
scaleLineWidth: 1,
|
||||
// Hover settings
|
||||
hover: {
|
||||
// Function - called when the user hovers over the items.
|
||||
// Parameters: array of active elements
|
||||
onHover: null,
|
||||
|
||||
// Boolean - Whether to show labels on the scale
|
||||
scaleShowLabels: true,
|
||||
// String - hover mode. Options are 'single', 'label', and 'dataset'
|
||||
// 'single' gets the nearest element
|
||||
// 'label' gets all of the elements at the given dataset index (do not use for scatter charts)
|
||||
// 'dataset' gets all the elements in the given dataset
|
||||
mode: 'single',
|
||||
|
||||
// Interpolated JS string - can access value
|
||||
scaleLabel: "<%=value%>",
|
||||
// Number - duration (in ms) of the tooltip animation. 0 to disable
|
||||
animationDuration: 400,
|
||||
},
|
||||
|
||||
// Boolean - Whether the scale should stick to integers, not floats even if drawing space is there
|
||||
scaleIntegersOnly: true,
|
||||
// Function - click handler to bind to chart area
|
||||
onClick: null,
|
||||
|
||||
// Boolean - Whether the scale should start at zero, or an order of magnitude down from the lowest value
|
||||
scaleBeginAtZero: false,
|
||||
// Tooltip configuration
|
||||
tooltips: {
|
||||
// Boolean - if true show tooltips
|
||||
enabled: true,
|
||||
|
||||
// String - Scale label font declaration for the scale label
|
||||
scaleFontFamily: "'Helvetica Neue', 'Helvetica', 'Arial', sans-serif",
|
||||
// Function - custom tooltip function to use
|
||||
custom: null,
|
||||
|
||||
// Number - Scale label font size in pixels
|
||||
scaleFontSize: 12,
|
||||
// String - color of tooltip background
|
||||
backgroundColor: "rgba(0,0,0,0.8)",
|
||||
|
||||
// String - Scale label font weight style
|
||||
scaleFontStyle: "normal",
|
||||
// String - fonts to use
|
||||
fontFamily: "'Helvetica Neue', 'Helvetica', 'Arial', sans-serif",
|
||||
|
||||
// String - Scale label font colour
|
||||
scaleFontColor: "#666",
|
||||
// Number - font size
|
||||
fontSize: 10,
|
||||
|
||||
// Boolean - whether or not the chart should be responsive and resize when the browser does.
|
||||
responsive: false,
|
||||
// String - font style
|
||||
fontStyle: "normal",
|
||||
|
||||
// Boolean - Determines whether to draw tooltips on the canvas or not
|
||||
showTooltips: true,
|
||||
// String - font color
|
||||
fontColor: "#fff",
|
||||
|
||||
// Array - Array of string names to attach tooltip events
|
||||
tooltipEvents: ["mousemove", "touchstart", "touchmove"],
|
||||
// String - title fonts
|
||||
titleFontFamily: "'Helvetica Neue', 'Helvetica', 'Arial', sans-serif",
|
||||
|
||||
// String - Tooltip background colour
|
||||
tooltipFillColor: "rgba(0,0,0,0.8)",
|
||||
// Number - title font size
|
||||
titleFontSize: 12,
|
||||
|
||||
// String - Tooltip label font declaration for the scale label
|
||||
tooltipFontFamily: "'Helvetica Neue', 'Helvetica', 'Arial', sans-serif",
|
||||
// String - title font style
|
||||
titleFontStyle: "bold",
|
||||
|
||||
// Number - Tooltip label font size in pixels
|
||||
tooltipFontSize: 14,
|
||||
// String - title font color
|
||||
titleFontColor: "#fff",
|
||||
|
||||
// String - Tooltip font weight style
|
||||
tooltipFontStyle: "normal",
|
||||
// Number -
|
||||
yPadding: 6,
|
||||
|
||||
// String - Tooltip label font colour
|
||||
tooltipFontColor: "#fff",
|
||||
// Number -
|
||||
xPadding: 6,
|
||||
|
||||
// String - Tooltip title font declaration for the scale label
|
||||
tooltipTitleFontFamily: "'Helvetica Neue', 'Helvetica', 'Arial', sans-serif",
|
||||
// Number -
|
||||
caretSize: 8,
|
||||
|
||||
// Number - Tooltip title font size in pixels
|
||||
tooltipTitleFontSize: 14,
|
||||
// Number - radius of rounded corners
|
||||
cornerRadius: 6,
|
||||
|
||||
// String - Tooltip title font weight style
|
||||
tooltipTitleFontStyle: "bold",
|
||||
// Number -
|
||||
xOffset: 10,
|
||||
|
||||
// String - Tooltip title font colour
|
||||
tooltipTitleFontColor: "#fff",
|
||||
// String - template string to use for tooltips in single mode
|
||||
template: [
|
||||
'<% if(label){ %>',
|
||||
'<%=label %>:',
|
||||
'<% } %>',
|
||||
'<%=value %>',
|
||||
].join(''),
|
||||
|
||||
// Number - pixel width of padding around tooltip text
|
||||
tooltipYPadding: 6,
|
||||
// String - template string to use for tooltips in label mode
|
||||
multiTemplate: [
|
||||
'<%if (datasetLabel){ %>',
|
||||
'<%=datasetLabel %>:',
|
||||
'<% } %>',
|
||||
'<%=value %>'
|
||||
].join(''),
|
||||
|
||||
// Number - pixel width of padding around tooltip text
|
||||
tooltipXPadding: 6,
|
||||
// String -
|
||||
multiKeyBackground: '#fff',
|
||||
},
|
||||
|
||||
// Number - Size of the caret on the tooltip
|
||||
tooltipCaretSize: 8,
|
||||
// String - default grey color. 'rgba(0,0,0,0.1)'
|
||||
defaultColor: defaultColor,
|
||||
|
||||
// Number - Pixel radius of the tooltip border
|
||||
tooltipCornerRadius: 6,
|
||||
// Element defaults
|
||||
elements: {
|
||||
// Default settings for all line elements
|
||||
line: {
|
||||
// Number - Bezier curve tension. Set to 0 for no bezier curves
|
||||
tension: 0.4,
|
||||
|
||||
// Number - Pixel offset from point x to tooltip edge
|
||||
tooltipXOffset: 10,
|
||||
{% raw %}
|
||||
// String - Template string for single tooltips
|
||||
tooltipTemplate: "<%if (label){%><%=label%>: <%}%><%= value %>",
|
||||
{% endraw %}
|
||||
// String - Template string for single tooltips
|
||||
multiTooltipTemplate: "<%= value %>",
|
||||
// String - the fill color
|
||||
backgroundColor: defaultColor,
|
||||
|
||||
// Function - Will fire on animation progression.
|
||||
onAnimationProgress: function(){},
|
||||
// Number - width of the line
|
||||
borderWidth: 3,
|
||||
|
||||
// Function - Will fire on animation completion.
|
||||
onAnimationComplete: function(){}
|
||||
// String = color of the line
|
||||
borderColor: defaultColor,
|
||||
|
||||
// Boolean - if true fill in the area between the line and the x axis with the background color
|
||||
fill: true,
|
||||
|
||||
// Boolean -
|
||||
skipNull: true,
|
||||
|
||||
// Boolean -
|
||||
drawNull: false,
|
||||
},
|
||||
// Settings for all point elements
|
||||
point: {
|
||||
// Number - radius of point circle
|
||||
radius: 3,
|
||||
|
||||
// String - fill color of point
|
||||
backgroundColor: defaultColor,
|
||||
|
||||
// Number - width of stroke of point circle
|
||||
borderWidth: 1,
|
||||
|
||||
// String - stroke color for point
|
||||
borderColor: defaultColor,
|
||||
|
||||
// Number - extra radius added to radius for hit detection
|
||||
hitRadius: 6,
|
||||
|
||||
// Number - radius of point circle when hovered
|
||||
hoverRadius: 4,
|
||||
|
||||
// Number - radius of circle stroke when hovered
|
||||
hoverBorderWidth: 2,
|
||||
},
|
||||
// Settings for all bar elements
|
||||
bar: {
|
||||
// String - fill color of bar
|
||||
backgroundColor: defaultColor,
|
||||
|
||||
// Number - width of stroke of line surrounding bar fill
|
||||
borderWidth: 0,
|
||||
|
||||
// String - Border color
|
||||
borderColor: defaultColor,
|
||||
|
||||
// Number -
|
||||
valueSpacing: 5,
|
||||
|
||||
// Number -
|
||||
datasetSpacing: 1,
|
||||
},
|
||||
// Settings for all slice elements
|
||||
slice: {
|
||||
// String - fill color
|
||||
backgroundColor: defaultColor,
|
||||
|
||||
// String - border color
|
||||
borderColor: "#fff",
|
||||
|
||||
// Number - border stroke width
|
||||
borderWidth: 2,
|
||||
},
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
+192
-46
@@ -13,7 +13,10 @@ Often, it is used to show trend data, and the comparison of two data sets.
|
||||
|
||||
###Example usage
|
||||
```javascript
|
||||
var myLineChart = new Chart(ctx).Line(data, options);
|
||||
var myLineChart = new Chart(ctx).Line({
|
||||
data: data,
|
||||
options: options
|
||||
});
|
||||
```
|
||||
###Data structure
|
||||
|
||||
@@ -23,22 +26,57 @@ 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)",
|
||||
data: [65, 59, 80, 81, 56, 55, 40]
|
||||
|
||||
// Boolean - if true fill the area under the line
|
||||
fill: false,
|
||||
|
||||
// String - the color to fill the area under the line with if fill is true
|
||||
backgroundColor: "rgba(220,220,220,0.2)",
|
||||
|
||||
// The properties below allow an array to be specified to change the value of the item at the given index
|
||||
|
||||
// String or array - Line color
|
||||
borderColor: "rgba(220,220,220,1)",
|
||||
|
||||
// String or array - Point stroke color
|
||||
pointBorderColor: "rgba(220,220,220,1)",
|
||||
|
||||
// String or array - Point fill color
|
||||
pointBackgroundColor: "#fff",
|
||||
|
||||
// Number or array - Stroke width of point border
|
||||
pointBorderWidth: 1,
|
||||
|
||||
// Number or array - Radius of point when hovered
|
||||
pointHoverRadius: 5,
|
||||
|
||||
// String or array - point background color when hovered
|
||||
pointHoverBackgroundColor: "rgba(220,220,220,1)",
|
||||
|
||||
// Point border color when hovered
|
||||
pointHoverBorderColor: "rgba(220,220,220,1)",
|
||||
|
||||
// Number or array - border width of point when hovered
|
||||
pointBorderWidth: 2,
|
||||
|
||||
// The actual data
|
||||
data: [65, 59, 80, 81, 56, 55, 40],
|
||||
|
||||
// String - If specified, binds the dataset to a certain y-axis. If not specified, the first y-axis is used.
|
||||
yAxisID: "y-axis-1",
|
||||
},
|
||||
{
|
||||
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)",
|
||||
fill: false,
|
||||
backgroundColor: "rgba(220,220,220,0.2)",
|
||||
borderColor: "rgba(220,220,220,1)",
|
||||
pointBorderColor: "rgba(220,220,220,1)",
|
||||
pointBackgroundColor: "#fff",
|
||||
pointBorderWidth: 1,
|
||||
pointHoverRadius: 5,
|
||||
pointHoverBackgroundColor: "rgba(220,220,220,1)",
|
||||
pointHoverBorderColor: "rgba(220,220,220,1)",
|
||||
pointBorderWidth: 2,
|
||||
data: [28, 48, 40, 19, 86, 27, 90]
|
||||
}
|
||||
]
|
||||
@@ -56,56 +94,164 @@ These are the customisation options specific to Line charts. These options are m
|
||||
|
||||
```javascript
|
||||
{
|
||||
// Boolean - if true, line stack on top of each other along the y axis
|
||||
stacked: false,
|
||||
|
||||
///Boolean - Whether grid lines are shown across the chart
|
||||
scaleShowGridLines : true,
|
||||
hover: {
|
||||
// String - We use a label hover mode since the x axis displays data by the index in the dataset
|
||||
mode: "label"
|
||||
},
|
||||
|
||||
//String - Colour of the grid lines
|
||||
scaleGridLineColor : "rgba(0,0,0,.05)",
|
||||
scales: {
|
||||
// The line 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'. To use a 'linear' axis on the x, use the scatter chart type
|
||||
scaleType: "dataset", // scatter should not use a dataset axis
|
||||
|
||||
//Number - Width of the grid lines
|
||||
scaleGridLineWidth : 1,
|
||||
// Boolean - if true, show the scale
|
||||
display: true,
|
||||
|
||||
//Boolean - Whether the line is curved between points
|
||||
bezierCurve : true,
|
||||
// String - position of the scale. possible options are "top" and "bottom" for dataset scales
|
||||
position: "bottom",
|
||||
|
||||
//Number - Tension of the bezier curve between points
|
||||
bezierCurveTension : 0.4,
|
||||
// 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
|
||||
|
||||
//Boolean - Whether to show a dot for each point
|
||||
pointDot : true,
|
||||
// grid line settings
|
||||
gridLines: {
|
||||
// Boolean - if true, show the grid lines
|
||||
show: true,
|
||||
|
||||
//Number - Radius of each point dot in pixels
|
||||
pointDotRadius : 4,
|
||||
// String - color of the grid lines
|
||||
color: "rgba(0, 0, 0, 0.05)",
|
||||
|
||||
//Number - Pixel width of point dot stroke
|
||||
pointDotStrokeWidth : 1,
|
||||
// Number - width of the grid lines
|
||||
lineWidth: 1,
|
||||
|
||||
//Number - amount extra to add to the radius to cater for hit detection outside the drawn point
|
||||
pointHitDetectionRadius : 20,
|
||||
// Boolean - if true draw lines on the chart area
|
||||
drawOnChartArea: true,
|
||||
|
||||
//Boolean - Whether to show a stroke for datasets
|
||||
datasetStroke : true,
|
||||
// Boolean - if true draw ticks in the axis area
|
||||
drawTicks: true,
|
||||
|
||||
//Number - Pixel width of dataset stroke
|
||||
datasetStrokeWidth : 2,
|
||||
// Number - width of the grid line for the first index (index 0)
|
||||
zeroLineWidth: 1,
|
||||
|
||||
//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].lineColor%>\"></span><%if(datasets[i].label){%><%=datasets[i].label%><%}%></li><%}%></ul>"
|
||||
{% endraw %}
|
||||
// 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",
|
||||
},
|
||||
}],
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
You can override these for your `Chart` instance by passing a second argument into the `Line` method as an object with the keys you want to override.
|
||||
You can override these for your `Chart` instance by passing a member `options` into the `Line` method.
|
||||
|
||||
For example, we could have a line chart without bezier curves between points by doing the following:
|
||||
For example, we could have a line chart display without an x axis by doing the following. The config merge is smart enough to handle arrays so that you do not need to specify all axis settings to change one thing.
|
||||
|
||||
```javascript
|
||||
new Chart(ctx).Line(data, {
|
||||
bezierCurve: false
|
||||
new Chart(ctx).Line({
|
||||
data: data,
|
||||
options: {
|
||||
xAxes: [{
|
||||
show: false
|
||||
}]
|
||||
}
|
||||
});
|
||||
// This will create a chart with all of the default options, merged from the global config,
|
||||
// and the Line chart defaults, but this particular instance will have `bezierCurve` set to false.
|
||||
|
||||
+174
-34
@@ -14,7 +14,10 @@ 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, options);
|
||||
var myBarChart = new Chart(ctx).Bar({
|
||||
data: data,
|
||||
options: options
|
||||
});
|
||||
```
|
||||
|
||||
### Data structure
|
||||
@@ -25,18 +28,36 @@ var data = {
|
||||
datasets: [
|
||||
{
|
||||
label: "My First dataset",
|
||||
fillColor: "rgba(220,220,220,0.5)",
|
||||
strokeColor: "rgba(220,220,220,0.8)",
|
||||
highlightFill: "rgba(220,220,220,0.75)",
|
||||
highlightStroke: "rgba(220,220,220,1)",
|
||||
data: [65, 59, 80, 81, 56, 55, 40]
|
||||
|
||||
// The properties below allow an array to be specified to change the value of the item at the given index
|
||||
// String or array - the bar color
|
||||
backgroundColor: "rgba(220,220,220,0.2)",
|
||||
|
||||
// String or array - bar stroke color
|
||||
borderColor: "rgba(220,220,220,1)",
|
||||
|
||||
// Number or array - bar border width
|
||||
borderWidth: 1,
|
||||
|
||||
// String or array - fill color when hovered
|
||||
hoverBackgroundColor: "rgba(220,220,220,0.2)",
|
||||
|
||||
// String or array - border color when hovered
|
||||
hoverBorderColor: "rgba(220,220,220,1)",
|
||||
|
||||
// The actual data
|
||||
data: [65, 59, 80, 81, 56, 55, 40],
|
||||
|
||||
// String - If specified, binds the dataset to a certain y-axis. If not specified, the first y-axis is used.
|
||||
yAxisID: "y-axis-1",
|
||||
},
|
||||
{
|
||||
label: "My Second dataset",
|
||||
fillColor: "rgba(151,187,205,0.5)",
|
||||
strokeColor: "rgba(151,187,205,0.8)",
|
||||
highlightFill: "rgba(151,187,205,0.75)",
|
||||
highlightStroke: "rgba(151,187,205,1)",
|
||||
backgroundColor: "rgba(220,220,220,0.2)",
|
||||
borderColor: "rgba(220,220,220,1)",
|
||||
borderWidth: 1,
|
||||
hoverBackgroundColor: "rgba(220,220,220,0.2)",
|
||||
hoverBorderColor: "rgba(220,220,220,1)",
|
||||
data: [28, 48, 40, 19, 86, 27, 90]
|
||||
}
|
||||
]
|
||||
@@ -53,34 +74,150 @@ These are the customisation options specific to Bar charts. These options are me
|
||||
|
||||
```javascript
|
||||
{
|
||||
//Boolean - Whether the scale should start at zero, or an order of magnitude down from the lowest value
|
||||
scaleBeginAtZero : true,
|
||||
// Boolean - if true, bars stack on top of each other
|
||||
stacked: false,
|
||||
|
||||
//Boolean - Whether grid lines are shown across the chart
|
||||
scaleShowGridLines : true,
|
||||
hover: {
|
||||
// String - We use a label hover mode since the x axis displays data by the index in the dataset
|
||||
mode: "label"
|
||||
},
|
||||
|
||||
//String - Colour of the grid lines
|
||||
scaleGridLineColor : "rgba(0,0,0,.05)",
|
||||
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
|
||||
|
||||
//Number - Width of the grid lines
|
||||
scaleGridLineWidth : 1,
|
||||
// Boolean - if true, show the scale
|
||||
display: true,
|
||||
|
||||
//Boolean - If there is a stroke on each bar
|
||||
barShowStroke : true,
|
||||
// String - position of the scale. possible options are "top" and "bottom" for dataset scales
|
||||
position: "bottom",
|
||||
|
||||
//Number - Pixel width of the bar stroke
|
||||
barStrokeWidth : 2,
|
||||
// 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
|
||||
|
||||
//Number - Spacing between each of the X value sets
|
||||
barValueSpacing : 5,
|
||||
// grid line settings
|
||||
gridLines: {
|
||||
// Boolean - if true, show the grid lines
|
||||
show: true,
|
||||
|
||||
//Number - Spacing between data sets within X values
|
||||
barDatasetSpacing : 1,
|
||||
{% 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].lineColor%>\"></span><%if(datasets[i].label){%><%=datasets[i].label%><%}%></li><%}%></ul>"
|
||||
{% endraw %}
|
||||
}
|
||||
// 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",
|
||||
},
|
||||
}],
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
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.
|
||||
@@ -88,8 +225,11 @@ You can override these for your `Chart` instance by passing a second argument in
|
||||
For example, we could have a bar chart without a stroke on each bar by doing the following:
|
||||
|
||||
```javascript
|
||||
new Chart(ctx).Bar(data, {
|
||||
barShowStroke: false
|
||||
new Chart(ctx).Bar({
|
||||
data: data,
|
||||
options: {
|
||||
barShowStroke: false
|
||||
}
|
||||
});
|
||||
// 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.
|
||||
@@ -140,4 +280,4 @@ Calling `removeData()` on your Chart instance will remove the first value for al
|
||||
```javascript
|
||||
myBarChart.removeData();
|
||||
// The chart will now animate and remove the first bar
|
||||
```
|
||||
```
|
||||
|
||||
@@ -110,7 +110,7 @@ These are the customisation options specific to Radar charts. These options are
|
||||
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].lineColor%>\"></span><%if(datasets[i].label){%><%=datasets[i].label%><%}%></li><%}%></ul>"
|
||||
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 %}
|
||||
}
|
||||
```
|
||||
|
||||
@@ -83,7 +83,7 @@ These are the customisation options specific to Polar Area charts. These options
|
||||
//Boolean - Stroke a line around each segment in the chart
|
||||
segmentShowStroke : true,
|
||||
|
||||
//String - The colour of the stroke on each segement.
|
||||
//String - The colour of the stroke on each segment.
|
||||
segmentStrokeColor : "#fff",
|
||||
|
||||
//Number - The width of the stroke value in pixels
|
||||
@@ -169,4 +169,4 @@ Calling `removeData(index)` on your Chart instance will remove segment at that p
|
||||
```javascript
|
||||
myPolarAreaChart.removeData();
|
||||
// Other segments will update to fill the empty space left.
|
||||
```
|
||||
```
|
||||
|
||||
@@ -3,11 +3,11 @@ title: Pie & Doughnut Charts
|
||||
anchor: doughnut-pie-chart
|
||||
---
|
||||
###Introduction
|
||||
Pie and doughnut charts are probably the most commonly used chart there are. They are divided into segments, the arc of each segment shows a the proportional value of each piece of data.
|
||||
Pie and doughnut charts are probably the most commonly used chart there are. They are divided into segments, the arc of each segment shows the proportional value of each piece of data.
|
||||
|
||||
They are excellent at showing the relational proportions between data.
|
||||
|
||||
Pie and doughnut charts in are effectively the same class in Chart.js, but have one different default value - their `percentageInnerCutout`. This equates what percentage of the inner should be cut out. This defaults to `0` for pie charts, and `50` for doughnuts.
|
||||
Pie and doughnut charts are effectively the same class in Chart.js, but have one different default value - their `percentageInnerCutout`. This equates what percentage of the inner should be cut out. This defaults to `0` for pie charts, and `50` for doughnuts.
|
||||
|
||||
They are also registered under two aliases in the `Chart` core. Other than their different default value, and different alias, they are exactly the same.
|
||||
|
||||
@@ -55,7 +55,7 @@ var data = [
|
||||
]
|
||||
```
|
||||
|
||||
For a pie chart, you must pass in an array of objects with a value and a 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.
|
||||
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.
|
||||
|
||||
### Chart options
|
||||
|
||||
@@ -104,13 +104,13 @@ new Chart(ctx).Doughnut(data, {
|
||||
// and the Doughnut chart defaults but this particular instance will have `animateScale` set to `true`.
|
||||
```
|
||||
|
||||
We can also change these defaults values for each Doughnut type that is created, this object is available at `Chart.defaults.Doughnut`. Pie charts also have a clone of these defaults available to change at `Chart.defaults.Pie`, with the only difference being `percentageInnerCutout` being set to 0.
|
||||
We can also change these default values for each Doughnut type that is created, this object is available at `Chart.defaults.Doughnut`. Pie charts also have a clone of these defaults available to change at `Chart.defaults.Pie`, with the only difference being `percentageInnerCutout` being set to 0.
|
||||
|
||||
### Prototype methods
|
||||
|
||||
#### .getSegmentsAtEvent( event )
|
||||
|
||||
Calling `getSegmentsAtEvent(event)` on your Chart instance passing an argument of an event, or jQuery event, will return the segment elements that are at that the same position of that event.
|
||||
Calling `getSegmentsAtEvent(event)` on your Chart instance passing an argument of an event, or jQuery event, will return the segment elements that are at the same position of that event.
|
||||
|
||||
```javascript
|
||||
canvas.onclick = function(evt){
|
||||
@@ -135,7 +135,7 @@ myDoughnutChart.update();
|
||||
|
||||
#### .addData( segmentData, index )
|
||||
|
||||
Calling `addData(segmentData, index)` on your Chart instance passing an object in the same format as in the constructor. There is an option second argument of 'index', this determines at what index the new segment should be inserted into the chart.
|
||||
Calling `addData(segmentData, index)` on your Chart instance passing an object in the same format as in the constructor. There is an optional second argument of 'index', this determines at what index the new segment should be inserted into the chart.
|
||||
|
||||
```javascript
|
||||
// An object in the same format as the original data source
|
||||
@@ -155,4 +155,4 @@ Calling `removeData(index)` on your Chart instance will remove segment at that p
|
||||
```javascript
|
||||
myDoughnutChart.removeData();
|
||||
// Other segments will update to fill the empty space left.
|
||||
```
|
||||
```
|
||||
|
||||
@@ -70,6 +70,39 @@ myLineChart.generateLegend();
|
||||
// => returns HTML string of a legend for this chart
|
||||
```
|
||||
|
||||
### External Tooltips
|
||||
|
||||
You can enable custom tooltips in the global or chart configuration like so:
|
||||
|
||||
```javascript
|
||||
var myPieChart = new Chart(ctx).Pie(data, {
|
||||
customTooltips: function(tooltip) {
|
||||
|
||||
// tooltip will be false if tooltip is not visible or should be hidden
|
||||
if (!tooltip) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Otherwise, tooltip will be an object with all tooltip properties like:
|
||||
|
||||
// tooltip.caretHeight
|
||||
// tooltip.caretPadding
|
||||
// tooltip.chart
|
||||
// tooltip.cornerRadius
|
||||
// tooltip.fillColor
|
||||
// tooltip.font...
|
||||
// tooltip.text
|
||||
// tooltip.x
|
||||
// tooltip.y
|
||||
// etc...
|
||||
|
||||
};
|
||||
});
|
||||
```
|
||||
|
||||
See files `sample/pie-customTooltips.html` and `sample/line-customTooltips.html` for examples on how to get started.
|
||||
|
||||
|
||||
### Writing new chart types
|
||||
|
||||
Chart.js 1.0 has been rewritten to provide a platform for developers to create their own custom chart types, and be able to share and utilise them through the Chart.js API.
|
||||
@@ -92,6 +125,9 @@ Chart.Type.extend({
|
||||
initialize: function(data){
|
||||
this.chart.ctx // The drawing context for this chart
|
||||
this.chart.canvas // the canvas node for this chart
|
||||
},
|
||||
// Used to draw something on the canvas
|
||||
draw: function() {
|
||||
}
|
||||
});
|
||||
|
||||
@@ -120,6 +156,13 @@ new Chart(ctx).LineAlt(data);
|
||||
// but this logs 'My Line chart extension' in the console.
|
||||
```
|
||||
|
||||
### Community extensions
|
||||
|
||||
- <a href="https://github.com/Regaddi/Chart.StackedBar.js" target="_blank">Stacked Bar Chart</a> by <a href="https://twitter.com/Regaddi" target="_blank">@Regaddi</a>
|
||||
- <a href="https://github.com/tannerlinsley/Chart.StackedArea.js" target="_blank">Stacked Bar Chart</a> by <a href="https://twitter.com/tannerlinsley" target="_blank">@tannerlinsley</a>
|
||||
- <a href="https://github.com/CAYdenberg/Chart.js" target="_blank">Error bars (bar and line charts)</a> by <a href="https://twitter.com/CAYdenberg" target="_blank">@CAYdenberg</a>
|
||||
- <a href="http://dima117.github.io/Chart.Scatter/" target="_blank">Scatter chart (number & date scales are supported)</a> by <a href="https://github.com/dima117" target="_blank">@dima117</a>
|
||||
|
||||
### Creating custom builds
|
||||
|
||||
Chart.js uses <a href="http://gulpjs.com/" target="_blank">gulp</a> to build the library into a single JavaScript file. We can use this same build script with custom parameters in order to build a custom version.
|
||||
|
||||
+57
-6
@@ -5,7 +5,14 @@ var gulp = require('gulp'),
|
||||
jshint = require('gulp-jshint'),
|
||||
size = require('gulp-size'),
|
||||
connect = require('gulp-connect'),
|
||||
exec = require('child_process').exec;
|
||||
replace = require('gulp-replace'),
|
||||
htmlv = require('gulp-html-validator'),
|
||||
inquirer = require('inquirer'),
|
||||
semver = require('semver'),
|
||||
exec = require('child_process').exec,
|
||||
fs = require('fs'),
|
||||
package = require('./package.json'),
|
||||
bower = require('./bower.json');
|
||||
|
||||
var srcDir = './src/';
|
||||
/*
|
||||
@@ -21,15 +28,18 @@ gulp.task('build', function(){
|
||||
isCustom = !!(util.env.types),
|
||||
outputDir = (isCustom) ? 'custom' : '.';
|
||||
if (isCustom){
|
||||
util.env.types.split(',').forEach(function(type){ return srcFiles.push(FileName(type))});
|
||||
util.env.types.split(',').forEach(function(type){ return srcFiles.push(FileName(type));});
|
||||
}
|
||||
else{
|
||||
// Seems gulp-concat remove duplicates - nice!
|
||||
// So we can use this to sort out dependency order - aka include Core first!
|
||||
srcFiles.push(srcDir+'*');
|
||||
}
|
||||
srcFiles.push('./node_modules/color/dist/color.min.js');
|
||||
|
||||
return gulp.src(srcFiles)
|
||||
.pipe(concat('Chart.js'))
|
||||
.pipe(replace('{{ version }}', package.version))
|
||||
.pipe(gulp.dest(outputDir))
|
||||
.pipe(uglify({preserveComments:'some'}))
|
||||
.pipe(concat('Chart.min.js'))
|
||||
@@ -37,7 +47,43 @@ gulp.task('build', function(){
|
||||
|
||||
function FileName(moduleName){
|
||||
return srcDir+'Chart.'+moduleName+'.js';
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
/*
|
||||
* Usage : gulp bump
|
||||
* Prompts: Version increment to bump
|
||||
* Output: - New version number written into package.json & bower.json
|
||||
*/
|
||||
|
||||
gulp.task('bump', function(complete){
|
||||
util.log('Current version:', util.colors.cyan(package.version));
|
||||
var choices = ['major', 'premajor', 'minor', 'preminor', 'patch', 'prepatch', 'prerelease'].map(function(versionType){
|
||||
return versionType + ' (v' + semver.inc(package.version, versionType) + ')';
|
||||
});
|
||||
inquirer.prompt({
|
||||
type: 'list',
|
||||
name: 'version',
|
||||
message: 'What version update would you like?',
|
||||
choices: choices
|
||||
}, function(res){
|
||||
var increment = res.version.split(' ')[0],
|
||||
newVersion = semver.inc(package.version, increment);
|
||||
|
||||
// Set the new versions into the bower/package object
|
||||
package.version = newVersion;
|
||||
bower.version = newVersion;
|
||||
|
||||
// Write these to their own files, then build the output
|
||||
fs.writeFileSync('package.json', JSON.stringify(package, null, 2));
|
||||
fs.writeFileSync('bower.json', JSON.stringify(bower, null, 2));
|
||||
|
||||
complete();
|
||||
});
|
||||
});
|
||||
|
||||
gulp.task('release', ['build'], function(){
|
||||
exec('git tag -a v' + package.version);
|
||||
});
|
||||
|
||||
gulp.task('jshint', function(){
|
||||
@@ -46,6 +92,11 @@ gulp.task('jshint', function(){
|
||||
.pipe(jshint.reporter('default'));
|
||||
});
|
||||
|
||||
gulp.task('valid', function(){
|
||||
return gulp.src('samples/*.html')
|
||||
.pipe(htmlv());
|
||||
});
|
||||
|
||||
gulp.task('library-size', function(){
|
||||
return gulp.src('Chart.min.js')
|
||||
.pipe(size({
|
||||
@@ -59,14 +110,14 @@ gulp.task('module-sizes', function(){
|
||||
.pipe(size({
|
||||
showFiles: true,
|
||||
gzip: true
|
||||
}))
|
||||
}));
|
||||
});
|
||||
|
||||
gulp.task('watch', function(){
|
||||
gulp.watch('./src/*', ['build']);
|
||||
});
|
||||
|
||||
gulp.task('test', ['jshint']);
|
||||
gulp.task('test', ['jshint', 'valid']);
|
||||
|
||||
gulp.task('size', ['library-size', 'module-sizes']);
|
||||
|
||||
@@ -74,7 +125,7 @@ gulp.task('default', ['build', 'watch']);
|
||||
|
||||
gulp.task('server', function(){
|
||||
connect.server({
|
||||
port: 8000,
|
||||
port: 8000
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
+29
-18
@@ -1,20 +1,31 @@
|
||||
{
|
||||
"name": "Chart.js",
|
||||
"homepage": "http://www.chartjs.org",
|
||||
"description": "Simple HTML5 charts using the canvas element.",
|
||||
"version": "1.0.1-beta",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/nnnick/Chart.js.git"
|
||||
},
|
||||
"dependences": {},
|
||||
"devDependencies": {
|
||||
"gulp": "3.5.x",
|
||||
"gulp-concat": "~2.1.x",
|
||||
"gulp-uglify": "~0.2.x",
|
||||
"gulp-util": "~2.2.x",
|
||||
"gulp-jshint": "~1.5.1",
|
||||
"gulp-size": "~0.4.0",
|
||||
"gulp-connect": "~2.0.5"
|
||||
}
|
||||
"name": "chart.js",
|
||||
"homepage": "http://www.chartjs.org",
|
||||
"description": "Simple HTML5 charts using the canvas element.",
|
||||
"version": "2.0.0-alpha",
|
||||
"main": "Chart.js",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/nnnick/Chart.js.git"
|
||||
},
|
||||
"dependences": {},
|
||||
"devDependencies": {
|
||||
"color": "git://github.com/chartjs/color",
|
||||
"gulp": "3.5.x",
|
||||
"gulp-concat": "~2.1.x",
|
||||
"gulp-connect": "~2.0.5",
|
||||
"gulp-html-validator": "^0.0.2",
|
||||
"gulp-jshint": "~1.5.1",
|
||||
"gulp-replace": "^0.4.0",
|
||||
"gulp-size": "~0.4.0",
|
||||
"gulp-uglify": "~0.2.x",
|
||||
"gulp-util": "~2.2.x",
|
||||
"inquirer": "^0.5.1",
|
||||
"jquery": "^2.1.4",
|
||||
"onecolor": "^2.5.0",
|
||||
"semver": "^3.0.1"
|
||||
},
|
||||
"spm": {
|
||||
"main": "Chart.js"
|
||||
}
|
||||
}
|
||||
|
||||
-25
@@ -1,25 +0,0 @@
|
||||
# Chart.js
|
||||
|
||||
*Simple HTML5 Charts using the canvas element* [chartjs.org](http://www.chartjs.org)
|
||||
|
||||
## Documentation
|
||||
|
||||
You can find documentation at [chartjs.org/docs](http://www.chartjs.org/docs). The markdown files that build the site are available under `/docs`. Please note - in some of the json examples of configuration you might notice some liquid tags - this is just for the generating the site html, please disregard.
|
||||
|
||||
## License
|
||||
|
||||
Chart.js is available under the [MIT license](http://opensource.org/licenses/MIT).
|
||||
|
||||
## Bugs & issues
|
||||
|
||||
When reporting bugs or issues, if you could include a link to a simple [jsbin](http://jsbin.com) or similar demonstrating the issue, that'd be really helpful.
|
||||
|
||||
|
||||
## Contributing
|
||||
New contributions to the library are welcome, just a couple of guidelines:
|
||||
|
||||
- Tabs for indentation, not spaces please.
|
||||
- Please ensure you're changing the individual files in `/src`, not the concatenated output in the `Chart.js` file in the root of the repo.
|
||||
- Please check that your code will pass `jshint` code standards, `gulp jshint` will run this for you.
|
||||
- Please keep pull requests concise, and document new functionality in the relevant `.md` file.
|
||||
- Consider whether your changes are useful for all users, or if creating a Chart.js extension would be more appropriate.
|
||||
@@ -0,0 +1,140 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>Bar Chart Multi Axis</title>
|
||||
<script src="../node_modules/jquery/dist/jquery.min.js"></script>
|
||||
<script src="../Chart.js"></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div style="width: 50%">
|
||||
<canvas id="canvas" height="450" width="600"></canvas>
|
||||
</div>
|
||||
<button id="randomizeData">Randomize Data</button>
|
||||
<script>
|
||||
var randomScalingFactor = function() {
|
||||
return (Math.random() > 0.5 ? 1.0 : -1.0) * Math.round(Math.random() * 100);
|
||||
};
|
||||
var randomColorFactor = function() {
|
||||
return Math.round(Math.random() * 255);
|
||||
};
|
||||
var randomColor = function() {
|
||||
return 'rgba(' + randomColorFactor() + ',' + randomColorFactor() + ',' + randomColorFactor() + ',.7)';
|
||||
};
|
||||
|
||||
var barChartData = {
|
||||
labels: ["January", "February", "March", "April", "May", "June", "July"],
|
||||
datasets: [{
|
||||
label: 'Dataset 1',
|
||||
backgroundColor: "rgba(220,220,220,0.5)",
|
||||
yAxisID: "y-axis-1",
|
||||
data: [randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()]
|
||||
}, {
|
||||
label: 'Dataset 2',
|
||||
backgroundColor: "rgba(151,187,205,0.5)",
|
||||
yAxisID: "y-axis-2",
|
||||
data: [randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()]
|
||||
}, {
|
||||
label: 'Dataset 3',
|
||||
backgroundColor: [randomColor(), randomColor(), randomColor(), randomColor(), randomColor(), randomColor(), randomColor()],
|
||||
yAxisID: "y-axis-1",
|
||||
data: [randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()]
|
||||
}]
|
||||
|
||||
};
|
||||
window.onload = function() {
|
||||
var ctx = document.getElementById("canvas").getContext("2d");
|
||||
window.myBar = new Chart(ctx).Bar({
|
||||
data: barChartData,
|
||||
options: {
|
||||
responsive: true,
|
||||
hoverMode: 'label',
|
||||
hoverAnimationDuration: 400,
|
||||
stacked: false,
|
||||
scales: {
|
||||
yAxes: [{
|
||||
scaleType: "linear", // only linear but allow scale type registration. This allows extensions to exist solely for log scale for instance
|
||||
display: true,
|
||||
position: "left",
|
||||
id: "y-axis-1",
|
||||
|
||||
// grid line settings
|
||||
gridLines: {
|
||||
show: true,
|
||||
color: "rgba(0, 0, 0, 0.05)",
|
||||
lineWidth: 1,
|
||||
drawOnChartArea: true,
|
||||
drawTicks: true,
|
||||
zeroLineWidth: 1,
|
||||
zeroLineColor: "rgba(0,0,0,0.25)",
|
||||
},
|
||||
|
||||
// scale numbers
|
||||
beginAtZero: false,
|
||||
integersOnly: false,
|
||||
override: null,
|
||||
|
||||
// label settings
|
||||
labels: {
|
||||
show: true,
|
||||
template: "<%=value%>",
|
||||
fontSize: 12,
|
||||
fontStyle: "normal",
|
||||
fontColor: "#666",
|
||||
fontFamily: "Helvetica Neue",
|
||||
}
|
||||
}, {
|
||||
scaleType: "linear", // only linear but allow scale type registration. This allows extensions to exist solely for log scale for instance
|
||||
display: true,
|
||||
position: "right",
|
||||
id: "y-axis-2",
|
||||
|
||||
// grid line settings
|
||||
gridLines: {
|
||||
show: true,
|
||||
color: "rgba(0, 0, 0, 0.05)",
|
||||
lineWidth: 1,
|
||||
drawOnChartArea: false, // only want the grid lines for one axis to show up
|
||||
drawTicks: false,
|
||||
zeroLineWidth: 1,
|
||||
zeroLineColor: "rgba(0,0,0,0.25)",
|
||||
},
|
||||
|
||||
// scale numbers
|
||||
beginAtZero: false,
|
||||
integersOnly: false,
|
||||
override: null,
|
||||
|
||||
// label settings
|
||||
labels: {
|
||||
show: true,
|
||||
template: "<%=value%>",
|
||||
fontSize: 12,
|
||||
fontStyle: "normal",
|
||||
fontColor: "#666",
|
||||
fontFamily: "Helvetica Neue",
|
||||
}
|
||||
}],
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
$('#randomizeData').click(function() {
|
||||
$.each(barChartData.datasets, function(i, dataset) {
|
||||
if (Chart.helpers.isArray(dataset.backgroundColor)) {
|
||||
dataset.backgroundColor= [randomColor(), randomColor(), randomColor(), randomColor(), randomColor(), randomColor(), randomColor()];
|
||||
} else {
|
||||
dataset.backgroundColor= randomColor();
|
||||
}
|
||||
|
||||
dataset.data = [randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()];
|
||||
|
||||
});
|
||||
window.myBar.update();
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
+53
-37
@@ -1,45 +1,61 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Bar Chart</title>
|
||||
<script src="../Chart.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div style="width: 50%">
|
||||
<canvas id="canvas" height="450" width="600"></canvas>
|
||||
</div>
|
||||
|
||||
<head>
|
||||
<title>Bar Chart</title>
|
||||
<script src="../node_modules/jquery/dist/jquery.min.js"></script>
|
||||
<script src="../Chart.js"></script>
|
||||
</head>
|
||||
|
||||
<script>
|
||||
var randomScalingFactor = function(){ return Math.round(Math.random()*100)};
|
||||
<body>
|
||||
<div style="width: 50%">
|
||||
<canvas id="canvas" height="450" width="600"></canvas>
|
||||
</div>
|
||||
<button id="randomizeData">Randomize Data</button>
|
||||
<script>
|
||||
var randomScalingFactor = function() {
|
||||
return (Math.random() > 0.5 ? 1.0 : -1.0) * Math.round(Math.random() * 100);
|
||||
};
|
||||
var randomColorFactor = function() {
|
||||
return Math.round(Math.random() * 255);
|
||||
};
|
||||
|
||||
var barChartData = {
|
||||
labels : ["January","February","March","April","May","June","July"],
|
||||
datasets : [
|
||||
{
|
||||
fillColor : "rgba(220,220,220,0.5)",
|
||||
strokeColor : "rgba(220,220,220,0.8)",
|
||||
highlightFill: "rgba(220,220,220,0.75)",
|
||||
highlightStroke: "rgba(220,220,220,1)",
|
||||
data : [randomScalingFactor(),randomScalingFactor(),randomScalingFactor(),randomScalingFactor(),randomScalingFactor(),randomScalingFactor(),randomScalingFactor()]
|
||||
},
|
||||
{
|
||||
fillColor : "rgba(151,187,205,0.5)",
|
||||
strokeColor : "rgba(151,187,205,0.8)",
|
||||
highlightFill : "rgba(151,187,205,0.75)",
|
||||
highlightStroke : "rgba(151,187,205,1)",
|
||||
data : [randomScalingFactor(),randomScalingFactor(),randomScalingFactor(),randomScalingFactor(),randomScalingFactor(),randomScalingFactor(),randomScalingFactor()]
|
||||
}
|
||||
]
|
||||
var barChartData = {
|
||||
labels: ["January", "February", "March", "April", "May", "June", "July"],
|
||||
datasets: [{
|
||||
label: 'Dataset 1',
|
||||
backgroundColor: "rgba(220,220,220,0.5)",
|
||||
data: [randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()]
|
||||
}, {
|
||||
label: 'Dataset 2',
|
||||
backgroundColor: "rgba(151,187,205,0.5)",
|
||||
data: [randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()]
|
||||
}, {
|
||||
label: 'Dataset 3',
|
||||
backgroundColor: "rgba(151,187,205,0.5)",
|
||||
data: [randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()]
|
||||
}]
|
||||
|
||||
}
|
||||
window.onload = function(){
|
||||
var ctx = document.getElementById("canvas").getContext("2d");
|
||||
window.myBar = new Chart(ctx).Bar(barChartData, {
|
||||
responsive : true
|
||||
});
|
||||
}
|
||||
};
|
||||
window.onload = function() {
|
||||
var ctx = document.getElementById("canvas").getContext("2d");
|
||||
window.myBar = new Chart(ctx).Bar({
|
||||
data: barChartData,
|
||||
options: {
|
||||
responsive: true,
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
$('#randomizeData').click(function() {
|
||||
$.each(barChartData.datasets, function(i, dataset) {
|
||||
dataset.backgroundColor = 'rgba(' + randomColorFactor() + ',' + randomColorFactor() + ',' + randomColorFactor() + ',.7)';
|
||||
dataset.data = [randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()];
|
||||
|
||||
});
|
||||
window.myBar.update();
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Doughnut Chart</title>
|
||||
<script src="../src/Chart.Core.js"></script>
|
||||
<script src="../src/Chart.Doughnut.js"></script>
|
||||
<style>
|
||||
body{
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
#canvas-holder{
|
||||
width:30%;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="canvas-holder">
|
||||
<canvas id="chart-area" width="500" height="500"/>
|
||||
</div>
|
||||
|
||||
|
||||
<script>
|
||||
|
||||
var doughnutData = [
|
||||
{
|
||||
value: 1,
|
||||
label: "One"
|
||||
},
|
||||
{
|
||||
value: 2,
|
||||
label: "Two"
|
||||
},
|
||||
{
|
||||
value: 3,
|
||||
label: "Three"
|
||||
},
|
||||
{
|
||||
value: 4,
|
||||
label: "Four"
|
||||
},
|
||||
{
|
||||
value: 5,
|
||||
label: "Five"
|
||||
}
|
||||
|
||||
];
|
||||
|
||||
window.onload = function(){
|
||||
var ctx = document.getElementById("chart-area").getContext("2d");
|
||||
window.myDoughnut = new Chart(ctx).Doughnut({
|
||||
data: doughnutData,
|
||||
options: {
|
||||
responsive : true
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
+101
-58
@@ -1,67 +1,110 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Doughnut Chart</title>
|
||||
<script src="../Chart.js"></script>
|
||||
<style>
|
||||
body{
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
#canvas-holder{
|
||||
width:30%;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="canvas-holder">
|
||||
<canvas id="chart-area" width="500" height="500"/>
|
||||
</div>
|
||||
|
||||
<head>
|
||||
<title>Doughnut Chart</title>
|
||||
<script src="../Chart.js"></script>
|
||||
<script src="http://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
|
||||
<style>
|
||||
body {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
#canvas-holder {
|
||||
width: 30%;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<script>
|
||||
<body>
|
||||
<div id="canvas-holder" style="width:100%">
|
||||
<canvas id="chart-area" width="500" height="500" />
|
||||
</div>
|
||||
<button id="randomizeData">Randomize Data</button>
|
||||
<script>
|
||||
var randomScalingFactor = function() {
|
||||
return Math.round(Math.random() * 100);
|
||||
};
|
||||
var randomColorFactor = function() {
|
||||
return Math.round(Math.random() * 255);
|
||||
};
|
||||
|
||||
var doughnutData = [
|
||||
{
|
||||
value: 300,
|
||||
color:"#F7464A",
|
||||
highlight: "#FF5A5E",
|
||||
label: "Red"
|
||||
},
|
||||
{
|
||||
value: 50,
|
||||
color: "#46BFBD",
|
||||
highlight: "#5AD3D1",
|
||||
label: "Green"
|
||||
},
|
||||
{
|
||||
value: 100,
|
||||
color: "#FDB45C",
|
||||
highlight: "#FFC870",
|
||||
label: "Yellow"
|
||||
},
|
||||
{
|
||||
value: 40,
|
||||
color: "#949FB1",
|
||||
highlight: "#A8B3C5",
|
||||
label: "Grey"
|
||||
},
|
||||
{
|
||||
value: 120,
|
||||
color: "#4D5360",
|
||||
highlight: "#616774",
|
||||
label: "Dark Grey"
|
||||
}
|
||||
var config = {
|
||||
data: {
|
||||
datasets: [{
|
||||
data: [
|
||||
randomScalingFactor(),
|
||||
randomScalingFactor(),
|
||||
randomScalingFactor(),
|
||||
randomScalingFactor(),
|
||||
randomScalingFactor(),
|
||||
],
|
||||
backgroundColor: [
|
||||
"#F7464A",
|
||||
"#46BFBD",
|
||||
"#FDB45C",
|
||||
"#949FB1",
|
||||
"#4D5360",
|
||||
],
|
||||
}, {
|
||||
data: [
|
||||
randomScalingFactor(),
|
||||
randomScalingFactor(),
|
||||
randomScalingFactor(),
|
||||
randomScalingFactor(),
|
||||
randomScalingFactor(),
|
||||
],
|
||||
backgroundColor: [
|
||||
"#F7464A",
|
||||
"#46BFBD",
|
||||
"#FDB45C",
|
||||
"#949FB1",
|
||||
"#4D5360",
|
||||
],
|
||||
}, {
|
||||
data: [
|
||||
randomScalingFactor(),
|
||||
randomScalingFactor(),
|
||||
randomScalingFactor(),
|
||||
randomScalingFactor(),
|
||||
randomScalingFactor(),
|
||||
],
|
||||
backgroundColor: [
|
||||
"#F7464A",
|
||||
"#46BFBD",
|
||||
"#FDB45C",
|
||||
"#949FB1",
|
||||
"#4D5360",
|
||||
],
|
||||
}],
|
||||
labels: [
|
||||
"Red",
|
||||
"Green",
|
||||
"Yellow",
|
||||
"Grey",
|
||||
"Dark Grey"
|
||||
]
|
||||
},
|
||||
options: {
|
||||
responsive: true
|
||||
}
|
||||
};
|
||||
|
||||
];
|
||||
window.onload = function() {
|
||||
var ctx = document.getElementById("chart-area").getContext("2d");
|
||||
window.myDoughnut = new Chart(ctx).Doughnut(config);
|
||||
};
|
||||
|
||||
window.onload = function(){
|
||||
var ctx = document.getElementById("chart-area").getContext("2d");
|
||||
window.myDoughnut = new Chart(ctx).Doughnut(doughnutData, {responsive : true});
|
||||
};
|
||||
$('#randomizeData').click(function() {
|
||||
$.each(config.data.datasets, function(i, piece) {
|
||||
$.each(piece.data, function(j, value) {
|
||||
config.data.datasets[i].data[j] = randomScalingFactor();
|
||||
});
|
||||
});
|
||||
window.myDoughnut.update();
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
|
||||
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -0,0 +1,132 @@
|
||||
<!doctype html>
|
||||
<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>
|
||||
#canvas-holder1 {
|
||||
width: 300px;
|
||||
margin: 20px auto;
|
||||
}
|
||||
#canvas-holder2 {
|
||||
width: 50%;
|
||||
margin: 20px 25%;
|
||||
}
|
||||
#chartjs-tooltip {
|
||||
opacity: 1;
|
||||
position: absolute;
|
||||
background: rgba(0, 0, 0, .7);
|
||||
color: white;
|
||||
padding: 3px;
|
||||
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;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="canvas-holder1">
|
||||
<canvas id="chart1" width="300" height="30" />
|
||||
</div>
|
||||
<div id="canvas-holder2">
|
||||
<canvas id="chart2" width="450" height="600" />
|
||||
</div>
|
||||
|
||||
<div id="chartjs-tooltip"></div>
|
||||
|
||||
|
||||
<script>
|
||||
|
||||
Chart.defaults.global.pointHitDetectionRadius = 1;
|
||||
Chart.defaults.global.customTooltips = function(tooltip) {
|
||||
|
||||
var tooltipEl = $('#chartjs-tooltip');
|
||||
|
||||
if (!tooltip) {
|
||||
tooltipEl.css({
|
||||
opacity: 0
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
tooltipEl.removeClass('above below');
|
||||
tooltipEl.addClass(tooltip.yAlign);
|
||||
|
||||
var innerHtml = '';
|
||||
for (var i = tooltip.labels.length - 1; i >= 0; i--) {
|
||||
innerHtml += [
|
||||
'<div class="chartjs-tooltip-section">',
|
||||
' <span class="chartjs-tooltip-key" style="background-color:' + tooltip.legendColors[i].fill + '"></span>',
|
||||
' <span class="chartjs-tooltip-value">' + tooltip.labels[i] + '</span>',
|
||||
'</div>'
|
||||
].join('');
|
||||
}
|
||||
tooltipEl.html(innerHtml);
|
||||
|
||||
tooltipEl.css({
|
||||
opacity: 1,
|
||||
left: tooltip.chart.canvas.offsetLeft + tooltip.x + 'px',
|
||||
top: tooltip.chart.canvas.offsetTop + tooltip.y + 'px',
|
||||
fontFamily: tooltip.fontFamily,
|
||||
fontSize: tooltip.fontSize,
|
||||
fontStyle: tooltip.fontStyle,
|
||||
});
|
||||
};
|
||||
var randomScalingFactor = function() {
|
||||
return Math.round(Math.random() * 100);
|
||||
};
|
||||
var lineChartData = {
|
||||
labels: ["January", "February", "March", "April", "May", "June", "July"],
|
||||
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)",
|
||||
data: [randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()]
|
||||
}, {
|
||||
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)",
|
||||
data: [randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()]
|
||||
}]
|
||||
};
|
||||
|
||||
window.onload = function() {
|
||||
var ctx1 = document.getElementById("chart1").getContext("2d");
|
||||
window.myLine = new Chart(ctx1).Line({
|
||||
data: lineChartData,
|
||||
options: {
|
||||
showScale: false,
|
||||
pointDot : true,
|
||||
responsive: true
|
||||
}
|
||||
});
|
||||
|
||||
var ctx2 = document.getElementById("chart2").getContext("2d");
|
||||
window.myLine = new Chart(ctx2).Line(lineChartData, {
|
||||
responsive: true
|
||||
});
|
||||
};
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -0,0 +1,140 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>Line Chart Multiple Axes</title>
|
||||
<script src="../Chart.js"></script>
|
||||
<script src="../node_modules/jquery/dist/jquery.min.js"></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div style="width:50%">
|
||||
<div>
|
||||
<canvas id="canvas" height="450" width="600"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
<button id="randomizeData">Randomize Data</button>
|
||||
<script>
|
||||
var randomScalingFactor = function() {
|
||||
return Math.round(Math.random() * 100 * (Math.random() > 0.5 ? -1 : 1));
|
||||
};
|
||||
var randomColor = function(opacity) {
|
||||
return 'rgba(' + Math.round(Math.random() * 255) + ',' + Math.round(Math.random() * 255) + ',' + Math.round(Math.random() * 255) + ',' + (opacity || '.3') + ')';
|
||||
};
|
||||
|
||||
var lineChartData = {
|
||||
labels: ["January", "February", "March", "April", "May", "June", "July"],
|
||||
datasets: [{
|
||||
label: "My First dataset",
|
||||
data: [randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()],
|
||||
yAxisID: "y-axis-1",
|
||||
}, {
|
||||
label: "My Second dataset",
|
||||
data: [randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()],
|
||||
yAxisID: "y-axis-2"
|
||||
}]
|
||||
};
|
||||
|
||||
$.each(lineChartData.datasets, function(i, dataset) {
|
||||
dataset.borderColor = randomColor(0.4);
|
||||
dataset.backgroundColor = randomColor(1);
|
||||
dataset.pointBorderColor = randomColor(0.7);
|
||||
dataset.pointBackgroundColor = randomColor(0.5);
|
||||
dataset.pointBorderWidth = 1;
|
||||
});
|
||||
|
||||
console.log(lineChartData);
|
||||
|
||||
window.onload = function() {
|
||||
var ctx = document.getElementById("canvas").getContext("2d");
|
||||
window.myLine = new Chart(ctx).Line({
|
||||
data: lineChartData,
|
||||
options: {
|
||||
responsive: true,
|
||||
hoverMode: 'label',
|
||||
stacked: false,
|
||||
scales: {
|
||||
xAxes: [{
|
||||
gridLines: {
|
||||
offsetGridLines: false
|
||||
}
|
||||
}],
|
||||
yAxes: [{
|
||||
scaleType: "linear", // only linear but allow scale type registration. This allows extensions to exist solely for log scale for instance
|
||||
display: true,
|
||||
position: "left",
|
||||
id: "y-axis-1",
|
||||
|
||||
// grid line settings
|
||||
gridLines: {
|
||||
show: true,
|
||||
color: "rgba(0, 0, 0, 0.05)",
|
||||
lineWidth: 1,
|
||||
drawOnChartArea: true,
|
||||
drawTicks: true,
|
||||
zeroLineWidth: 1,
|
||||
zeroLineColor: "rgba(0,0,0,0.25)",
|
||||
},
|
||||
|
||||
// scale numbers
|
||||
beginAtZero: false,
|
||||
integersOnly: false,
|
||||
override: null,
|
||||
|
||||
// label settings
|
||||
labels: {
|
||||
show: true,
|
||||
template: "<%=value%>",
|
||||
fontSize: 12,
|
||||
fontStyle: "normal",
|
||||
fontColor: "#666",
|
||||
fontFamily: "Helvetica Neue",
|
||||
}
|
||||
}, {
|
||||
scaleType: "linear", // only linear but allow scale type registration. This allows extensions to exist solely for log scale for instance
|
||||
display: true,
|
||||
position: "right",
|
||||
id: "y-axis-2",
|
||||
|
||||
// grid line settings
|
||||
gridLines: {
|
||||
show: true,
|
||||
color: "rgba(0, 0, 0, 0.05)",
|
||||
lineWidth: 1,
|
||||
drawOnChartArea: false, // only want the grid lines for one axis to show up
|
||||
drawTicks: false,
|
||||
zeroLineWidth: 1,
|
||||
zeroLineColor: "rgba(0,0,0,0.25)",
|
||||
},
|
||||
|
||||
// scale numbers
|
||||
beginAtZero: false,
|
||||
integersOnly: false,
|
||||
override: null,
|
||||
|
||||
// label settings
|
||||
labels: {
|
||||
show: true,
|
||||
template: "<%=value%>",
|
||||
fontSize: 12,
|
||||
fontStyle: "normal",
|
||||
fontColor: "#666",
|
||||
fontFamily: "Helvetica Neue",
|
||||
}
|
||||
}],
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
$('#randomizeData').click(function() {
|
||||
lineChartData.datasets[0].data = [randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()];
|
||||
|
||||
lineChartData.datasets[1].data = [randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()];
|
||||
|
||||
window.myLine.update();
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
+58
-45
@@ -1,54 +1,67 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Line Chart</title>
|
||||
<script src="../Chart.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div style="width:30%">
|
||||
<div>
|
||||
<canvas id="canvas" height="450" width="600"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<head>
|
||||
<title>Line Chart</title>
|
||||
<script src="../Chart.js"></script>
|
||||
<script src="../node_modules/jquery/dist/jquery.min.js"></script>
|
||||
</head>
|
||||
|
||||
<script>
|
||||
var randomScalingFactor = function(){ return Math.round(Math.random()*100)};
|
||||
var lineChartData = {
|
||||
labels : ["January","February","March","April","May","June","July"],
|
||||
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)",
|
||||
data : [randomScalingFactor(),randomScalingFactor(),randomScalingFactor(),randomScalingFactor(),randomScalingFactor(),randomScalingFactor(),randomScalingFactor()]
|
||||
},
|
||||
{
|
||||
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)",
|
||||
data : [randomScalingFactor(),randomScalingFactor(),randomScalingFactor(),randomScalingFactor(),randomScalingFactor(),randomScalingFactor(),randomScalingFactor()]
|
||||
}
|
||||
]
|
||||
<body>
|
||||
<div style="width:50%">
|
||||
<div>
|
||||
<canvas id="canvas" height="450" width="600"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
<button id="randomizeData">Randomize Data</button>
|
||||
<script>
|
||||
var randomScalingFactor = function() {
|
||||
return Math.round(Math.random() * 100 * (Math.random() > 0.5 ? -1 : 1));
|
||||
};
|
||||
var randomColor = function(opacity) {
|
||||
return 'rgba(' + Math.round(Math.random() * 255) + ',' + Math.round(Math.random() * 255) + ',' + Math.round(Math.random() * 255) + ',' + (opacity || '.3') + ')';
|
||||
};
|
||||
|
||||
}
|
||||
var config = {
|
||||
data: {
|
||||
labels: ["January", "February", "March", "April", "May", "June", "July"],
|
||||
datasets: [{
|
||||
label: "My First dataset",
|
||||
data: [randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()],
|
||||
fill: false,
|
||||
}, {
|
||||
label: "My Second dataset",
|
||||
data: [randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()],
|
||||
}]
|
||||
},
|
||||
options: {
|
||||
responsive: true
|
||||
}
|
||||
};
|
||||
|
||||
window.onload = function(){
|
||||
var ctx = document.getElementById("canvas").getContext("2d");
|
||||
window.myLine = new Chart(ctx).Line(lineChartData, {
|
||||
responsive: true
|
||||
});
|
||||
}
|
||||
$.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).Line(config);
|
||||
};
|
||||
|
||||
$('#randomizeData').click(function() {
|
||||
config.data.datasets[0].data = [randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()];
|
||||
|
||||
config.data.datasets[1].data = [randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()];
|
||||
|
||||
window.myLine.update();
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -0,0 +1,160 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>Pie 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-holder {
|
||||
width: 100%;
|
||||
margin-top: 50px;
|
||||
text-align: center;
|
||||
}
|
||||
#chartjs-tooltip {
|
||||
opacity: 1;
|
||||
position: absolute;
|
||||
background: rgba(0, 0, 0, .7);
|
||||
color: white;
|
||||
padding: 3px;
|
||||
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.below {
|
||||
-webkit-transform: translate(-50%, 0);
|
||||
transform: translate(-50%, 0);
|
||||
}
|
||||
#chartjs-tooltip.below:before {
|
||||
border: solid;
|
||||
border-color: #111 transparent;
|
||||
border-color: rgba(0, 0, 0, .8) transparent;
|
||||
border-width: 0 8px 8px 8px;
|
||||
bottom: 1em;
|
||||
content: "";
|
||||
display: block;
|
||||
left: 50%;
|
||||
position: absolute;
|
||||
z-index: 99;
|
||||
-webkit-transform: translate(-50%, -100%);
|
||||
transform: translate(-50%, -100%);
|
||||
}
|
||||
#chartjs-tooltip.above {
|
||||
-webkit-transform: translate(-50%, -100%);
|
||||
transform: translate(-50%, -100%);
|
||||
}
|
||||
#chartjs-tooltip.above:before {
|
||||
border: solid;
|
||||
border-color: #111 transparent;
|
||||
border-color: rgba(0, 0, 0, .8) transparent;
|
||||
border-width: 8px 8px 0 8px;
|
||||
bottom: 1em;
|
||||
content: "";
|
||||
display: block;
|
||||
left: 50%;
|
||||
top: 100%;
|
||||
position: absolute;
|
||||
z-index: 99;
|
||||
-webkit-transform: translate(-50%, 0);
|
||||
transform: translate(-50%, 0);
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="canvas-holder">
|
||||
<canvas id="chart-area1" width="50" height="50" />
|
||||
</div>
|
||||
<div id="canvas-holder">
|
||||
<canvas id="chart-area2" width="300" height="300" />
|
||||
</div>
|
||||
|
||||
<div id="chartjs-tooltip"></div>
|
||||
|
||||
|
||||
<script>
|
||||
Chart.defaults.global.customTooltips = function(tooltip) {
|
||||
|
||||
// Tooltip Element
|
||||
var tooltipEl = $('#chartjs-tooltip');
|
||||
|
||||
// Hide if no tooltip
|
||||
if (!tooltip) {
|
||||
tooltipEl.css({
|
||||
opacity: 0
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// Set caret Position
|
||||
tooltipEl.removeClass('above below');
|
||||
tooltipEl.addClass(tooltip.yAlign);
|
||||
|
||||
// Set Text
|
||||
tooltipEl.html(tooltip.text);
|
||||
|
||||
// Find Y Location on page
|
||||
var top;
|
||||
if (tooltip.yAlign == 'above') {
|
||||
top = tooltip.y - tooltip.caretHeight - tooltip.caretPadding;
|
||||
} else {
|
||||
top = tooltip.y + tooltip.caretHeight + tooltip.caretPadding;
|
||||
}
|
||||
|
||||
// Display, position, and set styles for font
|
||||
tooltipEl.css({
|
||||
opacity: 1,
|
||||
left: tooltip.chart.canvas.offsetLeft + tooltip.x + 'px',
|
||||
top: tooltip.chart.canvas.offsetTop + top + 'px',
|
||||
fontFamily: tooltip.fontFamily,
|
||||
fontSize: tooltip.fontSize,
|
||||
fontStyle: tooltip.fontStyle,
|
||||
});
|
||||
};
|
||||
|
||||
var pieData = [{
|
||||
value: 300,
|
||||
color: "#F7464A",
|
||||
highlight: "#FF5A5E",
|
||||
label: "Red"
|
||||
}, {
|
||||
value: 50,
|
||||
color: "#46BFBD",
|
||||
highlight: "#5AD3D1",
|
||||
label: "Green"
|
||||
}, {
|
||||
value: 100,
|
||||
color: "#FDB45C",
|
||||
highlight: "#FFC870",
|
||||
label: "Yellow"
|
||||
}, {
|
||||
value: 40,
|
||||
color: "#949FB1",
|
||||
highlight: "#A8B3C5",
|
||||
label: "Grey"
|
||||
}, {
|
||||
value: 120,
|
||||
color: "#4D5360",
|
||||
highlight: "#616774",
|
||||
label: "Dark Grey"
|
||||
}];
|
||||
|
||||
window.onload = function() {
|
||||
var ctx1 = document.getElementById("chart-area1").getContext("2d");
|
||||
window.myPie = new Chart(ctx1).Pie({
|
||||
data: pieData
|
||||
});
|
||||
|
||||
var ctx2 = document.getElementById("chart-area2").getContext("2d");
|
||||
window.myPie = new Chart(ctx2).Pie({
|
||||
data: pieData
|
||||
});
|
||||
};
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
+92
-49
@@ -1,58 +1,101 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Pie Chart</title>
|
||||
<script src="../Chart.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="canvas-holder">
|
||||
<canvas id="chart-area" width="300" height="300"/>
|
||||
</div>
|
||||
|
||||
<head>
|
||||
<title>Pie Chart</title>
|
||||
<script src="../Chart.js"></script>
|
||||
<script src="http://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
|
||||
</head>
|
||||
|
||||
<script>
|
||||
<body>
|
||||
<div id="canvas-holder">
|
||||
<canvas id="chart-area" width="300" height="300" />
|
||||
</div>
|
||||
<button id="randomizeData">Randomize Data</button>
|
||||
<script>
|
||||
var randomScalingFactor = function() {
|
||||
return Math.round(Math.random() * 100);
|
||||
};
|
||||
var randomColorFactor = function() {
|
||||
return Math.round(Math.random() * 255);
|
||||
};
|
||||
|
||||
var pieData = [
|
||||
{
|
||||
value: 300,
|
||||
color:"#F7464A",
|
||||
highlight: "#FF5A5E",
|
||||
label: "Red"
|
||||
},
|
||||
{
|
||||
value: 50,
|
||||
color: "#46BFBD",
|
||||
highlight: "#5AD3D1",
|
||||
label: "Green"
|
||||
},
|
||||
{
|
||||
value: 100,
|
||||
color: "#FDB45C",
|
||||
highlight: "#FFC870",
|
||||
label: "Yellow"
|
||||
},
|
||||
{
|
||||
value: 40,
|
||||
color: "#949FB1",
|
||||
highlight: "#A8B3C5",
|
||||
label: "Grey"
|
||||
},
|
||||
{
|
||||
value: 120,
|
||||
color: "#4D5360",
|
||||
highlight: "#616774",
|
||||
label: "Dark Grey"
|
||||
}
|
||||
var config = {
|
||||
data: {
|
||||
datasets: [{
|
||||
data: [
|
||||
randomScalingFactor(),
|
||||
randomScalingFactor(),
|
||||
randomScalingFactor(),
|
||||
randomScalingFactor(),
|
||||
randomScalingFactor(),
|
||||
],
|
||||
backgroundColor: [
|
||||
"#F7464A",
|
||||
"#46BFBD",
|
||||
"#FDB45C",
|
||||
"#949FB1",
|
||||
"#4D5360",
|
||||
],
|
||||
}, {
|
||||
data: [
|
||||
randomScalingFactor(),
|
||||
randomScalingFactor(),
|
||||
randomScalingFactor(),
|
||||
randomScalingFactor(),
|
||||
randomScalingFactor(),
|
||||
],
|
||||
backgroundColor: [
|
||||
"#F7464A",
|
||||
"#46BFBD",
|
||||
"#FDB45C",
|
||||
"#949FB1",
|
||||
"#4D5360",
|
||||
],
|
||||
}, {
|
||||
data: [
|
||||
randomScalingFactor(),
|
||||
randomScalingFactor(),
|
||||
randomScalingFactor(),
|
||||
randomScalingFactor(),
|
||||
randomScalingFactor(),
|
||||
],
|
||||
backgroundColor: [
|
||||
"#F7464A",
|
||||
"#46BFBD",
|
||||
"#FDB45C",
|
||||
"#949FB1",
|
||||
"#4D5360",
|
||||
],
|
||||
}],
|
||||
labels: [
|
||||
"Red",
|
||||
"Green",
|
||||
"Yellow",
|
||||
"Grey",
|
||||
"Dark Grey"
|
||||
]
|
||||
},
|
||||
options: {
|
||||
responsive: true
|
||||
}
|
||||
};
|
||||
|
||||
];
|
||||
window.onload = function() {
|
||||
var ctx = document.getElementById("chart-area").getContext("2d");
|
||||
window.myPie = new Chart(ctx).Pie(config);
|
||||
};
|
||||
|
||||
window.onload = function(){
|
||||
var ctx = document.getElementById("chart-area").getContext("2d");
|
||||
window.myPie = new Chart(ctx).Pie(pieData);
|
||||
};
|
||||
$('#randomizeData').click(function() {
|
||||
$.each(config.data.datasets, function(i, piece) {
|
||||
$.each(piece.data, function(j, value) {
|
||||
config.data.datasets[i].data[j] = randomScalingFactor();
|
||||
//config.data.datasets.backgroundColor[i] = 'rgba(' + randomColorFactor() + ',' + randomColorFactor() + ',' + randomColorFactor() + ',.7)';
|
||||
});
|
||||
});
|
||||
window.myPie.update();
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
|
||||
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
+62
-51
@@ -1,60 +1,71 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Polar Area Chart</title>
|
||||
<script src="../Chart.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="canvas-holder" style="width:30%">
|
||||
<canvas id="chart-area" width="300" height="300"/>
|
||||
</div>
|
||||
|
||||
<head>
|
||||
<title>Polar Area Chart</title>
|
||||
<script src="../Chart.js"></script>
|
||||
<script src="http://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
|
||||
</head>
|
||||
|
||||
<script>
|
||||
<body>
|
||||
<div id="canvas-holder" style="width:100%">
|
||||
<canvas id="chart-area" width="300" height="300" />
|
||||
</div>
|
||||
<button id="randomizeData">Randomize Data</button>
|
||||
<script>
|
||||
var randomScalingFactor = function() {
|
||||
return Math.round(Math.random() * 100);
|
||||
};
|
||||
var randomColorFactor = function() {
|
||||
return Math.round(Math.random() * 255);
|
||||
};
|
||||
|
||||
var polarData = [
|
||||
{
|
||||
value: 300,
|
||||
color:"#F7464A",
|
||||
highlight: "#FF5A5E",
|
||||
label: "Red"
|
||||
},
|
||||
{
|
||||
value: 50,
|
||||
color: "#46BFBD",
|
||||
highlight: "#5AD3D1",
|
||||
label: "Green"
|
||||
},
|
||||
{
|
||||
value: 100,
|
||||
color: "#FDB45C",
|
||||
highlight: "#FFC870",
|
||||
label: "Yellow"
|
||||
},
|
||||
{
|
||||
value: 40,
|
||||
color: "#949FB1",
|
||||
highlight: "#A8B3C5",
|
||||
label: "Grey"
|
||||
},
|
||||
{
|
||||
value: 120,
|
||||
color: "#4D5360",
|
||||
highlight: "#616774",
|
||||
label: "Dark Grey"
|
||||
}
|
||||
var config = {
|
||||
data: {
|
||||
datasets: [{
|
||||
data: [
|
||||
randomScalingFactor(),
|
||||
randomScalingFactor(),
|
||||
randomScalingFactor(),
|
||||
randomScalingFactor(),
|
||||
randomScalingFactor(),
|
||||
],
|
||||
backgroundColor: [
|
||||
"#F7464A",
|
||||
"#46BFBD",
|
||||
"#FDB45C",
|
||||
"#949FB1",
|
||||
"#4D5360",
|
||||
],
|
||||
labels: [
|
||||
"Red",
|
||||
"Green",
|
||||
"Yellow",
|
||||
"Grey",
|
||||
"Dark Grey"
|
||||
]
|
||||
}],
|
||||
},
|
||||
options: {
|
||||
responsive: true
|
||||
}
|
||||
};
|
||||
|
||||
];
|
||||
window.onload = function() {
|
||||
var ctx = document.getElementById("chart-area").getContext("2d");
|
||||
window.myPolarArea = new Chart(ctx).PolarArea(config);
|
||||
};
|
||||
|
||||
window.onload = function(){
|
||||
var ctx = document.getElementById("chart-area").getContext("2d");
|
||||
window.myPolarArea = new Chart(ctx).PolarArea(polarData, {
|
||||
responsive:true
|
||||
});
|
||||
};
|
||||
$('#randomizeData').click(function() {
|
||||
$.each(config.data.datasets, function(i, piece) {
|
||||
$.each(piece.data, function(j, value) {
|
||||
config.data.datasets[i].data[j] = randomScalingFactor();
|
||||
//config.data.datasets.backgroundColor[i] = 'rgba(' + randomColorFactor() + ',' + randomColorFactor() + ',' + randomColorFactor() + ',.7)';
|
||||
});
|
||||
});
|
||||
window.myPolarArea.update();
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
|
||||
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
+54
-46
@@ -1,53 +1,61 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Radar Chart</title>
|
||||
<script src="../Chart.js"></script>
|
||||
<meta name = "viewport" content = "initial-scale = 1, user-scalable = no">
|
||||
<style>
|
||||
canvas{
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div style="width:30%">
|
||||
<canvas id="canvas" height="450" width="450"></canvas>
|
||||
</div>
|
||||
|
||||
<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>
|
||||
|
||||
<script>
|
||||
var radarChartData = {
|
||||
labels: ["Eating", "Drinking", "Sleeping", "Designing", "Coding", "Cycling", "Running"],
|
||||
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)",
|
||||
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)",
|
||||
data: [28,48,40,19,96,27,100]
|
||||
}
|
||||
]
|
||||
};
|
||||
<body>
|
||||
<div style="width:100%">
|
||||
<canvas id="canvas" height="450" width="450"></canvas>
|
||||
</div>
|
||||
<button id="randomizeData">Randomize Data</button>
|
||||
<script>
|
||||
var randomScalingFactor = function() {
|
||||
return Math.round(Math.random() * 100);
|
||||
};
|
||||
var randomColorFactor = function() {
|
||||
return Math.round(Math.random() * 255);
|
||||
};
|
||||
|
||||
window.onload = function(){
|
||||
window.myRadar = new Chart(document.getElementById("canvas").getContext("2d")).Radar(radarChartData, {
|
||||
responsive: true
|
||||
});
|
||||
}
|
||||
var config = {
|
||||
data: {
|
||||
labels: ["Eating", "Drinking", "Sleeping", "Designing", "Coding", "Cycling", "Running"],
|
||||
datasets: [{
|
||||
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()]
|
||||
}, {
|
||||
label: "My Second dataset",
|
||||
backgroundColor: "rgba(151,187,205,0.2)",
|
||||
pointBackgroundColor: "rgba(151,187,205,1)",
|
||||
hoverPointBackgroundColor: "#fff",
|
||||
pointHighlightStroke: "rgba(151,187,205,1)",
|
||||
data: [null, randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()]
|
||||
}]
|
||||
},
|
||||
options: {
|
||||
responsive: true
|
||||
}
|
||||
};
|
||||
|
||||
window.onload = function() {
|
||||
window.myRadar = new Chart(document.getElementById("canvas").getContext("2d")).Radar(config);
|
||||
};
|
||||
|
||||
$('#randomizeData').click(function() {
|
||||
config.data.datasets[0].backgroundColor = 'rgba(' + randomColorFactor() + ',' + randomColorFactor() + ',' + randomColorFactor() + ',.3)';
|
||||
config.data.datasets[0].data = [randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()];
|
||||
|
||||
config.data.datasets[1].backgroundColor = 'rgba(' + randomColorFactor() + ',' + randomColorFactor() + ',' + randomColorFactor() + ',.3)';
|
||||
config.data.datasets[1].data = [randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()];
|
||||
|
||||
window.myRadar.update();
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -0,0 +1,223 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>Scatter Chart Multi Axis</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%">
|
||||
<div>
|
||||
<canvas id="canvas" height="450" width="600"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
<button id="randomizeData">Randomize Data</button>
|
||||
<script>
|
||||
var randomScalingFactor = function() {
|
||||
return (Math.random() > 0.5 ? 1.0 : -1.0) * Math.round(Math.random() * 100);
|
||||
};
|
||||
var randomColor = function(opacity) {
|
||||
return 'rgba(' + Math.round(Math.random() * 255) + ',' + Math.round(Math.random() * 255) + ',' + Math.round(Math.random() * 255) + ',' + (opacity || '.3') + ')';
|
||||
};
|
||||
|
||||
var scatterChartData = {
|
||||
datasets: [{
|
||||
label: "My First dataset",
|
||||
xAxisID: "x-axis-1",
|
||||
yAxisID: "y-axis-1",
|
||||
data: [{
|
||||
x: randomScalingFactor(),
|
||||
y: randomScalingFactor(),
|
||||
}, {
|
||||
x: randomScalingFactor(),
|
||||
y: randomScalingFactor(),
|
||||
}, {
|
||||
x: randomScalingFactor(),
|
||||
y: randomScalingFactor(),
|
||||
}, {
|
||||
x: randomScalingFactor(),
|
||||
y: randomScalingFactor(),
|
||||
}, {
|
||||
x: randomScalingFactor(),
|
||||
y: randomScalingFactor(),
|
||||
}, {
|
||||
x: randomScalingFactor(),
|
||||
y: randomScalingFactor(),
|
||||
}, {
|
||||
x: randomScalingFactor(),
|
||||
y: randomScalingFactor(),
|
||||
}]
|
||||
}, {
|
||||
label: "My Second dataset",
|
||||
xAxisID: "x-axis-1",
|
||||
yAxisID: "y-axis-2",
|
||||
data: [{
|
||||
x: randomScalingFactor(),
|
||||
y: randomScalingFactor(),
|
||||
}, {
|
||||
x: randomScalingFactor(),
|
||||
y: randomScalingFactor(),
|
||||
}, {
|
||||
x: randomScalingFactor(),
|
||||
y: randomScalingFactor(),
|
||||
}, {
|
||||
x: randomScalingFactor(),
|
||||
y: randomScalingFactor(),
|
||||
}, {
|
||||
x: randomScalingFactor(),
|
||||
y: randomScalingFactor(),
|
||||
}, {
|
||||
x: randomScalingFactor(),
|
||||
y: randomScalingFactor(),
|
||||
}, {
|
||||
x: randomScalingFactor(),
|
||||
y: randomScalingFactor(),
|
||||
}]
|
||||
}]
|
||||
};
|
||||
|
||||
$.each(scatterChartData.datasets, function(i, dataset) {
|
||||
dataset.borderColor = randomColor(0.4);
|
||||
dataset.backgroundColor = randomColor(0.1);
|
||||
dataset.pointBorderColor = randomColor(0.7);
|
||||
dataset.pointBackgroundColor = randomColor(0.5);
|
||||
dataset.pointBorderWidth = 1;
|
||||
});
|
||||
|
||||
console.log(scatterChartData);
|
||||
|
||||
window.onload = function() {
|
||||
var ctx = document.getElementById("canvas").getContext("2d");
|
||||
window.myScatter = new Chart(ctx).Scatter({
|
||||
data: scatterChartData,
|
||||
options: {
|
||||
responsive: true,
|
||||
hoverMode: 'single',
|
||||
scales: {
|
||||
xAxes: [{
|
||||
position: "bottom",
|
||||
gridLines: {
|
||||
zeroLineColor: "rgba(0,0,0,1)"
|
||||
}
|
||||
}],
|
||||
yAxes: [{
|
||||
scaleType: "linear", // only linear but allow scale type registration. This allows extensions to exist solely for log scale for instance
|
||||
display: true,
|
||||
position: "left",
|
||||
id: "y-axis-1",
|
||||
|
||||
// grid line settings
|
||||
gridLines: {
|
||||
show: true,
|
||||
color: "rgba(0, 0, 0, 0.05)",
|
||||
lineWidth: 1,
|
||||
drawOnChartArea: true,
|
||||
drawTicks: true,
|
||||
zeroLineWidth: 1,
|
||||
zeroLineColor: "rgba(0,0,0,0.25)",
|
||||
},
|
||||
|
||||
// scale numbers
|
||||
beginAtZero: false,
|
||||
integersOnly: false,
|
||||
override: null,
|
||||
|
||||
// label settings
|
||||
labels: {
|
||||
show: true,
|
||||
template: "<%=value%>",
|
||||
fontSize: 12,
|
||||
fontStyle: "normal",
|
||||
fontColor: "#666",
|
||||
fontFamily: "Helvetica Neue",
|
||||
}
|
||||
}, {
|
||||
scaleType: "linear", // only linear but allow scale type registration. This allows extensions to exist solely for log scale for instance
|
||||
display: true,
|
||||
position: "right",
|
||||
id: "y-axis-2",
|
||||
|
||||
// grid line settings
|
||||
gridLines: {
|
||||
show: true,
|
||||
color: "rgba(0, 0, 0, 0.05)",
|
||||
lineWidth: 1,
|
||||
drawOnChartArea: false, // only want the grid lines for one axis to show up
|
||||
drawTicks: false,
|
||||
zeroLineWidth: 1,
|
||||
zeroLineColor: "rgba(0,0,0,0.25)",
|
||||
},
|
||||
|
||||
// scale numbers
|
||||
beginAtZero: false,
|
||||
integersOnly: false,
|
||||
override: null,
|
||||
|
||||
// label settings
|
||||
labels: {
|
||||
show: true,
|
||||
template: "<%=value%>",
|
||||
fontSize: 12,
|
||||
fontStyle: "normal",
|
||||
fontColor: "#666",
|
||||
fontFamily: "Helvetica Neue",
|
||||
}
|
||||
}],
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
$('#randomizeData').click(function() {
|
||||
scatterChartData.datasets[0].data = [{
|
||||
x: randomScalingFactor(),
|
||||
y: randomScalingFactor(),
|
||||
}, {
|
||||
x: randomScalingFactor(),
|
||||
y: randomScalingFactor(),
|
||||
}, {
|
||||
x: randomScalingFactor(),
|
||||
y: randomScalingFactor(),
|
||||
}, {
|
||||
x: randomScalingFactor(),
|
||||
y: randomScalingFactor(),
|
||||
}, {
|
||||
x: randomScalingFactor(),
|
||||
y: randomScalingFactor(),
|
||||
}, {
|
||||
x: randomScalingFactor(),
|
||||
y: randomScalingFactor(),
|
||||
}, {
|
||||
x: randomScalingFactor(),
|
||||
y: randomScalingFactor(),
|
||||
}];
|
||||
scatterChartData.datasets[1].data = [{
|
||||
x: randomScalingFactor(),
|
||||
y: randomScalingFactor(),
|
||||
}, {
|
||||
x: randomScalingFactor(),
|
||||
y: randomScalingFactor(),
|
||||
}, {
|
||||
x: randomScalingFactor(),
|
||||
y: randomScalingFactor(),
|
||||
}, {
|
||||
x: randomScalingFactor(),
|
||||
y: randomScalingFactor(),
|
||||
}, {
|
||||
x: randomScalingFactor(),
|
||||
y: randomScalingFactor(),
|
||||
}, {
|
||||
x: randomScalingFactor(),
|
||||
y: randomScalingFactor(),
|
||||
}, {
|
||||
x: randomScalingFactor(),
|
||||
y: randomScalingFactor(),
|
||||
}]
|
||||
window.myScatter.update();
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -0,0 +1,155 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>Scatter 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%">
|
||||
<div>
|
||||
<canvas id="canvas" height="450" width="600"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
<button id="randomizeData">Randomize Data</button>
|
||||
<script>
|
||||
var randomScalingFactor = function() {
|
||||
return (Math.random() > 0.5 ? 1.0 : -1.0) * Math.round(Math.random() * 100);
|
||||
};
|
||||
var randomColor = function(opacity) {
|
||||
return 'rgba(' + Math.round(Math.random() * 255) + ',' + Math.round(Math.random() * 255) + ',' + Math.round(Math.random() * 255) + ',' + (opacity || '.3') + ')';
|
||||
};
|
||||
|
||||
var scatterChartData = {
|
||||
datasets: [{
|
||||
label: "My First dataset",
|
||||
data: [{
|
||||
x: randomScalingFactor(),
|
||||
y: randomScalingFactor(),
|
||||
}, {
|
||||
x: randomScalingFactor(),
|
||||
y: randomScalingFactor(),
|
||||
}, {
|
||||
x: randomScalingFactor(),
|
||||
y: randomScalingFactor(),
|
||||
}, {
|
||||
x: randomScalingFactor(),
|
||||
y: randomScalingFactor(),
|
||||
}, {
|
||||
x: randomScalingFactor(),
|
||||
y: randomScalingFactor(),
|
||||
}, {
|
||||
x: randomScalingFactor(),
|
||||
y: randomScalingFactor(),
|
||||
}, {
|
||||
x: randomScalingFactor(),
|
||||
y: randomScalingFactor(),
|
||||
}]
|
||||
}, {
|
||||
label: "My Second dataset",
|
||||
data: [{
|
||||
x: randomScalingFactor(),
|
||||
y: randomScalingFactor(),
|
||||
}, {
|
||||
x: randomScalingFactor(),
|
||||
y: randomScalingFactor(),
|
||||
}, {
|
||||
x: randomScalingFactor(),
|
||||
y: randomScalingFactor(),
|
||||
}, {
|
||||
x: randomScalingFactor(),
|
||||
y: randomScalingFactor(),
|
||||
}, {
|
||||
x: randomScalingFactor(),
|
||||
y: randomScalingFactor(),
|
||||
}, {
|
||||
x: randomScalingFactor(),
|
||||
y: randomScalingFactor(),
|
||||
}, {
|
||||
x: randomScalingFactor(),
|
||||
y: randomScalingFactor(),
|
||||
}]
|
||||
}]
|
||||
};
|
||||
|
||||
$.each(scatterChartData.datasets, function(i, dataset) {
|
||||
dataset.borderColor = randomColor(0.4);
|
||||
dataset.backgroundColor = randomColor(0.1);
|
||||
dataset.pointBorderColor = randomColor(0.7);
|
||||
dataset.pointBackgroundColor = randomColor(0.5);
|
||||
dataset.pointBorderWidth = 1;
|
||||
});
|
||||
|
||||
console.log(scatterChartData);
|
||||
|
||||
window.onload = function() {
|
||||
var ctx = document.getElementById("canvas").getContext("2d");
|
||||
window.myScatter = new Chart(ctx).Scatter({
|
||||
data: scatterChartData,
|
||||
options: {
|
||||
responsive: true,
|
||||
hoverMode: 'single', // should always use single for a scatter chart
|
||||
scales: {
|
||||
xAxes: [{
|
||||
gridLines: {
|
||||
zeroLineColor: "rgba(0,0,0,1)"
|
||||
}
|
||||
}]
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
$('#randomizeData').click(function() {
|
||||
scatterChartData.datasets[0].data = [{
|
||||
x: randomScalingFactor(),
|
||||
y: randomScalingFactor(),
|
||||
}, {
|
||||
x: randomScalingFactor(),
|
||||
y: randomScalingFactor(),
|
||||
}, {
|
||||
x: randomScalingFactor(),
|
||||
y: randomScalingFactor(),
|
||||
}, {
|
||||
x: randomScalingFactor(),
|
||||
y: randomScalingFactor(),
|
||||
}, {
|
||||
x: randomScalingFactor(),
|
||||
y: randomScalingFactor(),
|
||||
}, {
|
||||
x: randomScalingFactor(),
|
||||
y: randomScalingFactor(),
|
||||
}, {
|
||||
x: randomScalingFactor(),
|
||||
y: randomScalingFactor(),
|
||||
}];
|
||||
scatterChartData.datasets[1].data = [{
|
||||
x: randomScalingFactor(),
|
||||
y: randomScalingFactor(),
|
||||
}, {
|
||||
x: randomScalingFactor(),
|
||||
y: randomScalingFactor(),
|
||||
}, {
|
||||
x: randomScalingFactor(),
|
||||
y: randomScalingFactor(),
|
||||
}, {
|
||||
x: randomScalingFactor(),
|
||||
y: randomScalingFactor(),
|
||||
}, {
|
||||
x: randomScalingFactor(),
|
||||
y: randomScalingFactor(),
|
||||
}, {
|
||||
x: randomScalingFactor(),
|
||||
y: randomScalingFactor(),
|
||||
}, {
|
||||
x: randomScalingFactor(),
|
||||
y: randomScalingFactor(),
|
||||
}]
|
||||
window.myScatter.update();
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
+516
-250
@@ -1,295 +1,561 @@
|
||||
(function(){
|
||||
"use strict";
|
||||
(function() {
|
||||
"use strict";
|
||||
|
||||
var root = this,
|
||||
Chart = root.Chart,
|
||||
helpers = Chart.helpers;
|
||||
var root = this,
|
||||
Chart = root.Chart,
|
||||
helpers = Chart.helpers;
|
||||
|
||||
var defaultConfig = {
|
||||
|
||||
stacked: false,
|
||||
|
||||
hover: {
|
||||
mode: "label"
|
||||
},
|
||||
|
||||
scales: {
|
||||
xAxes: [{
|
||||
scaleType: "dataset", // scatter should not use a dataset axis
|
||||
display: true,
|
||||
position: "bottom",
|
||||
id: "x-axis-1", // need an ID so datasets can reference the scale
|
||||
|
||||
// grid line settings
|
||||
gridLines: {
|
||||
show: true,
|
||||
color: "rgba(0, 0, 0, 0.05)",
|
||||
lineWidth: 1,
|
||||
drawOnChartArea: true,
|
||||
drawTicks: true,
|
||||
zeroLineWidth: 1,
|
||||
zeroLineColor: "rgba(0,0,0,0.25)",
|
||||
offsetGridLines: true,
|
||||
},
|
||||
|
||||
// label settings
|
||||
labels: {
|
||||
show: true,
|
||||
template: "<%=value%>",
|
||||
fontSize: 12,
|
||||
fontStyle: "normal",
|
||||
fontColor: "#666",
|
||||
fontFamily: "Helvetica Neue",
|
||||
},
|
||||
}],
|
||||
yAxes: [{
|
||||
scaleType: "linear", // only linear but allow scale type registration. This allows extensions to exist solely for log scale for instance
|
||||
display: true,
|
||||
position: "left",
|
||||
id: "y-axis-1",
|
||||
|
||||
// grid line settings
|
||||
gridLines: {
|
||||
show: true,
|
||||
color: "rgba(0, 0, 0, 0.05)",
|
||||
lineWidth: 1,
|
||||
drawOnChartArea: true,
|
||||
drawTicks: true, // draw ticks extending towards the label
|
||||
zeroLineWidth: 1,
|
||||
zeroLineColor: "rgba(0,0,0,0.25)",
|
||||
},
|
||||
|
||||
// scale numbers
|
||||
beginAtZero: false,
|
||||
override: null,
|
||||
|
||||
// label settings
|
||||
labels: {
|
||||
show: true,
|
||||
template: "<%=value%>",
|
||||
fontSize: 12,
|
||||
fontStyle: "normal",
|
||||
fontColor: "#666",
|
||||
fontFamily: "Helvetica Neue",
|
||||
}
|
||||
}],
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
|
||||
var defaultConfig = {
|
||||
//Boolean - Whether the scale should start at zero, or an order of magnitude down from the lowest value
|
||||
scaleBeginAtZero : true,
|
||||
Chart.Type.extend({
|
||||
name: "Bar",
|
||||
defaults: defaultConfig,
|
||||
initialize: function() {
|
||||
|
||||
//Boolean - Whether grid lines are shown across the chart
|
||||
scaleShowGridLines : true,
|
||||
var _this = this;
|
||||
|
||||
//String - Colour of the grid lines
|
||||
scaleGridLineColor : "rgba(0,0,0,.05)",
|
||||
// Events
|
||||
helpers.bindEvents(this, this.options.events, this.events);
|
||||
|
||||
//Number - Width of the grid lines
|
||||
scaleGridLineWidth : 1,
|
||||
//Create a new bar for each piece of data
|
||||
helpers.each(this.data.datasets, function(dataset, datasetIndex) {
|
||||
dataset.metaData = [];
|
||||
helpers.each(dataset.data, function(dataPoint, index) {
|
||||
dataset.metaData.push(new Chart.Rectangle({
|
||||
_chart: this.chart,
|
||||
_datasetIndex: datasetIndex,
|
||||
_index: index,
|
||||
}));
|
||||
}, this);
|
||||
|
||||
//Boolean - If there is a stroke on each bar
|
||||
barShowStroke : true,
|
||||
// The bar chart only supports a single x axis because the x axis is always a dataset axis
|
||||
dataset.xAxisID = this.options.scales.xAxes[0].id;
|
||||
|
||||
//Number - Pixel width of the bar stroke
|
||||
barStrokeWidth : 2,
|
||||
if (!dataset.yAxisID) {
|
||||
dataset.yAxisID = this.options.scales.yAxes[0].id;
|
||||
}
|
||||
}, this);
|
||||
|
||||
//Number - Spacing between each of the X value sets
|
||||
barValueSpacing : 5,
|
||||
// Build and fit the scale. Needs to happen after the axis IDs have been set
|
||||
this.buildScale();
|
||||
|
||||
//Number - Spacing between data sets within X values
|
||||
barDatasetSpacing : 1,
|
||||
// Create tooltip instance exclusively for this chart with some defaults.
|
||||
this.tooltip = new Chart.Tooltip({
|
||||
_chart: this.chart,
|
||||
_data: this.data,
|
||||
_options: this.options,
|
||||
}, this);
|
||||
|
||||
//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].fillColor%>\"></span><%if(datasets[i].label){%><%=datasets[i].label%><%}%></li><%}%></ul>"
|
||||
// Need to fit scales before we reset elements.
|
||||
Chart.scaleService.fitScalesForChart(this, this.chart.width, this.chart.height);
|
||||
|
||||
};
|
||||
// So that we animate from the baseline
|
||||
this.resetElements();
|
||||
|
||||
// Update the chart with the latest data.
|
||||
this.update();
|
||||
},
|
||||
resetElements: function() {
|
||||
// Update the points
|
||||
this.eachElement(function(bar, index, dataset, datasetIndex) {
|
||||
var xScale = this.scales[this.data.datasets[datasetIndex].xAxisID];
|
||||
var yScale = this.scales[this.data.datasets[datasetIndex].yAxisID];
|
||||
|
||||
var yScalePoint;
|
||||
|
||||
if (yScale.min < 0 && yScale.max <0) {
|
||||
// all less than 0. use the top
|
||||
yScalePoint = yScale.getPixelForValue(yScale.max);
|
||||
} else if (yScale.min > 0 && yScale.max > 0) {
|
||||
yScalePoint = yScale.getPixelForValue(yScale.min);
|
||||
} else {
|
||||
yScalePoint = yScale.getPixelForValue(0);
|
||||
}
|
||||
|
||||
helpers.extend(bar, {
|
||||
// Utility
|
||||
_chart: this.chart,
|
||||
_xScale: xScale,
|
||||
_yScale: yScale,
|
||||
_datasetIndex: datasetIndex,
|
||||
_index: index,
|
||||
|
||||
// Desired view properties
|
||||
_model: {
|
||||
x: xScale.calculateBarX(this.data.datasets.length, datasetIndex, index),
|
||||
y: yScalePoint,
|
||||
|
||||
// Appearance
|
||||
base: yScale.calculateBarBase(datasetIndex, index),
|
||||
width: xScale.calculateBarWidth(this.data.datasets.length),
|
||||
backgroundColor: bar.custom && bar.custom.backgroundColor ? bar.custom.backgroundColor : helpers.getValueAtIndexOrDefault(this.data.datasets[datasetIndex].backgroundColor, index, this.options.elements.bar.backgroundColor),
|
||||
borderColor: bar.custom && bar.custom.borderColor ? bar.custom.borderColor : helpers.getValueAtIndexOrDefault(this.data.datasets[datasetIndex].borderColor, index, this.options.elements.bar.borderColor),
|
||||
borderWidth: bar.custom && bar.custom.borderWidth ? bar.custom.borderWidth : helpers.getValueAtIndexOrDefault(this.data.datasets[datasetIndex].borderWidth, index, this.options.elements.bar.borderWidth),
|
||||
|
||||
// Tooltip
|
||||
label: this.data.labels[index],
|
||||
datasetLabel: this.data.datasets[datasetIndex].label,
|
||||
},
|
||||
});
|
||||
bar.pivot();
|
||||
}, this);
|
||||
},
|
||||
update: function() {
|
||||
// Update the scale sizes
|
||||
Chart.scaleService.fitScalesForChart(this, this.chart.width, this.chart.height);
|
||||
|
||||
// Update the points
|
||||
this.eachElement(function(bar, index, dataset, datasetIndex) {
|
||||
var xScale = this.scales[this.data.datasets[datasetIndex].xAxisID];
|
||||
var yScale = this.scales[this.data.datasets[datasetIndex].yAxisID];
|
||||
|
||||
helpers.extend(bar, {
|
||||
// Utility
|
||||
_chart: this.chart,
|
||||
_xScale: xScale,
|
||||
_yScale: yScale,
|
||||
_datasetIndex: datasetIndex,
|
||||
_index: index,
|
||||
|
||||
// Desired view properties
|
||||
_model: {
|
||||
x: xScale.calculateBarX(this.data.datasets.length, datasetIndex, index),
|
||||
y: yScale.calculateBarY(datasetIndex, index),
|
||||
|
||||
// Appearance
|
||||
base: yScale.calculateBarBase(datasetIndex, index),
|
||||
width: xScale.calculateBarWidth(this.data.datasets.length),
|
||||
backgroundColor: bar.custom && bar.custom.backgroundColor ? bar.custom.backgroundColor : helpers.getValueAtIndexOrDefault(this.data.datasets[datasetIndex].backgroundColor, index, this.options.elements.bar.backgroundColor),
|
||||
borderColor: bar.custom && bar.custom.borderColor ? bar.custom.borderColor : helpers.getValueAtIndexOrDefault(this.data.datasets[datasetIndex].borderColor, index, this.options.elements.bar.borderColor),
|
||||
borderWidth: bar.custom && bar.custom.borderWidth ? bar.custom.borderWidth : helpers.getValueAtIndexOrDefault(this.data.datasets[datasetIndex].borderWidth, index, this.options.elements.bar.borderWidth),
|
||||
|
||||
// Tooltip
|
||||
label: this.data.labels[index],
|
||||
datasetLabel: this.data.datasets[datasetIndex].label,
|
||||
},
|
||||
});
|
||||
bar.pivot();
|
||||
}, this);
|
||||
|
||||
|
||||
Chart.Type.extend({
|
||||
name: "Bar",
|
||||
defaults : defaultConfig,
|
||||
initialize: function(data){
|
||||
this.render();
|
||||
},
|
||||
buildScale: function(labels) {
|
||||
var self = this;
|
||||
|
||||
//Expose options as a scope variable here so we can access it in the ScaleClass
|
||||
var options = this.options;
|
||||
// Function to determine the range of all the
|
||||
var calculateYRange = function() {
|
||||
this.min = null;
|
||||
this.max = null;
|
||||
|
||||
this.ScaleClass = Chart.Scale.extend({
|
||||
offsetGridLines : true,
|
||||
calculateBarX : function(datasetCount, datasetIndex, barIndex){
|
||||
//Reusable method for calculating the xPosition of a given bar based on datasetIndex & width of the bar
|
||||
var xWidth = this.calculateBaseWidth(),
|
||||
xAbsolute = this.calculateX(barIndex) - (xWidth/2),
|
||||
barWidth = this.calculateBarWidth(datasetCount);
|
||||
var positiveValues = [];
|
||||
var negativeValues = [];
|
||||
|
||||
return xAbsolute + (barWidth * datasetIndex) + (datasetIndex * options.barDatasetSpacing) + barWidth/2;
|
||||
},
|
||||
calculateBaseWidth : function(){
|
||||
return (this.calculateX(1) - this.calculateX(0)) - (2*options.barValueSpacing);
|
||||
},
|
||||
calculateBarWidth : function(datasetCount){
|
||||
//The padding between datasets is to the right of each bar, providing that there are more than 1 dataset
|
||||
var baseWidth = this.calculateBaseWidth() - ((datasetCount - 1) * options.barDatasetSpacing);
|
||||
if (self.options.stacked) {
|
||||
helpers.each(self.data.datasets, function(dataset) {
|
||||
if (dataset.yAxisID === this.id) {
|
||||
helpers.each(dataset.data, function(value, index) {
|
||||
positiveValues[index] = positiveValues[index] || 0;
|
||||
negativeValues[index] = negativeValues[index] || 0;
|
||||
|
||||
return (baseWidth / datasetCount);
|
||||
}
|
||||
});
|
||||
if (self.options.relativePoints) {
|
||||
positiveValues[index] = 100;
|
||||
} else {
|
||||
if (value < 0) {
|
||||
negativeValues[index] += value;
|
||||
} else {
|
||||
positiveValues[index] += value;
|
||||
}
|
||||
}
|
||||
}, this);
|
||||
}
|
||||
}, this);
|
||||
|
||||
this.datasets = [];
|
||||
var values = positiveValues.concat(negativeValues);
|
||||
this.min = helpers.min(values);
|
||||
this.max = helpers.max(values);
|
||||
|
||||
//Set up tooltip events on the chart
|
||||
if (this.options.showTooltips){
|
||||
helpers.bindEvents(this, this.options.tooltipEvents, function(evt){
|
||||
var activeBars = (evt.type !== 'mouseout') ? this.getBarsAtEvent(evt) : [];
|
||||
} else {
|
||||
helpers.each(self.data.datasets, function(dataset) {
|
||||
if (dataset.yAxisID === this.id) {
|
||||
helpers.each(dataset.data, function(value, index) {
|
||||
if (this.min === null) {
|
||||
this.min = value;
|
||||
} else if (value < this.min) {
|
||||
this.min = value;
|
||||
}
|
||||
|
||||
this.eachBars(function(bar){
|
||||
bar.restore(['fillColor', 'strokeColor']);
|
||||
});
|
||||
helpers.each(activeBars, function(activeBar){
|
||||
activeBar.fillColor = activeBar.highlightFill;
|
||||
activeBar.strokeColor = activeBar.highlightStroke;
|
||||
});
|
||||
this.showTooltip(activeBars);
|
||||
});
|
||||
}
|
||||
if (this.max === null) {
|
||||
this.max = value;
|
||||
} else if (value > this.max) {
|
||||
this.max = value;
|
||||
}
|
||||
}, this);
|
||||
}
|
||||
}, this);
|
||||
}
|
||||
};
|
||||
|
||||
//Declare the extension of the default point, to cater for the options passed in to the constructor
|
||||
this.BarClass = Chart.Rectangle.extend({
|
||||
strokeWidth : this.options.barStrokeWidth,
|
||||
showStroke : this.options.barShowStroke,
|
||||
ctx : this.chart.ctx
|
||||
});
|
||||
// Map of scale ID to scale object so we can lookup later
|
||||
this.scales = {};
|
||||
|
||||
//Iterate through each of the datasets, and build this into a property of the chart
|
||||
helpers.each(data.datasets,function(dataset,datasetIndex){
|
||||
// Build the x axis. The line chart only supports a single x axis
|
||||
var ScaleClass = Chart.scales.getScaleConstructor(this.options.scales.xAxes[0].scaleType);
|
||||
var xScale = new ScaleClass({
|
||||
ctx: this.chart.ctx,
|
||||
options: this.options.scales.xAxes[0],
|
||||
id: this.options.scales.xAxes[0].id,
|
||||
calculateRange: function() {
|
||||
this.labels = self.data.labels;
|
||||
this.min = 0;
|
||||
this.max = this.labels.length;
|
||||
},
|
||||
calculateBaseWidth: function() {
|
||||
return (this.getPixelForValue(null, 1, true) - this.getPixelForValue(null, 0, true)) - (2 * self.options.elements.bar.valueSpacing);
|
||||
},
|
||||
calculateBarWidth: function(datasetCount) {
|
||||
//The padding between datasets is to the right of each bar, providing that there are more than 1 dataset
|
||||
var baseWidth = this.calculateBaseWidth() - ((datasetCount - 1) * self.options.elements.bar.datasetSpacing);
|
||||
|
||||
var datasetObject = {
|
||||
label : dataset.label || null,
|
||||
fillColor : dataset.fillColor,
|
||||
strokeColor : dataset.strokeColor,
|
||||
bars : []
|
||||
};
|
||||
if (self.options.stacked) {
|
||||
return baseWidth;
|
||||
}
|
||||
return (baseWidth / datasetCount);
|
||||
},
|
||||
calculateBarX: function(datasetCount, datasetIndex, elementIndex) {
|
||||
var xWidth = this.calculateBaseWidth(),
|
||||
xAbsolute = this.getPixelForValue(null, elementIndex, true) - (xWidth / 2),
|
||||
barWidth = this.calculateBarWidth(datasetCount);
|
||||
|
||||
this.datasets.push(datasetObject);
|
||||
if (self.options.stacked) {
|
||||
return xAbsolute + barWidth / 2;
|
||||
}
|
||||
|
||||
helpers.each(dataset.data,function(dataPoint,index){
|
||||
if (helpers.isNumber(dataPoint)){
|
||||
//Add a new point for each piece of data, passing any required data to draw.
|
||||
datasetObject.bars.push(new this.BarClass({
|
||||
value : dataPoint,
|
||||
label : data.labels[index],
|
||||
strokeColor : dataset.strokeColor,
|
||||
fillColor : dataset.fillColor,
|
||||
highlightFill : dataset.highlightFill || dataset.fillColor,
|
||||
highlightStroke : dataset.highlightStroke || dataset.strokeColor
|
||||
}));
|
||||
}
|
||||
},this);
|
||||
return xAbsolute + (barWidth * datasetIndex) + (datasetIndex * self.options.elements.bar.datasetSpacing) + barWidth / 2;
|
||||
},
|
||||
});
|
||||
this.scales[xScale.id] = xScale;
|
||||
|
||||
},this);
|
||||
// Build up all the y scales
|
||||
helpers.each(this.options.scales.yAxes, function(yAxisOptions) {
|
||||
var ScaleClass = Chart.scales.getScaleConstructor(yAxisOptions.scaleType);
|
||||
var scale = new ScaleClass({
|
||||
ctx: this.chart.ctx,
|
||||
options: yAxisOptions,
|
||||
calculateRange: calculateYRange,
|
||||
calculateBarBase: function(datasetIndex, index) {
|
||||
var base = 0;
|
||||
|
||||
this.buildScale(data.labels);
|
||||
if (self.options.stacked) {
|
||||
|
||||
this.BarClass.prototype.base = this.scale.endPoint;
|
||||
var value = self.data.datasets[datasetIndex].data[index];
|
||||
|
||||
this.eachBars(function(bar, index, datasetIndex){
|
||||
helpers.extend(bar, {
|
||||
width : this.scale.calculateBarWidth(this.datasets.length),
|
||||
x: this.scale.calculateBarX(this.datasets.length, datasetIndex, index),
|
||||
y: this.scale.endPoint
|
||||
});
|
||||
bar.save();
|
||||
}, this);
|
||||
if (value < 0) {
|
||||
for (var i = 0; i < datasetIndex; i++) {
|
||||
if (self.data.datasets[i].yAxisID === this.id) {
|
||||
base += self.data.datasets[i].data[index] < 0 ? self.data.datasets[i].data[index] : 0;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (var j = 0; j < datasetIndex; j++) {
|
||||
if (self.data.datasets[j].yAxisID === this.id) {
|
||||
base += self.data.datasets[j].data[index] > 0 ? self.data.datasets[j].data[index] : 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.render();
|
||||
},
|
||||
update : function(){
|
||||
this.scale.update();
|
||||
// Reset any highlight colours before updating.
|
||||
helpers.each(this.activeElements, function(activeElement){
|
||||
activeElement.restore(['fillColor', 'strokeColor']);
|
||||
});
|
||||
return this.getPixelForValue(base);
|
||||
}
|
||||
|
||||
this.eachBars(function(bar){
|
||||
bar.save();
|
||||
});
|
||||
this.render();
|
||||
},
|
||||
eachBars : function(callback){
|
||||
helpers.each(this.datasets,function(dataset, datasetIndex){
|
||||
helpers.each(dataset.bars, callback, this, datasetIndex);
|
||||
},this);
|
||||
},
|
||||
getBarsAtEvent : function(e){
|
||||
var barsArray = [],
|
||||
eventPosition = helpers.getRelativePosition(e),
|
||||
datasetIterator = function(dataset){
|
||||
barsArray.push(dataset.bars[barIndex]);
|
||||
},
|
||||
barIndex;
|
||||
base = this.getPixelForValue(this.min);
|
||||
|
||||
for (var datasetIndex = 0; datasetIndex < this.datasets.length; datasetIndex++) {
|
||||
for (barIndex = 0; barIndex < this.datasets[datasetIndex].bars.length; barIndex++) {
|
||||
if (this.datasets[datasetIndex].bars[barIndex].inRange(eventPosition.x,eventPosition.y)){
|
||||
helpers.each(this.datasets, datasetIterator);
|
||||
return barsArray;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (this.beginAtZero || ((this.min <= 0 && this.max >= 0) || (this.min >= 0 && this.max <= 0))) {
|
||||
base = this.getPixelForValue(0);
|
||||
base += this.options.gridLines.lineWidth;
|
||||
} else if (this.min < 0 && this.max < 0) {
|
||||
// All values are negative. Use the top as the base
|
||||
base = this.getPixelForValue(this.max);
|
||||
}
|
||||
|
||||
return barsArray;
|
||||
},
|
||||
buildScale : function(labels){
|
||||
var self = this;
|
||||
return base;
|
||||
|
||||
var dataTotal = function(){
|
||||
var values = [];
|
||||
self.eachBars(function(bar){
|
||||
values.push(bar.value);
|
||||
});
|
||||
return values;
|
||||
};
|
||||
},
|
||||
calculateBarY: function(datasetIndex, index) {
|
||||
|
||||
var scaleOptions = {
|
||||
templateString : this.options.scaleLabel,
|
||||
height : this.chart.height,
|
||||
width : this.chart.width,
|
||||
ctx : this.chart.ctx,
|
||||
textColor : this.options.scaleFontColor,
|
||||
fontSize : this.options.scaleFontSize,
|
||||
fontStyle : this.options.scaleFontStyle,
|
||||
fontFamily : this.options.scaleFontFamily,
|
||||
valuesCount : labels.length,
|
||||
beginAtZero : this.options.scaleBeginAtZero,
|
||||
integersOnly : this.options.scaleIntegersOnly,
|
||||
calculateYRange: function(currentHeight){
|
||||
var updatedRanges = helpers.calculateScaleRange(
|
||||
dataTotal(),
|
||||
currentHeight,
|
||||
this.fontSize,
|
||||
this.beginAtZero,
|
||||
this.integersOnly
|
||||
);
|
||||
helpers.extend(this, updatedRanges);
|
||||
},
|
||||
xLabels : labels,
|
||||
font : helpers.fontString(this.options.scaleFontSize, this.options.scaleFontStyle, this.options.scaleFontFamily),
|
||||
lineWidth : this.options.scaleLineWidth,
|
||||
lineColor : this.options.scaleLineColor,
|
||||
gridLineWidth : (this.options.scaleShowGridLines) ? this.options.scaleGridLineWidth : 0,
|
||||
gridLineColor : (this.options.scaleShowGridLines) ? this.options.scaleGridLineColor : "rgba(0,0,0,0)",
|
||||
padding : (this.options.showScale) ? 0 : (this.options.barShowStroke) ? this.options.barStrokeWidth : 0,
|
||||
showLabels : this.options.scaleShowLabels,
|
||||
display : this.options.showScale
|
||||
};
|
||||
var value = self.data.datasets[datasetIndex].data[index];
|
||||
|
||||
if (this.options.scaleOverride){
|
||||
helpers.extend(scaleOptions, {
|
||||
calculateYRange: helpers.noop,
|
||||
steps: this.options.scaleSteps,
|
||||
stepValue: this.options.scaleStepWidth,
|
||||
min: this.options.scaleStartValue,
|
||||
max: this.options.scaleStartValue + (this.options.scaleSteps * this.options.scaleStepWidth)
|
||||
});
|
||||
}
|
||||
if (self.options.stacked) {
|
||||
|
||||
this.scale = new this.ScaleClass(scaleOptions);
|
||||
},
|
||||
addData : function(valuesArray,label){
|
||||
//Map the values array for each of the datasets
|
||||
helpers.each(valuesArray,function(value,datasetIndex){
|
||||
if (helpers.isNumber(value)){
|
||||
//Add a new point for each piece of data, passing any required data to draw.
|
||||
this.datasets[datasetIndex].bars.push(new this.BarClass({
|
||||
value : value,
|
||||
label : label,
|
||||
x: this.scale.calculateBarX(this.datasets.length, datasetIndex, this.scale.valuesCount+1),
|
||||
y: this.scale.endPoint,
|
||||
width : this.scale.calculateBarWidth(this.datasets.length),
|
||||
base : this.scale.endPoint,
|
||||
strokeColor : this.datasets[datasetIndex].strokeColor,
|
||||
fillColor : this.datasets[datasetIndex].fillColor
|
||||
}));
|
||||
}
|
||||
},this);
|
||||
var sumPos = 0,
|
||||
sumNeg = 0;
|
||||
|
||||
this.scale.addXLabel(label);
|
||||
//Then re-render the chart.
|
||||
this.update();
|
||||
},
|
||||
removeData : function(){
|
||||
this.scale.removeXLabel();
|
||||
//Then re-render the chart.
|
||||
helpers.each(this.datasets,function(dataset){
|
||||
dataset.bars.shift();
|
||||
},this);
|
||||
this.update();
|
||||
},
|
||||
reflow : function(){
|
||||
helpers.extend(this.BarClass.prototype,{
|
||||
y: this.scale.endPoint,
|
||||
base : this.scale.endPoint
|
||||
});
|
||||
var newScaleProps = helpers.extend({
|
||||
height : this.chart.height,
|
||||
width : this.chart.width
|
||||
});
|
||||
this.scale.update(newScaleProps);
|
||||
},
|
||||
draw : function(ease){
|
||||
var easingDecimal = ease || 1;
|
||||
this.clear();
|
||||
for (var i = 0; i < datasetIndex; i++) {
|
||||
if (self.data.datasets[i].data[index] < 0) {
|
||||
sumNeg += self.data.datasets[i].data[index] || 0;
|
||||
} else {
|
||||
sumPos += self.data.datasets[i].data[index] || 0;
|
||||
}
|
||||
}
|
||||
|
||||
var ctx = this.chart.ctx;
|
||||
if (value < 0) {
|
||||
return this.getPixelForValue(sumNeg + value);
|
||||
} else {
|
||||
return this.getPixelForValue(sumPos + value);
|
||||
}
|
||||
|
||||
this.scale.draw(easingDecimal);
|
||||
return this.getPixelForValue(value);
|
||||
}
|
||||
|
||||
//Draw all the bars for each dataset
|
||||
helpers.each(this.datasets,function(dataset,datasetIndex){
|
||||
helpers.each(dataset.bars,function(bar,index){
|
||||
bar.base = this.scale.endPoint;
|
||||
//Transition then draw
|
||||
bar.transition({
|
||||
x : this.scale.calculateBarX(this.datasets.length, datasetIndex, index),
|
||||
y : this.scale.calculateY(bar.value),
|
||||
width : this.scale.calculateBarWidth(this.datasets.length)
|
||||
}, easingDecimal).draw();
|
||||
},this);
|
||||
var offset = 0;
|
||||
|
||||
},this);
|
||||
}
|
||||
});
|
||||
for (var j = datasetIndex; j < self.data.datasets.length; j++) {
|
||||
if (j === datasetIndex && value) {
|
||||
offset += value;
|
||||
} else {
|
||||
offset = offset + value;
|
||||
}
|
||||
}
|
||||
|
||||
return this.getPixelForValue(value);
|
||||
},
|
||||
id: yAxisOptions.id,
|
||||
});
|
||||
|
||||
this.scales[scale.id] = scale;
|
||||
}, this);
|
||||
},
|
||||
draw: function(ease) {
|
||||
|
||||
var easingDecimal = ease || 1;
|
||||
this.clear();
|
||||
|
||||
// Draw all the scales
|
||||
helpers.each(this.scales, function(scale) {
|
||||
scale.draw(this.chartArea);
|
||||
}, this);
|
||||
|
||||
//Draw all the bars for each dataset
|
||||
this.eachElement(function(bar, index, datasetIndex) {
|
||||
bar.transition(easingDecimal).draw();
|
||||
}, this);
|
||||
|
||||
// Finally draw the tooltip
|
||||
this.tooltip.transition(easingDecimal).draw();
|
||||
},
|
||||
events: function(e) {
|
||||
|
||||
|
||||
}).call(this);
|
||||
// If exiting chart
|
||||
if (e.type == 'mouseout') {
|
||||
return this;
|
||||
}
|
||||
|
||||
this.lastActive = this.lastActive || [];
|
||||
|
||||
// Find Active Elements
|
||||
this.active = function() {
|
||||
switch (this.options.hover.mode) {
|
||||
case 'single':
|
||||
return this.getElementAtEvent(e);
|
||||
case 'label':
|
||||
return this.getElementsAtEvent(e);
|
||||
case 'dataset':
|
||||
return this.getDatasetAtEvent(e);
|
||||
default:
|
||||
return e;
|
||||
}
|
||||
}.call(this);
|
||||
|
||||
// On Hover hook
|
||||
if (this.options.hover.onHover) {
|
||||
this.options.hover.onHover.call(this, this.active);
|
||||
}
|
||||
|
||||
if (e.type == 'mouseup' || e.type == 'click') {
|
||||
if (this.options.onClick) {
|
||||
this.options.onClick.call(this, e, this.active);
|
||||
}
|
||||
}
|
||||
|
||||
var dataset;
|
||||
var index;
|
||||
// Remove styling for last active (even if it may still be active)
|
||||
if (this.lastActive.length) {
|
||||
switch (this.options.hover.mode) {
|
||||
case 'single':
|
||||
dataset = this.data.datasets[this.lastActive[0]._datasetIndex];
|
||||
index = this.lastActive[0]._index;
|
||||
|
||||
this.lastActive[0]._model.backgroundColor = this.lastActive[0].custom && this.lastActive[0].custom.backgroundColor ? this.lastActive[0].custom.backgroundColor : helpers.getValueAtIndexOrDefault(dataset.backgroundColor, index, this.options.elements.bar.backgroundColor);
|
||||
this.lastActive[0]._model.borderColor = this.lastActive[0].custom && this.lastActive[0].custom.borderColor ? this.lastActive[0].custom.borderColor : helpers.getValueAtIndexOrDefault(dataset.borderColor, index, this.options.elements.bar.borderColor);
|
||||
this.lastActive[0]._model.borderWidth = this.lastActive[0].custom && this.lastActive[0].custom.borderWidth ? this.lastActive[0].custom.borderWidth : helpers.getValueAtIndexOrDefault(dataset.borderWidth, index, this.options.elements.bar.borderWidth);
|
||||
break;
|
||||
case 'label':
|
||||
for (var i = 0; i < this.lastActive.length; i++) {
|
||||
dataset = this.data.datasets[this.lastActive[i]._datasetIndex];
|
||||
index = this.lastActive[i]._index;
|
||||
|
||||
this.lastActive[i]._model.backgroundColor = this.lastActive[i].custom && this.lastActive[i].custom.backgroundColor ? this.lastActive[i].custom.backgroundColor : helpers.getValueAtIndexOrDefault(dataset.backgroundColor, index, this.options.elements.bar.backgroundColor);
|
||||
this.lastActive[i]._model.borderColor = this.lastActive[i].custom && this.lastActive[i].custom.borderColor ? this.lastActive[i].custom.borderColor : helpers.getValueAtIndexOrDefault(dataset.borderColor, index, this.options.elements.bar.borderColor);
|
||||
this.lastActive[i]._model.borderWidth = this.lastActive[i].custom && this.lastActive[i].custom.borderWidth ? this.lastActive[i].custom.borderWidth : helpers.getValueAtIndexOrDefault(dataset.borderWidth, index, this.options.elements.bar.borderWidth);
|
||||
}
|
||||
break;
|
||||
case 'dataset':
|
||||
break;
|
||||
default:
|
||||
// Don't change anything
|
||||
}
|
||||
}
|
||||
|
||||
// Built in hover styling
|
||||
if (this.active.length && this.options.hover.mode) {
|
||||
switch (this.options.hover.mode) {
|
||||
case 'single':
|
||||
dataset = this.data.datasets[this.active[0]._datasetIndex];
|
||||
index = this.active[0]._index;
|
||||
|
||||
this.active[0]._model.backgroundColor = this.active[0].custom && this.active[0].custom.hoverBackgroundColor ? this.active[0].custom.hoverBackgroundColor : helpers.getValueAtIndexOrDefault(dataset.hoverBackgroundColor, index, helpers.color(this.active[0]._model.backgroundColor).saturate(0.5).darken(0.35).rgbString());
|
||||
this.active[0]._model.borderColor = this.active[0].custom && this.active[0].custom.hoverBorderColor ? this.active[0].custom.hoverBorderColor : helpers.getValueAtIndexOrDefault(dataset.hoverBorderColor, index, helpers.color(this.active[0]._model.borderColor).saturate(0.5).darken(0.35).rgbString());
|
||||
this.active[0]._model.borderWidth = this.active[0].custom && this.active[0].custom.hoverBorderWidth ? this.active[0].custom.hoverBorderWidth : helpers.getValueAtIndexOrDefault(dataset.borderWidth, index, this.active[0]._model.borderWidth);
|
||||
break;
|
||||
case 'label':
|
||||
for (var i = 0; i < this.active.length; i++) {
|
||||
dataset = this.data.datasets[this.active[i]._datasetIndex];
|
||||
index = this.active[i]._index;
|
||||
|
||||
this.active[i]._model.backgroundColor = this.active[i].custom && this.active[i].custom.hoverBackgroundColor ? this.active[i].custom.hoverBackgroundColor : helpers.getValueAtIndexOrDefault(dataset.hoverBackgroundColor, index, helpers.color(this.active[i]._model.backgroundColor).saturate(0.5).darken(0.35).rgbString());
|
||||
this.active[i]._model.borderColor = this.active[i].custom && this.active[i].custom.hoverBorderColor ? this.active[i].custom.hoverBorderColor : helpers.getValueAtIndexOrDefault(dataset.hoverBorderColor, index, helpers.color(this.active[i]._model.borderColor).saturate(0.5).darken(0.35).rgbString());
|
||||
this.active[i]._model.borderWidth = this.active[i].custom && this.active[i].custom.hoverBorderWidth ? this.active[i].custom.hoverBorderWidth : helpers.getValueAtIndexOrDefault(dataset.borderWidth, index, this.active[i]._model.borderWidth);
|
||||
}
|
||||
break;
|
||||
case 'dataset':
|
||||
break;
|
||||
default:
|
||||
// Don't change anything
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Built in Tooltips
|
||||
if (this.options.tooltips.enabled) {
|
||||
|
||||
// The usual updates
|
||||
this.tooltip.initialize();
|
||||
|
||||
// Active
|
||||
if (this.active.length) {
|
||||
this.tooltip._model.opacity = 1;
|
||||
|
||||
helpers.extend(this.tooltip, {
|
||||
_active: this.active,
|
||||
});
|
||||
|
||||
this.tooltip.update();
|
||||
} else {
|
||||
// Inactive
|
||||
this.tooltip._model.opacity = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
this.tooltip.pivot();
|
||||
|
||||
// Hover animations
|
||||
if (!this.animating) {
|
||||
var changed;
|
||||
|
||||
helpers.each(this.active, function(element, index) {
|
||||
if (element !== this.lastActive[index]) {
|
||||
changed = true;
|
||||
}
|
||||
}, 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.stop();
|
||||
this.render(this.options.hoverAnimationDuration);
|
||||
}
|
||||
}
|
||||
|
||||
// Remember Last Active
|
||||
this.lastActive = this.active;
|
||||
return this;
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
}).call(this);
|
||||
|
||||
+1976
-1876
Diferenças do arquivo suprimidas por serem muito extensas
Carregar Diff
+337
-154
@@ -1,184 +1,367 @@
|
||||
(function(){
|
||||
"use strict";
|
||||
(function() {
|
||||
"use strict";
|
||||
|
||||
var root = this,
|
||||
Chart = root.Chart,
|
||||
//Cache a local reference to Chart.helpers
|
||||
helpers = Chart.helpers;
|
||||
var root = this,
|
||||
Chart = root.Chart,
|
||||
//Cache a local reference to Chart.helpers
|
||||
helpers = Chart.helpers;
|
||||
|
||||
var defaultConfig = {
|
||||
//Boolean - Whether we should show a stroke on each segment
|
||||
segmentShowStroke : true,
|
||||
var defaultConfig = {
|
||||
|
||||
//String - The colour of each segment stroke
|
||||
segmentStrokeColor : "#fff",
|
||||
animation: {
|
||||
//Boolean - Whether we animate the rotation of the Doughnut
|
||||
animateRotate: true,
|
||||
|
||||
//Number - The width of each segment stroke
|
||||
segmentStrokeWidth : 2,
|
||||
//Boolean - Whether we animate scaling the Doughnut from the centre
|
||||
animateScale: false,
|
||||
},
|
||||
|
||||
//The percentage of the chart that we cut out of the middle.
|
||||
percentageInnerCutout : 50,
|
||||
hover: {
|
||||
mode: 'single'
|
||||
},
|
||||
|
||||
//Number - Amount of animation steps
|
||||
animationSteps : 100,
|
||||
//The percentage of the chart that we cut out of the middle.
|
||||
|
||||
//String - Animation easing effect
|
||||
animationEasing : "easeOutBounce",
|
||||
cutoutPercentage: 50,
|
||||
|
||||
//Boolean - Whether we animate the rotation of the Doughnut
|
||||
animateRotate : true,
|
||||
};
|
||||
|
||||
//Boolean - Whether we animate scaling the Doughnut from the centre
|
||||
animateScale : false,
|
||||
Chart.Type.extend({
|
||||
//Passing in a name registers this chart in the Chart namespace
|
||||
name: "Doughnut",
|
||||
//Providing a defaults will also register the deafults in the chart namespace
|
||||
defaults: defaultConfig,
|
||||
//Initialize is fired when the chart is initialized - Data is passed in as a parameter
|
||||
//Config is automatically merged by the core of Chart.js, and is available at this.options
|
||||
initialize: function() {
|
||||
|
||||
//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>"
|
||||
//Set up tooltip events on the chart
|
||||
helpers.bindEvents(this, this.options.events, this.events);
|
||||
|
||||
};
|
||||
//Create a new bar for each piece of data
|
||||
helpers.each(this.data.datasets, function(dataset, datasetIndex) {
|
||||
dataset.metaData = [];
|
||||
helpers.each(dataset.data, function(dataPoint, index) {
|
||||
dataset.metaData.push(new Chart.Arc({
|
||||
_chart: this.chart,
|
||||
_datasetIndex: datasetIndex,
|
||||
_index: index,
|
||||
_model: {}
|
||||
}));
|
||||
}, this);
|
||||
}, this);
|
||||
|
||||
// Create tooltip instance exclusively for this chart with some defaults.
|
||||
this.tooltip = new Chart.Tooltip({
|
||||
_chart: this.chart,
|
||||
_data: this.data,
|
||||
_options: this.options,
|
||||
}, this);
|
||||
|
||||
this.resetElements();
|
||||
|
||||
// Update the chart with the latest data.
|
||||
this.update();
|
||||
|
||||
},
|
||||
|
||||
calculateCircumference: function(dataset, value) {
|
||||
if (dataset.total > 0) {
|
||||
return (Math.PI * 2) * (value / dataset.total);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
},
|
||||
resetElements: function() {
|
||||
this.outerRadius = (helpers.min([this.chart.width, this.chart.height]) - this.options.elements.slice.borderWidth / 2) / 2;
|
||||
this.innerRadius = this.options.cutoutPercentage ? (this.outerRadius / 100) * (this.options.cutoutPercentage) : 1;
|
||||
this.radiusLength = (this.outerRadius - this.innerRadius) / this.data.datasets.length;
|
||||
|
||||
// Update the points
|
||||
helpers.each(this.data.datasets, function(dataset, datasetIndex) {
|
||||
// So that calculateCircumference works
|
||||
dataset.total = 0;
|
||||
helpers.each(dataset.data, function(value) {
|
||||
dataset.total += Math.abs(value);
|
||||
}, this);
|
||||
|
||||
dataset.outerRadius = this.outerRadius - (this.radiusLength * datasetIndex);
|
||||
dataset.innerRadius = dataset.outerRadius - this.radiusLength;
|
||||
|
||||
helpers.each(dataset.metaData, function(slice, index) {
|
||||
helpers.extend(slice, {
|
||||
_model: {
|
||||
x: this.chart.width / 2,
|
||||
y: this.chart.height / 2,
|
||||
startAngle: Math.PI * -0.5, // use - PI / 2 instead of 3PI / 2 to make animations better. It means that we never deal with overflow during the transition function
|
||||
circumference: (this.options.animation.animateRotate) ? 0 : this.calculateCircumference(metaSlice.value),
|
||||
outerRadius: (this.options.animation.animateScale) ? 0 : dataset.outerRadius,
|
||||
innerRadius: (this.options.animation.animateScale) ? 0 : dataset.innerRadius,
|
||||
|
||||
backgroundColor: slice.custom && slice.custom.backgroundColor ? slice.custom.backgroundColor : helpers.getValueAtIndexOrDefault(dataset.backgroundColor, index, this.options.elements.slice.backgroundColor),
|
||||
hoverBackgroundColor: slice.custom && slice.custom.hoverBackgroundColor ? slice.custom.hoverBackgroundColor : helpers.getValueAtIndexOrDefault(dataset.hoverBackgroundColor, index, this.options.elements.slice.hoverBackgroundColor),
|
||||
borderWidth: slice.custom && slice.custom.borderWidth ? slice.custom.borderWidth : helpers.getValueAtIndexOrDefault(dataset.borderWidth, index, this.options.elements.slice.borderWidth),
|
||||
borderColor: slice.custom && slice.custom.borderColor ? slice.custom.borderColor : helpers.getValueAtIndexOrDefault(dataset.borderColor, index, this.options.elements.slice.borderColor),
|
||||
|
||||
label: helpers.getValueAtIndexOrDefault(dataset.label, index, this.data.labels[index])
|
||||
},
|
||||
});
|
||||
|
||||
slice.pivot();
|
||||
}, this);
|
||||
|
||||
}, this);
|
||||
},
|
||||
update: function() {
|
||||
|
||||
this.outerRadius = (helpers.min([this.chart.width, this.chart.height]) - this.options.elements.slice.borderWidth / 2) / 2;
|
||||
this.innerRadius = this.options.cutoutPercentage ? (this.outerRadius / 100) * (this.options.cutoutPercentage) : 1;
|
||||
this.radiusLength = (this.outerRadius - this.innerRadius) / this.data.datasets.length;
|
||||
|
||||
|
||||
Chart.Type.extend({
|
||||
//Passing in a name registers this chart in the Chart namespace
|
||||
name: "Doughnut",
|
||||
//Providing a defaults will also register the deafults in the chart namespace
|
||||
defaults : defaultConfig,
|
||||
//Initialize is fired when the chart is initialized - Data is passed in as a parameter
|
||||
//Config is automatically merged by the core of Chart.js, and is available at this.options
|
||||
initialize: function(data){
|
||||
// Update the points
|
||||
helpers.each(this.data.datasets, function(dataset, datasetIndex) {
|
||||
|
||||
//Declare segments as a static property to prevent inheriting across the Chart type prototype
|
||||
this.segments = [];
|
||||
this.outerRadius = (helpers.min([this.chart.width,this.chart.height]) - this.options.segmentStrokeWidth/2)/2;
|
||||
dataset.total = 0;
|
||||
helpers.each(dataset.data, function(value) {
|
||||
dataset.total += Math.abs(value);
|
||||
}, this);
|
||||
|
||||
this.SegmentArc = Chart.Arc.extend({
|
||||
ctx : this.chart.ctx,
|
||||
x : this.chart.width/2,
|
||||
y : this.chart.height/2
|
||||
});
|
||||
|
||||
//Set up tooltip events on the chart
|
||||
if (this.options.showTooltips){
|
||||
helpers.bindEvents(this, this.options.tooltipEvents, function(evt){
|
||||
var activeSegments = (evt.type !== 'mouseout') ? this.getSegmentsAtEvent(evt) : [];
|
||||
dataset.outerRadius = this.outerRadius - (this.radiusLength * datasetIndex);
|
||||
|
||||
helpers.each(this.segments,function(segment){
|
||||
segment.restore(["fillColor"]);
|
||||
});
|
||||
helpers.each(activeSegments,function(activeSegment){
|
||||
activeSegment.fillColor = activeSegment.highlightColor;
|
||||
});
|
||||
this.showTooltip(activeSegments);
|
||||
});
|
||||
}
|
||||
this.calculateTotal(data);
|
||||
dataset.innerRadius = dataset.outerRadius - this.radiusLength;
|
||||
|
||||
helpers.each(data,function(datapoint, index){
|
||||
this.addData(datapoint, index, true);
|
||||
},this);
|
||||
helpers.each(dataset.metaData, function(slice, index) {
|
||||
|
||||
this.render();
|
||||
},
|
||||
getSegmentsAtEvent : function(e){
|
||||
var segmentsArray = [];
|
||||
helpers.extend(slice, {
|
||||
// Utility
|
||||
_chart: this.chart,
|
||||
_datasetIndex: datasetIndex,
|
||||
_index: index,
|
||||
|
||||
var location = helpers.getRelativePosition(e);
|
||||
// Desired view properties
|
||||
_model: {
|
||||
x: this.chart.width / 2,
|
||||
y: this.chart.height / 2,
|
||||
circumference: this.calculateCircumference(dataset, dataset.data[index]),
|
||||
outerRadius: dataset.outerRadius,
|
||||
innerRadius: dataset.innerRadius,
|
||||
|
||||
helpers.each(this.segments,function(segment){
|
||||
if (segment.inRange(location.x,location.y)) segmentsArray.push(segment);
|
||||
},this);
|
||||
return segmentsArray;
|
||||
},
|
||||
addData : function(segment, atIndex, silent){
|
||||
var index = atIndex || this.segments.length;
|
||||
this.segments.splice(index, 0, new this.SegmentArc({
|
||||
value : segment.value,
|
||||
outerRadius : (this.options.animateScale) ? 0 : this.outerRadius,
|
||||
innerRadius : (this.options.animateScale) ? 0 : (this.outerRadius/100) * this.options.percentageInnerCutout,
|
||||
fillColor : segment.color,
|
||||
highlightColor : segment.highlight || segment.color,
|
||||
showStroke : this.options.segmentShowStroke,
|
||||
strokeWidth : this.options.segmentStrokeWidth,
|
||||
strokeColor : this.options.segmentStrokeColor,
|
||||
startAngle : Math.PI * 1.5,
|
||||
circumference : (this.options.animateRotate) ? 0 : this.calculateCircumference(segment.value),
|
||||
label : segment.label
|
||||
}));
|
||||
if (!silent){
|
||||
this.reflow();
|
||||
this.update();
|
||||
}
|
||||
},
|
||||
calculateCircumference : function(value){
|
||||
return (Math.PI*2)*(value / this.total);
|
||||
},
|
||||
calculateTotal : function(data){
|
||||
this.total = 0;
|
||||
helpers.each(data,function(segment){
|
||||
this.total += segment.value;
|
||||
},this);
|
||||
},
|
||||
update : function(){
|
||||
this.calculateTotal(this.segments);
|
||||
backgroundColor: slice.custom && slice.custom.backgroundColor ? slice.custom.backgroundColor : helpers.getValueAtIndexOrDefault(dataset.backgroundColor, index, this.options.elements.slice.backgroundColor),
|
||||
hoverBackgroundColor: slice.custom && slice.custom.hoverBackgroundColor ? slice.custom.hoverBackgroundColor : helpers.getValueAtIndexOrDefault(dataset.hoverBackgroundColor, index, this.options.elements.slice.hoverBackgroundColor),
|
||||
borderWidth: slice.custom && slice.custom.borderWidth ? slice.custom.borderWidth : helpers.getValueAtIndexOrDefault(dataset.borderWidth, index, this.options.elements.slice.borderWidth),
|
||||
borderColor: slice.custom && slice.custom.borderColor ? slice.custom.borderColor : helpers.getValueAtIndexOrDefault(dataset.borderColor, index, this.options.elements.slice.borderColor),
|
||||
|
||||
// Reset any highlight colours before updating.
|
||||
helpers.each(this.activeElements, function(activeElement){
|
||||
activeElement.restore(['fillColor']);
|
||||
});
|
||||
label: helpers.getValueAtIndexOrDefault(dataset.label, index, this.data.labels[index])
|
||||
},
|
||||
});
|
||||
|
||||
helpers.each(this.segments,function(segment){
|
||||
segment.save();
|
||||
});
|
||||
this.render();
|
||||
},
|
||||
if (index === 0) {
|
||||
slice._model.startAngle = Math.PI * -0.5; // use - PI / 2 instead of 3PI / 2 to make animations better. It means that we never deal with overflow during the transition function
|
||||
} else {
|
||||
slice._model.startAngle = dataset.metaData[index - 1]._model.endAngle;
|
||||
}
|
||||
|
||||
removeData: function(atIndex){
|
||||
var indexToDelete = (helpers.isNumber(atIndex)) ? atIndex : this.segments.length-1;
|
||||
this.segments.splice(indexToDelete, 1);
|
||||
this.reflow();
|
||||
this.update();
|
||||
},
|
||||
slice._model.endAngle = slice._model.startAngle + slice._model.circumference;
|
||||
|
||||
reflow : function(){
|
||||
helpers.extend(this.SegmentArc.prototype,{
|
||||
x : this.chart.width/2,
|
||||
y : this.chart.height/2
|
||||
});
|
||||
this.outerRadius = (helpers.min([this.chart.width,this.chart.height]) - this.options.segmentStrokeWidth/2)/2;
|
||||
helpers.each(this.segments, function(segment){
|
||||
segment.update({
|
||||
outerRadius : this.outerRadius,
|
||||
innerRadius : (this.outerRadius/100) * this.options.percentageInnerCutout
|
||||
});
|
||||
}, this);
|
||||
},
|
||||
draw : function(easeDecimal){
|
||||
var animDecimal = (easeDecimal) ? easeDecimal : 1;
|
||||
this.clear();
|
||||
helpers.each(this.segments,function(segment,index){
|
||||
segment.transition({
|
||||
circumference : this.calculateCircumference(segment.value),
|
||||
outerRadius : this.outerRadius,
|
||||
innerRadius : (this.outerRadius/100) * this.options.percentageInnerCutout
|
||||
},animDecimal);
|
||||
|
||||
segment.endAngle = segment.startAngle + segment.circumference;
|
||||
//Check to see if it's the last slice, if not get the next and update its start angle
|
||||
if (index < dataset.data.length - 1) {
|
||||
dataset.metaData[index + 1]._model.startAngle = slice._model.endAngle;
|
||||
}
|
||||
|
||||
segment.draw();
|
||||
if (index === 0){
|
||||
segment.startAngle = Math.PI * 1.5;
|
||||
}
|
||||
//Check to see if it's the last segment, if not get the next and update the start angle
|
||||
if (index < this.segments.length-1){
|
||||
this.segments[index+1].startAngle = segment.endAngle;
|
||||
}
|
||||
},this);
|
||||
slice.pivot();
|
||||
}, this);
|
||||
|
||||
}
|
||||
});
|
||||
}, this);
|
||||
|
||||
Chart.types.Doughnut.extend({
|
||||
name : "Pie",
|
||||
defaults : helpers.merge(defaultConfig,{percentageInnerCutout : 0})
|
||||
});
|
||||
this.render();
|
||||
},
|
||||
draw: function(easeDecimal) {
|
||||
easeDecimal = easeDecimal || 1;
|
||||
this.clear();
|
||||
|
||||
}).call(this);
|
||||
this.eachElement(function(slice) {
|
||||
slice.transition(easeDecimal).draw();
|
||||
}, this);
|
||||
|
||||
this.tooltip.transition(easeDecimal).draw();
|
||||
},
|
||||
events: function(e) {
|
||||
|
||||
// If exiting chart
|
||||
if (e.type == 'mouseout') {
|
||||
return this;
|
||||
}
|
||||
|
||||
this.lastActive = this.lastActive || [];
|
||||
|
||||
// Find Active Elements
|
||||
this.active = function() {
|
||||
switch (this.options.hover.mode) {
|
||||
case 'single':
|
||||
return this.getSliceAtEvent(e);
|
||||
case 'label':
|
||||
return this.getSlicesAtEvent(e);
|
||||
case 'dataset':
|
||||
return this.getDatasetAtEvent(e);
|
||||
default:
|
||||
return e;
|
||||
}
|
||||
}.call(this);
|
||||
|
||||
// On Hover hook
|
||||
if (this.options.hover.onHover) {
|
||||
this.options.hover.onHover.call(this, this.active);
|
||||
}
|
||||
|
||||
if (e.type == 'mouseup' || e.type == 'click') {
|
||||
if (this.options.onClick) {
|
||||
this.options.onClick.call(this, e, this.active);
|
||||
}
|
||||
}
|
||||
|
||||
var dataset;
|
||||
var index;
|
||||
// Remove styling for last active (even if it may still be active)
|
||||
if (this.lastActive.length) {
|
||||
switch (this.options.hover.mode) {
|
||||
case 'single':
|
||||
dataset = this.data.datasets[this.lastActive[0]._datasetIndex];
|
||||
index = this.lastActive[0]._index;
|
||||
|
||||
this.lastActive[0]._model.backgroundColor = this.lastActive[0].custom && this.lastActive[0].custom.backgroundColor ? this.lastActive[0].custom.backgroundColor : helpers.getValueAtIndexOrDefault(dataset.backgroundColor, index, this.options.elements.slice.backgroundColor);
|
||||
this.lastActive[0]._model.borderColor = this.lastActive[0].custom && this.lastActive[0].custom.borderColor ? this.lastActive[0].custom.borderColor : helpers.getValueAtIndexOrDefault(dataset.borderColor, index, this.options.elements.slice.borderColor);
|
||||
this.lastActive[0]._model.borderWidth = this.lastActive[0].custom && this.lastActive[0].custom.borderWidth ? this.lastActive[0].custom.borderWidth : helpers.getValueAtIndexOrDefault(dataset.borderWidth, index, this.options.elements.slice.borderWidth);
|
||||
break;
|
||||
case 'label':
|
||||
for (var i = 0; i < this.lastActive.length; i++) {
|
||||
dataset = this.data.datasets[this.lastActive[i]._datasetIndex];
|
||||
index = this.lastActive[i]._index;
|
||||
|
||||
this.lastActive[i]._model.backgroundColor = this.lastActive[i].custom && this.lastActive[i].custom.backgroundColor ? this.lastActive[i].custom.backgroundColor : helpers.getValueAtIndexOrDefault(dataset.backgroundColor, index, this.options.elements.slice.backgroundColor);
|
||||
this.lastActive[i]._model.borderColor = this.lastActive[i].custom && this.lastActive[i].custom.borderColor ? this.lastActive[i].custom.borderColor : helpers.getValueAtIndexOrDefault(dataset.borderColor, index, this.options.elements.slice.borderColor);
|
||||
this.lastActive[i]._model.borderWidth = this.lastActive[i].custom && this.lastActive[i].custom.borderWidth ? this.lastActive[i].custom.borderWidth : helpers.getValueAtIndexOrDefault(dataset.borderWidth, index, this.options.elements.slice.borderWidth);
|
||||
}
|
||||
break;
|
||||
case 'dataset':
|
||||
break;
|
||||
default:
|
||||
// Don't change anything
|
||||
}
|
||||
}
|
||||
|
||||
// Built in hover styling
|
||||
if (this.active.length && this.options.hover.mode) {
|
||||
switch (this.options.hover.mode) {
|
||||
case 'single':
|
||||
dataset = this.data.datasets[this.active[0]._datasetIndex];
|
||||
index = this.active[0]._index;
|
||||
|
||||
this.active[0]._model.radius = this.active[0].custom && this.active[0].custom.hoverRadius ? this.active[0].custom.hoverRadius : helpers.getValueAtIndexOrDefault(dataset.hoverRadius, index, this.active[0]._model.radius + 2);
|
||||
this.active[0]._model.backgroundColor = this.active[0].custom && this.active[0].custom.hoverBackgroundColor ? this.active[0].custom.hoverBackgroundColor : helpers.getValueAtIndexOrDefault(dataset.hoverBackgroundColor, index, helpers.color(this.active[0]._model.backgroundColor).saturate(0.5).darken(0.35).rgbString());
|
||||
this.active[0]._model.borderColor = this.active[0].custom && this.active[0].custom.hoverBorderColor ? this.active[0].custom.hoverBorderColor : helpers.getValueAtIndexOrDefault(dataset.hoverBorderColor, index, this.active[0]._model.borderColor);
|
||||
this.active[0]._model.borderWidth = this.active[0].custom && this.active[0].custom.hoverBorderWidth ? this.active[0].custom.hoverBorderWidth : helpers.getValueAtIndexOrDefault(dataset.hoverBorderWidth, index, this.active[0]._model.borderWidth);
|
||||
break;
|
||||
case 'label':
|
||||
for (var i = 0; i < this.active.length; i++) {
|
||||
dataset = this.data.datasets[this.active[i]._datasetIndex];
|
||||
index = this.active[i]._index;
|
||||
|
||||
this.active[i]._model.radius = this.active[i].custom && this.active[i].custom.hoverRadius ? this.active[i].custom.hoverRadius : helpers.getValueAtIndexOrDefault(dataset.hoverRadius, index, this.active[i]._model.radius + 2);
|
||||
this.active[i]._model.backgroundColor = this.active[i].custom && this.active[i].custom.hoverBackgroundColor ? this.active[i].custom.hoverBackgroundColor : helpers.getValueAtIndexOrDefault(dataset.hoverBackgroundColor, index, helpers.color(this.active[i]._model.backgroundColor).saturate(0.5).darken(0.35).rgbString());
|
||||
this.active[i]._model.borderColor = this.active[i].custom && this.active[i].custom.hoverBorderColor ? this.active[i].custom.hoverBorderColor : helpers.getValueAtIndexOrDefault(dataset.hoverBorderColor, index, this.active[0]._model.borderColor);
|
||||
this.active[i]._model.borderWidth = this.active[i].custom && this.active[i].custom.hoverBorderWidth ? this.active[i].custom.hoverBorderWidth : helpers.getValueAtIndexOrDefault(dataset.hoverBorderWidth, index, this.active[i]._model.borderWidth);
|
||||
}
|
||||
break;
|
||||
case 'dataset':
|
||||
break;
|
||||
default:
|
||||
// Don't change anything
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Built in Tooltips
|
||||
if (this.options.tooltips.enabled) {
|
||||
|
||||
// The usual updates
|
||||
this.tooltip.initialize();
|
||||
|
||||
// Active
|
||||
if (this.active.length) {
|
||||
this.tooltip._model.opacity = 1;
|
||||
|
||||
helpers.extend(this.tooltip, {
|
||||
_active: this.active,
|
||||
});
|
||||
|
||||
this.tooltip.update();
|
||||
} else {
|
||||
// Inactive
|
||||
this.tooltip._model.opacity = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Hover animations
|
||||
this.tooltip.pivot();
|
||||
|
||||
if (!this.animating) {
|
||||
var changed;
|
||||
|
||||
helpers.each(this.active, function(element, index) {
|
||||
if (element !== this.lastActive[index]) {
|
||||
changed = true;
|
||||
}
|
||||
}, 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.stop();
|
||||
this.render(this.options.hover.animationDuration);
|
||||
}
|
||||
}
|
||||
|
||||
// Remember Last Active
|
||||
this.lastActive = this.active;
|
||||
return this;
|
||||
},
|
||||
getSliceAtEvent: function(e) {
|
||||
var elements = [];
|
||||
|
||||
var location = helpers.getRelativePosition(e);
|
||||
|
||||
this.eachElement(function(slice, index) {
|
||||
if (slice.inRange(location.x, location.y)) {
|
||||
elements.push(slice);
|
||||
}
|
||||
}, this);
|
||||
return elements;
|
||||
},
|
||||
/*getSlicesAtEvent: function(e) {
|
||||
var elements = [];
|
||||
|
||||
var location = helpers.getRelativePosition(e);
|
||||
|
||||
this.eachElement(function(slice, index) {
|
||||
if (slice.inGroupRange(location.x, location.y)) {
|
||||
elements.push(slice);
|
||||
}
|
||||
}, this);
|
||||
return elements;
|
||||
},*/
|
||||
});
|
||||
|
||||
Chart.types.Doughnut.extend({
|
||||
name: "Pie",
|
||||
defaults: helpers.merge(defaultConfig, {
|
||||
cutoutPercentage: 0
|
||||
})
|
||||
});
|
||||
|
||||
}).call(this);
|
||||
|
||||
+589
-313
@@ -1,344 +1,620 @@
|
||||
(function(){
|
||||
"use strict";
|
||||
(function() {
|
||||
"use strict";
|
||||
|
||||
var root = this,
|
||||
Chart = root.Chart,
|
||||
helpers = Chart.helpers;
|
||||
var root = this,
|
||||
Chart = root.Chart,
|
||||
helpers = Chart.helpers;
|
||||
|
||||
var defaultConfig = {
|
||||
var defaultConfig = {
|
||||
|
||||
///Boolean - Whether grid lines are shown across the chart
|
||||
scaleShowGridLines : true,
|
||||
stacked: false,
|
||||
|
||||
//String - Colour of the grid lines
|
||||
scaleGridLineColor : "rgba(0,0,0,.05)",
|
||||
hover: {
|
||||
mode: "label"
|
||||
},
|
||||
|
||||
//Number - Width of the grid lines
|
||||
scaleGridLineWidth : 1,
|
||||
scales: {
|
||||
xAxes: [{
|
||||
scaleType: "dataset", // scatter should not use a dataset axis
|
||||
display: true,
|
||||
position: "bottom",
|
||||
id: "x-axis-1", // need an ID so datasets can reference the scale
|
||||
|
||||
//Boolean - Whether the line is curved between points
|
||||
bezierCurve : true,
|
||||
// grid line settings
|
||||
gridLines: {
|
||||
show: true,
|
||||
color: "rgba(0, 0, 0, 0.05)",
|
||||
lineWidth: 1,
|
||||
drawOnChartArea: true,
|
||||
drawTicks: true,
|
||||
zeroLineWidth: 1,
|
||||
zeroLineColor: "rgba(0,0,0,0.25)",
|
||||
offsetGridLines: false,
|
||||
},
|
||||
|
||||
//Number - Tension of the bezier curve between points
|
||||
bezierCurveTension : 0.4,
|
||||
// label settings
|
||||
labels: {
|
||||
show: true,
|
||||
template: "<%=value%>",
|
||||
fontSize: 12,
|
||||
fontStyle: "normal",
|
||||
fontColor: "#666",
|
||||
fontFamily: "Helvetica Neue",
|
||||
},
|
||||
}],
|
||||
yAxes: [{
|
||||
scaleType: "linear", // only linear but allow scale type registration. This allows extensions to exist solely for log scale for instance
|
||||
display: true,
|
||||
position: "left",
|
||||
id: "y-axis-1",
|
||||
|
||||
//Boolean - Whether to show a dot for each point
|
||||
pointDot : true,
|
||||
// grid line settings
|
||||
gridLines: {
|
||||
show: true,
|
||||
color: "rgba(0, 0, 0, 0.05)",
|
||||
lineWidth: 1,
|
||||
drawOnChartArea: true,
|
||||
drawTicks: true, // draw ticks extending towards the label
|
||||
zeroLineWidth: 1,
|
||||
zeroLineColor: "rgba(0,0,0,0.25)",
|
||||
},
|
||||
|
||||
//Number - Radius of each point dot in pixels
|
||||
pointDotRadius : 4,
|
||||
// scale numbers
|
||||
beginAtZero: false,
|
||||
override: null,
|
||||
|
||||
//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,
|
||||
|
||||
//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>"
|
||||
|
||||
};
|
||||
// label settings
|
||||
labels: {
|
||||
show: true,
|
||||
template: "<%=value%>",
|
||||
fontSize: 12,
|
||||
fontStyle: "normal",
|
||||
fontColor: "#666",
|
||||
fontFamily: "Helvetica Neue",
|
||||
}
|
||||
}],
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
Chart.Type.extend({
|
||||
name: "Line",
|
||||
defaults : defaultConfig,
|
||||
initialize: function(data){
|
||||
//Declare the extension of the default point, to cater for the options passed in to the constructor
|
||||
this.PointClass = Chart.Point.extend({
|
||||
strokeWidth : this.options.pointDotStrokeWidth,
|
||||
radius : this.options.pointDotRadius,
|
||||
display: this.options.pointDot,
|
||||
hitDetectionRadius : this.options.pointHitDetectionRadius,
|
||||
ctx : this.chart.ctx,
|
||||
inRange : function(mouseX){
|
||||
return (Math.pow(mouseX-this.x, 2) < Math.pow(this.radius + this.hitDetectionRadius,2));
|
||||
}
|
||||
});
|
||||
Chart.Type.extend({
|
||||
name: "Line",
|
||||
defaults: defaultConfig,
|
||||
initialize: function() {
|
||||
|
||||
this.datasets = [];
|
||||
var _this = this;
|
||||
|
||||
//Set up tooltip events on the chart
|
||||
if (this.options.showTooltips){
|
||||
helpers.bindEvents(this, this.options.tooltipEvents, function(evt){
|
||||
var activePoints = (evt.type !== 'mouseout') ? this.getPointsAtEvent(evt) : [];
|
||||
this.eachPoints(function(point){
|
||||
point.restore(['fillColor', 'strokeColor']);
|
||||
});
|
||||
helpers.each(activePoints, function(activePoint){
|
||||
activePoint.fillColor = activePoint.highlightFill;
|
||||
activePoint.strokeColor = activePoint.highlightStroke;
|
||||
});
|
||||
this.showTooltip(activePoints);
|
||||
});
|
||||
}
|
||||
// Events
|
||||
helpers.bindEvents(this, this.options.events, this.events);
|
||||
|
||||
//Iterate through each of the datasets, and build this into a property of the chart
|
||||
helpers.each(data.datasets,function(dataset){
|
||||
// Create a new line and its points for each dataset and piece of data
|
||||
helpers.each(this.data.datasets, function(dataset, datasetIndex) {
|
||||
|
||||
var datasetObject = {
|
||||
label : dataset.label || null,
|
||||
fillColor : dataset.fillColor,
|
||||
strokeColor : dataset.strokeColor,
|
||||
pointColor : dataset.pointColor,
|
||||
pointStrokeColor : dataset.pointStrokeColor,
|
||||
points : []
|
||||
};
|
||||
dataset.metaDataset = new Chart.Line({
|
||||
_chart: this.chart,
|
||||
_datasetIndex: datasetIndex,
|
||||
_points: dataset.metaData,
|
||||
});
|
||||
|
||||
this.datasets.push(datasetObject);
|
||||
dataset.metaData = [];
|
||||
|
||||
helpers.each(dataset.data, function(dataPoint, index) {
|
||||
dataset.metaData.push(new Chart.Point({
|
||||
_datasetIndex: datasetIndex,
|
||||
_index: index,
|
||||
_chart: this.chart,
|
||||
_model: {
|
||||
x: 0, //xScale.getPixelForValue(null, index, true),
|
||||
y: 0, //this.chartArea.bottom,
|
||||
},
|
||||
}));
|
||||
|
||||
}, this);
|
||||
|
||||
// The line chart onlty supports a single x axis because the x axis is always a dataset axis
|
||||
dataset.xAxisID = this.options.scales.xAxes[0].id;
|
||||
|
||||
if (!dataset.yAxisID) {
|
||||
dataset.yAxisID = this.options.scales.yAxes[0].id;
|
||||
}
|
||||
|
||||
}, this);
|
||||
|
||||
// Build and fit the scale. Needs to happen after the axis IDs have been set
|
||||
this.buildScale();
|
||||
|
||||
// Create tooltip instance exclusively for this chart with some defaults.
|
||||
this.tooltip = new Chart.Tooltip({
|
||||
_chart: this.chart,
|
||||
_data: this.data,
|
||||
_options: this.options,
|
||||
}, this);
|
||||
|
||||
// Need to fit scales before we reset elements.
|
||||
Chart.scaleService.fitScalesForChart(this, this.chart.width, this.chart.height);
|
||||
|
||||
// Reset so that we animation from the baseline
|
||||
this.resetElements();
|
||||
|
||||
// Update that shiz
|
||||
this.update();
|
||||
},
|
||||
nextPoint: function(collection, index) {
|
||||
return collection[index + 1] || collection[index];
|
||||
},
|
||||
previousPoint: function(collection, index) {
|
||||
return collection[index - 1] || collection[index];
|
||||
},
|
||||
resetElements: function() {
|
||||
// Update the points
|
||||
this.eachElement(function(point, index, dataset, datasetIndex) {
|
||||
var xScale = this.scales[this.data.datasets[datasetIndex].xAxisID];
|
||||
var yScale = this.scales[this.data.datasets[datasetIndex].yAxisID];
|
||||
|
||||
var yScalePoint;
|
||||
|
||||
if (yScale.min < 0 && yScale.max <0) {
|
||||
// all less than 0. use the top
|
||||
yScalePoint = yScale.getPixelForValue(yScale.max);
|
||||
} else if (yScale.min > 0 && yScale.max > 0) {
|
||||
yScalePoint = yScale.getPixelForValue(yScale.min);
|
||||
} else {
|
||||
yScalePoint = yScale.getPixelForValue(0);
|
||||
}
|
||||
|
||||
helpers.extend(point, {
|
||||
// Utility
|
||||
_chart: this.chart,
|
||||
_xScale: xScale,
|
||||
_yScale: yScale,
|
||||
_datasetIndex: datasetIndex,
|
||||
_index: index,
|
||||
|
||||
// Desired view properties
|
||||
_model: {
|
||||
x: xScale.getPixelForValue(null, index, true), // value not used in dataset scale, but we want a consistent API between scales
|
||||
y: yScalePoint,
|
||||
|
||||
// Appearance
|
||||
tension: point.custom && point.custom.tension ? point.custom.tension : this.options.elements.line.tension,
|
||||
radius: point.custom && point.custom.radius ? point.custom.pointRadius : helpers.getValueAtIndexOrDefault(this.data.datasets[datasetIndex].pointRadius, index, this.options.elements.point.radius),
|
||||
backgroundColor: point.custom && point.custom.backgroundColor ? point.custom.backgroundColor : helpers.getValueAtIndexOrDefault(this.data.datasets[datasetIndex].pointBackgroundColor, index, this.options.elements.point.backgroundColor),
|
||||
borderColor: point.custom && point.custom.borderColor ? point.custom.borderColor : helpers.getValueAtIndexOrDefault(this.data.datasets[datasetIndex].pointBorderColor, index, this.options.elements.point.borderColor),
|
||||
borderWidth: point.custom && point.custom.borderWidth ? point.custom.borderWidth : helpers.getValueAtIndexOrDefault(this.data.datasets[datasetIndex].pointBorderWidth, index, this.options.elements.point.borderWidth),
|
||||
skip: typeof this.data.datasets[datasetIndex].data[index] != 'number',
|
||||
|
||||
// Tooltip
|
||||
hoverRadius: point.custom && point.custom.hoverRadius ? point.custom.hoverRadius : helpers.getValueAtIndexOrDefault(this.data.datasets[datasetIndex].pointHitRadius, index, this.options.elements.point.hitRadius),
|
||||
},
|
||||
});
|
||||
}, this);
|
||||
|
||||
// Update control points for the bezier curve
|
||||
this.eachElement(function(point, index, dataset, datasetIndex) {
|
||||
var controlPoints = helpers.splineCurve(
|
||||
this.previousPoint(dataset, index)._model,
|
||||
point._model,
|
||||
this.nextPoint(dataset, index)._model,
|
||||
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
|
||||
|
||||
// Cap puter bezier handles to the upper/lower scale bounds
|
||||
if (controlPoints.next.y > this.chartArea.bottom) {
|
||||
point._model.controlPointNextY = this.chartArea.bottom;
|
||||
} else if (controlPoints.next.y < this.chartArea.top) {
|
||||
point._model.controlPointNextY = this.chartArea.top;
|
||||
} else {
|
||||
point._model.controlPointNextY = controlPoints.next.y;
|
||||
}
|
||||
|
||||
// Cap inner bezier handles to the upper/lower scale bounds
|
||||
if (controlPoints.previous.y > this.chartArea.bottom) {
|
||||
point._model.controlPointPreviousY = this.chartArea.bottom;
|
||||
} else if (controlPoints.previous.y < this.chartArea.top) {
|
||||
point._model.controlPointPreviousY = this.chartArea.top;
|
||||
} else {
|
||||
point._model.controlPointPreviousY = controlPoints.previous.y;
|
||||
}
|
||||
|
||||
// Now pivot the point for animation
|
||||
point.pivot();
|
||||
}, this);
|
||||
},
|
||||
update: function() {
|
||||
|
||||
Chart.scaleService.fitScalesForChart(this, this.chart.width, this.chart.height);
|
||||
|
||||
// Update the lines
|
||||
this.eachDataset(function(dataset, datasetIndex) {
|
||||
var yScale = this.scales[dataset.yAxisID];
|
||||
|
||||
helpers.extend(dataset.metaDataset, {
|
||||
// Utility
|
||||
_scale: yScale,
|
||||
_datasetIndex: datasetIndex,
|
||||
// Data
|
||||
_children: dataset.metaData,
|
||||
// Model
|
||||
_model: {
|
||||
// Appearance
|
||||
tension: dataset.tension || this.options.elements.line.tension,
|
||||
backgroundColor: dataset.backgroundColor || this.options.elements.line.backgroundColor,
|
||||
borderWidth: dataset.borderWidth || this.options.elements.line.borderWidth,
|
||||
borderColor: dataset.borderColor || this.options.elements.line.borderColor,
|
||||
fill: dataset.fill !== undefined ? dataset.fill : this.options.elements.line.fill, // use the value from the dataset if it was provided. else fall back to the default
|
||||
skipNull: dataset.skipNull !== undefined ? dataset.skipNull : this.options.elements.line.skipNull,
|
||||
drawNull: dataset.drawNull !== undefined ? dataset.drawNull : this.options.elements.line.drawNull,
|
||||
// Scale
|
||||
scaleTop: yScale.top,
|
||||
scaleBottom: yScale.bottom,
|
||||
scaleZero: yScale.getPixelForValue(0),
|
||||
},
|
||||
});
|
||||
|
||||
dataset.metaDataset.pivot();
|
||||
});
|
||||
|
||||
// Update the points
|
||||
this.eachElement(function(point, index, dataset, datasetIndex) {
|
||||
var xScale = this.scales[this.data.datasets[datasetIndex].xAxisID];
|
||||
var yScale = this.scales[this.data.datasets[datasetIndex].yAxisID];
|
||||
|
||||
helpers.extend(point, {
|
||||
// Utility
|
||||
_chart: this.chart,
|
||||
_xScale: xScale,
|
||||
_yScale: yScale,
|
||||
_datasetIndex: datasetIndex,
|
||||
_index: index,
|
||||
|
||||
// Desired view properties
|
||||
_model: {
|
||||
x: xScale.getPixelForValue(null, index, true), // value not used in dataset scale, but we want a consistent API between scales
|
||||
y: yScale.getPointPixelForValue(this.data.datasets[datasetIndex].data[index], index, datasetIndex),
|
||||
|
||||
// Appearance
|
||||
tension: point.custom && point.custom.tension ? point.custom.tension : this.options.elements.line.tension,
|
||||
radius: point.custom && point.custom.radius ? point.custom.pointRadius : helpers.getValueAtIndexOrDefault(this.data.datasets[datasetIndex].pointRadius, index, this.options.elements.point.radius),
|
||||
backgroundColor: point.custom && point.custom.backgroundColor ? point.custom.backgroundColor : helpers.getValueAtIndexOrDefault(this.data.datasets[datasetIndex].pointBackgroundColor, index, this.options.elements.point.backgroundColor),
|
||||
borderColor: point.custom && point.custom.borderColor ? point.custom.borderColor : helpers.getValueAtIndexOrDefault(this.data.datasets[datasetIndex].pointBorderColor, index, this.options.elements.point.borderColor),
|
||||
borderWidth: point.custom && point.custom.borderWidth ? point.custom.borderWidth : helpers.getValueAtIndexOrDefault(this.data.datasets[datasetIndex].pointBorderWidth, index, this.options.elements.point.borderWidth),
|
||||
skip: typeof this.data.datasets[datasetIndex].data[index] != 'number',
|
||||
|
||||
// Tooltip
|
||||
hoverRadius: point.custom && point.custom.hoverRadius ? point.custom.hoverRadius : helpers.getValueAtIndexOrDefault(this.data.datasets[datasetIndex].pointHitRadius, index, this.options.elements.point.hitRadius),
|
||||
},
|
||||
});
|
||||
}, this);
|
||||
|
||||
|
||||
helpers.each(dataset.data,function(dataPoint,index){
|
||||
//Best way to do this? or in draw sequence...?
|
||||
if (helpers.isNumber(dataPoint)){
|
||||
//Add a new point for each piece of data, passing any required data to draw.
|
||||
datasetObject.points.push(new this.PointClass({
|
||||
value : dataPoint,
|
||||
label : data.labels[index],
|
||||
// x: this.scale.calculateX(index),
|
||||
// y: this.scale.endPoint,
|
||||
strokeColor : dataset.pointStrokeColor,
|
||||
fillColor : dataset.pointColor,
|
||||
highlightFill : dataset.pointHighlightFill || dataset.pointColor,
|
||||
highlightStroke : dataset.pointHighlightStroke || dataset.pointStrokeColor
|
||||
}));
|
||||
}
|
||||
},this);
|
||||
// Update control points for the bezier curve
|
||||
this.eachElement(function(point, index, dataset, datasetIndex) {
|
||||
var controlPoints = helpers.splineCurve(
|
||||
this.previousPoint(dataset, index)._model,
|
||||
point._model,
|
||||
this.nextPoint(dataset, index)._model,
|
||||
point._model.tension
|
||||
);
|
||||
|
||||
this.buildScale(data.labels);
|
||||
point._model.controlPointPreviousX = controlPoints.previous.x;
|
||||
point._model.controlPointNextX = controlPoints.next.x;
|
||||
|
||||
// Prevent the bezier going outside of the bounds of the graph
|
||||
|
||||
// Cap puter bezier handles to the upper/lower scale bounds
|
||||
if (controlPoints.next.y > this.chartArea.bottom) {
|
||||
point._model.controlPointNextY = this.chartArea.bottom;
|
||||
} else if (controlPoints.next.y < this.chartArea.top) {
|
||||
point._model.controlPointNextY = this.chartArea.top;
|
||||
} else {
|
||||
point._model.controlPointNextY = controlPoints.next.y;
|
||||
}
|
||||
|
||||
// Cap inner bezier handles to the upper/lower scale bounds
|
||||
if (controlPoints.previous.y > this.chartArea.bottom) {
|
||||
point._model.controlPointPreviousY = this.chartArea.bottom;
|
||||
} else if (controlPoints.previous.y < this.chartArea.top) {
|
||||
point._model.controlPointPreviousY = this.chartArea.top;
|
||||
} else {
|
||||
point._model.controlPointPreviousY = controlPoints.previous.y;
|
||||
}
|
||||
|
||||
// Now pivot the point for animation
|
||||
point.pivot();
|
||||
}, this);
|
||||
|
||||
this.render();
|
||||
},
|
||||
buildScale: function() {
|
||||
var self = this;
|
||||
|
||||
// Function to determine the range of all the
|
||||
var calculateYRange = function() {
|
||||
this.min = null;
|
||||
this.max = null;
|
||||
|
||||
var positiveValues = [];
|
||||
var negativeValues = [];
|
||||
|
||||
if (self.options.stacked) {
|
||||
helpers.each(self.data.datasets, function(dataset) {
|
||||
if (dataset.yAxisID === this.id) {
|
||||
helpers.each(dataset.data, function(value, index) {
|
||||
positiveValues[index] = positiveValues[index] || 0;
|
||||
negativeValues[index] = negativeValues[index] || 0;
|
||||
|
||||
if (self.options.relativePoints) {
|
||||
positiveValues[index] = 100;
|
||||
} else {
|
||||
if (value < 0) {
|
||||
negativeValues[index] += value;
|
||||
} else {
|
||||
positiveValues[index] += value;
|
||||
}
|
||||
}
|
||||
}, this);
|
||||
}
|
||||
}, this);
|
||||
|
||||
var values = positiveValues.concat(negativeValues);
|
||||
this.min = helpers.min(values);
|
||||
this.max = helpers.max(values);
|
||||
} else {
|
||||
helpers.each(self.data.datasets, function(dataset) {
|
||||
if (dataset.yAxisID === this.id) {
|
||||
helpers.each(dataset.data, function(value, index) {
|
||||
if (this.min === null) {
|
||||
this.min = value;
|
||||
} else if (value < this.min) {
|
||||
this.min = value;
|
||||
}
|
||||
|
||||
if (this.max === null) {
|
||||
this.max = value;
|
||||
} else if (value > this.max) {
|
||||
this.max = value;
|
||||
}
|
||||
}, this);
|
||||
}
|
||||
}, this);
|
||||
}
|
||||
};
|
||||
|
||||
// Map of scale ID to scale object so we can lookup later
|
||||
this.scales = {};
|
||||
|
||||
// Build the x axis. The line chart only supports a single x axis
|
||||
var ScaleClass = Chart.scales.getScaleConstructor(this.options.scales.xAxes[0].scaleType);
|
||||
var xScale = new ScaleClass({
|
||||
ctx: this.chart.ctx,
|
||||
options: this.options.scales.xAxes[0],
|
||||
calculateRange: function() {
|
||||
this.labels = self.data.labels;
|
||||
this.min = 0;
|
||||
this.max = this.labels.length;
|
||||
},
|
||||
id: this.options.scales.xAxes[0].id,
|
||||
});
|
||||
this.scales[xScale.id] = xScale;
|
||||
|
||||
// Build up all the y scales
|
||||
helpers.each(this.options.scales.yAxes, function(yAxisOptions) {
|
||||
var ScaleClass = Chart.scales.getScaleConstructor(yAxisOptions.scaleType);
|
||||
var scale = new ScaleClass({
|
||||
ctx: this.chart.ctx,
|
||||
options: yAxisOptions,
|
||||
calculateRange: calculateYRange,
|
||||
getPointPixelForValue: function(value, index, datasetIndex) {
|
||||
if (self.options.stacked) {
|
||||
var offsetPos = 0;
|
||||
var offsetNeg = 0;
|
||||
|
||||
for (var i = 0; i < datasetIndex; ++i) {
|
||||
if (self.data.datasets[i].data[index] < 0) {
|
||||
offsetNeg += self.data.datasets[i].data[index];
|
||||
} else {
|
||||
offsetPos += self.data.datasets[i].data[index];
|
||||
}
|
||||
}
|
||||
|
||||
if (value < 0) {
|
||||
return this.getPixelForValue(offsetNeg + value);
|
||||
} else {
|
||||
return this.getPixelForValue(offsetPos + value);
|
||||
}
|
||||
} else {
|
||||
return this.getPixelForValue(value);
|
||||
}
|
||||
},
|
||||
id: yAxisOptions.id,
|
||||
});
|
||||
|
||||
this.scales[scale.id] = scale;
|
||||
}, this);
|
||||
},
|
||||
draw: function(ease) {
|
||||
|
||||
var easingDecimal = ease || 1;
|
||||
this.clear();
|
||||
|
||||
// Draw all the scales
|
||||
helpers.each(this.scales, function(scale) {
|
||||
scale.draw(this.chartArea);
|
||||
}, this);
|
||||
|
||||
// reverse for-loop for proper stacking
|
||||
for (var i = this.data.datasets.length - 1; i >= 0; i--) {
|
||||
|
||||
var dataset = this.data.datasets[i];
|
||||
|
||||
// Transition Point Locations
|
||||
helpers.each(dataset.metaData, function(point, index) {
|
||||
point.transition(easingDecimal);
|
||||
}, this);
|
||||
|
||||
// Transition and Draw the line
|
||||
dataset.metaDataset.transition(easingDecimal).draw();
|
||||
|
||||
// Draw the points
|
||||
helpers.each(dataset.metaData, function(point) {
|
||||
point.draw();
|
||||
});
|
||||
}
|
||||
|
||||
// Finally draw the tooltip
|
||||
this.tooltip.transition(easingDecimal).draw();
|
||||
},
|
||||
events: function(e) {
|
||||
|
||||
// If exiting chart
|
||||
if (e.type == 'mouseout') {
|
||||
return this;
|
||||
}
|
||||
|
||||
this.lastActive = this.lastActive || [];
|
||||
|
||||
// Find Active Elements
|
||||
this.active = function() {
|
||||
switch (this.options.hover.mode) {
|
||||
case 'single':
|
||||
return this.getElementAtEvent(e);
|
||||
case 'label':
|
||||
return this.getElementsAtEvent(e);
|
||||
case 'dataset':
|
||||
return this.getDatasetAtEvent(e);
|
||||
default:
|
||||
return e;
|
||||
}
|
||||
}.call(this);
|
||||
|
||||
// On Hover hook
|
||||
if (this.options.hover.onHover) {
|
||||
this.options.hover.onHover.call(this, this.active);
|
||||
}
|
||||
|
||||
if (e.type == 'mouseup' || e.type == 'click') {
|
||||
if (this.options.onClick) {
|
||||
this.options.onClick.call(this, e, this.active);
|
||||
}
|
||||
}
|
||||
|
||||
var dataset;
|
||||
var index;
|
||||
// Remove styling for last active (even if it may still be active)
|
||||
if (this.lastActive.length) {
|
||||
switch (this.options.hover.mode) {
|
||||
case 'single':
|
||||
dataset = this.data.datasets[this.lastActive[0]._datasetIndex];
|
||||
index = this.lastActive[0]._index;
|
||||
|
||||
this.lastActive[0]._model.radius = this.lastActive[0].custom && this.lastActive[0].custom.radius ? this.lastActive[0].custom.pointRadius : helpers.getValueAtIndexOrDefault(dataset.pointRadius, index, this.options.elements.point.radius);
|
||||
this.lastActive[0]._model.backgroundColor = this.lastActive[0].custom && this.lastActive[0].custom.backgroundColor ? this.lastActive[0].custom.backgroundColor : helpers.getValueAtIndexOrDefault(dataset.pointBackgroundColor, index, this.options.elements.point.backgroundColor);
|
||||
this.lastActive[0]._model.borderColor = this.lastActive[0].custom && this.lastActive[0].custom.borderColor ? this.lastActive[0].custom.borderColor : helpers.getValueAtIndexOrDefault(dataset.pointBorderColor, index, this.options.elements.point.borderColor);
|
||||
this.lastActive[0]._model.borderWidth = this.lastActive[0].custom && this.lastActive[0].custom.borderWidth ? this.lastActive[0].custom.borderWidth : helpers.getValueAtIndexOrDefault(dataset.pointBorderWidth, index, this.options.elements.point.borderWidth);
|
||||
break;
|
||||
case 'label':
|
||||
for (var i = 0; i < this.lastActive.length; i++) {
|
||||
dataset = this.data.datasets[this.lastActive[i]._datasetIndex];
|
||||
index = this.lastActive[i]._index;
|
||||
|
||||
this.lastActive[i]._model.radius = this.lastActive[i].custom && this.lastActive[i].custom.radius ? this.lastActive[i].custom.pointRadius : helpers.getValueAtIndexOrDefault(dataset.pointRadius, index, this.options.elements.point.radius);
|
||||
this.lastActive[i]._model.backgroundColor = this.lastActive[i].custom && this.lastActive[i].custom.backgroundColor ? this.lastActive[i].custom.backgroundColor : helpers.getValueAtIndexOrDefault(dataset.pointBackgroundColor, index, this.options.elements.point.backgroundColor);
|
||||
this.lastActive[i]._model.borderColor = this.lastActive[i].custom && this.lastActive[i].custom.borderColor ? this.lastActive[i].custom.borderColor : helpers.getValueAtIndexOrDefault(dataset.pointBorderColor, index, this.options.elements.point.borderColor);
|
||||
this.lastActive[i]._model.borderWidth = this.lastActive[i].custom && this.lastActive[i].custom.borderWidth ? this.lastActive[i].custom.borderWidth : helpers.getValueAtIndexOrDefault(dataset.pointBorderWidth, index, this.options.elements.point.borderWidth);
|
||||
}
|
||||
break;
|
||||
case 'dataset':
|
||||
break;
|
||||
default:
|
||||
// Don't change anything
|
||||
}
|
||||
}
|
||||
|
||||
// Built in hover styling
|
||||
if (this.active.length && this.options.hover.mode) {
|
||||
switch (this.options.hover.mode) {
|
||||
case 'single':
|
||||
dataset = this.data.datasets[this.active[0]._datasetIndex];
|
||||
index = this.active[0]._index;
|
||||
|
||||
this.active[0]._model.radius = this.active[0].custom && this.active[0].custom.hoverRadius ? this.active[0].custom.hoverRadius : helpers.getValueAtIndexOrDefault(dataset.pointHoverRadius, index, this.active[0]._model.radius + 2);
|
||||
this.active[0]._model.backgroundColor = this.active[0].custom && this.active[0].custom.hoverBackgroundColor ? this.active[0].custom.hoverBackgroundColor : helpers.getValueAtIndexOrDefault(dataset.pointHoverBackgroundColor, index, helpers.color(this.active[0]._model.backgroundColor).saturate(0.5).darken(0.35).rgbString());
|
||||
this.active[0]._model.borderColor = this.active[0].custom && this.active[0].custom.hoverBorderColor ? this.active[0].custom.hoverBorderColor : helpers.getValueAtIndexOrDefault(dataset.pointHoverBorderColor, index, helpers.color(this.active[0]._model.borderColor).saturate(0.5).darken(0.35).rgbString());
|
||||
this.active[0]._model.borderWidth = this.active[0].custom && this.active[0].custom.hoverBorderWidth ? this.active[0].custom.hoverBorderWidth : helpers.getValueAtIndexOrDefault(dataset.pointBorderWidth, index, this.active[0]._model.borderWidth + 2);
|
||||
break;
|
||||
case 'label':
|
||||
for (var i = 0; i < this.active.length; i++) {
|
||||
dataset = this.data.datasets[this.active[i]._datasetIndex];
|
||||
index = this.active[i]._index;
|
||||
|
||||
this.active[i]._model.radius = this.active[i].custom && this.active[i].custom.hoverRadius ? this.active[i].custom.hoverRadius : helpers.getValueAtIndexOrDefault(dataset.pointHoverRadius, index, this.active[i]._model.radius + 2);
|
||||
this.active[i]._model.backgroundColor = this.active[i].custom && this.active[i].custom.hoverBackgroundColor ? this.active[i].custom.hoverBackgroundColor : helpers.getValueAtIndexOrDefault(dataset.pointHoverBackgroundColor, index, helpers.color(this.active[i]._model.backgroundColor).saturate(0.5).darken(0.35).rgbString());
|
||||
this.active[i]._model.borderColor = this.active[i].custom && this.active[i].custom.hoverBorderColor ? this.active[i].custom.hoverBorderColor : helpers.getValueAtIndexOrDefault(dataset.pointHoverBorderColor, index, helpers.color(this.active[i]._model.borderColor).saturate(0.5).darken(0.35).rgbString());
|
||||
this.active[i]._model.borderWidth = this.active[i].custom && this.active[i].custom.hoverBorderWidth ? this.active[i].custom.hoverBorderWidth : helpers.getValueAtIndexOrDefault(dataset.pointBorderWidth, index, this.active[i]._model.borderWidth + 2);
|
||||
}
|
||||
break;
|
||||
case 'dataset':
|
||||
break;
|
||||
default:
|
||||
// Don't change anything
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
this.eachPoints(function(point, index){
|
||||
helpers.extend(point, {
|
||||
x: this.scale.calculateX(index),
|
||||
y: this.scale.endPoint
|
||||
});
|
||||
point.save();
|
||||
}, this);
|
||||
// Built in Tooltips
|
||||
if (this.options.tooltips.enabled) {
|
||||
|
||||
},this);
|
||||
// The usual updates
|
||||
this.tooltip.initialize();
|
||||
|
||||
// Active
|
||||
if (this.active.length) {
|
||||
this.tooltip._model.opacity = 1;
|
||||
|
||||
helpers.extend(this.tooltip, {
|
||||
_active: this.active,
|
||||
});
|
||||
|
||||
this.tooltip.update();
|
||||
} else {
|
||||
// Inactive
|
||||
this.tooltip._model.opacity = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
this.render();
|
||||
},
|
||||
update : function(){
|
||||
this.scale.update();
|
||||
// Reset any highlight colours before updating.
|
||||
helpers.each(this.activeElements, function(activeElement){
|
||||
activeElement.restore(['fillColor', 'strokeColor']);
|
||||
});
|
||||
this.eachPoints(function(point){
|
||||
point.save();
|
||||
});
|
||||
this.render();
|
||||
},
|
||||
eachPoints : function(callback){
|
||||
helpers.each(this.datasets,function(dataset){
|
||||
helpers.each(dataset.points,callback,this);
|
||||
},this);
|
||||
},
|
||||
getPointsAtEvent : function(e){
|
||||
var pointsArray = [],
|
||||
eventPosition = helpers.getRelativePosition(e);
|
||||
helpers.each(this.datasets,function(dataset){
|
||||
helpers.each(dataset.points,function(point){
|
||||
if (point.inRange(eventPosition.x,eventPosition.y)) pointsArray.push(point);
|
||||
});
|
||||
},this);
|
||||
return pointsArray;
|
||||
},
|
||||
buildScale : function(labels){
|
||||
var self = this;
|
||||
// Hover animations
|
||||
this.tooltip.pivot();
|
||||
|
||||
var dataTotal = function(){
|
||||
var values = [];
|
||||
self.eachPoints(function(point){
|
||||
values.push(point.value);
|
||||
});
|
||||
if (!this.animating) {
|
||||
var changed;
|
||||
|
||||
return values;
|
||||
};
|
||||
helpers.each(this.active, function(element, index) {
|
||||
if (element !== this.lastActive[index]) {
|
||||
changed = true;
|
||||
}
|
||||
}, this);
|
||||
|
||||
var scaleOptions = {
|
||||
templateString : this.options.scaleLabel,
|
||||
height : this.chart.height,
|
||||
width : this.chart.width,
|
||||
ctx : this.chart.ctx,
|
||||
textColor : this.options.scaleFontColor,
|
||||
fontSize : this.options.scaleFontSize,
|
||||
fontStyle : this.options.scaleFontStyle,
|
||||
fontFamily : this.options.scaleFontFamily,
|
||||
valuesCount : labels.length,
|
||||
beginAtZero : this.options.scaleBeginAtZero,
|
||||
integersOnly : this.options.scaleIntegersOnly,
|
||||
calculateYRange : function(currentHeight){
|
||||
var updatedRanges = helpers.calculateScaleRange(
|
||||
dataTotal(),
|
||||
currentHeight,
|
||||
this.fontSize,
|
||||
this.beginAtZero,
|
||||
this.integersOnly
|
||||
);
|
||||
helpers.extend(this, updatedRanges);
|
||||
},
|
||||
xLabels : labels,
|
||||
font : helpers.fontString(this.options.scaleFontSize, this.options.scaleFontStyle, this.options.scaleFontFamily),
|
||||
lineWidth : this.options.scaleLineWidth,
|
||||
lineColor : this.options.scaleLineColor,
|
||||
gridLineWidth : (this.options.scaleShowGridLines) ? this.options.scaleGridLineWidth : 0,
|
||||
gridLineColor : (this.options.scaleShowGridLines) ? this.options.scaleGridLineColor : "rgba(0,0,0,0)",
|
||||
padding: (this.options.showScale) ? 0 : this.options.pointDotRadius + this.options.pointDotStrokeWidth,
|
||||
showLabels : this.options.scaleShowLabels,
|
||||
display : this.options.showScale
|
||||
};
|
||||
// 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)) {
|
||||
|
||||
if (this.options.scaleOverride){
|
||||
helpers.extend(scaleOptions, {
|
||||
calculateYRange: helpers.noop,
|
||||
steps: this.options.scaleSteps,
|
||||
stepValue: this.options.scaleStepWidth,
|
||||
min: this.options.scaleStartValue,
|
||||
max: this.options.scaleStartValue + (this.options.scaleSteps * this.options.scaleStepWidth)
|
||||
});
|
||||
}
|
||||
this.stop();
|
||||
this.render(this.options.hover.animationDuration);
|
||||
}
|
||||
}
|
||||
|
||||
// Remember Last Active
|
||||
this.lastActive = this.active;
|
||||
return this;
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
this.scale = new Chart.Scale(scaleOptions);
|
||||
},
|
||||
addData : function(valuesArray,label){
|
||||
//Map the values array for each of the datasets
|
||||
|
||||
helpers.each(valuesArray,function(value,datasetIndex){
|
||||
if (helpers.isNumber(value)){
|
||||
//Add a new point for each piece of data, passing any required data to draw.
|
||||
this.datasets[datasetIndex].points.push(new this.PointClass({
|
||||
value : value,
|
||||
label : label,
|
||||
x: this.scale.calculateX(this.scale.valuesCount+1),
|
||||
y: this.scale.endPoint,
|
||||
strokeColor : this.datasets[datasetIndex].pointStrokeColor,
|
||||
fillColor : this.datasets[datasetIndex].pointColor
|
||||
}));
|
||||
}
|
||||
},this);
|
||||
|
||||
this.scale.addXLabel(label);
|
||||
//Then re-render the chart.
|
||||
this.update();
|
||||
},
|
||||
removeData : function(){
|
||||
this.scale.removeXLabel();
|
||||
//Then re-render the chart.
|
||||
helpers.each(this.datasets,function(dataset){
|
||||
dataset.points.shift();
|
||||
},this);
|
||||
this.update();
|
||||
},
|
||||
reflow : function(){
|
||||
var newScaleProps = helpers.extend({
|
||||
height : this.chart.height,
|
||||
width : this.chart.width
|
||||
});
|
||||
this.scale.update(newScaleProps);
|
||||
},
|
||||
draw : function(ease){
|
||||
var easingDecimal = ease || 1;
|
||||
this.clear();
|
||||
|
||||
var ctx = this.chart.ctx;
|
||||
|
||||
this.scale.draw(easingDecimal);
|
||||
|
||||
|
||||
helpers.each(this.datasets,function(dataset){
|
||||
|
||||
//Transition each point first so that the line and point drawing isn't out of sync
|
||||
//We can use this extra loop to calculate the control points of this dataset also in this loop
|
||||
|
||||
helpers.each(dataset.points,function(point,index){
|
||||
point.transition({
|
||||
y : this.scale.calculateY(point.value),
|
||||
x : this.scale.calculateX(index)
|
||||
}, easingDecimal);
|
||||
|
||||
},this);
|
||||
|
||||
|
||||
// Control points need to be calculated in a seperate loop, because we need to know the current x/y of the point
|
||||
// This would cause issues when there is no animation, because the y of the next point would be 0, so beziers would be skewed
|
||||
if (this.options.bezierCurve){
|
||||
helpers.each(dataset.points,function(point,index){
|
||||
//If we're at the start or end, we don't have a previous/next point
|
||||
//By setting the tension to 0 here, the curve will transition to straight at the end
|
||||
if (index === 0){
|
||||
point.controlPoints = helpers.splineCurve(point,point,dataset.points[index+1],0);
|
||||
}
|
||||
else if (index >= dataset.points.length-1){
|
||||
point.controlPoints = helpers.splineCurve(dataset.points[index-1],point,point,0);
|
||||
}
|
||||
else{
|
||||
point.controlPoints = helpers.splineCurve(dataset.points[index-1],point,dataset.points[index+1],this.options.bezierCurveTension);
|
||||
}
|
||||
},this);
|
||||
}
|
||||
|
||||
|
||||
//Draw the line between all the points
|
||||
ctx.lineWidth = this.options.datasetStrokeWidth;
|
||||
ctx.strokeStyle = dataset.strokeColor;
|
||||
ctx.beginPath();
|
||||
helpers.each(dataset.points,function(point,index){
|
||||
if (index>0){
|
||||
if(this.options.bezierCurve){
|
||||
ctx.bezierCurveTo(
|
||||
dataset.points[index-1].controlPoints.outer.x,
|
||||
dataset.points[index-1].controlPoints.outer.y,
|
||||
point.controlPoints.inner.x,
|
||||
point.controlPoints.inner.y,
|
||||
point.x,
|
||||
point.y
|
||||
);
|
||||
}
|
||||
else{
|
||||
ctx.lineTo(point.x,point.y);
|
||||
}
|
||||
|
||||
}
|
||||
else{
|
||||
ctx.moveTo(point.x,point.y);
|
||||
}
|
||||
},this);
|
||||
ctx.stroke();
|
||||
|
||||
|
||||
if (this.options.datasetFill){
|
||||
//Round off the line by going to the base of the chart, back to the start, then fill.
|
||||
ctx.lineTo(dataset.points[dataset.points.length-1].x, this.scale.endPoint);
|
||||
ctx.lineTo(this.scale.calculateX(0), this.scale.endPoint);
|
||||
ctx.fillStyle = dataset.fillColor;
|
||||
ctx.closePath();
|
||||
ctx.fill();
|
||||
}
|
||||
|
||||
//Now draw the points over the line
|
||||
//A little inefficient double looping, but better than the line
|
||||
//lagging behind the point positions
|
||||
helpers.each(dataset.points,function(point){
|
||||
point.draw();
|
||||
});
|
||||
|
||||
},this);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
}).call(this);
|
||||
}).call(this);
|
||||
|
||||
+369
-214
@@ -1,248 +1,403 @@
|
||||
(function(){
|
||||
"use strict";
|
||||
(function() {
|
||||
"use strict";
|
||||
|
||||
var root = this,
|
||||
Chart = root.Chart,
|
||||
//Cache a local reference to Chart.helpers
|
||||
helpers = Chart.helpers;
|
||||
var root = this,
|
||||
Chart = root.Chart,
|
||||
//Cache a local reference to Chart.helpers
|
||||
helpers = Chart.helpers;
|
||||
|
||||
var defaultConfig = {
|
||||
//Boolean - Show a backdrop to the scale label
|
||||
scaleShowLabelBackdrop : true,
|
||||
var defaultConfig = {
|
||||
|
||||
//String - The colour of the label backdrop
|
||||
scaleBackdropColor : "rgba(255,255,255,0.75)",
|
||||
scale: {
|
||||
scaleType: "radialLinear",
|
||||
display: true,
|
||||
|
||||
// Boolean - Whether the scale should begin at zero
|
||||
scaleBeginAtZero : true,
|
||||
//Boolean - Whether to animate scaling the chart from the centre
|
||||
animate: false,
|
||||
|
||||
//Number - The backdrop padding above & below the label in pixels
|
||||
scaleBackdropPaddingY : 2,
|
||||
lineArc: true,
|
||||
|
||||
//Number - The backdrop padding to the side of the label in pixels
|
||||
scaleBackdropPaddingX : 2,
|
||||
// grid line settings
|
||||
gridLines: {
|
||||
show: true,
|
||||
color: "rgba(0, 0, 0, 0.05)",
|
||||
lineWidth: 1,
|
||||
},
|
||||
|
||||
//Boolean - Show line for each value in the scale
|
||||
scaleShowLine : true,
|
||||
// scale numbers
|
||||
beginAtZero: true,
|
||||
|
||||
//Boolean - Stroke a line around each segment in the chart
|
||||
segmentShowStroke : true,
|
||||
// label settings
|
||||
labels: {
|
||||
show: true,
|
||||
template: "<%=value%>",
|
||||
fontSize: 12,
|
||||
fontStyle: "normal",
|
||||
fontColor: "#666",
|
||||
fontFamily: "Helvetica Neue",
|
||||
|
||||
//String - The colour of the stroke on each segement.
|
||||
segmentStrokeColor : "#fff",
|
||||
//Boolean - Show a backdrop to the scale label
|
||||
showLabelBackdrop: true,
|
||||
|
||||
//Number - The width of the stroke value in pixels
|
||||
segmentStrokeWidth : 2,
|
||||
//String - The colour of the label backdrop
|
||||
backdropColor: "rgba(255,255,255,0.75)",
|
||||
|
||||
//Number - Amount of animation steps
|
||||
animationSteps : 100,
|
||||
//Number - The backdrop padding above & below the label in pixels
|
||||
backdropPaddingY: 2,
|
||||
|
||||
//String - Animation easing effect.
|
||||
animationEasing : "easeOutBounce",
|
||||
//Number - The backdrop padding to the side of the label in pixels
|
||||
backdropPaddingX: 2,
|
||||
}
|
||||
},
|
||||
|
||||
//Boolean - Whether to animate the rotation of the chart
|
||||
animateRotate : true,
|
||||
|
||||
//Boolean - Whether to animate scaling the chart from the centre
|
||||
animateScale : false,
|
||||
|
||||
//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>"
|
||||
};
|
||||
//Boolean - Whether to animate the rotation of the chart
|
||||
animateRotate: true,
|
||||
};
|
||||
|
||||
|
||||
Chart.Type.extend({
|
||||
//Passing in a name registers this chart in the Chart namespace
|
||||
name: "PolarArea",
|
||||
//Providing a defaults will also register the deafults in the chart namespace
|
||||
defaults : defaultConfig,
|
||||
//Initialize is fired when the chart is initialized - Data is passed in as a parameter
|
||||
//Config is automatically merged by the core of Chart.js, and is available at this.options
|
||||
initialize: function(data){
|
||||
this.segments = [];
|
||||
//Declare segment class as a chart instance specific class, so it can share props for this instance
|
||||
this.SegmentArc = Chart.Arc.extend({
|
||||
showStroke : this.options.segmentShowStroke,
|
||||
strokeWidth : this.options.segmentStrokeWidth,
|
||||
strokeColor : this.options.segmentStrokeColor,
|
||||
ctx : this.chart.ctx,
|
||||
innerRadius : 0,
|
||||
x : this.chart.width/2,
|
||||
y : this.chart.height/2
|
||||
});
|
||||
this.scale = new Chart.RadialScale({
|
||||
display: this.options.showScale,
|
||||
fontStyle: this.options.scaleFontStyle,
|
||||
fontSize: this.options.scaleFontSize,
|
||||
fontFamily: this.options.scaleFontFamily,
|
||||
fontColor: this.options.scaleFontColor,
|
||||
showLabels: this.options.scaleShowLabels,
|
||||
showLabelBackdrop: this.options.scaleShowLabelBackdrop,
|
||||
backdropColor: this.options.scaleBackdropColor,
|
||||
backdropPaddingY : this.options.scaleBackdropPaddingY,
|
||||
backdropPaddingX: this.options.scaleBackdropPaddingX,
|
||||
lineWidth: (this.options.scaleShowLine) ? this.options.scaleLineWidth : 0,
|
||||
lineColor: this.options.scaleLineColor,
|
||||
lineArc: true,
|
||||
width: this.chart.width,
|
||||
height: this.chart.height,
|
||||
xCenter: this.chart.width/2,
|
||||
yCenter: this.chart.height/2,
|
||||
ctx : this.chart.ctx,
|
||||
templateString: this.options.scaleLabel,
|
||||
valuesCount: data.length
|
||||
});
|
||||
Chart.Type.extend({
|
||||
//Passing in a name registers this chart in the Chart namespace
|
||||
name: "PolarArea",
|
||||
//Providing a defaults will also register the deafults in the chart namespace
|
||||
defaults: defaultConfig,
|
||||
//Initialize is fired when the chart is initialized - Data is passed in as a parameter
|
||||
//Config is automatically merged by the core of Chart.js, and is available at this.options
|
||||
initialize: function() {
|
||||
|
||||
this.updateScaleRange(data);
|
||||
// Scale setup
|
||||
var self = this;
|
||||
var ScaleClass = Chart.scales.getScaleConstructor(this.options.scale.scaleType);
|
||||
this.scale = new ScaleClass({
|
||||
options: this.options.scale,
|
||||
lineArc: true,
|
||||
width: this.chart.width,
|
||||
height: this.chart.height,
|
||||
xCenter: this.chart.width / 2,
|
||||
yCenter: this.chart.height / 2,
|
||||
ctx: this.chart.ctx,
|
||||
valuesCount: this.data.length,
|
||||
calculateRange: function() {
|
||||
this.min = null;
|
||||
this.max = null;
|
||||
|
||||
this.scale.update();
|
||||
helpers.each(self.data.datasets[0].data, function(value) {
|
||||
if (this.min === null) {
|
||||
this.min = value;
|
||||
} else if (value < this.min) {
|
||||
this.min = value;
|
||||
}
|
||||
|
||||
helpers.each(data,function(segment,index){
|
||||
this.addData(segment,index,true);
|
||||
},this);
|
||||
if (this.max === null) {
|
||||
this.max = value;
|
||||
} else if (value > this.max) {
|
||||
this.max = value;
|
||||
}
|
||||
}, this);
|
||||
}
|
||||
});
|
||||
|
||||
//Set up tooltip events on the chart
|
||||
if (this.options.showTooltips){
|
||||
helpers.bindEvents(this, this.options.tooltipEvents, function(evt){
|
||||
var activeSegments = (evt.type !== 'mouseout') ? this.getSegmentsAtEvent(evt) : [];
|
||||
helpers.each(this.segments,function(segment){
|
||||
segment.restore(["fillColor"]);
|
||||
});
|
||||
helpers.each(activeSegments,function(activeSegment){
|
||||
activeSegment.fillColor = activeSegment.highlightColor;
|
||||
});
|
||||
this.showTooltip(activeSegments);
|
||||
});
|
||||
}
|
||||
helpers.bindEvents(this, this.options.events, this.events);
|
||||
|
||||
this.render();
|
||||
},
|
||||
getSegmentsAtEvent : function(e){
|
||||
var segmentsArray = [];
|
||||
//Set up tooltip events on the chart
|
||||
helpers.bindEvents(this, this.options.events, this.events);
|
||||
|
||||
var location = helpers.getRelativePosition(e);
|
||||
//Create a new bar for each piece of data
|
||||
helpers.each(this.data.datasets, function(dataset, datasetIndex) {
|
||||
dataset.metaData = [];
|
||||
helpers.each(dataset.data, function(dataPoint, index) {
|
||||
dataset.metaData.push(new Chart.Arc({
|
||||
_chart: this.chart,
|
||||
_datasetIndex: datasetIndex,
|
||||
_index: index,
|
||||
_model: {}
|
||||
}));
|
||||
}, this);
|
||||
}, this);
|
||||
|
||||
helpers.each(this.segments,function(segment){
|
||||
if (segment.inRange(location.x,location.y)) segmentsArray.push(segment);
|
||||
},this);
|
||||
return segmentsArray;
|
||||
},
|
||||
addData : function(segment, atIndex, silent){
|
||||
var index = atIndex || this.segments.length;
|
||||
// Create tooltip instance exclusively for this chart with some defaults.
|
||||
this.tooltip = new Chart.Tooltip({
|
||||
_chart: this.chart,
|
||||
_data: this.data,
|
||||
_options: this.options,
|
||||
}, this);
|
||||
|
||||
this.segments.splice(index, 0, new this.SegmentArc({
|
||||
fillColor: segment.color,
|
||||
highlightColor: segment.highlight || segment.color,
|
||||
label: segment.label,
|
||||
value: segment.value,
|
||||
outerRadius: (this.options.animateScale) ? 0 : this.scale.calculateCenterOffset(segment.value),
|
||||
circumference: (this.options.animateRotate) ? 0 : this.scale.getCircumference(),
|
||||
startAngle: Math.PI * 1.5
|
||||
}));
|
||||
if (!silent){
|
||||
this.reflow();
|
||||
this.update();
|
||||
}
|
||||
},
|
||||
removeData: function(atIndex){
|
||||
var indexToDelete = (helpers.isNumber(atIndex)) ? atIndex : this.segments.length-1;
|
||||
this.segments.splice(indexToDelete, 1);
|
||||
this.reflow();
|
||||
this.update();
|
||||
},
|
||||
calculateTotal: function(data){
|
||||
this.total = 0;
|
||||
helpers.each(data,function(segment){
|
||||
this.total += segment.value;
|
||||
},this);
|
||||
this.scale.valuesCount = this.segments.length;
|
||||
},
|
||||
updateScaleRange: function(datapoints){
|
||||
var valuesArray = [];
|
||||
helpers.each(datapoints,function(segment){
|
||||
valuesArray.push(segment.value);
|
||||
});
|
||||
// Fit the scale before we animate
|
||||
this.updateScaleRange();
|
||||
this.scale.calculateRange();
|
||||
Chart.scaleService.fitScalesForChart(this, this.chart.width, this.chart.height);
|
||||
|
||||
var scaleSizes = (this.options.scaleOverride) ?
|
||||
{
|
||||
steps: this.options.scaleSteps,
|
||||
stepValue: this.options.scaleStepWidth,
|
||||
min: this.options.scaleStartValue,
|
||||
max: this.options.scaleStartValue + (this.options.scaleSteps * this.options.scaleStepWidth)
|
||||
} :
|
||||
helpers.calculateScaleRange(
|
||||
valuesArray,
|
||||
helpers.min([this.chart.width, this.chart.height])/2,
|
||||
this.options.scaleFontSize,
|
||||
this.options.scaleBeginAtZero,
|
||||
this.options.scaleIntegersOnly
|
||||
);
|
||||
// so that we animate nicely
|
||||
this.resetElements();
|
||||
|
||||
helpers.extend(
|
||||
this.scale,
|
||||
scaleSizes,
|
||||
{
|
||||
size: helpers.min([this.chart.width, this.chart.height]),
|
||||
xCenter: this.chart.width/2,
|
||||
yCenter: this.chart.height/2
|
||||
}
|
||||
);
|
||||
// Update the chart with the latest data.
|
||||
this.update();
|
||||
|
||||
},
|
||||
update : function(){
|
||||
this.calculateTotal(this.segments);
|
||||
},
|
||||
updateScaleRange: function() {
|
||||
helpers.extend(this.scale, {
|
||||
size: helpers.min([this.chart.width, this.chart.height]),
|
||||
xCenter: this.chart.width / 2,
|
||||
yCenter: this.chart.height / 2
|
||||
});
|
||||
},
|
||||
resetElements: function() {
|
||||
var circumference = 1 / this.data.datasets[0].data.length * 2;
|
||||
|
||||
helpers.each(this.segments,function(segment){
|
||||
segment.save();
|
||||
});
|
||||
this.render();
|
||||
},
|
||||
reflow : function(){
|
||||
helpers.extend(this.SegmentArc.prototype,{
|
||||
x : this.chart.width/2,
|
||||
y : this.chart.height/2
|
||||
});
|
||||
this.updateScaleRange(this.segments);
|
||||
this.scale.update();
|
||||
// Map new data to data points
|
||||
helpers.each(this.data.datasets[0].metaData, function(slice, index) {
|
||||
|
||||
helpers.extend(this.scale,{
|
||||
xCenter: this.chart.width/2,
|
||||
yCenter: this.chart.height/2
|
||||
});
|
||||
var value = this.data.datasets[0].data[index];
|
||||
|
||||
helpers.each(this.segments, function(segment){
|
||||
segment.update({
|
||||
outerRadius : this.scale.calculateCenterOffset(segment.value)
|
||||
});
|
||||
}, this);
|
||||
var startAngle = Math.PI * 1.5 + (Math.PI * circumference) * index;
|
||||
var endAngle = startAngle + (circumference * Math.PI);
|
||||
|
||||
},
|
||||
draw : function(ease){
|
||||
var easingDecimal = ease || 1;
|
||||
//Clear & draw the canvas
|
||||
this.clear();
|
||||
helpers.each(this.segments,function(segment, index){
|
||||
segment.transition({
|
||||
circumference : this.scale.getCircumference(),
|
||||
outerRadius : this.scale.calculateCenterOffset(segment.value)
|
||||
},easingDecimal);
|
||||
helpers.extend(slice, {
|
||||
_index: index,
|
||||
_model: {
|
||||
x: this.chart.width / 2,
|
||||
y: this.chart.height / 2,
|
||||
innerRadius: 0,
|
||||
outerRadius: 0,
|
||||
startAngle: Math.PI * 1.5,
|
||||
endAngle: Math.PI * 1.5,
|
||||
|
||||
segment.endAngle = segment.startAngle + segment.circumference;
|
||||
backgroundColor: slice.custom && slice.custom.backgroundColor ? slice.custom.backgroundColor : helpers.getValueAtIndexOrDefault(this.data.datasets[0].backgroundColor, index, this.options.elements.slice.backgroundColor),
|
||||
hoverBackgroundColor: slice.custom && slice.custom.hoverBackgroundColor ? slice.custom.hoverBackgroundColor : helpers.getValueAtIndexOrDefault(this.data.datasets[0].hoverBackgroundColor, index, this.options.elements.slice.hoverBackgroundColor),
|
||||
borderWidth: slice.custom && slice.custom.borderWidth ? slice.custom.borderWidth : helpers.getValueAtIndexOrDefault(this.data.datasets[0].borderWidth, index, this.options.elements.slice.borderWidth),
|
||||
borderColor: slice.custom && slice.custom.borderColor ? slice.custom.borderColor : helpers.getValueAtIndexOrDefault(this.data.datasets[0].borderColor, index, this.options.elements.slice.borderColor),
|
||||
|
||||
// If we've removed the first segment we need to set the first one to
|
||||
// start at the top.
|
||||
if (index === 0){
|
||||
segment.startAngle = Math.PI * 1.5;
|
||||
}
|
||||
label: helpers.getValueAtIndexOrDefault(this.data.datasets[0].labels, index, this.data.datasets[0].labels[index])
|
||||
},
|
||||
});
|
||||
|
||||
//Check to see if it's the last segment, if not get the next and update the start angle
|
||||
if (index < this.segments.length - 1){
|
||||
this.segments[index+1].startAngle = segment.endAngle;
|
||||
}
|
||||
segment.draw();
|
||||
}, this);
|
||||
this.scale.draw();
|
||||
}
|
||||
});
|
||||
slice.pivot();
|
||||
}, this);
|
||||
},
|
||||
update: function() {
|
||||
|
||||
}).call(this);
|
||||
this.updateScaleRange();
|
||||
this.scale.calculateRange();
|
||||
this.scale.generateTicks();
|
||||
this.scale.buildYLabels();
|
||||
|
||||
Chart.scaleService.fitScalesForChart(this, this.chart.width, this.chart.height);
|
||||
|
||||
var circumference = 1 / this.data.datasets[0].data.length * 2;
|
||||
|
||||
// Map new data to data points
|
||||
helpers.each(this.data.datasets[0].metaData, function(slice, index) {
|
||||
|
||||
var value = this.data.datasets[0].data[index];
|
||||
|
||||
var startAngle = Math.PI * 1.5 + (Math.PI * circumference) * index;
|
||||
var endAngle = startAngle + (circumference * Math.PI);
|
||||
|
||||
helpers.extend(slice, {
|
||||
_index: index,
|
||||
_model: {
|
||||
x: this.chart.width / 2,
|
||||
y: this.chart.height / 2,
|
||||
innerRadius: 0,
|
||||
outerRadius: this.scale.calculateCenterOffset(value),
|
||||
startAngle: startAngle,
|
||||
endAngle: endAngle,
|
||||
|
||||
backgroundColor: slice.custom && slice.custom.backgroundColor ? slice.custom.backgroundColor : helpers.getValueAtIndexOrDefault(this.data.datasets[0].backgroundColor, index, this.options.elements.slice.backgroundColor),
|
||||
hoverBackgroundColor: slice.custom && slice.custom.hoverBackgroundColor ? slice.custom.hoverBackgroundColor : helpers.getValueAtIndexOrDefault(this.data.datasets[0].hoverBackgroundColor, index, this.options.elements.slice.hoverBackgroundColor),
|
||||
borderWidth: slice.custom && slice.custom.borderWidth ? slice.custom.borderWidth : helpers.getValueAtIndexOrDefault(this.data.datasets[0].borderWidth, index, this.options.elements.slice.borderWidth),
|
||||
borderColor: slice.custom && slice.custom.borderColor ? slice.custom.borderColor : helpers.getValueAtIndexOrDefault(this.data.datasets[0].borderColor, index, this.options.elements.slice.borderColor),
|
||||
|
||||
label: helpers.getValueAtIndexOrDefault(this.data.datasets[0].labels, index, this.data.datasets[0].labels[index])
|
||||
},
|
||||
});
|
||||
slice.pivot();
|
||||
|
||||
console.log(slice);
|
||||
|
||||
}, this);
|
||||
|
||||
this.render();
|
||||
},
|
||||
draw: function(ease) {
|
||||
var easingDecimal = ease || 1;
|
||||
|
||||
this.clear();
|
||||
|
||||
helpers.each(this.data.datasets[0].metaData, function(slice, index) {
|
||||
slice.transition(easingDecimal).draw();
|
||||
}, this);
|
||||
|
||||
this.scale.draw();
|
||||
|
||||
this.tooltip.transition(easingDecimal).draw();
|
||||
},
|
||||
events: function(e) {
|
||||
|
||||
// If exiting chart
|
||||
if (e.type == 'mouseout') {
|
||||
return this;
|
||||
}
|
||||
|
||||
this.lastActive = this.lastActive || [];
|
||||
|
||||
// Find Active Elements
|
||||
this.active = function() {
|
||||
switch (this.options.hover.mode) {
|
||||
case 'single':
|
||||
return this.getSliceAtEvent(e);
|
||||
case 'label':
|
||||
return this.getSlicesAtEvent(e);
|
||||
case 'dataset':
|
||||
return this.getDatasetAtEvent(e);
|
||||
default:
|
||||
return e;
|
||||
}
|
||||
}.call(this);
|
||||
|
||||
// On Hover hook
|
||||
if (this.options.hover.onHover) {
|
||||
this.options.hover.onHover.call(this, this.active);
|
||||
}
|
||||
|
||||
if (e.type == 'mouseup' || e.type == 'click') {
|
||||
if (this.options.onClick) {
|
||||
this.options.onClick.call(this, e, this.active);
|
||||
}
|
||||
}
|
||||
|
||||
var dataset;
|
||||
var index;
|
||||
// Remove styling for last active (even if it may still be active)
|
||||
if (this.lastActive.length) {
|
||||
switch (this.options.hover.mode) {
|
||||
case 'single':
|
||||
dataset = this.data.datasets[this.lastActive[0]._datasetIndex];
|
||||
index = this.lastActive[0]._index;
|
||||
|
||||
this.lastActive[0]._model.backgroundColor = this.lastActive[0].custom && this.lastActive[0].custom.backgroundColor ? this.lastActive[0].custom.backgroundColor : helpers.getValueAtIndexOrDefault(dataset.backgroundColor, index, this.options.elements.slice.backgroundColor);
|
||||
this.lastActive[0]._model.borderColor = this.lastActive[0].custom && this.lastActive[0].custom.borderColor ? this.lastActive[0].custom.borderColor : helpers.getValueAtIndexOrDefault(dataset.borderColor, index, this.options.elements.slice.borderColor);
|
||||
this.lastActive[0]._model.borderWidth = this.lastActive[0].custom && this.lastActive[0].custom.borderWidth ? this.lastActive[0].custom.borderWidth : helpers.getValueAtIndexOrDefault(dataset.borderWidth, index, this.options.elements.slice.borderWidth);
|
||||
break;
|
||||
case 'label':
|
||||
for (var i = 0; i < this.lastActive.length; i++) {
|
||||
dataset = this.data.datasets[this.lastActive[i]._datasetIndex];
|
||||
index = this.lastActive[i]._index;
|
||||
|
||||
this.lastActive[i]._model.backgroundColor = this.lastActive[i].custom && this.lastActive[i].custom.backgroundColor ? this.lastActive[i].custom.backgroundColor : helpers.getValueAtIndexOrDefault(dataset.backgroundColor, index, this.options.elements.slice.backgroundColor);
|
||||
this.lastActive[i]._model.borderColor = this.lastActive[i].custom && this.lastActive[i].custom.borderColor ? this.lastActive[i].custom.borderColor : helpers.getValueAtIndexOrDefault(dataset.borderColor, index, this.options.elements.slice.borderColor);
|
||||
this.lastActive[i]._model.borderWidth = this.lastActive[i].custom && this.lastActive[i].custom.borderWidth ? this.lastActive[i].custom.borderWidth : helpers.getValueAtIndexOrDefault(dataset.borderWidth, index, this.options.elements.slice.borderWidth);
|
||||
}
|
||||
break;
|
||||
case 'dataset':
|
||||
break;
|
||||
default:
|
||||
// Don't change anything
|
||||
}
|
||||
}
|
||||
|
||||
// Built in hover styling
|
||||
if (this.active.length && this.options.hover.mode) {
|
||||
switch (this.options.hover.mode) {
|
||||
case 'single':
|
||||
dataset = this.data.datasets[this.active[0]._datasetIndex];
|
||||
index = this.active[0]._index;
|
||||
|
||||
this.active[0]._model.radius = this.active[0].custom && this.active[0].custom.hoverRadius ? this.active[0].custom.hoverRadius : helpers.getValueAtIndexOrDefault(dataset.pointHoverRadius, index, this.active[0]._model.radius + 2);
|
||||
this.active[0]._model.backgroundColor = this.active[0].custom && this.active[0].custom.hoverBackgroundColor ? this.active[0].custom.hoverBackgroundColor : helpers.getValueAtIndexOrDefault(dataset.pointHoverBackgroundColor, index, helpers.color(this.active[0]._model.backgroundColor).saturate(0.5).darken(0.35).rgbString());
|
||||
this.active[0]._model.borderColor = this.active[0].custom && this.active[0].custom.hoverBorderColor ? this.active[0].custom.hoverBorderColor : helpers.getValueAtIndexOrDefault(dataset.pointHoverBorderColor, index, helpers.color(this.active[0]._model.borderColor).saturate(0.5).darken(0.35).rgbString());
|
||||
this.active[0]._model.borderWidth = this.active[0].custom && this.active[0].custom.hoverBorderWidth ? this.active[0].custom.hoverBorderWidth : helpers.getValueAtIndexOrDefault(dataset.pointBorderWidth, index, this.active[0]._model.borderWidth + 2);
|
||||
break;
|
||||
case 'label':
|
||||
for (var i = 0; i < this.active.length; i++) {
|
||||
dataset = this.data.datasets[this.active[i]._datasetIndex];
|
||||
index = this.active[i]._index;
|
||||
|
||||
this.active[i]._model.radius = this.active[i].custom && this.active[i].custom.hoverRadius ? this.active[i].custom.hoverRadius : helpers.getValueAtIndexOrDefault(dataset.pointHoverRadius, index, this.active[i]._model.radius + 2);
|
||||
this.active[i]._model.backgroundColor = this.active[i].custom && this.active[i].custom.hoverBackgroundColor ? this.active[i].custom.hoverBackgroundColor : helpers.getValueAtIndexOrDefault(dataset.pointHoverBackgroundColor, index, helpers.color(this.active[i]._model.backgroundColor).saturate(0.5).darken(0.35).rgbString());
|
||||
this.active[i]._model.borderColor = this.active[i].custom && this.active[i].custom.hoverBorderColor ? this.active[i].custom.hoverBorderColor : helpers.getValueAtIndexOrDefault(dataset.pointHoverBorderColor, index, helpers.color(this.active[i]._model.borderColor).saturate(0.5).darken(0.35).rgbString());
|
||||
this.active[i]._model.borderWidth = this.active[i].custom && this.active[i].custom.hoverBorderWidth ? this.active[i].custom.hoverBorderWidth : helpers.getValueAtIndexOrDefault(dataset.pointBorderWidth, index, this.active[i]._model.borderWidth + 2);
|
||||
}
|
||||
break;
|
||||
case 'dataset':
|
||||
break;
|
||||
default:
|
||||
// Don't change anything
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Built in Tooltips
|
||||
if (this.options.tooltips.enabled) {
|
||||
|
||||
// The usual updates
|
||||
this.tooltip.initialize();
|
||||
|
||||
// Active
|
||||
if (this.active.length) {
|
||||
this.tooltip._model.opacity = 1;
|
||||
|
||||
helpers.extend(this.tooltip, {
|
||||
_active: this.active,
|
||||
});
|
||||
|
||||
this.tooltip.update();
|
||||
} else {
|
||||
// Inactive
|
||||
this.tooltip._model.opacity = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Hover animations
|
||||
this.tooltip.pivot();
|
||||
|
||||
if (!this.animating) {
|
||||
var changed;
|
||||
|
||||
helpers.each(this.active, function(element, index) {
|
||||
if (element !== this.lastActive[index]) {
|
||||
changed = true;
|
||||
}
|
||||
}, 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.stop();
|
||||
this.render(this.options.hover.animationDuration);
|
||||
}
|
||||
}
|
||||
|
||||
// Remember Last Active
|
||||
this.lastActive = this.active;
|
||||
return this;
|
||||
},
|
||||
getSliceAtEvent: function(e) {
|
||||
var elements = [];
|
||||
|
||||
var location = helpers.getRelativePosition(e);
|
||||
|
||||
this.eachElement(function(slice, index) {
|
||||
if (slice.inRange(location.x, location.y)) {
|
||||
elements.push(slice);
|
||||
}
|
||||
}, this);
|
||||
return elements;
|
||||
},
|
||||
/*getSlicesAtEvent: function(e) {
|
||||
var elements = [];
|
||||
|
||||
var location = helpers.getRelativePosition(e);
|
||||
|
||||
this.eachElement(function(slice, index) {
|
||||
if (slice.inGroupRange(location.x, location.y)) {
|
||||
elements.push(slice);
|
||||
}
|
||||
}, this);
|
||||
return elements;
|
||||
},*/
|
||||
});
|
||||
|
||||
}).call(this);
|
||||
|
||||
+443
-279
@@ -1,342 +1,506 @@
|
||||
(function(){
|
||||
"use strict";
|
||||
(function() {
|
||||
"use strict";
|
||||
|
||||
var root = this,
|
||||
Chart = root.Chart,
|
||||
helpers = Chart.helpers;
|
||||
var root = this,
|
||||
Chart = root.Chart,
|
||||
helpers = Chart.helpers;
|
||||
|
||||
|
||||
|
||||
Chart.Type.extend({
|
||||
name: "Radar",
|
||||
defaults:{
|
||||
//Boolean - Whether to show lines for each scale point
|
||||
scaleShowLine : true,
|
||||
Chart.Type.extend({
|
||||
name: "Radar",
|
||||
defaults: {
|
||||
|
||||
//Boolean - Whether we show the angle lines out of the radar
|
||||
angleShowLineOut : true,
|
||||
scale: {
|
||||
scaleType: "radialLinear",
|
||||
display: true,
|
||||
|
||||
//Boolean - Whether to show labels on the scale
|
||||
scaleShowLabels : false,
|
||||
//Boolean - Whether to animate scaling the chart from the centre
|
||||
animate: false,
|
||||
|
||||
// Boolean - Whether the scale should begin at zero
|
||||
scaleBeginAtZero : true,
|
||||
lineArc: false,
|
||||
|
||||
//String - Colour of the angle line
|
||||
angleLineColor : "rgba(0,0,0,.1)",
|
||||
// grid line settings
|
||||
gridLines: {
|
||||
show: true,
|
||||
color: "rgba(0, 0, 0, 0.05)",
|
||||
lineWidth: 1,
|
||||
},
|
||||
|
||||
//Number - Pixel width of the angle line
|
||||
angleLineWidth : 1,
|
||||
angleLines: {
|
||||
show: true,
|
||||
color: "rgba(0,0,0,.1)",
|
||||
lineWidth: 1
|
||||
},
|
||||
|
||||
//String - Point label font declaration
|
||||
pointLabelFontFamily : "'Arial'",
|
||||
// scale numbers
|
||||
beginAtZero: true,
|
||||
|
||||
//String - Point label font weight
|
||||
pointLabelFontStyle : "normal",
|
||||
// label settings
|
||||
labels: {
|
||||
show: true,
|
||||
template: "<%=value%>",
|
||||
fontSize: 12,
|
||||
fontStyle: "normal",
|
||||
fontColor: "#666",
|
||||
fontFamily: "Helvetica Neue",
|
||||
|
||||
//Number - Point label font size in pixels
|
||||
pointLabelFontSize : 10,
|
||||
//Boolean - Show a backdrop to the scale label
|
||||
showLabelBackdrop: true,
|
||||
|
||||
//String - Point label font colour
|
||||
pointLabelFontColor : "#666",
|
||||
//String - The colour of the label backdrop
|
||||
backdropColor: "rgba(255,255,255,0.75)",
|
||||
|
||||
//Boolean - Whether to show a dot for each point
|
||||
pointDot : true,
|
||||
//Number - The backdrop padding above & below the label in pixels
|
||||
backdropPaddingY: 2,
|
||||
|
||||
//Number - Radius of each point dot in pixels
|
||||
pointDotRadius : 3,
|
||||
//Number - The backdrop padding to the side of the label in pixels
|
||||
backdropPaddingX: 2,
|
||||
},
|
||||
|
||||
//Number - Pixel width of point dot stroke
|
||||
pointDotStrokeWidth : 1,
|
||||
pointLabels: {
|
||||
//String - Point label font declaration
|
||||
fontFamily: "'Arial'",
|
||||
|
||||
//Number - amount extra to add to the radius to cater for hit detection outside the drawn point
|
||||
pointHitDetectionRadius : 20,
|
||||
//String - Point label font weight
|
||||
fontStyle: "normal",
|
||||
|
||||
//Boolean - Whether to show a stroke for datasets
|
||||
datasetStroke : true,
|
||||
//Number - Point label font size in pixels
|
||||
fontSize: 10,
|
||||
|
||||
//Number - Pixel width of dataset stroke
|
||||
datasetStrokeWidth : 2,
|
||||
//String - Point label font colour
|
||||
fontColor: "#666",
|
||||
},
|
||||
},
|
||||
|
||||
//Boolean - Whether to fill the dataset with a colour
|
||||
datasetFill : true,
|
||||
elements: {
|
||||
line: {
|
||||
tension: 0, // no bezier in radar
|
||||
}
|
||||
},
|
||||
|
||||
//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>"
|
||||
//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>"
|
||||
|
||||
},
|
||||
},
|
||||
|
||||
initialize: function(data){
|
||||
this.PointClass = Chart.Point.extend({
|
||||
strokeWidth : this.options.pointDotStrokeWidth,
|
||||
radius : this.options.pointDotRadius,
|
||||
display: this.options.pointDot,
|
||||
hitDetectionRadius : this.options.pointHitDetectionRadius,
|
||||
ctx : this.chart.ctx
|
||||
});
|
||||
initialize: function() {
|
||||
// Events
|
||||
helpers.bindEvents(this, this.options.events, this.events);
|
||||
|
||||
this.datasets = [];
|
||||
// Create a new line and its points for each dataset and piece of data
|
||||
helpers.each(this.data.datasets, function(dataset, datasetIndex) {
|
||||
|
||||
this.buildScale(data);
|
||||
dataset.metaDataset = new Chart.Line({
|
||||
_chart: this.chart,
|
||||
_datasetIndex: datasetIndex,
|
||||
_points: dataset.metaData,
|
||||
_loop: true
|
||||
});
|
||||
|
||||
//Set up tooltip events on the chart
|
||||
if (this.options.showTooltips){
|
||||
helpers.bindEvents(this, this.options.tooltipEvents, function(evt){
|
||||
var activePointsCollection = (evt.type !== 'mouseout') ? this.getPointsAtEvent(evt) : [];
|
||||
dataset.metaData = [];
|
||||
|
||||
this.eachPoints(function(point){
|
||||
point.restore(['fillColor', 'strokeColor']);
|
||||
});
|
||||
helpers.each(activePointsCollection, function(activePoint){
|
||||
activePoint.fillColor = activePoint.highlightFill;
|
||||
activePoint.strokeColor = activePoint.highlightStroke;
|
||||
});
|
||||
helpers.each(dataset.data, function(dataPoint, index) {
|
||||
dataset.metaData.push(new Chart.Point({
|
||||
_datasetIndex: datasetIndex,
|
||||
_index: index,
|
||||
_chart: this.chart,
|
||||
_model: {
|
||||
x: 0, //xScale.getPixelForValue(null, index, true),
|
||||
y: 0, //this.chartArea.bottom,
|
||||
},
|
||||
}));
|
||||
|
||||
this.showTooltip(activePointsCollection);
|
||||
});
|
||||
}
|
||||
}, this);
|
||||
}, this);
|
||||
|
||||
//Iterate through each of the datasets, and build this into a property of the chart
|
||||
helpers.each(data.datasets,function(dataset){
|
||||
// Build the scale.
|
||||
this.buildScale();
|
||||
|
||||
var datasetObject = {
|
||||
label: dataset.label || null,
|
||||
fillColor : dataset.fillColor,
|
||||
strokeColor : dataset.strokeColor,
|
||||
pointColor : dataset.pointColor,
|
||||
pointStrokeColor : dataset.pointStrokeColor,
|
||||
points : []
|
||||
};
|
||||
// Create tooltip instance exclusively for this chart with some defaults.
|
||||
this.tooltip = new Chart.Tooltip({
|
||||
_chart: this.chart,
|
||||
_data: this.data,
|
||||
_options: this.options,
|
||||
}, this);
|
||||
|
||||
this.datasets.push(datasetObject);
|
||||
// Need to fit scales before we reset elements.
|
||||
Chart.scaleService.fitScalesForChart(this, this.chart.width, this.chart.height);
|
||||
|
||||
helpers.each(dataset.data,function(dataPoint,index){
|
||||
//Best way to do this? or in draw sequence...?
|
||||
if (helpers.isNumber(dataPoint)){
|
||||
//Add a new point for each piece of data, passing any required data to draw.
|
||||
var pointPosition;
|
||||
if (!this.scale.animation){
|
||||
pointPosition = this.scale.getPointPosition(index, this.scale.calculateCenterOffset(dataPoint));
|
||||
}
|
||||
datasetObject.points.push(new this.PointClass({
|
||||
value : dataPoint,
|
||||
label : data.labels[index],
|
||||
x: (this.options.animation) ? this.scale.xCenter : pointPosition.x,
|
||||
y: (this.options.animation) ? this.scale.yCenter : pointPosition.y,
|
||||
strokeColor : dataset.pointStrokeColor,
|
||||
fillColor : dataset.pointColor,
|
||||
highlightFill : dataset.pointHighlightFill || dataset.pointColor,
|
||||
highlightStroke : dataset.pointHighlightStroke || dataset.pointStrokeColor
|
||||
}));
|
||||
}
|
||||
},this);
|
||||
// Reset so that we animation from the baseline
|
||||
this.resetElements();
|
||||
|
||||
},this);
|
||||
// Update that shiz
|
||||
this.update();
|
||||
},
|
||||
nextPoint: function(collection, index) {
|
||||
return collection[index + 1] || collection[0];
|
||||
},
|
||||
previousPoint: function(collection, index) {
|
||||
return collection[index - 1] || collection[collection.length - 1];
|
||||
},
|
||||
resetElements: function() {
|
||||
|
||||
this.render();
|
||||
},
|
||||
eachPoints : function(callback){
|
||||
helpers.each(this.datasets,function(dataset){
|
||||
helpers.each(dataset.points,callback,this);
|
||||
},this);
|
||||
},
|
||||
// Update the points
|
||||
this.eachElement(function(point, index, dataset, datasetIndex) {
|
||||
helpers.extend(point, {
|
||||
// Utility
|
||||
_chart: this.chart,
|
||||
_datasetIndex: datasetIndex,
|
||||
_index: index,
|
||||
_scale: this.scale,
|
||||
|
||||
getPointsAtEvent : function(evt){
|
||||
var mousePosition = helpers.getRelativePosition(evt),
|
||||
fromCenter = helpers.getAngleFromPoint({
|
||||
x: this.scale.xCenter,
|
||||
y: this.scale.yCenter
|
||||
}, mousePosition);
|
||||
// Desired view properties
|
||||
_model: {
|
||||
x: this.scale.xCenter,
|
||||
y: this.scale.yCenter,
|
||||
|
||||
var anglePerIndex = (Math.PI * 2) /this.scale.valuesCount,
|
||||
pointIndex = Math.round((fromCenter.angle - Math.PI * 1.5) / anglePerIndex),
|
||||
activePointsCollection = [];
|
||||
// Appearance
|
||||
tension: point.custom && point.custom.tension ? point.custom.tension : this.options.elements.line.tension,
|
||||
radius: point.custom && point.custom.radius ? point.custom.pointRadius : helpers.getValueAtIndexOrDefault(this.data.datasets[datasetIndex].pointRadius, index, this.options.elements.point.radius),
|
||||
backgroundColor: point.custom && point.custom.backgroundColor ? point.custom.backgroundColor : helpers.getValueAtIndexOrDefault(this.data.datasets[datasetIndex].pointBackgroundColor, index, this.options.elements.point.backgroundColor),
|
||||
borderColor: point.custom && point.custom.borderColor ? point.custom.borderColor : helpers.getValueAtIndexOrDefault(this.data.datasets[datasetIndex].pointBorderColor, index, this.options.elements.point.borderColor),
|
||||
borderWidth: point.custom && point.custom.borderWidth ? point.custom.borderWidth : helpers.getValueAtIndexOrDefault(this.data.datasets[datasetIndex].pointBorderWidth, index, this.options.elements.point.borderWidth),
|
||||
skip: typeof this.data.datasets[datasetIndex].data[index] != 'number',
|
||||
|
||||
// If we're at the top, make the pointIndex 0 to get the first of the array.
|
||||
if (pointIndex >= this.scale.valuesCount || pointIndex < 0){
|
||||
pointIndex = 0;
|
||||
}
|
||||
// Tooltip
|
||||
hoverRadius: point.custom && point.custom.hoverRadius ? point.custom.hoverRadius : helpers.getValueAtIndexOrDefault(this.data.datasets[datasetIndex].pointHitRadius, index, this.options.elements.point.hitRadius),
|
||||
},
|
||||
});
|
||||
}, this);
|
||||
|
||||
if (fromCenter.distance <= this.scale.drawingArea){
|
||||
helpers.each(this.datasets, function(dataset){
|
||||
activePointsCollection.push(dataset.points[pointIndex]);
|
||||
});
|
||||
}
|
||||
// Update control points for the bezier curve
|
||||
this.eachElement(function(point, index, dataset, datasetIndex) {
|
||||
var controlPoints = helpers.splineCurve(
|
||||
this.previousPoint(dataset, index)._model,
|
||||
point._model,
|
||||
this.nextPoint(dataset, index)._model,
|
||||
point._model.tension
|
||||
);
|
||||
|
||||
return activePointsCollection;
|
||||
},
|
||||
point._model.controlPointPreviousX = this.scale.xCenter;
|
||||
point._model.controlPointPreviousY = this.scale.yCenter;
|
||||
point._model.controlPointNextX = this.scale.xCenter;
|
||||
point._model.controlPointNextY = this.scale.yCenter;
|
||||
|
||||
buildScale : function(data){
|
||||
this.scale = new Chart.RadialScale({
|
||||
display: this.options.showScale,
|
||||
fontStyle: this.options.scaleFontStyle,
|
||||
fontSize: this.options.scaleFontSize,
|
||||
fontFamily: this.options.scaleFontFamily,
|
||||
fontColor: this.options.scaleFontColor,
|
||||
showLabels: this.options.scaleShowLabels,
|
||||
showLabelBackdrop: this.options.scaleShowLabelBackdrop,
|
||||
backdropColor: this.options.scaleBackdropColor,
|
||||
backdropPaddingY : this.options.scaleBackdropPaddingY,
|
||||
backdropPaddingX: this.options.scaleBackdropPaddingX,
|
||||
lineWidth: (this.options.scaleShowLine) ? this.options.scaleLineWidth : 0,
|
||||
lineColor: this.options.scaleLineColor,
|
||||
angleLineColor : this.options.angleLineColor,
|
||||
angleLineWidth : (this.options.angleShowLineOut) ? this.options.angleLineWidth : 0,
|
||||
// Point labels at the edge of each line
|
||||
pointLabelFontColor : this.options.pointLabelFontColor,
|
||||
pointLabelFontSize : this.options.pointLabelFontSize,
|
||||
pointLabelFontFamily : this.options.pointLabelFontFamily,
|
||||
pointLabelFontStyle : this.options.pointLabelFontStyle,
|
||||
height : this.chart.height,
|
||||
width: this.chart.width,
|
||||
xCenter: this.chart.width/2,
|
||||
yCenter: this.chart.height/2,
|
||||
ctx : this.chart.ctx,
|
||||
templateString: this.options.scaleLabel,
|
||||
labels: data.labels,
|
||||
valuesCount: data.datasets[0].data.length
|
||||
});
|
||||
// Now pivot the point for animation
|
||||
point.pivot();
|
||||
}, this);
|
||||
},
|
||||
update: function() {
|
||||
Chart.scaleService.fitScalesForChart(this, this.chart.width, this.chart.height);
|
||||
|
||||
this.scale.setScaleSize();
|
||||
this.updateScaleRange(data.datasets);
|
||||
this.scale.buildYLabels();
|
||||
},
|
||||
updateScaleRange: function(datasets){
|
||||
var valuesArray = (function(){
|
||||
var totalDataArray = [];
|
||||
helpers.each(datasets,function(dataset){
|
||||
if (dataset.data){
|
||||
totalDataArray = totalDataArray.concat(dataset.data);
|
||||
}
|
||||
else {
|
||||
helpers.each(dataset.points, function(point){
|
||||
totalDataArray.push(point.value);
|
||||
});
|
||||
}
|
||||
});
|
||||
return totalDataArray;
|
||||
})();
|
||||
// Update the lines
|
||||
this.eachDataset(function(dataset, datasetIndex) {
|
||||
helpers.extend(dataset.metaDataset, {
|
||||
// Utility
|
||||
_datasetIndex: datasetIndex,
|
||||
|
||||
// Data
|
||||
_children: dataset.metaData,
|
||||
|
||||
// Model
|
||||
_model: {
|
||||
// Appearance
|
||||
tension: dataset.tension || this.options.elements.line.tension,
|
||||
backgroundColor: dataset.backgroundColor || this.options.elements.line.backgroundColor,
|
||||
borderWidth: dataset.borderWidth || this.options.elements.line.borderWidth,
|
||||
borderColor: dataset.borderColor || this.options.elements.line.borderColor,
|
||||
fill: dataset.fill !== undefined ? dataset.fill : this.options.elements.line.fill, // use the value from the dataset if it was provided. else fall back to the default
|
||||
skipNull: dataset.skipNull !== undefined ? dataset.skipNull : this.options.elements.line.skipNull,
|
||||
drawNull: dataset.drawNull !== undefined ? dataset.drawNull : this.options.elements.line.drawNull,
|
||||
|
||||
// Scale
|
||||
scaleTop: this.scale.top,
|
||||
scaleBottom: this.scale.bottom,
|
||||
scaleZero: this.scale.getPointPosition(0),
|
||||
},
|
||||
});
|
||||
|
||||
dataset.metaDataset.pivot();
|
||||
});
|
||||
|
||||
// Update the points
|
||||
this.eachElement(function(point, index, dataset, datasetIndex) {
|
||||
var pointPosition = this.scale.getPointPosition(index, this.scale.calculateCenterOffset(this.data.datasets[datasetIndex].data[index]));
|
||||
|
||||
helpers.extend(point, {
|
||||
// Utility
|
||||
_chart: this.chart,
|
||||
_datasetIndex: datasetIndex,
|
||||
_index: index,
|
||||
|
||||
// Desired view properties
|
||||
_model: {
|
||||
x: pointPosition.x, // value not used in dataset scale, but we want a consistent API between scales
|
||||
y: pointPosition.y,
|
||||
|
||||
// Appearance
|
||||
tension: point.custom && point.custom.tension ? point.custom.tension : this.options.elements.line.tension,
|
||||
radius: point.custom && point.custom.radius ? point.custom.pointRadius : helpers.getValueAtIndexOrDefault(this.data.datasets[datasetIndex].pointRadius, index, this.options.elements.point.radius),
|
||||
backgroundColor: point.custom && point.custom.backgroundColor ? point.custom.backgroundColor : helpers.getValueAtIndexOrDefault(this.data.datasets[datasetIndex].pointBackgroundColor, index, this.options.elements.point.backgroundColor),
|
||||
borderColor: point.custom && point.custom.borderColor ? point.custom.borderColor : helpers.getValueAtIndexOrDefault(this.data.datasets[datasetIndex].pointBorderColor, index, this.options.elements.point.borderColor),
|
||||
borderWidth: point.custom && point.custom.borderWidth ? point.custom.borderWidth : helpers.getValueAtIndexOrDefault(this.data.datasets[datasetIndex].pointBorderWidth, index, this.options.elements.point.borderWidth),
|
||||
skip: typeof this.data.datasets[datasetIndex].data[index] != 'number',
|
||||
|
||||
// Tooltip
|
||||
hoverRadius: point.custom && point.custom.hoverRadius ? point.custom.hoverRadius : helpers.getValueAtIndexOrDefault(this.data.datasets[datasetIndex].pointHitRadius, index, this.options.elements.point.hitRadius),
|
||||
},
|
||||
});
|
||||
}, this);
|
||||
|
||||
|
||||
var scaleSizes = (this.options.scaleOverride) ?
|
||||
{
|
||||
steps: this.options.scaleSteps,
|
||||
stepValue: this.options.scaleStepWidth,
|
||||
min: this.options.scaleStartValue,
|
||||
max: this.options.scaleStartValue + (this.options.scaleSteps * this.options.scaleStepWidth)
|
||||
} :
|
||||
helpers.calculateScaleRange(
|
||||
valuesArray,
|
||||
helpers.min([this.chart.width, this.chart.height])/2,
|
||||
this.options.scaleFontSize,
|
||||
this.options.scaleBeginAtZero,
|
||||
this.options.scaleIntegersOnly
|
||||
);
|
||||
// Update control points for the bezier curve
|
||||
this.eachElement(function(point, index, dataset, datasetIndex) {
|
||||
var controlPoints = helpers.splineCurve(
|
||||
this.previousPoint(dataset, index)._model,
|
||||
point._model,
|
||||
this.nextPoint(dataset, index)._model,
|
||||
point._model.tension
|
||||
);
|
||||
|
||||
helpers.extend(
|
||||
this.scale,
|
||||
scaleSizes
|
||||
);
|
||||
point._model.controlPointPreviousX = controlPoints.previous.x;
|
||||
point._model.controlPointNextX = controlPoints.next.x;
|
||||
|
||||
},
|
||||
addData : function(valuesArray,label){
|
||||
//Map the values array for each of the datasets
|
||||
this.scale.valuesCount++;
|
||||
helpers.each(valuesArray,function(value,datasetIndex){
|
||||
if (helpers.isNumber(value)){
|
||||
var pointPosition = this.scale.getPointPosition(this.scale.valuesCount, this.scale.calculateCenterOffset(value));
|
||||
this.datasets[datasetIndex].points.push(new this.PointClass({
|
||||
value : value,
|
||||
label : label,
|
||||
x: pointPosition.x,
|
||||
y: pointPosition.y,
|
||||
strokeColor : this.datasets[datasetIndex].pointStrokeColor,
|
||||
fillColor : this.datasets[datasetIndex].pointColor
|
||||
}));
|
||||
}
|
||||
},this);
|
||||
// Prevent the bezier going outside of the bounds of the graph
|
||||
|
||||
this.scale.labels.push(label);
|
||||
// Cap puter bezier handles to the upper/lower scale bounds
|
||||
if (controlPoints.next.y > this.chartArea.bottom) {
|
||||
point._model.controlPointNextY = this.chartArea.bottom;
|
||||
} else if (controlPoints.next.y < this.chartArea.top) {
|
||||
point._model.controlPointNextY = this.chartArea.top;
|
||||
} else {
|
||||
point._model.controlPointNextY = controlPoints.next.y;
|
||||
}
|
||||
|
||||
this.reflow();
|
||||
// Cap inner bezier handles to the upper/lower scale bounds
|
||||
if (controlPoints.previous.y > this.chartArea.bottom) {
|
||||
point._model.controlPointPreviousY = this.chartArea.bottom;
|
||||
} else if (controlPoints.previous.y < this.chartArea.top) {
|
||||
point._model.controlPointPreviousY = this.chartArea.top;
|
||||
} else {
|
||||
point._model.controlPointPreviousY = controlPoints.previous.y;
|
||||
}
|
||||
|
||||
this.update();
|
||||
},
|
||||
removeData : function(){
|
||||
this.scale.valuesCount--;
|
||||
this.scale.labels.shift();
|
||||
helpers.each(this.datasets,function(dataset){
|
||||
dataset.points.shift();
|
||||
},this);
|
||||
this.reflow();
|
||||
this.update();
|
||||
},
|
||||
update : function(){
|
||||
this.eachPoints(function(point){
|
||||
point.save();
|
||||
});
|
||||
this.render();
|
||||
},
|
||||
reflow: function(){
|
||||
helpers.extend(this.scale, {
|
||||
width : this.chart.width,
|
||||
height: this.chart.height,
|
||||
size : helpers.min([this.chart.width, this.chart.height]),
|
||||
xCenter: this.chart.width/2,
|
||||
yCenter: this.chart.height/2
|
||||
});
|
||||
this.updateScaleRange(this.datasets);
|
||||
this.scale.setScaleSize();
|
||||
this.scale.buildYLabels();
|
||||
},
|
||||
draw : function(ease){
|
||||
var easeDecimal = ease || 1,
|
||||
ctx = this.chart.ctx;
|
||||
this.clear();
|
||||
this.scale.draw();
|
||||
// Now pivot the point for animation
|
||||
point.pivot();
|
||||
}, this);
|
||||
|
||||
helpers.each(this.datasets,function(dataset){
|
||||
this.render();
|
||||
},
|
||||
buildScale: function() {
|
||||
var self = this;
|
||||
|
||||
//Transition each point first so that the line and point drawing isn't out of sync
|
||||
helpers.each(dataset.points,function(point,index){
|
||||
point.transition(this.scale.getPointPosition(index, this.scale.calculateCenterOffset(point.value)), easeDecimal);
|
||||
},this);
|
||||
var ScaleConstructor = Chart.scales.getScaleConstructor(this.options.scale.scaleType);
|
||||
this.scale = new ScaleConstructor({
|
||||
options: this.options.scale,
|
||||
height: this.chart.height,
|
||||
width: this.chart.width,
|
||||
xCenter: this.chart.width / 2,
|
||||
yCenter: this.chart.height / 2,
|
||||
ctx: this.chart.ctx,
|
||||
labels: this.data.labels,
|
||||
valuesCount: this.data.datasets[0].data.length,
|
||||
calculateRange: function() {
|
||||
this.min = null;
|
||||
this.max = null;
|
||||
|
||||
helpers.each(self.data.datasets, function(dataset) {
|
||||
if (dataset.yAxisID === this.id) {
|
||||
helpers.each(dataset.data, function(value, index) {
|
||||
if (this.min === null) {
|
||||
this.min = value;
|
||||
} else if (value < this.min) {
|
||||
this.min = value;
|
||||
}
|
||||
|
||||
if (this.max === null) {
|
||||
this.max = value;
|
||||
} else if (value > this.max) {
|
||||
this.max = value;
|
||||
}
|
||||
}, this);
|
||||
}
|
||||
}, this);
|
||||
}
|
||||
});
|
||||
|
||||
//Draw the line between all the points
|
||||
ctx.lineWidth = this.options.datasetStrokeWidth;
|
||||
ctx.strokeStyle = dataset.strokeColor;
|
||||
ctx.beginPath();
|
||||
helpers.each(dataset.points,function(point,index){
|
||||
if (index === 0){
|
||||
ctx.moveTo(point.x,point.y);
|
||||
}
|
||||
else{
|
||||
ctx.lineTo(point.x,point.y);
|
||||
}
|
||||
},this);
|
||||
ctx.closePath();
|
||||
ctx.stroke();
|
||||
this.scale.setScaleSize();
|
||||
this.scale.calculateRange();
|
||||
this.scale.generateTicks();
|
||||
this.scale.buildYLabels();
|
||||
},
|
||||
draw: function(ease) {
|
||||
var easingDecimal = ease || 1;
|
||||
this.clear();
|
||||
|
||||
ctx.fillStyle = dataset.fillColor;
|
||||
ctx.fill();
|
||||
// Draw all the scales
|
||||
this.scale.draw(this.chartArea);
|
||||
|
||||
//Now draw the points over the line
|
||||
//A little inefficient double looping, but better than the line
|
||||
//lagging behind the point positions
|
||||
helpers.each(dataset.points,function(point){
|
||||
point.draw();
|
||||
});
|
||||
// reverse for-loop for proper stacking
|
||||
for (var i = this.data.datasets.length - 1; i >= 0; i--) {
|
||||
|
||||
},this);
|
||||
var dataset = this.data.datasets[i];
|
||||
|
||||
}
|
||||
// Transition Point Locations
|
||||
helpers.each(dataset.metaData, function(point, index) {
|
||||
point.transition(easingDecimal);
|
||||
}, this);
|
||||
|
||||
});
|
||||
// Transition and Draw the line
|
||||
dataset.metaDataset.transition(easingDecimal).draw();
|
||||
|
||||
// Draw the points
|
||||
helpers.each(dataset.metaData, function(point) {
|
||||
point.draw();
|
||||
});
|
||||
}
|
||||
|
||||
// Finally draw the tooltip
|
||||
this.tooltip.transition(easingDecimal).draw();
|
||||
},
|
||||
events: function(e) {
|
||||
|
||||
// If exiting chart
|
||||
if (e.type == 'mouseout') {
|
||||
return this;
|
||||
}
|
||||
|
||||
this.lastActive = this.lastActive || [];
|
||||
|
||||
}).call(this);
|
||||
// Find Active Elements
|
||||
this.active = function() {
|
||||
switch (this.options.hover.mode) {
|
||||
case 'single':
|
||||
return this.getElementAtEvent(e);
|
||||
case 'label':
|
||||
return this.getElementsAtEvent(e);
|
||||
case 'dataset':
|
||||
return this.getDatasetAtEvent(e);
|
||||
default:
|
||||
return e;
|
||||
}
|
||||
}.call(this);
|
||||
|
||||
// On Hover hook
|
||||
if (this.options.hover.onHover) {
|
||||
this.options.hover.onHover.call(this, this.active);
|
||||
}
|
||||
|
||||
if (e.type == 'mouseup' || e.type == 'click') {
|
||||
if (this.options.onClick) {
|
||||
this.options.onClick.call(this, e, this.active);
|
||||
}
|
||||
}
|
||||
|
||||
var dataset;
|
||||
var index;
|
||||
// Remove styling for last active (even if it may still be active)
|
||||
if (this.lastActive.length) {
|
||||
switch (this.options.hover.mode) {
|
||||
case 'single':
|
||||
dataset = this.data.datasets[this.lastActive[0]._datasetIndex];
|
||||
index = this.lastActive[0]._index;
|
||||
|
||||
this.lastActive[0]._model.radius = this.lastActive[0].custom && this.lastActive[0].custom.radius ? this.lastActive[0].custom.pointRadius : helpers.getValueAtIndexOrDefault(dataset.pointRadius, index, this.options.elements.point.radius);
|
||||
this.lastActive[0]._model.backgroundColor = this.lastActive[0].custom && this.lastActive[0].custom.backgroundColor ? this.lastActive[0].custom.backgroundColor : helpers.getValueAtIndexOrDefault(dataset.pointBackgroundColor, index, this.options.elements.point.backgroundColor);
|
||||
this.lastActive[0]._model.borderColor = this.lastActive[0].custom && this.lastActive[0].custom.borderColor ? this.lastActive[0].custom.borderColor : helpers.getValueAtIndexOrDefault(dataset.pointBorderColor, index, this.options.elements.point.borderColor);
|
||||
this.lastActive[0]._model.borderWidth = this.lastActive[0].custom && this.lastActive[0].custom.borderWidth ? this.lastActive[0].custom.borderWidth : helpers.getValueAtIndexOrDefault(dataset.pointBorderWidth, index, this.options.elements.point.borderWidth);
|
||||
break;
|
||||
case 'label':
|
||||
for (var i = 0; i < this.lastActive.length; i++) {
|
||||
dataset = this.data.datasets[this.lastActive[i]._datasetIndex];
|
||||
index = this.lastActive[i]._index;
|
||||
|
||||
this.lastActive[i]._model.radius = this.lastActive[i].custom && this.lastActive[i].custom.radius ? this.lastActive[i].custom.pointRadius : helpers.getValueAtIndexOrDefault(dataset.pointRadius, index, this.options.elements.point.radius);
|
||||
this.lastActive[i]._model.backgroundColor = this.lastActive[i].custom && this.lastActive[i].custom.backgroundColor ? this.lastActive[i].custom.backgroundColor : helpers.getValueAtIndexOrDefault(dataset.pointBackgroundColor, index, this.options.elements.point.backgroundColor);
|
||||
this.lastActive[i]._model.borderColor = this.lastActive[i].custom && this.lastActive[i].custom.borderColor ? this.lastActive[i].custom.borderColor : helpers.getValueAtIndexOrDefault(dataset.pointBorderColor, index, this.options.elements.point.borderColor);
|
||||
this.lastActive[i]._model.borderWidth = this.lastActive[i].custom && this.lastActive[i].custom.borderWidth ? this.lastActive[i].custom.borderWidth : helpers.getValueAtIndexOrDefault(dataset.pointBorderWidth, index, this.options.elements.point.borderWidth);
|
||||
}
|
||||
break;
|
||||
case 'dataset':
|
||||
break;
|
||||
default:
|
||||
// Don't change anything
|
||||
}
|
||||
}
|
||||
|
||||
// Built in hover styling
|
||||
if (this.active.length && this.options.hover.mode) {
|
||||
switch (this.options.hover.mode) {
|
||||
case 'single':
|
||||
dataset = this.data.datasets[this.active[0]._datasetIndex];
|
||||
index = this.active[0]._index;
|
||||
|
||||
this.active[0]._model.radius = this.active[0].custom && this.active[0].custom.hoverRadius ? this.active[0].custom.hoverRadius : helpers.getValueAtIndexOrDefault(dataset.pointHoverRadius, index, this.active[0]._model.radius + 2);
|
||||
this.active[0]._model.backgroundColor = this.active[0].custom && this.active[0].custom.hoverBackgroundColor ? this.active[0].custom.hoverBackgroundColor : helpers.getValueAtIndexOrDefault(dataset.pointHoverBackgroundColor, index, helpers.color(this.active[0]._model.backgroundColor).saturate(0.5).darken(0.35).rgbString());
|
||||
this.active[0]._model.borderColor = this.active[0].custom && this.active[0].custom.hoverBorderColor ? this.active[0].custom.hoverBorderColor : helpers.getValueAtIndexOrDefault(dataset.pointHoverBorderColor, index, helpers.color(this.active[0]._model.borderColor).saturate(0.5).darken(0.35).rgbString());
|
||||
this.active[0]._model.borderWidth = this.active[0].custom && this.active[0].custom.hoverBorderWidth ? this.active[0].custom.hoverBorderWidth : helpers.getValueAtIndexOrDefault(dataset.pointBorderWidth, index, this.active[0]._model.borderWidth + 2);
|
||||
break;
|
||||
case 'label':
|
||||
for (var i = 0; i < this.active.length; i++) {
|
||||
dataset = this.data.datasets[this.active[i]._datasetIndex];
|
||||
index = this.active[i]._index;
|
||||
|
||||
this.active[i]._model.radius = this.active[i].custom && this.active[i].custom.hoverRadius ? this.active[i].custom.hoverRadius : helpers.getValueAtIndexOrDefault(dataset.pointHoverRadius, index, this.active[i]._model.radius + 2);
|
||||
this.active[i]._model.backgroundColor = this.active[i].custom && this.active[i].custom.hoverBackgroundColor ? this.active[i].custom.hoverBackgroundColor : helpers.getValueAtIndexOrDefault(dataset.pointHoverBackgroundColor, index, helpers.color(this.active[i]._model.backgroundColor).saturate(0.5).darken(0.35).rgbString());
|
||||
this.active[i]._model.borderColor = this.active[i].custom && this.active[i].custom.hoverBorderColor ? this.active[i].custom.hoverBorderColor : helpers.getValueAtIndexOrDefault(dataset.pointHoverBorderColor, index, helpers.color(this.active[i]._model.borderColor).saturate(0.5).darken(0.35).rgbString());
|
||||
this.active[i]._model.borderWidth = this.active[i].custom && this.active[i].custom.hoverBorderWidth ? this.active[i].custom.hoverBorderWidth : helpers.getValueAtIndexOrDefault(dataset.pointBorderWidth, index, this.active[i]._model.borderWidth + 2);
|
||||
}
|
||||
break;
|
||||
case 'dataset':
|
||||
break;
|
||||
default:
|
||||
// Don't change anything
|
||||
}
|
||||
}
|
||||
|
||||
// Built in Tooltips
|
||||
if (this.options.tooltips.enabled) {
|
||||
|
||||
// The usual updates
|
||||
this.tooltip.initialize();
|
||||
|
||||
// Active
|
||||
if (this.active.length) {
|
||||
this.tooltip._model.opacity = 1;
|
||||
|
||||
helpers.extend(this.tooltip, {
|
||||
_active: this.active,
|
||||
});
|
||||
|
||||
this.tooltip.update();
|
||||
} else {
|
||||
// Inactive
|
||||
this.tooltip._model.opacity = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Hover animations
|
||||
this.tooltip.pivot();
|
||||
|
||||
if (!this.animating) {
|
||||
var changed;
|
||||
|
||||
helpers.each(this.active, function(element, index) {
|
||||
if (element !== this.lastActive[index]) {
|
||||
changed = true;
|
||||
}
|
||||
}, 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.stop();
|
||||
this.render(this.options.hover.animationDuration);
|
||||
}
|
||||
}
|
||||
|
||||
// Remember Last Active
|
||||
this.lastActive = this.active;
|
||||
return this;
|
||||
},
|
||||
});
|
||||
}).call(this);
|
||||
|
||||
Diferenças do arquivo suprimidas por serem muito extensas
Carregar Diff
@@ -0,0 +1,593 @@
|
||||
(function() {
|
||||
"use strict";
|
||||
|
||||
var root = this,
|
||||
Chart = root.Chart,
|
||||
helpers = Chart.helpers;
|
||||
|
||||
var defaultConfig = {
|
||||
hover: {
|
||||
mode: 'single',
|
||||
},
|
||||
|
||||
scales: {
|
||||
xAxes: [{
|
||||
scaleType: "linear", // scatter should not use a dataset axis
|
||||
display: true,
|
||||
position: "bottom",
|
||||
id: "x-axis-1", // need an ID so datasets can reference the scale
|
||||
|
||||
// grid line settings
|
||||
gridLines: {
|
||||
show: true,
|
||||
color: "rgba(0, 0, 0, 0.05)",
|
||||
lineWidth: 1,
|
||||
drawOnChartArea: true,
|
||||
drawTicks: true,
|
||||
zeroLineWidth: 1,
|
||||
zeroLineColor: "rgba(0,0,0,0.25)",
|
||||
},
|
||||
|
||||
// scale numbers
|
||||
beginAtZero: false,
|
||||
integersOnly: false,
|
||||
override: null,
|
||||
|
||||
// label settings
|
||||
labels: {
|
||||
show: true,
|
||||
template: "<%=value%>",
|
||||
fontSize: 12,
|
||||
fontStyle: "normal",
|
||||
fontColor: "#666",
|
||||
fontFamily: "Helvetica Neue",
|
||||
},
|
||||
}],
|
||||
yAxes: [{
|
||||
scaleType: "linear", // only linear but allow scale type registration. This allows extensions to exist solely for log scale for instance
|
||||
display: true,
|
||||
position: "left",
|
||||
id: "y-axis-1",
|
||||
|
||||
// grid line settings
|
||||
gridLines: {
|
||||
show: true,
|
||||
color: "rgba(0, 0, 0, 0.05)",
|
||||
lineWidth: 1,
|
||||
drawOnChartArea: true,
|
||||
drawTicks: true, // draw ticks extending towards the label
|
||||
zeroLineWidth: 1,
|
||||
zeroLineColor: "rgba(0,0,0,0.25)",
|
||||
},
|
||||
|
||||
// scale numbers
|
||||
beginAtZero: false,
|
||||
integersOnly: false,
|
||||
override: null,
|
||||
|
||||
// label settings
|
||||
labels: {
|
||||
show: true,
|
||||
template: "<%=value%>",
|
||||
fontSize: 12,
|
||||
fontStyle: "normal",
|
||||
fontColor: "#666",
|
||||
fontFamily: "Helvetica Neue",
|
||||
}
|
||||
}],
|
||||
},
|
||||
|
||||
//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].borderColor%>\"></span><%if(datasets[i].label){%><%=datasets[i].label%><%}%></li><%}%></ul>",
|
||||
|
||||
tooltips: {
|
||||
template: "(<%= value.x %>, <%= value.y %>)",
|
||||
multiTemplate: "<%if (datasetLabel){%><%=datasetLabel%>: <%}%>(<%= value.x %>, <%= value.y %>)",
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
|
||||
Chart.Type.extend({
|
||||
name: "Scatter",
|
||||
defaults: defaultConfig,
|
||||
initialize: function() {
|
||||
|
||||
// Events
|
||||
helpers.bindEvents(this, this.options.events, this.events);
|
||||
|
||||
//Custom Point Defaults
|
||||
helpers.each(this.data.datasets, function(dataset, datasetIndex) {
|
||||
dataset.metaDataset = new Chart.Line({
|
||||
_chart: this.chart,
|
||||
_datasetIndex: datasetIndex,
|
||||
_points: dataset.metaData,
|
||||
});
|
||||
|
||||
dataset.metaData = [];
|
||||
|
||||
helpers.each(dataset.data, function(dataPoint, index) {
|
||||
dataset.metaData.push(new Chart.Point({
|
||||
_datasetIndex: datasetIndex,
|
||||
_index: index,
|
||||
_chart: this.chart,
|
||||
_model: {
|
||||
x: 0, //xScale.getPixelForValue(null, index, true),
|
||||
y: 0, //this.chartArea.bottom,
|
||||
},
|
||||
}));
|
||||
|
||||
}, this);
|
||||
|
||||
// The line chart onlty supports a single x axis because the x axis is always a dataset axis
|
||||
if (!dataset.xAxisID) {
|
||||
dataset.xAxisID = this.options.scales.xAxes[0].id;
|
||||
}
|
||||
|
||||
if (!dataset.yAxisID) {
|
||||
dataset.yAxisID = this.options.scales.yAxes[0].id;
|
||||
}
|
||||
|
||||
}, this);
|
||||
|
||||
// Build and fit the scale. Needs to happen after the axis IDs have been set
|
||||
this.buildScale();
|
||||
|
||||
// Create tooltip instance exclusively for this chart with some defaults.
|
||||
this.tooltip = new Chart.Tooltip({
|
||||
_chart: this.chart,
|
||||
_data: this.data,
|
||||
_options: this.options,
|
||||
}, this);
|
||||
|
||||
// Need to fit scales before we reset elements.
|
||||
Chart.scaleService.fitScalesForChart(this, this.chart.width, this.chart.height);
|
||||
|
||||
// Reset so that we animation from the baseline
|
||||
this.resetElements();
|
||||
|
||||
// Update that shiz
|
||||
this.update();
|
||||
},
|
||||
nextPoint: function(collection, index) {
|
||||
return collection[index + 1] || collection[index];
|
||||
},
|
||||
previousPoint: function(collection, index) {
|
||||
return collection[index - 1] || collection[index];
|
||||
},
|
||||
resetElements: function() {
|
||||
// Update the points
|
||||
this.eachElement(function(point, index, dataset, datasetIndex) {
|
||||
var xScale = this.scales[this.data.datasets[datasetIndex].xAxisID];
|
||||
var yScale = this.scales[this.data.datasets[datasetIndex].yAxisID];
|
||||
|
||||
var yScalePoint;
|
||||
|
||||
if (yScale.min < 0 && yScale.max < 0) {
|
||||
// all less than 0. use the top
|
||||
yScalePoint = yScale.getPixelForValue(yScale.max);
|
||||
} else if (yScale.min > 0 && yScale.max > 0) {
|
||||
yScalePoint = yScale.getPixelForValue(yScale.min);
|
||||
} else {
|
||||
yScalePoint = yScale.getPixelForValue(0);
|
||||
}
|
||||
|
||||
helpers.extend(point, {
|
||||
// Utility
|
||||
_chart: this.chart,
|
||||
_xScale: xScale,
|
||||
_yScale: yScale,
|
||||
_datasetIndex: datasetIndex,
|
||||
_index: index,
|
||||
|
||||
// Desired view properties
|
||||
_model: {
|
||||
x: xScale.getPixelForValue(this.data.datasets[datasetIndex].data[index].x), // value not used in dataset scale, but we want a consistent API between scales
|
||||
y: yScalePoint,
|
||||
|
||||
// Appearance
|
||||
tension: point.custom && point.custom.tension ? point.custom.tension : this.options.elements.line.tension,
|
||||
radius: point.custom && point.custom.radius ? point.custom.pointRadius : helpers.getValueAtIndexOrDefault(this.data.datasets[datasetIndex].pointRadius, index, this.options.elements.point.radius),
|
||||
backgroundColor: point.custom && point.custom.backgroundColor ? point.custom.backgroundColor : helpers.getValueAtIndexOrDefault(this.data.datasets[datasetIndex].pointBackgroundColor, index, this.options.elements.point.backgroundColor),
|
||||
borderColor: point.custom && point.custom.borderColor ? point.custom.borderColor : helpers.getValueAtIndexOrDefault(this.data.datasets[datasetIndex].pointBorderColor, index, this.options.elements.point.borderColor),
|
||||
borderWidth: point.custom && point.custom.borderWidth ? point.custom.borderWidth : helpers.getValueAtIndexOrDefault(this.data.datasets[datasetIndex].pointBorderWidth, index, this.options.elements.point.borderWidth),
|
||||
skip: (typeof this.data.datasets[datasetIndex].data[index].x != 'number') || (typeof this.data.datasets[datasetIndex].data[index].y != 'number'),
|
||||
|
||||
// Tooltip
|
||||
hoverRadius: point.custom && point.custom.hoverRadius ? point.custom.hoverRadius : helpers.getValueAtIndexOrDefault(this.data.datasets[datasetIndex].pointHitRadius, index, this.options.elements.point.hitRadius),
|
||||
},
|
||||
});
|
||||
}, this);
|
||||
|
||||
// Update control points for the bezier curve
|
||||
this.eachElement(function(point, index, dataset, datasetIndex) {
|
||||
var controlPoints = helpers.splineCurve(
|
||||
this.previousPoint(dataset, index)._model,
|
||||
point._model,
|
||||
this.nextPoint(dataset, index)._model,
|
||||
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
|
||||
|
||||
// Cap puter bezier handles to the upper/lower scale bounds
|
||||
if (controlPoints.next.y > this.chartArea.bottom) {
|
||||
point._model.controlPointNextY = this.chartArea.bottom;
|
||||
} else if (controlPoints.next.y < this.chartArea.top) {
|
||||
point._model.controlPointNextY = this.chartArea.top;
|
||||
} else {
|
||||
point._model.controlPointNextY = controlPoints.next.y;
|
||||
}
|
||||
|
||||
// Cap inner bezier handles to the upper/lower scale bounds
|
||||
if (controlPoints.previous.y > this.chartArea.bottom) {
|
||||
point._model.controlPointPreviousY = this.chartArea.bottom;
|
||||
} else if (controlPoints.previous.y < this.chartArea.top) {
|
||||
point._model.controlPointPreviousY = this.chartArea.top;
|
||||
} else {
|
||||
point._model.controlPointPreviousY = controlPoints.previous.y;
|
||||
}
|
||||
|
||||
// Now pivot the point for animation
|
||||
point.pivot();
|
||||
}, this);
|
||||
},
|
||||
update: function() {
|
||||
Chart.scaleService.fitScalesForChart(this, this.chart.width, this.chart.height);
|
||||
|
||||
// Update the lines
|
||||
this.eachDataset(function(dataset, datasetIndex) {
|
||||
var yScale = this.scales[dataset.yAxisID];
|
||||
|
||||
helpers.extend(dataset.metaDataset, {
|
||||
// Utility
|
||||
_scale: yScale,
|
||||
_datasetIndex: datasetIndex,
|
||||
// Data
|
||||
_children: dataset.metaData,
|
||||
// Model
|
||||
_model: {
|
||||
// Appearance
|
||||
tension: dataset.tension || this.options.elements.line.tension,
|
||||
backgroundColor: dataset.backgroundColor || this.options.elements.line.backgroundColor,
|
||||
borderWidth: dataset.borderWidth || this.options.elements.line.borderWidth,
|
||||
borderColor: dataset.borderColor || this.options.elements.line.borderColor,
|
||||
fill: dataset.fill !== undefined ? dataset.fill : this.options.elements.line.fill, // use the value from the dataset if it was provided. else fall back to the default
|
||||
skipNull: dataset.skipNull !== undefined ? dataset.skipNull : this.options.elements.line.skipNull,
|
||||
drawNull: dataset.drawNull !== undefined ? dataset.drawNull : this.options.elements.line.drawNull,
|
||||
// Scale
|
||||
scaleTop: yScale.top,
|
||||
scaleBottom: yScale.bottom,
|
||||
scaleZero: yScale.getPixelForValue(0),
|
||||
},
|
||||
});
|
||||
|
||||
dataset.metaDataset.pivot();
|
||||
});
|
||||
|
||||
// Update the points
|
||||
this.eachElement(function(point, index, dataset, datasetIndex) {
|
||||
var xScale = this.scales[this.data.datasets[datasetIndex].xAxisID];
|
||||
var yScale = this.scales[this.data.datasets[datasetIndex].yAxisID];
|
||||
|
||||
helpers.extend(point, {
|
||||
// Utility
|
||||
_chart: this.chart,
|
||||
_xScale: xScale,
|
||||
_yScale: yScale,
|
||||
_datasetIndex: datasetIndex,
|
||||
_index: index,
|
||||
|
||||
// Desired view properties
|
||||
_model: {
|
||||
x: xScale.getPixelForValue(this.data.datasets[datasetIndex].data[index].x),
|
||||
y: yScale.getPixelForValue(this.data.datasets[datasetIndex].data[index].y),
|
||||
|
||||
// Appearance
|
||||
tension: point.custom && point.custom.tension ? point.custom.tension : this.options.elements.line.tension,
|
||||
radius: point.custom && point.custom.radius ? point.custom.pointRadius : helpers.getValueAtIndexOrDefault(this.data.datasets[datasetIndex].pointRadius, index, this.options.elements.point.radius),
|
||||
backgroundColor: point.custom && point.custom.backgroundColor ? point.custom.backgroundColor : helpers.getValueAtIndexOrDefault(this.data.datasets[datasetIndex].pointBackgroundColor, index, this.options.elements.point.backgroundColor),
|
||||
borderColor: point.custom && point.custom.borderColor ? point.custom.borderColor : helpers.getValueAtIndexOrDefault(this.data.datasets[datasetIndex].pointBorderColor, index, this.options.elements.point.borderColor),
|
||||
borderWidth: point.custom && point.custom.borderWidth ? point.custom.borderWidth : helpers.getValueAtIndexOrDefault(this.data.datasets[datasetIndex].pointBorderWidth, index, this.options.elements.point.borderWidth),
|
||||
skip: (typeof this.data.datasets[datasetIndex].data[index].x != 'number') || (typeof this.data.datasets[datasetIndex].data[index].y != 'number'),
|
||||
|
||||
// Tooltip
|
||||
hoverRadius: point.custom && point.custom.hoverRadius ? point.custom.hoverRadius : helpers.getValueAtIndexOrDefault(this.data.datasets[datasetIndex].pointHitRadius, index, this.options.elements.point.hitRadius),
|
||||
},
|
||||
});
|
||||
}, this);
|
||||
|
||||
|
||||
// Update control points for the bezier curve
|
||||
this.eachElement(function(point, index, dataset, datasetIndex) {
|
||||
var controlPoints = helpers.splineCurve(
|
||||
this.previousPoint(dataset, index)._model,
|
||||
point._model,
|
||||
this.nextPoint(dataset, index)._model,
|
||||
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
|
||||
|
||||
// Cap puter bezier handles to the upper/lower scale bounds
|
||||
if (controlPoints.next.y > this.chartArea.bottom) {
|
||||
point._model.controlPointNextY = this.chartArea.bottom;
|
||||
} else if (controlPoints.next.y < this.chartArea.top) {
|
||||
point._model.controlPointNextY = this.chartArea.top;
|
||||
} else {
|
||||
point._model.controlPointNextY = controlPoints.next.y;
|
||||
}
|
||||
|
||||
// Cap inner bezier handles to the upper/lower scale bounds
|
||||
if (controlPoints.previous.y > this.chartArea.bottom) {
|
||||
point._model.controlPointPreviousY = this.chartArea.bottom;
|
||||
} else if (controlPoints.previous.y < this.chartArea.top) {
|
||||
point._model.controlPointPreviousY = this.chartArea.top;
|
||||
} else {
|
||||
point._model.controlPointPreviousY = controlPoints.previous.y;
|
||||
}
|
||||
|
||||
// Now pivot the point for animation
|
||||
point.pivot();
|
||||
}, this);
|
||||
|
||||
this.render();
|
||||
},
|
||||
buildScale: function() {
|
||||
var self = this;
|
||||
|
||||
var calculateXRange = function() {
|
||||
this.min = null;
|
||||
this.max = null;
|
||||
|
||||
helpers.each(self.data.datasets, function(dataset) {
|
||||
// Only set the scale range for datasets that actually use this axis
|
||||
if (dataset.xAxisID === this.id) {
|
||||
helpers.each(dataset.data, function(value) {
|
||||
if (this.min === null) {
|
||||
this.min = value.x;
|
||||
} else if (value.x < this.min) {
|
||||
this.min = value.x;
|
||||
}
|
||||
|
||||
if (this.max === null) {
|
||||
this.max = value.x;
|
||||
} else if (value.x > this.max) {
|
||||
this.max = value.x;
|
||||
}
|
||||
}, this);
|
||||
}
|
||||
}, this);
|
||||
};
|
||||
|
||||
var calculateYRange = function() {
|
||||
this.min = null;
|
||||
this.max = null;
|
||||
|
||||
helpers.each(self.data.datasets, function(dataset) {
|
||||
if (dataset.yAxisID === this.id) {
|
||||
helpers.each(dataset.data, function(value) {
|
||||
if (this.min === null) {
|
||||
this.min = value.y;
|
||||
} else if (value.y < this.min) {
|
||||
this.min = value.y;
|
||||
}
|
||||
|
||||
if (this.max === null) {
|
||||
this.max = value.y;
|
||||
} else if (value.y > this.max) {
|
||||
this.max = value.y;
|
||||
}
|
||||
}, this);
|
||||
}
|
||||
}, this);
|
||||
};
|
||||
|
||||
// Map of scale ID to scale object so we can lookup later
|
||||
this.scales = {};
|
||||
|
||||
helpers.each(this.options.scales.xAxes, function(xAxisOptions) {
|
||||
var ScaleClass = Chart.scales.getScaleConstructor(xAxisOptions.scaleType);
|
||||
var scale = new ScaleClass({
|
||||
ctx: this.chart.ctx,
|
||||
options: xAxisOptions,
|
||||
calculateRange: calculateXRange,
|
||||
id: xAxisOptions.id,
|
||||
});
|
||||
|
||||
this.scales[scale.id] = scale;
|
||||
}, this);
|
||||
|
||||
helpers.each(this.options.scales.yAxes, function(yAxisOptions) {
|
||||
var ScaleClass = Chart.scales.getScaleConstructor(yAxisOptions.scaleType);
|
||||
var scale = new ScaleClass({
|
||||
ctx: this.chart.ctx,
|
||||
options: yAxisOptions,
|
||||
calculateRange: calculateYRange,
|
||||
id: yAxisOptions.id,
|
||||
getPointPixelForValue: function(value, index, datasetIndex) {
|
||||
return this.getPixelForValue(value);
|
||||
}
|
||||
});
|
||||
|
||||
this.scales[scale.id] = scale;
|
||||
}, this);
|
||||
},
|
||||
draw: function(ease) {
|
||||
var easingDecimal = ease || 1;
|
||||
this.clear();
|
||||
|
||||
// Draw all the scales
|
||||
helpers.each(this.scales, function(scale) {
|
||||
scale.draw(this.chartArea);
|
||||
}, this);
|
||||
|
||||
// reverse for-loop for proper stacking
|
||||
for (var i = this.data.datasets.length - 1; i >= 0; i--) {
|
||||
|
||||
var dataset = this.data.datasets[i];
|
||||
|
||||
// Transition Point Locations
|
||||
helpers.each(dataset.metaData, function(point, index) {
|
||||
point.transition(easingDecimal);
|
||||
}, this);
|
||||
|
||||
// Transition and Draw the line
|
||||
dataset.metaDataset.transition(easingDecimal).draw();
|
||||
|
||||
// Draw the points
|
||||
helpers.each(dataset.metaData, function(point) {
|
||||
point.draw();
|
||||
});
|
||||
}
|
||||
|
||||
// Finally draw the tooltip
|
||||
this.tooltip.transition(easingDecimal).draw();
|
||||
},
|
||||
events: function(e) {
|
||||
// If exiting chart
|
||||
if (e.type == 'mouseout') {
|
||||
return this;
|
||||
}
|
||||
|
||||
this.lastActive = this.lastActive || [];
|
||||
|
||||
// Find Active Elements
|
||||
this.active = function() {
|
||||
switch (this.options.hover.mode) {
|
||||
case 'single':
|
||||
return this.getElementAtEvent(e);
|
||||
case 'label':
|
||||
return this.getElementsAtEvent(e);
|
||||
case 'dataset':
|
||||
return this.getDatasetAtEvent(e);
|
||||
default:
|
||||
return e;
|
||||
}
|
||||
}.call(this);
|
||||
|
||||
// On Hover hook
|
||||
if (this.options.hover.onHover) {
|
||||
this.options.hover.onHover.call(this, this.active);
|
||||
}
|
||||
|
||||
var dataset;
|
||||
var index;
|
||||
// Remove styling for last active (even if it may still be active)
|
||||
if (this.lastActive.length) {
|
||||
switch (this.options.hover.mode) {
|
||||
case 'single':
|
||||
dataset = this.data.datasets[this.lastActive[0]._datasetIndex];
|
||||
index = this.lastActive[0]._index;
|
||||
|
||||
this.lastActive[0]._model.radius = this.lastActive[0].custom && this.lastActive[0].custom.radius ? this.lastActive[0].custom.pointRadius : helpers.getValueAtIndexOrDefault(dataset.pointRadius, index, this.options.elements.point.radius);
|
||||
this.lastActive[0]._model.backgroundColor = this.lastActive[0].custom && this.lastActive[0].custom.backgroundColor ? this.lastActive[0].custom.backgroundColor : helpers.getValueAtIndexOrDefault(dataset.pointBackgroundColor, index, this.options.elements.point.backgroundColor);
|
||||
this.lastActive[0]._model.borderColor = this.lastActive[0].custom && this.lastActive[0].custom.borderColor ? this.lastActive[0].custom.borderColor : helpers.getValueAtIndexOrDefault(dataset.pointBorderColor, index, this.options.elements.point.borderColor);
|
||||
this.lastActive[0]._model.borderWidth = this.lastActive[0].custom && this.lastActive[0].custom.borderWidth ? this.lastActive[0].custom.borderWidth : helpers.getValueAtIndexOrDefault(dataset.pointBorderWidth, index, this.options.elements.point.borderWidth);
|
||||
break;
|
||||
case 'label':
|
||||
for (var i = 0; i < this.lastActive.length; i++) {
|
||||
dataset = this.data.datasets[this.lastActive[i]._datasetIndex];
|
||||
index = this.lastActive[i]._index;
|
||||
|
||||
this.lastActive[i]._model.radius = this.lastActive[i].custom && this.lastActive[i].custom.radius ? this.lastActive[i].custom.pointRadius : helpers.getValueAtIndexOrDefault(dataset.pointRadius, index, this.options.elements.point.radius);
|
||||
this.lastActive[i]._model.backgroundColor = this.lastActive[i].custom && this.lastActive[i].custom.backgroundColor ? this.lastActive[i].custom.backgroundColor : helpers.getValueAtIndexOrDefault(dataset.pointBackgroundColor, index, this.options.elements.point.backgroundColor);
|
||||
this.lastActive[i]._model.borderColor = this.lastActive[i].custom && this.lastActive[i].custom.borderColor ? this.lastActive[i].custom.borderColor : helpers.getValueAtIndexOrDefault(dataset.pointBorderColor, index, this.options.elements.point.borderColor);
|
||||
this.lastActive[i]._model.borderWidth = this.lastActive[i].custom && this.lastActive[i].custom.borderWidth ? this.lastActive[i].custom.borderWidth : helpers.getValueAtIndexOrDefault(dataset.pointBorderWidth, index, this.options.elements.point.borderWidth);
|
||||
}
|
||||
break;
|
||||
case 'dataset':
|
||||
break;
|
||||
default:
|
||||
// Don't change anything
|
||||
}
|
||||
}
|
||||
|
||||
// Built in hover styling
|
||||
if (this.active.length && this.options.hover.mode) {
|
||||
switch (this.options.hover.mode) {
|
||||
case 'single':
|
||||
dataset = this.data.datasets[this.active[0]._datasetIndex];
|
||||
index = this.active[0]._index;
|
||||
|
||||
this.active[0]._model.radius = this.active[0].custom && this.active[0].custom.hoverRadius ? this.active[0].custom.hoverRadius : helpers.getValueAtIndexOrDefault(dataset.pointHoverRadius, index, this.active[0]._model.radius + 2);
|
||||
this.active[0]._model.backgroundColor = this.active[0].custom && this.active[0].custom.hoverBackgroundColor ? this.active[0].custom.hoverBackgroundColor : helpers.getValueAtIndexOrDefault(dataset.pointHoverBackgroundColor, index, helpers.color(this.active[0]._model.backgroundColor).saturate(0.5).darken(0.35).rgbString());
|
||||
this.active[0]._model.borderColor = this.active[0].custom && this.active[0].custom.hoverBorderColor ? this.active[0].custom.hoverBorderColor : helpers.getValueAtIndexOrDefault(dataset.pointHoverBorderColor, index, helpers.color(this.active[0]._model.borderColor).saturate(0.5).darken(0.35).rgbString());
|
||||
this.active[0]._model.borderWidth = this.active[0].custom && this.active[0].custom.hoverBorderWidth ? this.active[0].custom.hoverBorderWidth : helpers.getValueAtIndexOrDefault(dataset.pointBorderWidth, index, this.active[0]._model.borderWidth + 2);
|
||||
break;
|
||||
case 'label':
|
||||
for (var i = 0; i < this.active.length; i++) {
|
||||
dataset = this.data.datasets[this.active[i]._datasetIndex];
|
||||
index = this.active[i]._index;
|
||||
|
||||
this.active[i]._model.radius = this.active[i].custom && this.active[i].custom.hoverRadius ? this.active[i].custom.hoverRadius : helpers.getValueAtIndexOrDefault(dataset.pointHoverRadius, index, this.active[i]._model.radius + 2);
|
||||
this.active[i]._model.backgroundColor = this.active[i].custom && this.active[i].custom.hoverBackgroundColor ? this.active[i].custom.hoverBackgroundColor : helpers.getValueAtIndexOrDefault(dataset.pointHoverBackgroundColor, index, helpers.color(this.active[i]._model.backgroundColor).saturate(0.5).darken(0.35).rgbString());
|
||||
this.active[i]._model.borderColor = this.active[i].custom && this.active[i].custom.hoverBorderColor ? this.active[i].custom.hoverBorderColor : helpers.getValueAtIndexOrDefault(dataset.pointHoverBorderColor, index, helpers.color(this.active[i]._model.borderColor).saturate(0.5).darken(0.35).rgbString());
|
||||
this.active[i]._model.borderWidth = this.active[i].custom && this.active[i].custom.hoverBorderWidth ? this.active[i].custom.hoverBorderWidth : helpers.getValueAtIndexOrDefault(dataset.pointBorderWidth, index, this.active[i]._model.borderWidth + 2);
|
||||
}
|
||||
break;
|
||||
case 'dataset':
|
||||
break;
|
||||
default:
|
||||
// Don't change anything
|
||||
}
|
||||
}
|
||||
|
||||
// Built in Tooltips
|
||||
if (this.options.tooltips.enabled) {
|
||||
|
||||
// The usual updates
|
||||
this.tooltip.initialize();
|
||||
|
||||
// Active
|
||||
if (this.active.length) {
|
||||
this.tooltip._model.opacity = 1;
|
||||
|
||||
helpers.extend(this.tooltip, {
|
||||
_active: this.active,
|
||||
});
|
||||
|
||||
this.tooltip.update();
|
||||
} else {
|
||||
// Inactive
|
||||
this.tooltip._model.opacity = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Hover animations
|
||||
this.tooltip.pivot();
|
||||
|
||||
if (!this.animating) {
|
||||
var changed;
|
||||
|
||||
helpers.each(this.active, function(element, index) {
|
||||
if (element !== this.lastActive[index]) {
|
||||
changed = true;
|
||||
}
|
||||
}, 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.stop();
|
||||
this.render(this.options.hoverAnimationDuration);
|
||||
}
|
||||
}
|
||||
|
||||
// Remember Last Active
|
||||
this.lastActive = this.active;
|
||||
return this;
|
||||
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
}).call(this);
|
||||
Referência em uma Nova Issue
Bloquear um usuário