284 lines
9 KiB
JavaScript
284 lines
9 KiB
JavaScript
|
/**
|
||
|
* @filename Ex.plugin.Pinchemu.js
|
||
|
*
|
||
|
* @name Pinch emulator plugin for Sencha Touch
|
||
|
* @fileOverview Emulation of double touch pinch event for desktops
|
||
|
*
|
||
|
* @author Constantine V. Smirnov kostysh(at)gmail.com
|
||
|
* @date 20120220
|
||
|
* @version 0.2
|
||
|
* @license Free
|
||
|
*
|
||
|
* @requires Sencha Touch 2.0
|
||
|
*
|
||
|
* Usage:
|
||
|
|
||
|
.....
|
||
|
items: [
|
||
|
{
|
||
|
xtype: 'panel',
|
||
|
id: 'mypinchitem',
|
||
|
plugins: [
|
||
|
{
|
||
|
xclass: 'Ext.plugin.Pinchemu',
|
||
|
helpers: true//enable touches visualization
|
||
|
}
|
||
|
]
|
||
|
}
|
||
|
]
|
||
|
|
||
|
*
|
||
|
*/
|
||
|
|
||
|
Ext.define('DE.plugin.Pinchemu', {
|
||
|
extend: 'Ext.Component',
|
||
|
alias: 'plugin.pinchemu',
|
||
|
|
||
|
config: {
|
||
|
helpers: true
|
||
|
},
|
||
|
|
||
|
init: function(cmp) {
|
||
|
var self = this;
|
||
|
|
||
|
self.touchHelpers = [];
|
||
|
|
||
|
self.touchHelpers[0] = Ext.create('Ext.Button', {
|
||
|
top: 0,
|
||
|
left: 0,
|
||
|
style: 'opacity: 0.6;',
|
||
|
iconMask: true,
|
||
|
round: true,
|
||
|
hidden: true
|
||
|
});
|
||
|
|
||
|
self.touchHelpers[1] = Ext.create('Ext.Button', {
|
||
|
top: 0,
|
||
|
left: 0,
|
||
|
style: 'opacity: 0.6;',
|
||
|
iconMask: true,
|
||
|
round: true,
|
||
|
hidden: true
|
||
|
});
|
||
|
|
||
|
Ext.Viewport.add(self.touchHelpers[0]);
|
||
|
Ext.Viewport.add(self.touchHelpers[1]);
|
||
|
|
||
|
self.cmp = cmp;
|
||
|
self.cmp.on({
|
||
|
scope: self,
|
||
|
painted: self.initPinchsim
|
||
|
});
|
||
|
},
|
||
|
|
||
|
//Plugin initialisation
|
||
|
initPinchsim: function() {
|
||
|
var self = this;
|
||
|
|
||
|
this.pinchStarted = false;
|
||
|
|
||
|
var item = self.cmp;
|
||
|
|
||
|
if (!item.pinchSimEnabled) {
|
||
|
|
||
|
if (item.rendered) {
|
||
|
self.initHandlers(item);
|
||
|
} else {
|
||
|
item.on({
|
||
|
painted: self.initHandlers
|
||
|
});
|
||
|
}
|
||
|
}
|
||
|
},
|
||
|
|
||
|
initHandlers: function(item) {
|
||
|
var self = this;
|
||
|
|
||
|
//Setup touch handlers on enabled item
|
||
|
item.element.on({
|
||
|
scope: self,
|
||
|
touchstart: function(ev) {
|
||
|
if ((ev.event.ctrlKey || ev.event.shiftKey) &&
|
||
|
self.pinchStarted === false) {
|
||
|
self.pinchStarted = true;
|
||
|
|
||
|
if (ev.event.ctrlKey) {
|
||
|
self.zoomStart = 100;
|
||
|
self.zoomDirection = 1;
|
||
|
} else if (ev.event.shiftKey) {
|
||
|
self.zoomStart = 340;
|
||
|
self.zoomDirection = -1;
|
||
|
}
|
||
|
|
||
|
self.zoomFactor = 1;
|
||
|
|
||
|
self.onTouchStart(item, ev);
|
||
|
}
|
||
|
},
|
||
|
|
||
|
touchend: function(ev) {
|
||
|
if (self.pinchStarted) {
|
||
|
self.pinchStarted = false;
|
||
|
self.onTouchEnd(item, ev);
|
||
|
}
|
||
|
},
|
||
|
|
||
|
touchcancel: function(ev) {
|
||
|
if (self.pinchStarted) {
|
||
|
self.pinchStarted = false;
|
||
|
self.onTouchEnd(item, ev);
|
||
|
}
|
||
|
},
|
||
|
|
||
|
touchmove: function(ev) {
|
||
|
if ((ev.event.ctrlKey || ev.event.shiftKey) &&
|
||
|
this.pinchStarted === true) {
|
||
|
self.onTouchMove(item, ev);
|
||
|
} else if (self.pinchStarted) {
|
||
|
self.pinchStarted = false;
|
||
|
self.onTouchEnd(item, ev);
|
||
|
}
|
||
|
}
|
||
|
});
|
||
|
|
||
|
item.pinchSimEnabled = true;
|
||
|
},
|
||
|
|
||
|
showHelpers: function(ev) {
|
||
|
var touches = ev.touches;
|
||
|
if (typeof touches === 'object' && this.getHelpers()) {
|
||
|
this.moveHelpers(touches);
|
||
|
this.setHelpersArrows(ev);
|
||
|
this.touchHelpers[0].show();
|
||
|
this.touchHelpers[1].show();
|
||
|
}
|
||
|
},
|
||
|
|
||
|
setHelpersArrows: function(ev) {
|
||
|
if (ev.event.ctrlKey) {
|
||
|
this.touchHelpers[0].setIconCls('arrow_right');
|
||
|
this.touchHelpers[1].setIconCls('arrow_left');
|
||
|
} else {
|
||
|
this.touchHelpers[0].setIconCls('arrow_left');
|
||
|
this.touchHelpers[1].setIconCls('arrow_right');
|
||
|
}
|
||
|
},
|
||
|
|
||
|
moveHelpers: function(touches) {
|
||
|
this.touchHelpers[0].setTop(touches[0].point.y);
|
||
|
this.touchHelpers[0].setLeft(touches[0].point.x);
|
||
|
this.touchHelpers[1].setTop(touches[1].point.y);
|
||
|
this.touchHelpers[1].setLeft(touches[1].point.x);
|
||
|
},
|
||
|
|
||
|
hideHelpers: function() {
|
||
|
this.touchHelpers[0].hide();
|
||
|
this.touchHelpers[1].hide();
|
||
|
},
|
||
|
|
||
|
//Converting of single touch event to double touch
|
||
|
convertEvent: function(ev) {
|
||
|
var self = this;
|
||
|
|
||
|
//Clone of original touch object
|
||
|
var touches = Array.prototype.slice.call(ev.touches);
|
||
|
|
||
|
if (!touches) {
|
||
|
touches = self.lastTouches;//at the pinchend only
|
||
|
}
|
||
|
|
||
|
ev.touches = touches;
|
||
|
|
||
|
if (touches.length > 0) {
|
||
|
|
||
|
if (!self.touchStartPoint) {
|
||
|
|
||
|
var startX = touches[0].point.x;
|
||
|
var startY = touches[0].point.y;
|
||
|
var startPageX = touches[0].pageX;
|
||
|
var startPageY = touches[0].pageY;
|
||
|
|
||
|
touches[0].point.x = touches[0].point.x + self.zoomStart / 2;
|
||
|
touches[0].pageX = touches[0].pageX + self.zoomStart / 2;
|
||
|
|
||
|
//Build new touch point
|
||
|
touches[1] = {};
|
||
|
touches[1].identifier = 2;
|
||
|
touches[1].pageX = startPageX - self.zoomStart / 2;
|
||
|
touches[1].pageY = startPageY;
|
||
|
touches[1].point = touches[0].point.clone();
|
||
|
touches[1].point.x = startX - self.zoomStart / 2;
|
||
|
touches[1].point.y = touches[0].point.y;
|
||
|
touches[1].target = touches[0].target;
|
||
|
touches[1].targets = touches[0].targets;
|
||
|
touches[1].timeStamp = touches[0].timeStamp;
|
||
|
|
||
|
//Remember the current start point
|
||
|
this.touchStartPoint = {
|
||
|
x: startX,
|
||
|
y: startY,
|
||
|
pageX: startPageX,
|
||
|
pageY: startPageY,
|
||
|
distance: touches[0].point.getDistanceTo(touches[1].point)
|
||
|
};
|
||
|
|
||
|
} else {
|
||
|
|
||
|
touches[0].point = self.lastTouches[0].point.clone();//replace original by previous
|
||
|
touches[0].point.x = Ext.Number.constrain(self.lastTouches[0].point.x + self.zoomFactor * self.zoomDirection,
|
||
|
self.touchStartPoint.x + self.zoomFactor);
|
||
|
touches[0].pageX = Ext.Number.constrain(self.lastTouches[0].pageX + self.zoomFactor * self.zoomDirection,
|
||
|
self.touchStartPoint.x + self.zoomFactor);
|
||
|
|
||
|
touches[1] = {};
|
||
|
touches[1].point = self.lastTouches[1].point.clone();
|
||
|
touches[1].point.x = Ext.Number.constrain(self.lastTouches[1].point.x - self.zoomFactor * self.zoomDirection,
|
||
|
self.touchStartPoint.x + self.zoomFactor);
|
||
|
touches[1].pageX = Ext.Number.constrain(self.lastTouches[1].pageX - self.zoomFactor * self.zoomDirection,
|
||
|
self.touchStartPoint.x + self.zoomFactor);
|
||
|
touches[1].pageY = self.lastTouches[1].pageY;
|
||
|
touches[1].target = touches[0].target;
|
||
|
touches[1].targets = touches[0].targets;
|
||
|
touches[1].timeStamp = touches[0].timeStamp;
|
||
|
|
||
|
}
|
||
|
|
||
|
self.lastTouches = touches;
|
||
|
}
|
||
|
|
||
|
ev.scale = self.getNewScale(ev);
|
||
|
return ev;
|
||
|
},
|
||
|
|
||
|
getNewScale: function(ev) {
|
||
|
var self = this;
|
||
|
|
||
|
if (ev.touches.length > 0) {
|
||
|
var newDistance = ev.touches[0].point.getDistanceTo(ev.touches[1].point);
|
||
|
self.lastScale = newDistance / self.touchStartPoint.distance;
|
||
|
return self.lastScale;
|
||
|
} else {
|
||
|
return self.lastScale;
|
||
|
}
|
||
|
},
|
||
|
|
||
|
onTouchStart: function() {
|
||
|
this.lastScale = 1;
|
||
|
var ev = this.convertEvent(arguments[1]);
|
||
|
this.showHelpers(ev);
|
||
|
},
|
||
|
|
||
|
onTouchMove: function() {
|
||
|
var ev = this.convertEvent(arguments[1]);
|
||
|
this.lastTouches = Array.prototype.slice.call(ev.touches);
|
||
|
this.moveHelpers(ev.touches);
|
||
|
},
|
||
|
|
||
|
onTouchEnd: function() {
|
||
|
var ev = this.convertEvent(arguments[1]);
|
||
|
this.hideHelpers();
|
||
|
this.touchStartPoint = null;
|
||
|
this.lastTouches = null;
|
||
|
this.lastScale = null;
|
||
|
}
|
||
|
});
|