mirror of
https://github.com/chartjs/Chart.js
synced 2025-04-29 15:57:22 +08:00
Make Chart.Animation/animations/Tooltip
importable (#5382)
This commit is contained in:
parent
9fbac88938
commit
d284686452
@ -1,5 +1,6 @@
|
||||
{
|
||||
"indent-style": "tabs",
|
||||
"line-end-style": false,
|
||||
"attr-quote-style": "double",
|
||||
"spec-char-escape": false,
|
||||
"attr-bans": [
|
||||
|
@ -8,6 +8,8 @@ Chart.helpers = require('./helpers/index');
|
||||
// @todo dispatch these helpers into appropriated helpers/helpers.* file and write unit tests!
|
||||
require('./core/core.helpers')(Chart);
|
||||
|
||||
Chart.Animation = require('./core/core.animation');
|
||||
Chart.animationService = require('./core/core.animations');
|
||||
Chart.defaults = require('./core/core.defaults');
|
||||
Chart.Element = require('./core/core.element');
|
||||
Chart.elements = require('./elements/index');
|
||||
@ -16,13 +18,12 @@ Chart.layouts = require('./core/core.layouts');
|
||||
Chart.platform = require('./platforms/platform');
|
||||
Chart.plugins = require('./core/core.plugins');
|
||||
Chart.Ticks = require('./core/core.ticks');
|
||||
Chart.Tooltip = require('./core/core.tooltip');
|
||||
|
||||
require('./core/core.animation')(Chart);
|
||||
require('./core/core.controller')(Chart);
|
||||
require('./core/core.datasetController')(Chart);
|
||||
require('./core/core.scaleService')(Chart);
|
||||
require('./core/core.scale')(Chart);
|
||||
require('./core/core.tooltip')(Chart);
|
||||
|
||||
require('./scales/scale.linearbase')(Chart);
|
||||
require('./scales/scale.category')(Chart);
|
||||
|
@ -1,172 +1,43 @@
|
||||
/* global window: false */
|
||||
'use strict';
|
||||
|
||||
var defaults = require('./core.defaults');
|
||||
var Element = require('./core.element');
|
||||
var helpers = require('../helpers/index');
|
||||
|
||||
defaults._set('global', {
|
||||
animation: {
|
||||
duration: 1000,
|
||||
easing: 'easeOutQuart',
|
||||
onProgress: helpers.noop,
|
||||
onComplete: helpers.noop
|
||||
var exports = module.exports = Element.extend({
|
||||
chart: null, // the animation associated chart instance
|
||||
currentStep: 0, // the current animation step
|
||||
numSteps: 60, // default number of steps
|
||||
easing: '', // the easing to use for this animation
|
||||
render: null, // render function used by the animation service
|
||||
|
||||
onAnimationProgress: null, // user specified callback to fire on each step of the animation
|
||||
onAnimationComplete: null, // user specified callback to fire when the animation finishes
|
||||
});
|
||||
|
||||
// DEPRECATIONS
|
||||
|
||||
/**
|
||||
* Provided for backward compatibility, use Chart.Animation instead
|
||||
* @prop Chart.Animation#animationObject
|
||||
* @deprecated since version 2.6.0
|
||||
* @todo remove at version 3
|
||||
*/
|
||||
Object.defineProperty(exports.prototype, 'animationObject', {
|
||||
get: function() {
|
||||
return this;
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = function(Chart) {
|
||||
|
||||
Chart.Animation = Element.extend({
|
||||
chart: null, // the animation associated chart instance
|
||||
currentStep: 0, // the current animation step
|
||||
numSteps: 60, // default number of steps
|
||||
easing: '', // the easing to use for this animation
|
||||
render: null, // render function used by the animation service
|
||||
|
||||
onAnimationProgress: null, // user specified callback to fire on each step of the animation
|
||||
onAnimationComplete: null, // user specified callback to fire when the animation finishes
|
||||
});
|
||||
|
||||
Chart.animationService = {
|
||||
frameDuration: 17,
|
||||
animations: [],
|
||||
dropFrames: 0,
|
||||
request: null,
|
||||
|
||||
/**
|
||||
* @param {Chart} chart - The chart to animate.
|
||||
* @param {Chart.Animation} animation - The animation that we will animate.
|
||||
* @param {Number} duration - The animation duration in ms.
|
||||
* @param {Boolean} lazy - if true, the chart is not marked as animating to enable more responsive interactions
|
||||
*/
|
||||
addAnimation: function(chart, animation, duration, lazy) {
|
||||
var animations = this.animations;
|
||||
var i, ilen;
|
||||
|
||||
animation.chart = chart;
|
||||
|
||||
if (!lazy) {
|
||||
chart.animating = true;
|
||||
}
|
||||
|
||||
for (i = 0, ilen = animations.length; i < ilen; ++i) {
|
||||
if (animations[i].chart === chart) {
|
||||
animations[i] = animation;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
animations.push(animation);
|
||||
|
||||
// If there are no animations queued, manually kickstart a digest, for lack of a better word
|
||||
if (animations.length === 1) {
|
||||
this.requestAnimationFrame();
|
||||
}
|
||||
},
|
||||
|
||||
cancelAnimation: function(chart) {
|
||||
var index = helpers.findIndex(this.animations, function(animation) {
|
||||
return animation.chart === chart;
|
||||
});
|
||||
|
||||
if (index !== -1) {
|
||||
this.animations.splice(index, 1);
|
||||
chart.animating = false;
|
||||
}
|
||||
},
|
||||
|
||||
requestAnimationFrame: function() {
|
||||
var me = this;
|
||||
if (me.request === null) {
|
||||
// Skip animation frame requests until the active one is executed.
|
||||
// This can happen when processing mouse events, e.g. 'mousemove'
|
||||
// and 'mouseout' events will trigger multiple renders.
|
||||
me.request = helpers.requestAnimFrame.call(window, function() {
|
||||
me.request = null;
|
||||
me.startDigest();
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
startDigest: function() {
|
||||
var me = this;
|
||||
var startTime = Date.now();
|
||||
var framesToDrop = 0;
|
||||
|
||||
if (me.dropFrames > 1) {
|
||||
framesToDrop = Math.floor(me.dropFrames);
|
||||
me.dropFrames = me.dropFrames % 1;
|
||||
}
|
||||
|
||||
me.advance(1 + framesToDrop);
|
||||
|
||||
var endTime = Date.now();
|
||||
|
||||
me.dropFrames += (endTime - startTime) / me.frameDuration;
|
||||
|
||||
// Do we have more stuff to animate?
|
||||
if (me.animations.length > 0) {
|
||||
me.requestAnimationFrame();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
advance: function(count) {
|
||||
var animations = this.animations;
|
||||
var animation, chart;
|
||||
var i = 0;
|
||||
|
||||
while (i < animations.length) {
|
||||
animation = animations[i];
|
||||
chart = animation.chart;
|
||||
|
||||
animation.currentStep = (animation.currentStep || 0) + count;
|
||||
animation.currentStep = Math.min(animation.currentStep, animation.numSteps);
|
||||
|
||||
helpers.callback(animation.render, [chart, animation], chart);
|
||||
helpers.callback(animation.onAnimationProgress, [animation], chart);
|
||||
|
||||
if (animation.currentStep >= animation.numSteps) {
|
||||
helpers.callback(animation.onAnimationComplete, [animation], chart);
|
||||
chart.animating = false;
|
||||
animations.splice(i, 1);
|
||||
} else {
|
||||
++i;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Provided for backward compatibility, use Chart.Animation instead
|
||||
* @prop Chart.Animation#animationObject
|
||||
* @deprecated since version 2.6.0
|
||||
* @todo remove at version 3
|
||||
*/
|
||||
Object.defineProperty(Chart.Animation.prototype, 'animationObject', {
|
||||
get: function() {
|
||||
return this;
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Provided for backward compatibility, use Chart.Animation#chart instead
|
||||
* @prop Chart.Animation#chartInstance
|
||||
* @deprecated since version 2.6.0
|
||||
* @todo remove at version 3
|
||||
*/
|
||||
Object.defineProperty(Chart.Animation.prototype, 'chartInstance', {
|
||||
get: function() {
|
||||
return this.chart;
|
||||
},
|
||||
set: function(value) {
|
||||
this.chart = value;
|
||||
}
|
||||
});
|
||||
|
||||
};
|
||||
/**
|
||||
* Provided for backward compatibility, use Chart.Animation#chart instead
|
||||
* @prop Chart.Animation#chartInstance
|
||||
* @deprecated since version 2.6.0
|
||||
* @todo remove at version 3
|
||||
*/
|
||||
Object.defineProperty(exports.prototype, 'chartInstance', {
|
||||
get: function() {
|
||||
return this.chart;
|
||||
},
|
||||
set: function(value) {
|
||||
this.chart = value;
|
||||
}
|
||||
});
|
||||
|
129
src/core/core.animations.js
Normal file
129
src/core/core.animations.js
Normal file
@ -0,0 +1,129 @@
|
||||
/* global window: false */
|
||||
'use strict';
|
||||
|
||||
var defaults = require('./core.defaults');
|
||||
var helpers = require('../helpers/index');
|
||||
|
||||
defaults._set('global', {
|
||||
animation: {
|
||||
duration: 1000,
|
||||
easing: 'easeOutQuart',
|
||||
onProgress: helpers.noop,
|
||||
onComplete: helpers.noop
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = {
|
||||
frameDuration: 17,
|
||||
animations: [],
|
||||
dropFrames: 0,
|
||||
request: null,
|
||||
|
||||
/**
|
||||
* @param {Chart} chart - The chart to animate.
|
||||
* @param {Chart.Animation} animation - The animation that we will animate.
|
||||
* @param {Number} duration - The animation duration in ms.
|
||||
* @param {Boolean} lazy - if true, the chart is not marked as animating to enable more responsive interactions
|
||||
*/
|
||||
addAnimation: function(chart, animation, duration, lazy) {
|
||||
var animations = this.animations;
|
||||
var i, ilen;
|
||||
|
||||
animation.chart = chart;
|
||||
|
||||
if (!lazy) {
|
||||
chart.animating = true;
|
||||
}
|
||||
|
||||
for (i = 0, ilen = animations.length; i < ilen; ++i) {
|
||||
if (animations[i].chart === chart) {
|
||||
animations[i] = animation;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
animations.push(animation);
|
||||
|
||||
// If there are no animations queued, manually kickstart a digest, for lack of a better word
|
||||
if (animations.length === 1) {
|
||||
this.requestAnimationFrame();
|
||||
}
|
||||
},
|
||||
|
||||
cancelAnimation: function(chart) {
|
||||
var index = helpers.findIndex(this.animations, function(animation) {
|
||||
return animation.chart === chart;
|
||||
});
|
||||
|
||||
if (index !== -1) {
|
||||
this.animations.splice(index, 1);
|
||||
chart.animating = false;
|
||||
}
|
||||
},
|
||||
|
||||
requestAnimationFrame: function() {
|
||||
var me = this;
|
||||
if (me.request === null) {
|
||||
// Skip animation frame requests until the active one is executed.
|
||||
// This can happen when processing mouse events, e.g. 'mousemove'
|
||||
// and 'mouseout' events will trigger multiple renders.
|
||||
me.request = helpers.requestAnimFrame.call(window, function() {
|
||||
me.request = null;
|
||||
me.startDigest();
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
startDigest: function() {
|
||||
var me = this;
|
||||
var startTime = Date.now();
|
||||
var framesToDrop = 0;
|
||||
|
||||
if (me.dropFrames > 1) {
|
||||
framesToDrop = Math.floor(me.dropFrames);
|
||||
me.dropFrames = me.dropFrames % 1;
|
||||
}
|
||||
|
||||
me.advance(1 + framesToDrop);
|
||||
|
||||
var endTime = Date.now();
|
||||
|
||||
me.dropFrames += (endTime - startTime) / me.frameDuration;
|
||||
|
||||
// Do we have more stuff to animate?
|
||||
if (me.animations.length > 0) {
|
||||
me.requestAnimationFrame();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
advance: function(count) {
|
||||
var animations = this.animations;
|
||||
var animation, chart;
|
||||
var i = 0;
|
||||
|
||||
while (i < animations.length) {
|
||||
animation = animations[i];
|
||||
chart = animation.chart;
|
||||
|
||||
animation.currentStep = (animation.currentStep || 0) + count;
|
||||
animation.currentStep = Math.min(animation.currentStep, animation.numSteps);
|
||||
|
||||
helpers.callback(animation.render, [chart, animation], chart);
|
||||
helpers.callback(animation.onAnimationProgress, [animation], chart);
|
||||
|
||||
if (animation.currentStep >= animation.numSteps) {
|
||||
helpers.callback(animation.onAnimationComplete, [animation], chart);
|
||||
chart.animating = false;
|
||||
animations.splice(i, 1);
|
||||
} else {
|
||||
++i;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
@ -1,11 +1,14 @@
|
||||
'use strict';
|
||||
|
||||
var Animation = require('./core.animation');
|
||||
var animations = require('./core.animations');
|
||||
var defaults = require('./core.defaults');
|
||||
var helpers = require('../helpers/index');
|
||||
var Interaction = require('./core.interaction');
|
||||
var layouts = require('./core.layouts');
|
||||
var platform = require('../platforms/platform');
|
||||
var plugins = require('./core.plugins');
|
||||
var Tooltip = require('./core.tooltip');
|
||||
|
||||
module.exports = function(Chart) {
|
||||
|
||||
@ -164,7 +167,7 @@ module.exports = function(Chart) {
|
||||
|
||||
stop: function() {
|
||||
// Stops any current animation loop occurring
|
||||
Chart.animationService.cancelAnimation(this);
|
||||
animations.cancelAnimation(this);
|
||||
return this;
|
||||
},
|
||||
|
||||
@ -519,7 +522,7 @@ module.exports = function(Chart) {
|
||||
};
|
||||
|
||||
if (animationOptions && ((typeof duration !== 'undefined' && duration !== 0) || (typeof duration === 'undefined' && animationOptions.duration !== 0))) {
|
||||
var animation = new Chart.Animation({
|
||||
var animation = new Animation({
|
||||
numSteps: (duration || animationOptions.duration) / 16.66, // 60 fps
|
||||
easing: config.easing || animationOptions.easing,
|
||||
|
||||
@ -535,12 +538,12 @@ module.exports = function(Chart) {
|
||||
onAnimationComplete: onComplete
|
||||
});
|
||||
|
||||
Chart.animationService.addAnimation(me, animation, duration, lazy);
|
||||
animations.addAnimation(me, animation, duration, lazy);
|
||||
} else {
|
||||
me.draw();
|
||||
|
||||
// See https://github.com/chartjs/Chart.js/issues/3781
|
||||
onComplete(new Chart.Animation({numSteps: 0, chart: me}));
|
||||
onComplete(new Animation({numSteps: 0, chart: me}));
|
||||
}
|
||||
|
||||
return me;
|
||||
@ -775,7 +778,7 @@ module.exports = function(Chart) {
|
||||
|
||||
initToolTip: function() {
|
||||
var me = this;
|
||||
me.tooltip = new Chart.Tooltip({
|
||||
me.tooltip = new Tooltip({
|
||||
_chart: me,
|
||||
_chartInstance: me, // deprecated, backward compatibility
|
||||
_data: me.data,
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,4 +1,3 @@
|
||||
// Test the bubble chart default config
|
||||
describe('Default Configs', function() {
|
||||
describe('Bubble Chart', function() {
|
||||
it('should return correct tooltip strings', function() {
|
||||
|
44
test/specs/global.namespace.tests.js
Normal file
44
test/specs/global.namespace.tests.js
Normal file
@ -0,0 +1,44 @@
|
||||
describe('Chart namespace', function() {
|
||||
describe('Chart', function() {
|
||||
it('should a function (constructor)', function() {
|
||||
expect(Chart instanceof Function).toBeTruthy();
|
||||
});
|
||||
it('should define "core" properties', function() {
|
||||
expect(Chart instanceof Function).toBeTruthy();
|
||||
expect(Chart.Animation instanceof Object).toBeTruthy();
|
||||
expect(Chart.animationService instanceof Object).toBeTruthy();
|
||||
expect(Chart.defaults instanceof Object).toBeTruthy();
|
||||
expect(Chart.Element instanceof Object).toBeTruthy();
|
||||
expect(Chart.Interaction instanceof Object).toBeTruthy();
|
||||
expect(Chart.layouts instanceof Object).toBeTruthy();
|
||||
expect(Chart.plugins instanceof Object).toBeTruthy();
|
||||
expect(Chart.platform instanceof Object).toBeTruthy();
|
||||
expect(Chart.Ticks instanceof Object).toBeTruthy();
|
||||
expect(Chart.Tooltip instanceof Object).toBeTruthy();
|
||||
expect(Chart.Tooltip.positioners instanceof Object).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
describe('Chart.elements', function() {
|
||||
it('should be an object', function() {
|
||||
expect(Chart.elements instanceof Object).toBeTruthy();
|
||||
});
|
||||
it('should contains "elements" classes', function() {
|
||||
expect(Chart.elements.Arc instanceof Function).toBeTruthy();
|
||||
expect(Chart.elements.Line instanceof Function).toBeTruthy();
|
||||
expect(Chart.elements.Point instanceof Function).toBeTruthy();
|
||||
expect(Chart.elements.Rectangle instanceof Function).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
describe('Chart.helpers', function() {
|
||||
it('should be an object', function() {
|
||||
expect(Chart.helpers instanceof Object).toBeTruthy();
|
||||
});
|
||||
it('should contains "helpers" namespaces', function() {
|
||||
expect(Chart.helpers.easing instanceof Object).toBeTruthy();
|
||||
expect(Chart.helpers.canvas instanceof Object).toBeTruthy();
|
||||
expect(Chart.helpers.options instanceof Object).toBeTruthy();
|
||||
});
|
||||
});
|
||||
});
|
Loading…
x
Reference in New Issue
Block a user