]>
git.proxmox.com Git - sencha-touch.git/blob - src/src/chart/interactions/CrossZoom.js
2 * @class Ext.chart.interactions.CrossZoom
3 * @extends Ext.chart.interactions.Abstract
5 * The CrossZoom interaction allows the user to zoom in on a selected area of the chart.
8 * var lineChart = new Ext.chart.CartesianChart({
14 * fields: ['name', 'data1', 'data2', 'data3', 'data4', 'data5'],
16 * {'name':'metric one', 'data1':10, 'data2':12, 'data3':14, 'data4':8, 'data5':13},
17 * {'name':'metric two', 'data1':7, 'data2':8, 'data3':16, 'data4':10, 'data5':3},
18 * {'name':'metric three', 'data1':5, 'data2':2, 'data3':14, 'data4':12, 'data5':7},
19 * {'name':'metric four', 'data1':2, 'data2':14, 'data3':6, 'data4':1, 'data5':23},
20 * {'name':'metric five', 'data1':27, 'data2':38, 'data3':36, 'data4':13, 'data5':33}
28 * text: 'Sample Values',
38 * text: 'Sample Values',
49 * stroke: 'rgb(143,203,203)'
55 * path: ['M', -2, 0, 0, 2, 2, 0, 0, -2, 'Z'],
75 * Ext.Viewport.setLayout('fit');
76 * Ext.Viewport.add(lineChart);
78 Ext
.define('Ext.chart.interactions.CrossZoom', {
80 extend
: 'Ext.chart.interactions.Abstract',
83 alias
: 'interaction.crosszoom',
87 * @cfg {Object/Array} axes
88 * Specifies which axes should be made navigable. The config value can take the following formats:
90 * - An Object whose keys correspond to the {@link Ext.chart.axis.Axis#position position} of each
91 * axis that should be made navigable. Each key's value can either be an Object with further
92 * configuration options for each axis or simply `true` for a default set of options.
104 * If using the full Object form, the following options can be specified for each axis:
106 * - minZoom (Number) A minimum zoom level for the axis. Defaults to `1` which is its natural size.
107 * - maxZoom (Number) A maximum zoom level for the axis. Defaults to `10`.
108 * - startZoom (Number) A starting zoom level for the axis. Defaults to `1`.
109 * - allowZoom (Boolean) Whether zooming is allowed for the axis. Defaults to `true`.
110 * - allowPan (Boolean) Whether panning is allowed for the axis. Defaults to `true`.
111 * - startPan (Boolean) A starting panning offset for the axis. Defaults to `0`.
113 * - An Array of strings, each one corresponding to the {@link Ext.chart.axis.Axis#position position}
114 * of an axis that should be made navigable. The default options will be used for each named axis.
118 * axes: ['left', 'bottom']
121 * If the `axes` config is not specified, it will default to making all axes navigable with the
122 * default axis options.
131 stopAnimationBeforeSync
: false,
133 zoomAnimationInProgress
: false,
135 constructor: function () {
136 this.callSuper(arguments
);
137 this.zoomHistory
= [];
140 applyAxes: function (axesConfig
) {
142 if (axesConfig
=== true) {
149 } else if (Ext
.isArray(axesConfig
)) {
150 // array of axis names - translate to full object form
152 Ext
.each(axesConfig
, function (axis
) {
155 } else if (Ext
.isObject(axesConfig
)) {
156 Ext
.iterate(axesConfig
, function (key
, val
) {
157 // axis name with `true` value -> translate to object
160 } else if (val
!== false) {
168 applyUndoButton: function (button
, oldButton
) {
174 return Ext
.create('Ext.Button', Ext
.apply({
179 handler: function () {
183 } else if (oldButton
) {
188 getGestures: function () {
191 gestures
[me
.getGesture()] = 'onGesture';
192 gestures
[me
.getGesture() + 'start'] = 'onGestureStart';
193 gestures
[me
.getGesture() + 'end'] = 'onGestureEnd';
194 gestures
.doubletap
= 'onDoubleTap';
198 getSurface: function () {
199 return this.getChart() && this.getChart().getSurface('main');
202 setSeriesOpacity: function (opacity
) {
203 var surface
= this.getChart() && this.getChart().getSurface('series-surface', 'series');
205 surface
.element
.setStyle('opacity', opacity
);
209 onGestureStart: function (e
) {
211 chart
= me
.getChart(),
212 surface
= me
.getSurface(),
213 region
= chart
.getInnerRegion(),
214 chartWidth
= region
[2],
215 chartHeight
= region
[3],
216 xy
= chart
.element
.getXY(),
217 x
= e
.pageX
- xy
[0] - region
[0],
218 y
= e
.pageY
- xy
[1] - region
[1];
220 if (me
.zoomAnimationInProgress
) {
223 if (x
> 0 && x
< chartWidth
&& y
> 0 && y
< chartHeight
) {
224 me
.lockEvents(me
.getGesture());
227 me
.selectionRect
= surface
.add({
230 fillStyle
: 'rgba(80,80,140,0.5)',
231 strokeStyle
: 'rgba(80,80,140,1)',
239 me
.setSeriesOpacity(0.8);
244 onGesture: function (e
) {
246 if (me
.zoomAnimationInProgress
) {
249 if (me
.getLocks()[me
.getGesture()] === me
) {
250 var chart
= me
.getChart(),
251 surface
= me
.getSurface(),
252 region
= chart
.getInnerRegion(),
253 chartWidth
= region
[2],
254 chartHeight
= region
[3],
255 xy
= chart
.element
.getXY(),
256 x
= e
.pageX
- xy
[0] - region
[0],
257 y
= e
.pageY
- xy
[1] - region
[1];
261 } else if (x
> chartWidth
) {
266 } else if (y
> chartHeight
) {
269 me
.selectionRect
.setAttributes({
270 width
: x
- me
.startX
,
271 height
: y
- me
.startY
273 if (Math
.abs(me
.startX
- x
) < 11 || Math
.abs(me
.startY
- y
) < 11) {
274 me
.selectionRect
.setAttributes({globalAlpha
: 0.5});
276 me
.selectionRect
.setAttributes({globalAlpha
: 1});
278 surface
.renderFrame();
283 onGestureEnd: function (e
) {
285 if (me
.zoomAnimationInProgress
) {
288 if (me
.getLocks()[me
.getGesture()] === me
) {
289 var chart
= me
.getChart(),
290 surface
= me
.getSurface(),
291 region
= chart
.getInnerRegion(),
292 chartWidth
= region
[2],
293 chartHeight
= region
[3],
294 xy
= chart
.element
.getXY(),
295 x
= e
.pageX
- xy
[0] - region
[0],
296 y
= e
.pageY
- xy
[1] - region
[1];
300 } else if (x
> chartWidth
) {
305 } else if (y
> chartHeight
) {
308 if (Math
.abs(me
.startX
- x
) < 11 || Math
.abs(me
.startY
- y
) < 11) {
309 surface
.remove(me
.selectionRect
);
312 Math
.min(me
.startX
, x
) / chartWidth
,
313 1 - Math
.max(me
.startY
, y
) / chartHeight
,
314 Math
.max(me
.startX
, x
) / chartWidth
,
315 1 - Math
.min(me
.startY
, y
) / chartHeight
318 me
.selectionRect
.setAttributes({
319 x
: Math
.min(me
.startX
, x
),
320 y
: Math
.min(me
.startY
, y
),
321 width
: Math
.abs(me
.startX
- x
),
322 height
: Math
.abs(me
.startY
- y
)
325 me
.selectionRect
.fx
.setConfig(chart
.getAnimate() || {duration
: 0});
326 me
.selectionRect
.setAttributes({
334 me
.zoomAnimationInProgress
= true;
336 chart
.suspendThicknessChanged();
337 me
.selectionRect
.fx
.on('animationend', function () {
338 chart
.resumeThicknessChanged();
340 surface
.remove(me
.selectionRect
);
341 me
.selectionRect
= null;
343 me
.zoomAnimationInProgress
= false;
347 surface
.renderFrame();
349 me
.unlockEvents(me
.getGesture());
350 me
.setSeriesOpacity(1.0);
352 if (!me
.zoomAnimationInProgress
) {
353 surface
.remove(me
.selectionRect
);
354 me
.selectionRect
= null;
359 zoomBy: function (region
) {
361 axisConfigs
= me
.getAxes(),
362 axes
= me
.getChart().getAxes(),
366 for (var i
= 0; i
< axes
.length
; i
++) {
368 config
= axisConfigs
[axis
.getPosition()];
369 if (config
&& config
.allowZoom
!== false) {
370 var isSide
= axis
.isSide(),
371 oldRange
= axis
.getVisibleRange();
372 zoomMap
[axis
.getId()] = oldRange
.slice(0);
374 axis
.setVisibleRange([
375 (oldRange
[1] - oldRange
[0]) * region
[0] + oldRange
[0],
376 (oldRange
[1] - oldRange
[0]) * region
[2] + oldRange
[0]
379 axis
.setVisibleRange([
380 (oldRange
[1] - oldRange
[0]) * region
[1] + oldRange
[0],
381 (oldRange
[1] - oldRange
[0]) * region
[3] + oldRange
[0]
387 me
.zoomHistory
.push(zoomMap
);
388 me
.getUndoButton().setDisabled(false);
391 undoZoom: function () {
392 var zoomMap
= this.zoomHistory
.pop(),
393 axes
= this.getChart().getAxes();
395 for (var i
= 0; i
< axes
.length
; i
++) {
397 if (zoomMap
[axis
.getId()]) {
398 axis
.setVisibleRange(zoomMap
[axis
.getId()]);
402 this.getUndoButton().setDisabled(this.zoomHistory
.length
=== 0);
406 onDoubleTap: function (e
) {