web-apps/apps/documenteditor/mobile/app/plugin/Pinchemu.js

284 lines
9 KiB
JavaScript
Raw Normal View History

2016-03-11 00:48:53 +00:00
/**
* @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;
}
});