first commit
This commit is contained in:
12
chart/zoom/.gitignore
vendored
Executable file
12
chart/zoom/.gitignore
vendored
Executable file
@ -0,0 +1,12 @@
|
||||
.DS_Store
|
||||
|
||||
node_modules/*
|
||||
custom/*
|
||||
|
||||
docs/index.md
|
||||
|
||||
bower_components/
|
||||
|
||||
coverage/*
|
||||
|
||||
nbproject/*
|
25
chart/zoom/.travis.yml
Executable file
25
chart/zoom/.travis.yml
Executable file
@ -0,0 +1,25 @@
|
||||
language: node_js
|
||||
node_js:
|
||||
- "6.2"
|
||||
|
||||
before_install:
|
||||
- "export CHROME_BIN=/usr/bin/google-chrome"
|
||||
- "export DISPLAY=:99.0"
|
||||
- "sh -e /etc/init.d/xvfb start"
|
||||
|
||||
before_script:
|
||||
- npm install
|
||||
|
||||
script:
|
||||
- gulp jshint
|
||||
|
||||
sudo: required
|
||||
dist: trusty
|
||||
|
||||
addons:
|
||||
firefox: latest
|
||||
apt:
|
||||
sources:
|
||||
- google-chrome
|
||||
packages:
|
||||
- google-chrome-stable
|
64
chart/zoom/CONTRIBUTING.md
Executable file
64
chart/zoom/CONTRIBUTING.md
Executable file
@ -0,0 +1,64 @@
|
||||
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/chartjs/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/chartjs/Chart.js/blob/master/docs/07-Advanced.md#writing-new-chart-types) in the documentation or consider [creating a plugin](https://github.com/chartjs/Chart.js/blob/master/docs/07-Advanced.md#creating-plugins).
|
||||
|
||||
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`](https://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](https://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.
|
||||
|
||||
|
||||
Local development
|
||||
-----------------
|
||||
|
||||
Run `npm install` to install all the libraries, then run `gulp dev --test` to build and run tests as you make changes.
|
||||
|
||||
|
||||
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.
|
||||
|
||||
Be advised that **Chart.js 1.0.2 is in feature-complete status**. Pull requests adding new features to the 1.x branch will be disregarded.
|
||||
|
||||
Guidelines:
|
||||
|
||||
- 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/chartjs/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/chartjs/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.
|
||||
- We have a very active Slack community that you can join at https://chartjs-slack-automation.herokuapp.com. If you think you can help, we'd love to have you!
|
||||
|
||||
License
|
||||
-------
|
||||
|
||||
By contributing your code, you agree to license your contribution under the [MIT license](https://github.com/chartjs/Chart.js/blob/master/LICENSE.md).
|
8
chart/zoom/LICENSE.md
Executable file
8
chart/zoom/LICENSE.md
Executable file
@ -0,0 +1,8 @@
|
||||
The MIT License (MIT)
|
||||
Copyright (c) 2013-2016 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:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
69
chart/zoom/README.md
Executable file
69
chart/zoom/README.md
Executable file
@ -0,0 +1,69 @@
|
||||
# chartjs-plugin-zoom
|
||||
|
||||
A zoom and pan plugin for Chart.js >= 2.1.0
|
||||
|
||||
Panning can be done via the mouse or with a finger.
|
||||
Zooming is done via the mouse wheel or via a pinch gesture. [Hammer JS](https://hammerjs.github.io/) is used for gesture recognition.
|
||||
|
||||
[Live Codepen Demo](https://codepen.io/pen/PGabEK)
|
||||
|
||||
## Configuration
|
||||
|
||||
To configure the zoom and pan plugin, you can simply add new config options to your chart config.
|
||||
|
||||
```javascript
|
||||
{
|
||||
// Container for pan options
|
||||
pan: {
|
||||
// Boolean to enable panning
|
||||
enabled: true,
|
||||
|
||||
// Panning directions. Remove the appropriate direction to disable
|
||||
// Eg. 'y' would only allow panning in the y direction
|
||||
mode: 'xy'
|
||||
},
|
||||
|
||||
// Container for zoom options
|
||||
zoom: {
|
||||
// Boolean to enable zooming
|
||||
enabled: true,
|
||||
|
||||
// Zooming directions. Remove the appropriate direction to disable
|
||||
// Eg. 'y' would only allow zooming in the y direction
|
||||
mode: 'xy',
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## To-do Items
|
||||
The following features still need to be done:
|
||||
* Pan limits. We should be able to set limits for all axes or for a single axis, identified by ID, that are the maximum and minimum values, in data values, that can be panned to.
|
||||
* Zoom limits. Similar to pan limits but for zooming
|
||||
* Panning of category scales (the ones that use strings as labels)
|
||||
* Zooming of category scales (the ones that use strings as labels)
|
||||
|
||||
## Installation
|
||||
|
||||
To download a zip, go to the chartjs-plugin-zoom.js on Github
|
||||
|
||||
To install via npm / bower:
|
||||
|
||||
```bash
|
||||
npm install chartjs-plugin-zoom --save
|
||||
```
|
||||
|
||||
Prior to v0.4.0, this plugin was known as 'Chart.Zoom.js'. Old versions are still available on npm under that name.
|
||||
|
||||
## Documentation
|
||||
|
||||
You can find documentation for Chart.js at [www.chartjs.org/docs](https://www.chartjs.org/docs).
|
||||
|
||||
Examples for this plugin are available in the [samples folder](samples).
|
||||
|
||||
## 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/chartjs/chartjs-plugin-zoom.js/blob/master/CONTRIBUTING.md) first.
|
||||
|
||||
## License
|
||||
|
||||
chartjs-plugin-zoom.js is available under the [MIT license](https://opensource.org/licenses/MIT).
|
BIN
chart/zoom/chartjs-plugin-zoom-master.zip
Executable file
BIN
chart/zoom/chartjs-plugin-zoom-master.zip
Executable file
Binary file not shown.
502
chart/zoom/chartjs-plugin-zoom.js
Executable file
502
chart/zoom/chartjs-plugin-zoom.js
Executable file
@ -0,0 +1,502 @@
|
||||
/*!
|
||||
* chartjs-plugin-zoom
|
||||
* https://chartjs.org/
|
||||
* Version: 0.4.5
|
||||
*
|
||||
* Copyright 2016 Evert Timberg
|
||||
* Released under the MIT license
|
||||
* https://github.com/chartjs/chartjs-plugin-zoom/blob/master/LICENSE.md
|
||||
*/
|
||||
(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
|
||||
|
||||
},{}],2:[function(require,module,exports){
|
||||
/*jslint browser:true, devel:true, white:true, vars:true */
|
||||
/*global require*/
|
||||
|
||||
// hammer JS for touch support
|
||||
var Hammer = require('hammerjs');
|
||||
Hammer = typeof(Hammer) === 'function' ? Hammer : window.Hammer;
|
||||
|
||||
// Get the chart variable
|
||||
var Chart = require('chart.js');
|
||||
Chart = typeof(Chart) === 'function' ? Chart : window.Chart;
|
||||
var helpers = Chart.helpers;
|
||||
|
||||
// Take the zoom namespace of Chart
|
||||
var zoomNS = Chart.Zoom = Chart.Zoom || {};
|
||||
|
||||
// Where we store functions to handle different scale types
|
||||
var zoomFunctions = zoomNS.zoomFunctions = zoomNS.zoomFunctions || {};
|
||||
var panFunctions = zoomNS.panFunctions = zoomNS.panFunctions || {};
|
||||
|
||||
// Default options if none are provided
|
||||
var defaultOptions = zoomNS.defaults = {
|
||||
pan: {
|
||||
enabled: true,
|
||||
mode: 'xy',
|
||||
speed: 20,
|
||||
threshold: 10,
|
||||
},
|
||||
zoom: {
|
||||
enabled: true,
|
||||
mode: 'xy',
|
||||
sensitivity: 3,
|
||||
}
|
||||
};
|
||||
|
||||
function directionEnabled(mode, dir) {
|
||||
if (mode === undefined) {
|
||||
return true;
|
||||
} else if (typeof mode === 'string') {
|
||||
return mode.indexOf(dir) !== -1;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function zoomIndexScale(scale, zoom, center, zoomOptions) {
|
||||
var labels = scale.chart.data.labels;
|
||||
var minIndex = scale.minIndex;
|
||||
var lastLabelIndex = labels.length - 1;
|
||||
var maxIndex = scale.maxIndex;
|
||||
var sensitivity = zoomOptions.sensitivity;
|
||||
var chartCenter = scale.isHorizontal() ? scale.left + (scale.width/2) : scale.top + (scale.height/2);
|
||||
var centerPointer = scale.isHorizontal() ? center.x : center.y;
|
||||
|
||||
zoomNS.zoomCumulativeDelta = zoom > 1 ? zoomNS.zoomCumulativeDelta + 1 : zoomNS.zoomCumulativeDelta - 1;
|
||||
|
||||
if (Math.abs(zoomNS.zoomCumulativeDelta) > sensitivity){
|
||||
if(zoomNS.zoomCumulativeDelta < 0){
|
||||
if(centerPointer <= chartCenter){
|
||||
if (minIndex <= 0){
|
||||
maxIndex = Math.min(lastLabelIndex, maxIndex + 1);
|
||||
} else{
|
||||
minIndex = Math.max(0, minIndex - 1);
|
||||
}
|
||||
} else if(centerPointer > chartCenter){
|
||||
if (maxIndex >= lastLabelIndex){
|
||||
minIndex = Math.max(0, minIndex - 1);
|
||||
} else{
|
||||
maxIndex = Math.min(lastLabelIndex, maxIndex + 1);
|
||||
}
|
||||
}
|
||||
zoomNS.zoomCumulativeDelta = 0;
|
||||
}
|
||||
else if(zoomNS.zoomCumulativeDelta > 0){
|
||||
if(centerPointer <= chartCenter){
|
||||
minIndex = minIndex < maxIndex ? minIndex = Math.min(maxIndex, minIndex + 1) : minIndex;
|
||||
} else if(centerPointer > chartCenter){
|
||||
maxIndex = maxIndex > minIndex ? maxIndex = Math.max(minIndex, maxIndex - 1) : maxIndex;
|
||||
}
|
||||
zoomNS.zoomCumulativeDelta = 0;
|
||||
}
|
||||
scale.options.ticks.min = labels[minIndex];
|
||||
scale.options.ticks.max = labels[maxIndex];
|
||||
}
|
||||
}
|
||||
|
||||
function zoomTimeScale(scale, zoom, center) {
|
||||
var options = scale.options;
|
||||
|
||||
var range;
|
||||
var min_percent;
|
||||
if (scale.isHorizontal()) {
|
||||
range = scale.right - scale.left;
|
||||
min_percent = (center.x - scale.left) / range;
|
||||
} else {
|
||||
range = scale.bottom - scale.top;
|
||||
min_percent = (center.y - scale.top) / range;
|
||||
}
|
||||
|
||||
var max_percent = 1 - min_percent;
|
||||
var newDiff = range * (zoom - 1);
|
||||
|
||||
var minDelta = newDiff * min_percent;
|
||||
var maxDelta = newDiff * max_percent;
|
||||
|
||||
options.time.min = scale.getValueForPixel(scale.getPixelForValue(scale.firstTick) + minDelta);
|
||||
options.time.max = scale.getValueForPixel(scale.getPixelForValue(scale.lastTick) - maxDelta);
|
||||
}
|
||||
|
||||
function zoomNumericalScale(scale, zoom, center) {
|
||||
var range = scale.max - scale.min;
|
||||
var newDiff = range * (zoom - 1);
|
||||
|
||||
var cursorPixel = scale.isHorizontal() ? center.x : center.y;
|
||||
var min_percent = (scale.getValueForPixel(cursorPixel) - scale.min) / range;
|
||||
var max_percent = 1 - min_percent;
|
||||
|
||||
var minDelta = newDiff * min_percent;
|
||||
var maxDelta = newDiff * max_percent;
|
||||
|
||||
scale.options.ticks.min = scale.min + minDelta;
|
||||
scale.options.ticks.max = scale.max - maxDelta;
|
||||
}
|
||||
|
||||
function zoomScale(scale, zoom, center, zoomOptions) {
|
||||
var fn = zoomFunctions[scale.options.type];
|
||||
if (fn) {
|
||||
fn(scale, zoom, center, zoomOptions);
|
||||
}
|
||||
}
|
||||
|
||||
function doZoom(chartInstance, zoom, center) {
|
||||
var ca = chartInstance.chartArea;
|
||||
if (!center) {
|
||||
center = {
|
||||
x: (ca.left + ca.right) / 2,
|
||||
y: (ca.top + ca.bottom) / 2,
|
||||
};
|
||||
}
|
||||
|
||||
var zoomOptions = chartInstance.options.zoom;
|
||||
|
||||
if (zoomOptions && helpers.getValueOrDefault(zoomOptions.enabled, defaultOptions.zoom.enabled)) {
|
||||
// Do the zoom here
|
||||
var zoomMode = helpers.getValueOrDefault(chartInstance.options.zoom.mode, defaultOptions.zoom.mode);
|
||||
zoomOptions.sensitivity = helpers.getValueOrDefault(chartInstance.options.zoom.sensitivity, defaultOptions.zoom.sensitivity);
|
||||
|
||||
helpers.each(chartInstance.scales, function(scale, id) {
|
||||
if (scale.isHorizontal() && directionEnabled(zoomMode, 'x')) {
|
||||
zoomScale(scale, zoom, center, zoomOptions);
|
||||
} else if (!scale.isHorizontal() && directionEnabled(zoomMode, 'y')) {
|
||||
// Do Y zoom
|
||||
zoomScale(scale, zoom, center, zoomOptions);
|
||||
}
|
||||
});
|
||||
|
||||
chartInstance.update(0);
|
||||
}
|
||||
}
|
||||
|
||||
function panIndexScale(scale, delta, panOptions) {
|
||||
var labels = scale.chart.data.labels;
|
||||
var lastLabelIndex = labels.length - 1;
|
||||
var offsetAmt = Math.max((scale.ticks.length - ((scale.options.gridLines.offsetGridLines) ? 0 : 1)), 1);
|
||||
var panSpeed = panOptions.speed;
|
||||
var minIndex = scale.minIndex;
|
||||
var step = Math.round(scale.width / (offsetAmt * panSpeed));
|
||||
var maxIndex;
|
||||
|
||||
zoomNS.panCumulativeDelta += delta;
|
||||
|
||||
minIndex = zoomNS.panCumulativeDelta > step ? Math.max(0, minIndex -1) : zoomNS.panCumulativeDelta < -step ? Math.min(lastLabelIndex - offsetAmt + 1, minIndex + 1) : minIndex;
|
||||
zoomNS.panCumulativeDelta = minIndex !== scale.minIndex ? 0 : zoomNS.panCumulativeDelta;
|
||||
|
||||
maxIndex = Math.min(lastLabelIndex, minIndex + offsetAmt - 1);
|
||||
|
||||
scale.options.ticks.min = labels[minIndex];
|
||||
scale.options.ticks.max = labels[maxIndex];
|
||||
}
|
||||
|
||||
function panTimeScale(scale, delta) {
|
||||
var options = scale.options;
|
||||
options.time.min = scale.getValueForPixel(scale.getPixelForValue(scale.firstTick) - delta);
|
||||
options.time.max = scale.getValueForPixel(scale.getPixelForValue(scale.lastTick) - delta);
|
||||
}
|
||||
|
||||
function panNumericalScale(scale, delta) {
|
||||
var tickOpts = scale.options.ticks;
|
||||
var start = scale.start,
|
||||
end = scale.end;
|
||||
|
||||
if (tickOpts.reverse) {
|
||||
tickOpts.max = scale.getValueForPixel(scale.getPixelForValue(start) - delta);
|
||||
tickOpts.min = scale.getValueForPixel(scale.getPixelForValue(end) - delta);
|
||||
} else {
|
||||
tickOpts.min = scale.getValueForPixel(scale.getPixelForValue(start) - delta);
|
||||
tickOpts.max = scale.getValueForPixel(scale.getPixelForValue(end) - delta);
|
||||
}
|
||||
}
|
||||
|
||||
function panScale(scale, delta, panOptions) {
|
||||
var fn = panFunctions[scale.options.type];
|
||||
if (fn) {
|
||||
fn(scale, delta, panOptions);
|
||||
}
|
||||
}
|
||||
|
||||
function doPan(chartInstance, deltaX, deltaY) {
|
||||
var panOptions = chartInstance.options.pan;
|
||||
if (panOptions && helpers.getValueOrDefault(panOptions.enabled, defaultOptions.pan.enabled)) {
|
||||
var panMode = helpers.getValueOrDefault(chartInstance.options.pan.mode, defaultOptions.pan.mode);
|
||||
panOptions.speed = helpers.getValueOrDefault(chartInstance.options.pan.speed, defaultOptions.pan.speed);
|
||||
|
||||
helpers.each(chartInstance.scales, function(scale, id) {
|
||||
if (scale.isHorizontal() && directionEnabled(panMode, 'x') && deltaX !== 0) {
|
||||
panScale(scale, deltaX, panOptions);
|
||||
} else if (!scale.isHorizontal() && directionEnabled(panMode, 'y') && deltaY !== 0) {
|
||||
panScale(scale, deltaY, panOptions);
|
||||
}
|
||||
});
|
||||
|
||||
chartInstance.update(0);
|
||||
}
|
||||
}
|
||||
|
||||
function positionInChartArea(chartInstance, position) {
|
||||
return (position.x >= chartInstance.chartArea.left && position.x <= chartInstance.chartArea.right) &&
|
||||
(position.y >= chartInstance.chartArea.top && position.y <= chartInstance.chartArea.bottom);
|
||||
}
|
||||
|
||||
function getYAxis(chartInstance) {
|
||||
var scales = chartInstance.scales;
|
||||
|
||||
for (var scaleId in scales) {
|
||||
var scale = scales[scaleId];
|
||||
|
||||
if (!scale.isHorizontal()) {
|
||||
return scale;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Store these for later
|
||||
zoomNS.zoomFunctions.category = zoomIndexScale;
|
||||
zoomNS.zoomFunctions.time = zoomTimeScale;
|
||||
zoomNS.zoomFunctions.linear = zoomNumericalScale;
|
||||
zoomNS.zoomFunctions.logarithmic = zoomNumericalScale;
|
||||
zoomNS.panFunctions.category = panIndexScale;
|
||||
zoomNS.panFunctions.time = panTimeScale;
|
||||
zoomNS.panFunctions.linear = panNumericalScale;
|
||||
zoomNS.panFunctions.logarithmic = panNumericalScale;
|
||||
// Globals for catergory pan and zoom
|
||||
zoomNS.panCumulativeDelta = 0;
|
||||
zoomNS.zoomCumulativeDelta = 0;
|
||||
|
||||
// Chartjs Zoom Plugin
|
||||
var zoomPlugin = {
|
||||
afterInit: function(chartInstance) {
|
||||
helpers.each(chartInstance.scales, function(scale) {
|
||||
scale.originalOptions = JSON.parse(JSON.stringify(scale.options));
|
||||
});
|
||||
|
||||
chartInstance.resetZoom = function() {
|
||||
helpers.each(chartInstance.scales, function(scale, id) {
|
||||
var timeOptions = scale.options.time;
|
||||
var tickOptions = scale.options.ticks;
|
||||
|
||||
if (timeOptions) {
|
||||
delete timeOptions.min;
|
||||
delete timeOptions.max;
|
||||
}
|
||||
|
||||
if (tickOptions) {
|
||||
delete tickOptions.min;
|
||||
delete tickOptions.max;
|
||||
}
|
||||
|
||||
scale.options = helpers.configMerge(scale.options, scale.originalOptions);
|
||||
});
|
||||
|
||||
helpers.each(chartInstance.data.datasets, function(dataset, id) {
|
||||
dataset._meta = null;
|
||||
});
|
||||
|
||||
chartInstance.update();
|
||||
};
|
||||
|
||||
},
|
||||
beforeInit: function(chartInstance) {
|
||||
chartInstance.zoom = {};
|
||||
|
||||
var node = chartInstance.zoom.node = chartInstance.chart.ctx.canvas;
|
||||
|
||||
var options = chartInstance.options;
|
||||
var panThreshold = helpers.getValueOrDefault(options.pan ? options.pan.threshold : undefined, zoomNS.defaults.pan.threshold);
|
||||
|
||||
if (options.zoom && options.zoom.drag) {
|
||||
// Only want to zoom horizontal axis
|
||||
options.zoom.mode = 'x';
|
||||
|
||||
chartInstance.zoom._mouseDownHandler = function(event) {
|
||||
chartInstance.zoom._dragZoomStart = event;
|
||||
};
|
||||
node.addEventListener('mousedown', chartInstance.zoom._mouseDownHandler);
|
||||
|
||||
chartInstance.zoom._mouseMoveHandler = function(event){
|
||||
if (chartInstance.zoom._dragZoomStart) {
|
||||
chartInstance.zoom._dragZoomEnd = event;
|
||||
chartInstance.update(0);
|
||||
}
|
||||
|
||||
chartInstance.update(0);
|
||||
};
|
||||
node.addEventListener('mousemove', chartInstance.zoom._mouseMoveHandler);
|
||||
|
||||
chartInstance.zoom._mouseUpHandler = function(event){
|
||||
if (chartInstance.zoom._dragZoomStart) {
|
||||
var chartArea = chartInstance.chartArea;
|
||||
var yAxis = getYAxis(chartInstance);
|
||||
var beginPoint = chartInstance.zoom._dragZoomStart;
|
||||
var offsetX = beginPoint.target.getBoundingClientRect().left;
|
||||
var startX = Math.min(beginPoint.clientX, event.clientX) - offsetX;
|
||||
var endX = Math.max(beginPoint.clientX, event.clientX) - offsetX;
|
||||
var dragDistance = endX - startX;
|
||||
var chartDistance = chartArea.right - chartArea.left;
|
||||
var zoom = 1 + ((chartDistance - dragDistance) / chartDistance );
|
||||
|
||||
if (dragDistance > 0) {
|
||||
doZoom(chartInstance, zoom, {
|
||||
x: (dragDistance / 2) + startX,
|
||||
y: (yAxis.bottom - yAxis.top) / 2,
|
||||
});
|
||||
}
|
||||
|
||||
chartInstance.zoom._dragZoomStart = null;
|
||||
chartInstance.zoom._dragZoomEnd = null;
|
||||
}
|
||||
};
|
||||
node.addEventListener('mouseup', chartInstance.zoom._mouseUpHandler);
|
||||
} else {
|
||||
chartInstance.zoom._wheelHandler = function(event) {
|
||||
var rect = event.target.getBoundingClientRect();
|
||||
var offsetX = event.clientX - rect.left;
|
||||
var offsetY = event.clientY - rect.top;
|
||||
|
||||
var center = {
|
||||
x : offsetX,
|
||||
y : offsetY
|
||||
};
|
||||
|
||||
if (event.deltaY < 0) {
|
||||
doZoom(chartInstance, 1.1, center);
|
||||
} else {
|
||||
doZoom(chartInstance, 0.909, center);
|
||||
}
|
||||
// Prevent the event from triggering the default behavior (eg. Content scrolling).
|
||||
event.preventDefault();
|
||||
};
|
||||
|
||||
node.addEventListener('wheel', chartInstance.zoom._wheelHandler);
|
||||
}
|
||||
|
||||
if (Hammer) {
|
||||
var mc = new Hammer.Manager(node);
|
||||
mc.add(new Hammer.Pinch());
|
||||
mc.add(new Hammer.Pan({
|
||||
threshold: panThreshold
|
||||
}));
|
||||
|
||||
// Hammer reports the total scaling. We need the incremental amount
|
||||
var currentPinchScaling;
|
||||
var handlePinch = function handlePinch(e) {
|
||||
var diff = 1 / (currentPinchScaling) * e.scale;
|
||||
doZoom(chartInstance, diff, e.center);
|
||||
|
||||
// Keep track of overall scale
|
||||
currentPinchScaling = e.scale;
|
||||
};
|
||||
|
||||
mc.on('pinchstart', function(e) {
|
||||
currentPinchScaling = 1; // reset tracker
|
||||
});
|
||||
mc.on('pinch', handlePinch);
|
||||
mc.on('pinchend', function(e) {
|
||||
handlePinch(e);
|
||||
currentPinchScaling = null; // reset
|
||||
zoomNS.zoomCumulativeDelta = 0;
|
||||
});
|
||||
|
||||
var currentDeltaX = null, currentDeltaY = null, panning = false;
|
||||
var handlePan = function handlePan(e) {
|
||||
if (currentDeltaX !== null && currentDeltaY !== null) {
|
||||
panning = true;
|
||||
var deltaX = e.deltaX - currentDeltaX;
|
||||
var deltaY = e.deltaY - currentDeltaY;
|
||||
currentDeltaX = e.deltaX;
|
||||
currentDeltaY = e.deltaY;
|
||||
doPan(chartInstance, deltaX, deltaY);
|
||||
}
|
||||
};
|
||||
|
||||
mc.on('panstart', function(e) {
|
||||
currentDeltaX = 0;
|
||||
currentDeltaY = 0;
|
||||
handlePan(e);
|
||||
});
|
||||
mc.on('panmove', handlePan);
|
||||
mc.on('panend', function(e) {
|
||||
currentDeltaX = null;
|
||||
currentDeltaY = null;
|
||||
zoomNS.panCumulativeDelta = 0;
|
||||
setTimeout(function() { panning = false; }, 500);
|
||||
});
|
||||
|
||||
chartInstance.zoom._ghostClickHandler = function(e) {
|
||||
if (panning) {
|
||||
e.stopImmediatePropagation();
|
||||
e.preventDefault();
|
||||
}
|
||||
};
|
||||
node.addEventListener('click', chartInstance.zoom._ghostClickHandler);
|
||||
|
||||
chartInstance._mc = mc;
|
||||
}
|
||||
},
|
||||
|
||||
beforeDatasetsDraw: function(chartInstance) {
|
||||
var ctx = chartInstance.chart.ctx;
|
||||
var chartArea = chartInstance.chartArea;
|
||||
ctx.save();
|
||||
ctx.beginPath();
|
||||
|
||||
if (chartInstance.zoom._dragZoomEnd) {
|
||||
var yAxis = getYAxis(chartInstance);
|
||||
var beginPoint = chartInstance.zoom._dragZoomStart;
|
||||
var endPoint = chartInstance.zoom._dragZoomEnd;
|
||||
var offsetX = beginPoint.target.getBoundingClientRect().left;
|
||||
var startX = Math.min(beginPoint.clientX, endPoint.clientX) - offsetX;
|
||||
var endX = Math.max(beginPoint.clientX, endPoint.clientX) - offsetX;
|
||||
var rectWidth = endX - startX;
|
||||
|
||||
|
||||
ctx.fillStyle = 'rgba(225,225,225,0.3)';
|
||||
ctx.lineWidth = 5;
|
||||
ctx.fillRect(startX, yAxis.top, rectWidth, yAxis.bottom - yAxis.top);
|
||||
}
|
||||
|
||||
ctx.rect(chartArea.left, chartArea.top, chartArea.right - chartArea.left, chartArea.bottom - chartArea.top);
|
||||
ctx.clip();
|
||||
},
|
||||
|
||||
afterDatasetsDraw: function(chartInstance) {
|
||||
chartInstance.chart.ctx.restore();
|
||||
},
|
||||
|
||||
destroy: function(chartInstance) {
|
||||
if (chartInstance.zoom) {
|
||||
var options = chartInstance.options;
|
||||
var node = chartInstance.zoom.node;
|
||||
|
||||
if (options.zoom && options.zoom.drag) {
|
||||
node.removeEventListener('mousedown', chartInstance.zoom._mouseDownHandler);
|
||||
node.removeEventListener('mousemove', chartInstance.zoom._mouseMoveHandler);
|
||||
node.removeEventListener('mouseup', chartInstance.zoom._mouseUpHandler);
|
||||
} else {
|
||||
node.removeEventListener('wheel', chartInstance.zoom._wheelHandler);
|
||||
}
|
||||
|
||||
if (Hammer) {
|
||||
node.removeEventListener('click', chartInstance.zoom._ghostClickHandler);
|
||||
}
|
||||
|
||||
delete chartInstance.zoom;
|
||||
|
||||
var mc = chartInstance._mc;
|
||||
if (mc) {
|
||||
mc.remove('pinchstart');
|
||||
mc.remove('pinch');
|
||||
mc.remove('pinchend');
|
||||
mc.remove('panstart');
|
||||
mc.remove('pan');
|
||||
mc.remove('panend');
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = zoomPlugin;
|
||||
Chart.pluginService.register(zoomPlugin);
|
||||
|
||||
},{"chart.js":1,"hammerjs":1}]},{},[2]);
|
10
chart/zoom/chartjs-plugin-zoom.min.js
vendored
Executable file
10
chart/zoom/chartjs-plugin-zoom.min.js
vendored
Executable file
File diff suppressed because one or more lines are too long
4
chart/zoom/config.jshintrc
Executable file
4
chart/zoom/config.jshintrc
Executable file
@ -0,0 +1,4 @@
|
||||
{
|
||||
"node": true,
|
||||
"predef": [ "require", "module" ]
|
||||
}
|
90
chart/zoom/gulpfile.js
Executable file
90
chart/zoom/gulpfile.js
Executable file
@ -0,0 +1,90 @@
|
||||
var gulp = require('gulp'),
|
||||
concat = require('gulp-concat'),
|
||||
uglify = require('gulp-uglify'),
|
||||
util = require('gulp-util'),
|
||||
jshint = require('gulp-jshint'),
|
||||
replace = require('gulp-replace'),
|
||||
insert = require('gulp-insert'),
|
||||
inquirer = require('inquirer'),
|
||||
semver = require('semver'),
|
||||
exec = require('child_process').exec,
|
||||
fs = require('fs'),
|
||||
package = require('./package.json'),
|
||||
browserify = require('browserify'),
|
||||
streamify = require('gulp-streamify'),
|
||||
source = require('vinyl-source-stream'),
|
||||
merge = require('merge-stream');
|
||||
|
||||
var srcDir = './src/';
|
||||
var outDir = './';
|
||||
|
||||
var header = "/*!\n\
|
||||
* chartjs-plugin-zoom\n\
|
||||
* https://chartjs.org/\n\
|
||||
* Version: {{ version }}\n\
|
||||
*\n\
|
||||
* Copyright 2016 Evert Timberg\n\
|
||||
* Released under the MIT license\n\
|
||||
* https://github.com/chartjs/chartjs-plugin-zoom/blob/master/LICENSE.md\n\
|
||||
*/\n";
|
||||
|
||||
gulp.task('build', buildTask);
|
||||
gulp.task('bump', bumpTask);
|
||||
gulp.task('jshint', jshintTask);
|
||||
|
||||
function buildTask() {
|
||||
var nonBundled = browserify('./src/chart.zoom.js')
|
||||
.ignore('chart.js')
|
||||
.ignore('hammerjs')
|
||||
.bundle()
|
||||
.pipe(source('chartjs-plugin-zoom.js'))
|
||||
.pipe(insert.prepend(header))
|
||||
.pipe(streamify(replace('{{ version }}', package.version)))
|
||||
.pipe(gulp.dest(outDir))
|
||||
.pipe(streamify(uglify({
|
||||
preserveComments: 'some'
|
||||
})))
|
||||
.pipe(streamify(concat('chartjs-plugin-zoom.min.js')))
|
||||
.pipe(gulp.dest(outDir));
|
||||
|
||||
return nonBundled;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Usage : gulp bump
|
||||
* Prompts: Version increment to bump
|
||||
* Output: - New version number written into package.json & bower.json
|
||||
*/
|
||||
function bumpTask(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();
|
||||
});
|
||||
}
|
||||
|
||||
function jshintTask() {
|
||||
return gulp.src(srcDir + '**/*.js')
|
||||
.pipe(jshint('config.jshintrc'))
|
||||
.pipe(jshint.reporter('jshint-stylish'))
|
||||
.pipe(jshint.reporter('fail'));
|
||||
}
|
33
chart/zoom/package.json
Executable file
33
chart/zoom/package.json
Executable file
@ -0,0 +1,33 @@
|
||||
{
|
||||
"name": "chartjs-plugin-zoom",
|
||||
"description": "Simple HTML5 charts using the canvas element.",
|
||||
"version": "0.4.5",
|
||||
"author": "Evert Timberg <evert.timberg@gmail.com>",
|
||||
"license": "MIT",
|
||||
"main": "src/chart.zoom.js",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/chartjs/chartjs-plugin-zoom.git"
|
||||
},
|
||||
"devDependencies": {
|
||||
"browserify": "^13.0.0",
|
||||
"gulp": "3.9.x",
|
||||
"gulp-concat": "^2.6.0",
|
||||
"gulp-insert": "^0.5.0",
|
||||
"gulp-jshint": "^2.0.0",
|
||||
"gulp-replace": "^0.5.4",
|
||||
"gulp-streamify": "^1.0.2",
|
||||
"gulp-uglify": "^1.5.3",
|
||||
"gulp-util": "^3.0.7",
|
||||
"inquirer": "^1.0.2",
|
||||
"jshint": "^2.9.2",
|
||||
"jshint-stylish": "^2.2.0",
|
||||
"merge-stream": "^1.0.0",
|
||||
"semver": "^5.1.0",
|
||||
"vinyl-source-stream": "^1.1.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"chart.js": "^2.1.5",
|
||||
"hammerjs": "^2.0.8"
|
||||
}
|
||||
}
|
109
chart/zoom/samples/pan-bar.html
Executable file
109
chart/zoom/samples/pan-bar.html
Executable file
@ -0,0 +1,109 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>Bar Chart Pan</title>
|
||||
<script src="../node_modules/chart.js/dist/Chart.bundle.js"></script>
|
||||
<script src="../node_modules/hammerjs/hammer.min.js"></script>
|
||||
<script src="../chartjs-plugin-zoom.js"></script>
|
||||
|
||||
<style>
|
||||
canvas {
|
||||
-moz-user-select: none;
|
||||
-webkit-user-select: none;
|
||||
-ms-user-select: none;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="container" style="width: 75%;">
|
||||
<canvas id="canvas"></canvas>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
var MONTHS = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
|
||||
|
||||
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", "August", "September", "October", "November", "December"],
|
||||
datasets: [{
|
||||
label: 'Dataset 1',
|
||||
backgroundColor: "rgba(220,220,220,0.5)",
|
||||
data: [randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()]
|
||||
}, {
|
||||
hidden: false,
|
||||
label: 'Dataset 2',
|
||||
backgroundColor: "rgba(255,187,205,1)",
|
||||
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, {
|
||||
type: 'bar',
|
||||
data: barChartData,
|
||||
options: {
|
||||
// Elements options apply to all of the options unless overridden in a dataset
|
||||
// In this case, we are setting the border of each bar to be 2px wide and green
|
||||
elements: {
|
||||
rectangle: {
|
||||
borderWidth: 2,
|
||||
borderColor: 'rgb(0, 255, 0)',
|
||||
borderSkipped: 'bottom'
|
||||
}
|
||||
},
|
||||
responsive: true,
|
||||
legend: {
|
||||
position: 'top',
|
||||
},
|
||||
title: {
|
||||
display: true,
|
||||
text: 'Chart.js Bar Chart'
|
||||
},
|
||||
pan: {
|
||||
enabled: true,
|
||||
mode: 'xy',
|
||||
speed: 10,
|
||||
threshold: 10
|
||||
},
|
||||
zoom: {
|
||||
enabled: true,
|
||||
mode: 'y',
|
||||
limits: {
|
||||
max: 10,
|
||||
min: 0.5
|
||||
}
|
||||
},
|
||||
scales: {
|
||||
xAxes: [{
|
||||
ticks: {
|
||||
min: 'March',
|
||||
max: 'May'
|
||||
}
|
||||
}]
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
108
chart/zoom/samples/zoom-bar-x._testhtml
Executable file
108
chart/zoom/samples/zoom-bar-x._testhtml
Executable file
@ -0,0 +1,108 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>Bar Chart Zoom</title>
|
||||
<script src="../../Chart.bundle.js"></script>
|
||||
<script src="../node_modules/hammerjs/hammer.min.js"></script>
|
||||
<script src="../chartjs-plugin-zoom.js"></script>
|
||||
|
||||
<style>
|
||||
canvas {
|
||||
-moz-user-select: none;
|
||||
-webkit-user-select: none;
|
||||
-ms-user-select: none;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="container" style="width: 75%;">
|
||||
<canvas id="canvas"></canvas>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
var MONTHS = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
|
||||
|
||||
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-16", "February-16", "March-16", "April-16", "May-16", "June-16", "July-16", "August-16", "September-16", "October-16", "November-16", "December-16", "January-17", "February-17", "March-17", "April-17", "May-17", "June-17", "July-17", "August-17", "September-17", "October-17", "November-17", "December-17"],
|
||||
datasets: [{
|
||||
label: 'Dataset 1',
|
||||
backgroundColor: "rgba(220,220,220,0.5)",
|
||||
data: [randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()]
|
||||
}, {
|
||||
hidden: false,
|
||||
label: 'Dataset 2',
|
||||
backgroundColor: "rgba(255,187,205,1)",
|
||||
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, {
|
||||
type: 'bar',
|
||||
data: barChartData,
|
||||
options: {
|
||||
// Elements options apply to all of the options unless overridden in a dataset
|
||||
// In this case, we are setting the border of each bar to be 2px wide and green
|
||||
elements: {
|
||||
rectangle: {
|
||||
borderWidth: 2,
|
||||
borderColor: 'rgb(0, 255, 0)',
|
||||
borderSkipped: 'bottom'
|
||||
}
|
||||
},
|
||||
responsive: true,
|
||||
legend: {
|
||||
position: 'top',
|
||||
},
|
||||
title: {
|
||||
display: true,
|
||||
text: 'Chart.js Bar Chart'
|
||||
},
|
||||
pan: {
|
||||
enabled: true,
|
||||
mode: 'xy' // is panning about the y axis neccessary for bar charts?
|
||||
},
|
||||
zoom: {
|
||||
enabled: true,
|
||||
mode: 'x',
|
||||
sensitivity: 3,
|
||||
limits: {
|
||||
max: 10,
|
||||
min: 0.5
|
||||
}
|
||||
},
|
||||
scales: {
|
||||
xAxes: [{
|
||||
ticks: {
|
||||
min: 'February-16',
|
||||
max: 'June-16'
|
||||
}
|
||||
}]
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
108
chart/zoom/samples/zoom-bar-x.html
Executable file
108
chart/zoom/samples/zoom-bar-x.html
Executable file
@ -0,0 +1,108 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>Bar Chart Zoom</title>
|
||||
<script src="../../Chart.bundle.js"></script>
|
||||
<script src="../node_modules/hammerjs/hammer.min.js"></script>
|
||||
<script src="../chartjs-plugin-zoom.js"></script>
|
||||
|
||||
<style>
|
||||
canvas {
|
||||
-moz-user-select: none;
|
||||
-webkit-user-select: none;
|
||||
-ms-user-select: none;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="container" style="width: 75%;">
|
||||
<canvas id="canvas"></canvas>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
var MONTHS = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
|
||||
|
||||
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-16", "February-16", "March-16", "April-16", "May-16", "June-16", "July-16", "August-16", "September-16", "October-16", "November-16", "December-16", "January-17", "February-17", "March-17", "April-17", "May-17", "June-17", "July-17", "August-17", "September-17", "October-17", "November-17", "December-17"],
|
||||
datasets: [{
|
||||
label: 'Dataset 1',
|
||||
backgroundColor: "rgba(220,220,220,0.5)",
|
||||
data: [randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()]
|
||||
}, {
|
||||
hidden: false,
|
||||
label: 'Dataset 2',
|
||||
backgroundColor: "rgba(255,187,205,1)",
|
||||
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, {
|
||||
type: 'bar',
|
||||
data: barChartData,
|
||||
options: {
|
||||
// Elements options apply to all of the options unless overridden in a dataset
|
||||
// In this case, we are setting the border of each bar to be 2px wide and green
|
||||
elements: {
|
||||
rectangle: {
|
||||
borderWidth: 2,
|
||||
borderColor: 'rgb(0, 255, 0)',
|
||||
borderSkipped: 'bottom'
|
||||
}
|
||||
},
|
||||
responsive: true,
|
||||
legend: {
|
||||
position: 'top',
|
||||
},
|
||||
title: {
|
||||
display: true,
|
||||
text: 'Chart.js Bar Chart'
|
||||
},
|
||||
pan: {
|
||||
enabled: true,
|
||||
mode: 'xy' // is panning about the y axis neccessary for bar charts?
|
||||
},
|
||||
zoom: {
|
||||
enabled: true,
|
||||
mode: 'x',
|
||||
sensitivity: 3,
|
||||
limits: {
|
||||
max: 10,
|
||||
min: 0.5
|
||||
}
|
||||
},
|
||||
scales: {
|
||||
xAxes: [{
|
||||
ticks: {
|
||||
min: 'February-16',
|
||||
max: 'June-16'
|
||||
}
|
||||
}]
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
100
chart/zoom/samples/zoom-bar-x_test.html
Executable file
100
chart/zoom/samples/zoom-bar-x_test.html
Executable file
@ -0,0 +1,100 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>Bar Chart Zoom</title>
|
||||
<script src="../../Chart.bundle.js"></script>
|
||||
<script src="../node_modules/hammerjs/hammer.min.js"></script>
|
||||
<script src="../chartjs-plugin-zoom.js"></script>
|
||||
|
||||
<style>
|
||||
canvas {
|
||||
-moz-user-select: none;
|
||||
-webkit-user-select: none;
|
||||
-ms-user-select: none;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="container" style="width: 75%;">
|
||||
<canvas id="canvas"></canvas>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
var MONTHS = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
|
||||
|
||||
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-16", "February-16", "March-16", "April-16", "May-16", "June-16", "July-16", "August-16", "September-16", "October-16", "November-16", "December-16", "January-17", "February-17", "March-17", "April-17", "May-17", "June-17", "July-17", "August-17", "September-17", "October-17", "November-17", "December-17"],
|
||||
datasets: [{
|
||||
label: 'Dataset 1',
|
||||
backgroundColor: "rgba(220,220,220,0.5)",
|
||||
data: [randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()]
|
||||
}, {
|
||||
hidden: false,
|
||||
label: 'Dataset 2',
|
||||
backgroundColor: "rgba(255,187,205,1)",
|
||||
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, {
|
||||
type: 'bar',
|
||||
data: barChartData,
|
||||
options: {
|
||||
// Elements options apply to all of the options unless overridden in a dataset
|
||||
// In this case, we are setting the border of each bar to be 2px wide and green
|
||||
elements: {
|
||||
rectangle: {
|
||||
borderWidth: 2,
|
||||
borderColor: 'rgb(0, 255, 0)',
|
||||
borderSkipped: 'bottom'
|
||||
}
|
||||
},
|
||||
responsive: true,
|
||||
legend: {
|
||||
position: 'top',
|
||||
},
|
||||
title: {
|
||||
display: true,
|
||||
text: 'Chart.js Bar Chart'
|
||||
},
|
||||
pan: {
|
||||
enabled: true,
|
||||
mode: 'xy' // is panning about the y axis neccessary for bar charts?
|
||||
},
|
||||
zoom: {
|
||||
enabled: true,
|
||||
mode: 'x',
|
||||
sensitivity: 3,
|
||||
limits: {
|
||||
max: 10,
|
||||
min: 0.5
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
107
chart/zoom/samples/zoom-bar.html
Executable file
107
chart/zoom/samples/zoom-bar.html
Executable file
@ -0,0 +1,107 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>Bar Chart Zoom</title>
|
||||
<script src="../node_modules/chart.js/dist/Chart.bundle.js"></script>
|
||||
<script src="../node_modules/hammerjs/hammer.min.js"></script>
|
||||
<script src="../chartjs-plugin-zoom.js"></script>
|
||||
|
||||
<style>
|
||||
canvas {
|
||||
-moz-user-select: none;
|
||||
-webkit-user-select: none;
|
||||
-ms-user-select: none;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="container" style="width: 75%;">
|
||||
<canvas id="canvas"></canvas>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
var MONTHS = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
|
||||
|
||||
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", "August", "September", "October", "November", "December"],
|
||||
datasets: [{
|
||||
label: 'Dataset 1',
|
||||
backgroundColor: "rgba(220,220,220,0.5)",
|
||||
data: [randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()]
|
||||
}, {
|
||||
hidden: false,
|
||||
label: 'Dataset 2',
|
||||
backgroundColor: "rgba(255,187,205,1)",
|
||||
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, {
|
||||
type: 'bar',
|
||||
data: barChartData,
|
||||
options: {
|
||||
// Elements options apply to all of the options unless overridden in a dataset
|
||||
// In this case, we are setting the border of each bar to be 2px wide and green
|
||||
elements: {
|
||||
rectangle: {
|
||||
borderWidth: 2,
|
||||
borderColor: 'rgb(0, 255, 0)',
|
||||
borderSkipped: 'bottom'
|
||||
}
|
||||
},
|
||||
responsive: true,
|
||||
legend: {
|
||||
position: 'top',
|
||||
},
|
||||
title: {
|
||||
display: true,
|
||||
text: 'Chart.js Bar Chart'
|
||||
},
|
||||
pan: {
|
||||
enabled: true,
|
||||
mode: 'y'
|
||||
},
|
||||
zoom: {
|
||||
enabled: true,
|
||||
mode: 'y',
|
||||
limits: {
|
||||
max: 10,
|
||||
min: 0.5
|
||||
}
|
||||
},
|
||||
scales: {
|
||||
xAxes: [{
|
||||
ticks: {
|
||||
min: 'February',
|
||||
max: 'June'
|
||||
}
|
||||
}]
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
101
chart/zoom/samples/zoom-horizontal-bar.html
Executable file
101
chart/zoom/samples/zoom-horizontal-bar.html
Executable file
@ -0,0 +1,101 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>Horizontal Bar Chart Zoom</title>
|
||||
<script src="../node_modules/chart.js/dist/Chart.bundle.js"></script>
|
||||
<script src="../node_modules/hammerjs/hammer.min.js"></script>
|
||||
<script src="../chartjs-plugin-zoom.js"></script>
|
||||
|
||||
<style>
|
||||
canvas {
|
||||
-moz-user-select: none;
|
||||
-webkit-user-select: none;
|
||||
-ms-user-select: none;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="container" style="width: 75%;">
|
||||
<canvas id="canvas"></canvas>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
var MONTHS = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
|
||||
|
||||
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-16", "February-16", "March-16", "April-16", "May-16", "June-16", "July-16", "August-16", "September-16", "October-16", "November-16", "December-16", "January-17", "February-17", "March-17", "April-17", "May-17", "June-17", "July-17", "August-17", "September-17", "October-17", "November-17", "December-17"],
|
||||
datasets: [{
|
||||
label: 'Dataset 1',
|
||||
backgroundColor: "rgba(220,220,220,0.5)",
|
||||
data: [randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()]
|
||||
}, {
|
||||
hidden: false,
|
||||
label: 'Dataset 2',
|
||||
backgroundColor: "rgba(255,187,205,1)",
|
||||
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, {
|
||||
type: 'horizontalBar',
|
||||
data: barChartData,
|
||||
options: {
|
||||
// Elements options apply to all of the options unless overridden in a dataset
|
||||
// In this case, we are setting the border of each bar to be 2px wide and green
|
||||
elements: {
|
||||
rectangle: {
|
||||
borderWidth: 2,
|
||||
borderColor: 'rgb(0, 255, 0)',
|
||||
borderSkipped: 'bottom'
|
||||
}
|
||||
},
|
||||
responsive: true,
|
||||
legend: {
|
||||
position: 'top',
|
||||
},
|
||||
title: {
|
||||
display: true,
|
||||
text: 'Chart.js Bar Chart'
|
||||
},
|
||||
pan: {
|
||||
enabled: true,
|
||||
mode: 'y'
|
||||
},
|
||||
zoom: {
|
||||
enabled: true,
|
||||
mode: 'xy'
|
||||
},
|
||||
scales: {
|
||||
yAxes: [{
|
||||
ticks: {
|
||||
min: 'April-16',
|
||||
max: 'August-16'
|
||||
}
|
||||
}]
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
207
chart/zoom/samples/zoom-log.html
Executable file
207
chart/zoom/samples/zoom-log.html
Executable file
@ -0,0 +1,207 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>Scatter Chart</title>
|
||||
<script src="../node_modules/chart.js/dist/Chart.bundle.js"></script>
|
||||
<script src="../node_modules/hammerjs/hammer.min.js"></script>
|
||||
<script src="../chartjs-plugin-zoom.js"></script>
|
||||
<style>
|
||||
canvas {
|
||||
-moz-user-select: none;
|
||||
-webkit-user-select: none;
|
||||
-ms-user-select: none;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div style="width:75%">
|
||||
<div>
|
||||
<canvas id="canvas"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
var randomScalingFactor = function() {
|
||||
return Math.round(Math.random() * 10.0) * Math.pow(10, Math.ceil(Math.random() * 5));
|
||||
};
|
||||
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: "V(node2)",
|
||||
data: [{
|
||||
x: 1,
|
||||
y: -1.711e-2,
|
||||
}, {
|
||||
x: 1.26,
|
||||
y: -2.708e-2,
|
||||
}, {
|
||||
x: 1.58,
|
||||
y: -4.285e-2,
|
||||
}, {
|
||||
x: 2.0,
|
||||
y: -6.772e-2,
|
||||
}, {
|
||||
x: 2.51,
|
||||
y: -1.068e-1,
|
||||
}, {
|
||||
x: 3.16,
|
||||
y: -1.681e-1,
|
||||
}, {
|
||||
x: 3.98,
|
||||
y: -2.635e-1,
|
||||
}, {
|
||||
x: 5.01,
|
||||
y: -4.106e-1,
|
||||
}, {
|
||||
x: 6.31,
|
||||
y: -6.339e-1,
|
||||
}, {
|
||||
x: 7.94,
|
||||
y: -9.659e-1,
|
||||
}, {
|
||||
x: 10.00,
|
||||
y: -1.445,
|
||||
}, {
|
||||
x: 12.6,
|
||||
y: -2.110,
|
||||
}, {
|
||||
x: 15.8,
|
||||
y: -2.992,
|
||||
}, {
|
||||
x: 20.0,
|
||||
y: -4.102,
|
||||
}, {
|
||||
x: 25.1,
|
||||
y: -5.429,
|
||||
}, {
|
||||
x: 31.6,
|
||||
y: -6.944,
|
||||
}, {
|
||||
x: 39.8,
|
||||
y: -8.607,
|
||||
}, {
|
||||
x: 50.1,
|
||||
y: -1.038e1,
|
||||
}, {
|
||||
x: 63.1,
|
||||
y: -1.223e1,
|
||||
}, {
|
||||
x: 79.4,
|
||||
y: -1.413e1,
|
||||
}, {
|
||||
x: 100.00,
|
||||
y: -1.607e1,
|
||||
}, {
|
||||
x: 126,
|
||||
y: -1.803e1,
|
||||
}, {
|
||||
x: 158,
|
||||
y: -2e1,
|
||||
}, {
|
||||
x: 200,
|
||||
y: -2.199e1,
|
||||
}, {
|
||||
x: 251,
|
||||
y: -2.398e1,
|
||||
}, {
|
||||
x: 316,
|
||||
y: -2.597e1,
|
||||
}, {
|
||||
x: 398,
|
||||
y: -2.797e1,
|
||||
}, {
|
||||
x: 501,
|
||||
y: -2.996e1,
|
||||
}, {
|
||||
x: 631,
|
||||
y: -3.196e1,
|
||||
}, {
|
||||
x: 794,
|
||||
y: -3.396e1,
|
||||
}, {
|
||||
x: 1000,
|
||||
y: -3.596e1,
|
||||
},]
|
||||
}]
|
||||
};
|
||||
|
||||
scatterChartData.datasets.forEach(function(dataset) {
|
||||
dataset.borderColor = randomColor(0.4);
|
||||
dataset.backgroundColor = randomColor(0.1);
|
||||
dataset.pointBorderColor = randomColor(0.7);
|
||||
dataset.pointBackgroundColor = randomColor(0.5);
|
||||
dataset.pointBorderWidth = 1;
|
||||
});
|
||||
|
||||
window.onload = function() {
|
||||
var ctx = document.getElementById("canvas").getContext("2d");
|
||||
window.myScatter = Chart.Scatter(ctx, {
|
||||
data: scatterChartData,
|
||||
options: {
|
||||
title: {
|
||||
display: true,
|
||||
text: 'Chart.js Scatter Chart - Logarithmic X-Axis'
|
||||
},
|
||||
scales: {
|
||||
xAxes: [{
|
||||
type: 'logarithmic',
|
||||
position: 'bottom',
|
||||
ticks: {
|
||||
userCallback: function(tick) {
|
||||
var remain = tick / (Math.pow(10, Math.floor(Chart.helpers.log10(tick))));
|
||||
if (remain === 1 || remain === 2 || remain === 5) {
|
||||
return tick.toString() + "Hz";
|
||||
}
|
||||
return '';
|
||||
},
|
||||
maxRotation: 0
|
||||
},
|
||||
scaleLabel: {
|
||||
labelString: 'Frequency',
|
||||
display: true,
|
||||
},
|
||||
}],
|
||||
yAxes: [{
|
||||
type: 'linear',
|
||||
ticks: {
|
||||
userCallback: function(tick) {
|
||||
return tick.toFixed(0) + "dB";
|
||||
}
|
||||
},
|
||||
scaleLabel: {
|
||||
labelString: 'Voltage',
|
||||
display: true
|
||||
}
|
||||
}]
|
||||
},
|
||||
pan: {
|
||||
enabled: true,
|
||||
mode: 'xy',
|
||||
limits: {
|
||||
xmin: 1e-4,
|
||||
ymin: -50,
|
||||
ymax: 10
|
||||
},
|
||||
xScale0: {
|
||||
max: 1e4
|
||||
}
|
||||
},
|
||||
zoom: {
|
||||
enabled: true,
|
||||
mode: 'xy',
|
||||
limits: {
|
||||
max: 10,
|
||||
min: 0.5
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
142
chart/zoom/samples/zoom-time.html
Executable file
142
chart/zoom/samples/zoom-time.html
Executable file
@ -0,0 +1,142 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>Line Chart</title>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.13.0/moment.min.js"></script>
|
||||
<script src="../node_modules/chart.js/dist/Chart.js"></script>
|
||||
<script src="../node_modules/hammerjs/hammer.min.js"></script>
|
||||
<script src="../chartjs-plugin-zoom.js"></script>
|
||||
<style>
|
||||
canvas {
|
||||
-moz-user-select: none;
|
||||
-webkit-user-select: none;
|
||||
-ms-user-select: none;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div style="width:75%;">
|
||||
<button onclick="resetZoom()">Reset Zoom</button>
|
||||
<canvas id="canvas"></canvas>
|
||||
</div>
|
||||
<script>
|
||||
var timeFormat = 'MM/DD/YYYY HH:mm';
|
||||
|
||||
function randomScalingFactor() {
|
||||
return Math.round(Math.random() * 100 * (Math.random() > 0.5 ? -1 : 1));
|
||||
}
|
||||
|
||||
function randomColorFactor() {
|
||||
return Math.round(Math.random() * 255);
|
||||
}
|
||||
|
||||
function randomColor(opacity) {
|
||||
return 'rgba(' + randomColorFactor() + ',' + randomColorFactor() + ',' + randomColorFactor() + ',' + (opacity || '.3') + ')';
|
||||
}
|
||||
|
||||
function newDate(days) {
|
||||
return moment().add(days, 'd').toDate();
|
||||
}
|
||||
|
||||
function newDateString(days) {
|
||||
return moment().add(days, 'd').format(timeFormat);
|
||||
}
|
||||
|
||||
function newTimestamp(days) {
|
||||
return moment().add(days, 'd').unix();
|
||||
}
|
||||
|
||||
function resetZoom() {
|
||||
window.myLine.resetZoom()
|
||||
}
|
||||
|
||||
var config = {
|
||||
type: 'line',
|
||||
data: {
|
||||
labels: [newDate(0), newDate(1), newDate(2), newDate(3), newDate(4), newDate(5), newDate(6)], // Date Objects
|
||||
datasets: [{
|
||||
label: "My First dataset",
|
||||
data: [randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()],
|
||||
fill: false,
|
||||
borderDash: [5, 5],
|
||||
}, {
|
||||
label: "My Second dataset",
|
||||
data: [randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()],
|
||||
}, {
|
||||
label: "Dataset with point data",
|
||||
data: [{
|
||||
x: newDateString(0),
|
||||
y: randomScalingFactor()
|
||||
}, {
|
||||
x: newDateString(5),
|
||||
y: randomScalingFactor()
|
||||
}, {
|
||||
x: newDateString(7),
|
||||
y: randomScalingFactor()
|
||||
}, {
|
||||
x: newDateString(15),
|
||||
y: randomScalingFactor()
|
||||
}],
|
||||
fill: false
|
||||
}]
|
||||
},
|
||||
options: {
|
||||
responsive: true,
|
||||
title:{
|
||||
display:true,
|
||||
text:"Chart.js Time Scale"
|
||||
},
|
||||
scales: {
|
||||
xAxes: [{
|
||||
type: "time",
|
||||
time: {
|
||||
format: timeFormat,
|
||||
// round: 'day'
|
||||
tooltipFormat: 'll HH:mm'
|
||||
},
|
||||
scaleLabel: {
|
||||
display: true,
|
||||
labelString: 'Date'
|
||||
},
|
||||
ticks: {
|
||||
maxRotation: 0
|
||||
}
|
||||
}, ],
|
||||
yAxes: [{
|
||||
scaleLabel: {
|
||||
display: true,
|
||||
labelString: 'value'
|
||||
}
|
||||
}]
|
||||
},
|
||||
zoom: {
|
||||
enabled: true,
|
||||
drag: true,
|
||||
mode: 'x',
|
||||
limits: {
|
||||
max: 10,
|
||||
min: 0.5
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
config.data.datasets.forEach(function(dataset) {
|
||||
dataset.borderColor = randomColor(0.4);
|
||||
dataset.backgroundColor = randomColor(0.5);
|
||||
dataset.pointBorderColor = randomColor(0.7);
|
||||
dataset.pointBackgroundColor = randomColor(0.5);
|
||||
dataset.pointBorderWidth = 1;
|
||||
});
|
||||
|
||||
window.onload = function() {
|
||||
var ctx = document.getElementById("canvas").getContext("2d");
|
||||
window.myLine = new Chart(ctx, config);
|
||||
|
||||
};
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
78
chart/zoom/samples/zoom.html
Executable file
78
chart/zoom/samples/zoom.html
Executable file
@ -0,0 +1,78 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>Scatter Chart</title>
|
||||
<script src="../../Chart.bundle.js"></script>
|
||||
<script src="../../js1.js"></script>
|
||||
<script src="../../js1.svg"></script>
|
||||
<script src="../../js2.js"></script>
|
||||
<script src="../../js3.js"></script>
|
||||
<script src="../../Chart.Zoom.js"></script>
|
||||
<script src='../../samples/utils.js'></script>
|
||||
|
||||
<script src="../node_modules/hammerjs/hammer.min.js"></script>
|
||||
<style>
|
||||
canvas {
|
||||
-moz-user-select: none;
|
||||
-webkit-user-select: none;
|
||||
-ms-user-select: none;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div style="width:75%">
|
||||
<div>
|
||||
<canvas id="myChart"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<script>var ctx = document.getElementById("myChart");
|
||||
var myChart = new Chart(ctx, {
|
||||
type: 'line',
|
||||
data: {
|
||||
labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange","R1ed", "Blu1e", "Yello1w", "Gr1een", "Pu1rple", "Oran1ge"],
|
||||
datasets: [{
|
||||
label: '# of Votes',
|
||||
data: [12, 19, 3, 5, 2, 3,12, 19, 3, 5, 2, 3]
|
||||
}]
|
||||
},
|
||||
options: {
|
||||
scales: {
|
||||
yAxes: [{
|
||||
ticks: {
|
||||
beginAtZero:true
|
||||
}
|
||||
}]
|
||||
},
|
||||
// Container for pan options
|
||||
pan: {
|
||||
// Boolean to enable panning
|
||||
enabled: true,
|
||||
|
||||
// Panning directions. Remove the appropriate direction to disable
|
||||
// Eg. 'y' would only allow panning in the y direction
|
||||
mode: 'x'
|
||||
},
|
||||
|
||||
// Container for zoom options
|
||||
zoom: {
|
||||
// Boolean to enable zooming
|
||||
enabled: true,
|
||||
|
||||
// Zooming directions. Remove the appropriate direction to disable
|
||||
// Eg. 'y' would only allow zooming in the y direction
|
||||
mode: 'x',
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
<button onclick="window.myScatter.destroy()">Destroy</button>
|
||||
<button onclick="window.myScatter.destroy(); window.onload()">Reload</button>
|
||||
</body>
|
||||
|
||||
</html>
|
488
chart/zoom/src/chart.zoom.js
Executable file
488
chart/zoom/src/chart.zoom.js
Executable file
@ -0,0 +1,488 @@
|
||||
/*jslint browser:true, devel:true, white:true, vars:true */
|
||||
/*global require*/
|
||||
|
||||
// hammer JS for touch support
|
||||
var Hammer = require('hammerjs');
|
||||
Hammer = typeof(Hammer) === 'function' ? Hammer : window.Hammer;
|
||||
|
||||
// Get the chart variable
|
||||
var Chart = require('chart.js');
|
||||
Chart = typeof(Chart) === 'function' ? Chart : window.Chart;
|
||||
var helpers = Chart.helpers;
|
||||
|
||||
// Take the zoom namespace of Chart
|
||||
var zoomNS = Chart.Zoom = Chart.Zoom || {};
|
||||
|
||||
// Where we store functions to handle different scale types
|
||||
var zoomFunctions = zoomNS.zoomFunctions = zoomNS.zoomFunctions || {};
|
||||
var panFunctions = zoomNS.panFunctions = zoomNS.panFunctions || {};
|
||||
|
||||
// Default options if none are provided
|
||||
var defaultOptions = zoomNS.defaults = {
|
||||
pan: {
|
||||
enabled: true,
|
||||
mode: 'xy',
|
||||
speed: 20,
|
||||
threshold: 10,
|
||||
},
|
||||
zoom: {
|
||||
enabled: true,
|
||||
mode: 'xy',
|
||||
sensitivity: 3,
|
||||
}
|
||||
};
|
||||
|
||||
function directionEnabled(mode, dir) {
|
||||
if (mode === undefined) {
|
||||
return true;
|
||||
} else if (typeof mode === 'string') {
|
||||
return mode.indexOf(dir) !== -1;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function zoomIndexScale(scale, zoom, center, zoomOptions) {
|
||||
var labels = scale.chart.data.labels;
|
||||
var minIndex = scale.minIndex;
|
||||
var lastLabelIndex = labels.length - 1;
|
||||
var maxIndex = scale.maxIndex;
|
||||
var sensitivity = zoomOptions.sensitivity;
|
||||
var chartCenter = scale.isHorizontal() ? scale.left + (scale.width/2) : scale.top + (scale.height/2);
|
||||
var centerPointer = scale.isHorizontal() ? center.x : center.y;
|
||||
|
||||
zoomNS.zoomCumulativeDelta = zoom > 1 ? zoomNS.zoomCumulativeDelta + 1 : zoomNS.zoomCumulativeDelta - 1;
|
||||
|
||||
if (Math.abs(zoomNS.zoomCumulativeDelta) > sensitivity){
|
||||
if(zoomNS.zoomCumulativeDelta < 0){
|
||||
if(centerPointer <= chartCenter){
|
||||
if (minIndex <= 0){
|
||||
maxIndex = Math.min(lastLabelIndex, maxIndex + 1);
|
||||
} else{
|
||||
minIndex = Math.max(0, minIndex - 1);
|
||||
}
|
||||
} else if(centerPointer > chartCenter){
|
||||
if (maxIndex >= lastLabelIndex){
|
||||
minIndex = Math.max(0, minIndex - 1);
|
||||
} else{
|
||||
maxIndex = Math.min(lastLabelIndex, maxIndex + 1);
|
||||
}
|
||||
}
|
||||
zoomNS.zoomCumulativeDelta = 0;
|
||||
}
|
||||
else if(zoomNS.zoomCumulativeDelta > 0){
|
||||
if(centerPointer <= chartCenter){
|
||||
minIndex = minIndex < maxIndex ? minIndex = Math.min(maxIndex, minIndex + 1) : minIndex;
|
||||
} else if(centerPointer > chartCenter){
|
||||
maxIndex = maxIndex > minIndex ? maxIndex = Math.max(minIndex, maxIndex - 1) : maxIndex;
|
||||
}
|
||||
zoomNS.zoomCumulativeDelta = 0;
|
||||
}
|
||||
scale.options.ticks.min = labels[minIndex];
|
||||
scale.options.ticks.max = labels[maxIndex];
|
||||
}
|
||||
}
|
||||
|
||||
function zoomTimeScale(scale, zoom, center) {
|
||||
var options = scale.options;
|
||||
|
||||
var range;
|
||||
var min_percent;
|
||||
if (scale.isHorizontal()) {
|
||||
range = scale.right - scale.left;
|
||||
min_percent = (center.x - scale.left) / range;
|
||||
} else {
|
||||
range = scale.bottom - scale.top;
|
||||
min_percent = (center.y - scale.top) / range;
|
||||
}
|
||||
|
||||
var max_percent = 1 - min_percent;
|
||||
var newDiff = range * (zoom - 1);
|
||||
|
||||
var minDelta = newDiff * min_percent;
|
||||
var maxDelta = newDiff * max_percent;
|
||||
|
||||
options.time.min = scale.getValueForPixel(scale.getPixelForValue(scale.firstTick) + minDelta);
|
||||
options.time.max = scale.getValueForPixel(scale.getPixelForValue(scale.lastTick) - maxDelta);
|
||||
}
|
||||
|
||||
function zoomNumericalScale(scale, zoom, center) {
|
||||
var range = scale.max - scale.min;
|
||||
var newDiff = range * (zoom - 1);
|
||||
|
||||
var cursorPixel = scale.isHorizontal() ? center.x : center.y;
|
||||
var min_percent = (scale.getValueForPixel(cursorPixel) - scale.min) / range;
|
||||
var max_percent = 1 - min_percent;
|
||||
|
||||
var minDelta = newDiff * min_percent;
|
||||
var maxDelta = newDiff * max_percent;
|
||||
|
||||
scale.options.ticks.min = scale.min + minDelta;
|
||||
scale.options.ticks.max = scale.max - maxDelta;
|
||||
}
|
||||
|
||||
function zoomScale(scale, zoom, center, zoomOptions) {
|
||||
var fn = zoomFunctions[scale.options.type];
|
||||
if (fn) {
|
||||
fn(scale, zoom, center, zoomOptions);
|
||||
}
|
||||
}
|
||||
|
||||
function doZoom(chartInstance, zoom, center) {
|
||||
var ca = chartInstance.chartArea;
|
||||
if (!center) {
|
||||
center = {
|
||||
x: (ca.left + ca.right) / 2,
|
||||
y: (ca.top + ca.bottom) / 2,
|
||||
};
|
||||
}
|
||||
|
||||
var zoomOptions = chartInstance.options.zoom;
|
||||
|
||||
if (zoomOptions && helpers.getValueOrDefault(zoomOptions.enabled, defaultOptions.zoom.enabled)) {
|
||||
// Do the zoom here
|
||||
var zoomMode = helpers.getValueOrDefault(chartInstance.options.zoom.mode, defaultOptions.zoom.mode);
|
||||
zoomOptions.sensitivity = helpers.getValueOrDefault(chartInstance.options.zoom.sensitivity, defaultOptions.zoom.sensitivity);
|
||||
|
||||
helpers.each(chartInstance.scales, function(scale, id) {
|
||||
if (scale.isHorizontal() && directionEnabled(zoomMode, 'x')) {
|
||||
zoomScale(scale, zoom, center, zoomOptions);
|
||||
} else if (!scale.isHorizontal() && directionEnabled(zoomMode, 'y')) {
|
||||
// Do Y zoom
|
||||
zoomScale(scale, zoom, center, zoomOptions);
|
||||
}
|
||||
});
|
||||
|
||||
chartInstance.update(0);
|
||||
}
|
||||
}
|
||||
|
||||
function panIndexScale(scale, delta, panOptions) {
|
||||
var labels = scale.chart.data.labels;
|
||||
var lastLabelIndex = labels.length - 1;
|
||||
var offsetAmt = Math.max((scale.ticks.length - ((scale.options.gridLines.offsetGridLines) ? 0 : 1)), 1);
|
||||
var panSpeed = panOptions.speed;
|
||||
var minIndex = scale.minIndex;
|
||||
var step = Math.round(scale.width / (offsetAmt * panSpeed));
|
||||
var maxIndex;
|
||||
|
||||
zoomNS.panCumulativeDelta += delta;
|
||||
|
||||
minIndex = zoomNS.panCumulativeDelta > step ? Math.max(0, minIndex -1) : zoomNS.panCumulativeDelta < -step ? Math.min(lastLabelIndex - offsetAmt + 1, minIndex + 1) : minIndex;
|
||||
zoomNS.panCumulativeDelta = minIndex !== scale.minIndex ? 0 : zoomNS.panCumulativeDelta;
|
||||
|
||||
maxIndex = Math.min(lastLabelIndex, minIndex + offsetAmt - 1);
|
||||
|
||||
scale.options.ticks.min = labels[minIndex];
|
||||
scale.options.ticks.max = labels[maxIndex];
|
||||
}
|
||||
|
||||
function panTimeScale(scale, delta) {
|
||||
var options = scale.options;
|
||||
options.time.min = scale.getValueForPixel(scale.getPixelForValue(scale.firstTick) - delta);
|
||||
options.time.max = scale.getValueForPixel(scale.getPixelForValue(scale.lastTick) - delta);
|
||||
}
|
||||
|
||||
function panNumericalScale(scale, delta) {
|
||||
var tickOpts = scale.options.ticks;
|
||||
var start = scale.start,
|
||||
end = scale.end;
|
||||
|
||||
if (tickOpts.reverse) {
|
||||
tickOpts.max = scale.getValueForPixel(scale.getPixelForValue(start) - delta);
|
||||
tickOpts.min = scale.getValueForPixel(scale.getPixelForValue(end) - delta);
|
||||
} else {
|
||||
tickOpts.min = scale.getValueForPixel(scale.getPixelForValue(start) - delta);
|
||||
tickOpts.max = scale.getValueForPixel(scale.getPixelForValue(end) - delta);
|
||||
}
|
||||
}
|
||||
|
||||
function panScale(scale, delta, panOptions) {
|
||||
var fn = panFunctions[scale.options.type];
|
||||
if (fn) {
|
||||
fn(scale, delta, panOptions);
|
||||
}
|
||||
}
|
||||
|
||||
function doPan(chartInstance, deltaX, deltaY) {
|
||||
var panOptions = chartInstance.options.pan;
|
||||
if (panOptions && helpers.getValueOrDefault(panOptions.enabled, defaultOptions.pan.enabled)) {
|
||||
var panMode = helpers.getValueOrDefault(chartInstance.options.pan.mode, defaultOptions.pan.mode);
|
||||
panOptions.speed = helpers.getValueOrDefault(chartInstance.options.pan.speed, defaultOptions.pan.speed);
|
||||
|
||||
helpers.each(chartInstance.scales, function(scale, id) {
|
||||
if (scale.isHorizontal() && directionEnabled(panMode, 'x') && deltaX !== 0) {
|
||||
panScale(scale, deltaX, panOptions);
|
||||
} else if (!scale.isHorizontal() && directionEnabled(panMode, 'y') && deltaY !== 0) {
|
||||
panScale(scale, deltaY, panOptions);
|
||||
}
|
||||
});
|
||||
|
||||
chartInstance.update(0);
|
||||
}
|
||||
}
|
||||
|
||||
function positionInChartArea(chartInstance, position) {
|
||||
return (position.x >= chartInstance.chartArea.left && position.x <= chartInstance.chartArea.right) &&
|
||||
(position.y >= chartInstance.chartArea.top && position.y <= chartInstance.chartArea.bottom);
|
||||
}
|
||||
|
||||
function getYAxis(chartInstance) {
|
||||
var scales = chartInstance.scales;
|
||||
|
||||
for (var scaleId in scales) {
|
||||
var scale = scales[scaleId];
|
||||
|
||||
if (!scale.isHorizontal()) {
|
||||
return scale;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Store these for later
|
||||
zoomNS.zoomFunctions.category = zoomIndexScale;
|
||||
zoomNS.zoomFunctions.time = zoomTimeScale;
|
||||
zoomNS.zoomFunctions.linear = zoomNumericalScale;
|
||||
zoomNS.zoomFunctions.logarithmic = zoomNumericalScale;
|
||||
zoomNS.panFunctions.category = panIndexScale;
|
||||
zoomNS.panFunctions.time = panTimeScale;
|
||||
zoomNS.panFunctions.linear = panNumericalScale;
|
||||
zoomNS.panFunctions.logarithmic = panNumericalScale;
|
||||
// Globals for catergory pan and zoom
|
||||
zoomNS.panCumulativeDelta = 0;
|
||||
zoomNS.zoomCumulativeDelta = 0;
|
||||
|
||||
// Chartjs Zoom Plugin
|
||||
var zoomPlugin = {
|
||||
afterInit: function(chartInstance) {
|
||||
helpers.each(chartInstance.scales, function(scale) {
|
||||
scale.originalOptions = JSON.parse(JSON.stringify(scale.options));
|
||||
});
|
||||
|
||||
chartInstance.resetZoom = function() {
|
||||
helpers.each(chartInstance.scales, function(scale, id) {
|
||||
var timeOptions = scale.options.time;
|
||||
var tickOptions = scale.options.ticks;
|
||||
|
||||
if (timeOptions) {
|
||||
delete timeOptions.min;
|
||||
delete timeOptions.max;
|
||||
}
|
||||
|
||||
if (tickOptions) {
|
||||
delete tickOptions.min;
|
||||
delete tickOptions.max;
|
||||
}
|
||||
|
||||
scale.options = helpers.configMerge(scale.options, scale.originalOptions);
|
||||
});
|
||||
|
||||
helpers.each(chartInstance.data.datasets, function(dataset, id) {
|
||||
dataset._meta = null;
|
||||
});
|
||||
|
||||
chartInstance.update();
|
||||
};
|
||||
|
||||
},
|
||||
beforeInit: function(chartInstance) {
|
||||
chartInstance.zoom = {};
|
||||
|
||||
var node = chartInstance.zoom.node = chartInstance.chart.ctx.canvas;
|
||||
|
||||
var options = chartInstance.options;
|
||||
var panThreshold = helpers.getValueOrDefault(options.pan ? options.pan.threshold : undefined, zoomNS.defaults.pan.threshold);
|
||||
|
||||
if (options.zoom && options.zoom.drag) {
|
||||
// Only want to zoom horizontal axis
|
||||
options.zoom.mode = 'x';
|
||||
|
||||
chartInstance.zoom._mouseDownHandler = function(event) {
|
||||
chartInstance.zoom._dragZoomStart = event;
|
||||
};
|
||||
node.addEventListener('mousedown', chartInstance.zoom._mouseDownHandler);
|
||||
|
||||
chartInstance.zoom._mouseMoveHandler = function(event){
|
||||
if (chartInstance.zoom._dragZoomStart) {
|
||||
chartInstance.zoom._dragZoomEnd = event;
|
||||
chartInstance.update(0);
|
||||
}
|
||||
|
||||
chartInstance.update(0);
|
||||
};
|
||||
node.addEventListener('mousemove', chartInstance.zoom._mouseMoveHandler);
|
||||
|
||||
chartInstance.zoom._mouseUpHandler = function(event){
|
||||
if (chartInstance.zoom._dragZoomStart) {
|
||||
var chartArea = chartInstance.chartArea;
|
||||
var yAxis = getYAxis(chartInstance);
|
||||
var beginPoint = chartInstance.zoom._dragZoomStart;
|
||||
var offsetX = beginPoint.target.getBoundingClientRect().left;
|
||||
var startX = Math.min(beginPoint.clientX, event.clientX) - offsetX;
|
||||
var endX = Math.max(beginPoint.clientX, event.clientX) - offsetX;
|
||||
var dragDistance = endX - startX;
|
||||
var chartDistance = chartArea.right - chartArea.left;
|
||||
var zoom = 1 + ((chartDistance - dragDistance) / chartDistance );
|
||||
|
||||
if (dragDistance > 0) {
|
||||
doZoom(chartInstance, zoom, {
|
||||
x: (dragDistance / 2) + startX,
|
||||
y: (yAxis.bottom - yAxis.top) / 2,
|
||||
});
|
||||
}
|
||||
|
||||
chartInstance.zoom._dragZoomStart = null;
|
||||
chartInstance.zoom._dragZoomEnd = null;
|
||||
}
|
||||
};
|
||||
node.addEventListener('mouseup', chartInstance.zoom._mouseUpHandler);
|
||||
} else {
|
||||
chartInstance.zoom._wheelHandler = function(event) {
|
||||
var rect = event.target.getBoundingClientRect();
|
||||
var offsetX = event.clientX - rect.left;
|
||||
var offsetY = event.clientY - rect.top;
|
||||
|
||||
var center = {
|
||||
x : offsetX,
|
||||
y : offsetY
|
||||
};
|
||||
|
||||
if (event.deltaY < 0) {
|
||||
doZoom(chartInstance, 1.1, center);
|
||||
} else {
|
||||
doZoom(chartInstance, 0.909, center);
|
||||
}
|
||||
// Prevent the event from triggering the default behavior (eg. Content scrolling).
|
||||
event.preventDefault();
|
||||
};
|
||||
|
||||
node.addEventListener('wheel', chartInstance.zoom._wheelHandler);
|
||||
}
|
||||
|
||||
if (Hammer) {
|
||||
var mc = new Hammer.Manager(node);
|
||||
mc.add(new Hammer.Pinch());
|
||||
mc.add(new Hammer.Pan({
|
||||
threshold: panThreshold
|
||||
}));
|
||||
|
||||
// Hammer reports the total scaling. We need the incremental amount
|
||||
var currentPinchScaling;
|
||||
var handlePinch = function handlePinch(e) {
|
||||
var diff = 1 / (currentPinchScaling) * e.scale;
|
||||
doZoom(chartInstance, diff, e.center);
|
||||
|
||||
// Keep track of overall scale
|
||||
currentPinchScaling = e.scale;
|
||||
};
|
||||
|
||||
mc.on('pinchstart', function(e) {
|
||||
currentPinchScaling = 1; // reset tracker
|
||||
});
|
||||
mc.on('pinch', handlePinch);
|
||||
mc.on('pinchend', function(e) {
|
||||
handlePinch(e);
|
||||
currentPinchScaling = null; // reset
|
||||
zoomNS.zoomCumulativeDelta = 0;
|
||||
});
|
||||
|
||||
var currentDeltaX = null, currentDeltaY = null, panning = false;
|
||||
var handlePan = function handlePan(e) {
|
||||
if (currentDeltaX !== null && currentDeltaY !== null) {
|
||||
panning = true;
|
||||
var deltaX = e.deltaX - currentDeltaX;
|
||||
var deltaY = e.deltaY - currentDeltaY;
|
||||
currentDeltaX = e.deltaX;
|
||||
currentDeltaY = e.deltaY;
|
||||
doPan(chartInstance, deltaX, deltaY);
|
||||
}
|
||||
};
|
||||
|
||||
mc.on('panstart', function(e) {
|
||||
currentDeltaX = 0;
|
||||
currentDeltaY = 0;
|
||||
handlePan(e);
|
||||
});
|
||||
mc.on('panmove', handlePan);
|
||||
mc.on('panend', function(e) {
|
||||
currentDeltaX = null;
|
||||
currentDeltaY = null;
|
||||
zoomNS.panCumulativeDelta = 0;
|
||||
setTimeout(function() { panning = false; }, 500);
|
||||
});
|
||||
|
||||
chartInstance.zoom._ghostClickHandler = function(e) {
|
||||
if (panning) {
|
||||
e.stopImmediatePropagation();
|
||||
e.preventDefault();
|
||||
}
|
||||
};
|
||||
node.addEventListener('click', chartInstance.zoom._ghostClickHandler);
|
||||
|
||||
chartInstance._mc = mc;
|
||||
}
|
||||
},
|
||||
|
||||
beforeDatasetsDraw: function(chartInstance) {
|
||||
var ctx = chartInstance.chart.ctx;
|
||||
var chartArea = chartInstance.chartArea;
|
||||
ctx.save();
|
||||
ctx.beginPath();
|
||||
|
||||
if (chartInstance.zoom._dragZoomEnd) {
|
||||
var yAxis = getYAxis(chartInstance);
|
||||
var beginPoint = chartInstance.zoom._dragZoomStart;
|
||||
var endPoint = chartInstance.zoom._dragZoomEnd;
|
||||
var offsetX = beginPoint.target.getBoundingClientRect().left;
|
||||
var startX = Math.min(beginPoint.clientX, endPoint.clientX) - offsetX;
|
||||
var endX = Math.max(beginPoint.clientX, endPoint.clientX) - offsetX;
|
||||
var rectWidth = endX - startX;
|
||||
|
||||
|
||||
ctx.fillStyle = 'rgba(225,225,225,0.3)';
|
||||
ctx.lineWidth = 5;
|
||||
ctx.fillRect(startX, yAxis.top, rectWidth, yAxis.bottom - yAxis.top);
|
||||
}
|
||||
|
||||
ctx.rect(chartArea.left, chartArea.top, chartArea.right - chartArea.left, chartArea.bottom - chartArea.top);
|
||||
ctx.clip();
|
||||
},
|
||||
|
||||
afterDatasetsDraw: function(chartInstance) {
|
||||
chartInstance.chart.ctx.restore();
|
||||
},
|
||||
|
||||
destroy: function(chartInstance) {
|
||||
if (chartInstance.zoom) {
|
||||
var options = chartInstance.options;
|
||||
var node = chartInstance.zoom.node;
|
||||
|
||||
if (options.zoom && options.zoom.drag) {
|
||||
node.removeEventListener('mousedown', chartInstance.zoom._mouseDownHandler);
|
||||
node.removeEventListener('mousemove', chartInstance.zoom._mouseMoveHandler);
|
||||
node.removeEventListener('mouseup', chartInstance.zoom._mouseUpHandler);
|
||||
} else {
|
||||
node.removeEventListener('wheel', chartInstance.zoom._wheelHandler);
|
||||
}
|
||||
|
||||
if (Hammer) {
|
||||
node.removeEventListener('click', chartInstance.zoom._ghostClickHandler);
|
||||
}
|
||||
|
||||
delete chartInstance.zoom;
|
||||
|
||||
var mc = chartInstance._mc;
|
||||
if (mc) {
|
||||
mc.remove('pinchstart');
|
||||
mc.remove('pinch');
|
||||
mc.remove('pinchend');
|
||||
mc.remove('panstart');
|
||||
mc.remove('pan');
|
||||
mc.remove('panend');
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = zoomPlugin;
|
||||
Chart.pluginService.register(zoomPlugin);
|
Reference in New Issue
Block a user