scratchjr/src/utils/Events.js
2016-01-21 16:49:58 -05:00

313 lines
7.9 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
the caller should define the window event and call startDrag with the appropiate values
*/
import {gn, scaleMultiplier, isTablet} from './lib';
let dragged = false;
let dragthumbnail = undefined;
let dragmousex = 0;
let dragmousey = 0;
let timeoutEvent = undefined;
let dragcanvas = undefined;
let dragDiv = undefined;
let fcnstart = undefined;
let fcnend = undefined;
let updatefcn = undefined;
let fcnclick = undefined;
let scaleStartsAt = 1;
let delta = 10;
let pinchcenter = {
x: 0,
y: 0,
distance: 0
};
let lastZoomScale = 1;
export default class Events {
// Getters/setters for globally used properties
static get dragged () {
return dragged;
}
static set dragged (newDragged) {
dragged = newDragged;
}
static get dragthumbnail () {
return dragthumbnail;
}
static set dragthumbnail (newDragthumbnail) {
dragthumbnail = newDragthumbnail;
}
static get dragmousex () {
return dragmousex;
}
static set dragmousex (newDragmousex) {
dragmousex = newDragmousex;
}
static get dragmousey () {
return dragmousey;
}
static set dragmousey (newDragmousey) {
dragmousey = newDragmousey;
}
static get timeoutEvent () {
return timeoutEvent;
}
static set timeoutEvent (newTimeoutEvent) {
timeoutEvent = newTimeoutEvent;
}
static get dragcanvas () {
return dragcanvas;
}
static set dragcanvas (newDragcanvas) {
dragcanvas = newDragcanvas;
}
static get dragDiv () {
return dragDiv;
}
static get scaleStartsAt () {
return scaleStartsAt;
}
static set scaleStartsAt (newScaleStartsAt) {
scaleStartsAt = newScaleStartsAt;
}
static get pinchcenter () {
return pinchcenter;
}
// Instead of popping the dragging block, etc to the outer-most frame,
// which causes delays while the content is reflowed, we create a
// small drag div that is a parent of frame that the dragging block
// can be a child of. This improves dragging performance.
static init () {
dragDiv = document.createElement('div');
dragDiv.id = 'dragDiv';
dragDiv.style.position = 'absolute';
dragDiv.style.width = '0px'; // size doesn't matter since children float
dragDiv.style.height = '0px';
dragDiv.style.zIndex = 7001; // slightly higher than ScratchJr.dragginLayer
var frameDiv = gn('frame');
frameDiv.appendChild(dragDiv);
}
static startDrag (e, c, atstart, atend, atdrag, atclick, athold) {
dragged = false;
var pt = Events.getTargetPoint(e);
dragmousex = pt.x;
dragmousey = pt.y;
dragthumbnail = c;
fcnstart = atstart;
fcnend = atend;
fcnclick = atclick;
if (athold) {
Events.holdit(c, athold);
}
updatefcn = atdrag;
if (isTablet) { // startDrag event setting
delta = 10 * scaleMultiplier;
window.ontouchmove = function (evt) {
Events.mouseMove(evt);
};
window.ontouchend = function (evt) {
Events.mouseUp(evt);
};
window.ontouchleave = function (evt) {
Events.mouseUp(evt);
};
window.ontouchcancel = function (evt) {
Events.mouseUp(evt);
};
} else {
delta = 7;
window.onmousemove = function (evt) {
Events.mouseMove(evt);
};
window.onmouseup = function (evt) {
Events.mouseUp(evt);
};
}
}
static holdit (c, fcn) {
var repeat = function () {
Events.clearEvents();
fcn(dragthumbnail);
Events.clearDragAndDrop();
};
timeoutEvent = setTimeout(repeat, 500);
}
static clearDragAndDrop () {
timeoutEvent = undefined;
dragcanvas = undefined;
dragged = false;
dragthumbnail = undefined;
fcnstart = undefined;
fcnend = undefined;
updatefcn = undefined;
fcnclick = undefined;
}
static mouseMove (e) {
// be forgiving about the click
var pt = Events.getTargetPoint(e);
if (!dragged && (Events.distance(dragmousex - pt.x, dragmousey - pt.y) < delta)) {
return;
}
if (timeoutEvent) {
clearTimeout(timeoutEvent);
}
timeoutEvent = undefined;
if (!dragged) {
fcnstart(e);
}
dragged = true;
if (updatefcn) {
updatefcn(e, dragcanvas);
}
dragmousex = pt.x;
dragmousey = pt.y;
}
static distance (dx, dy) {
return Math.round(Math.sqrt((dx * dx) + (dy * dy)));
}
static mouseUp (e) {
if (timeoutEvent) {
clearTimeout(timeoutEvent);
}
timeoutEvent = undefined;
Events.clearEvents();
if (!dragged) {
Events.itIsAClick(e);
} else {
Events.performMouseUpAction(e);
}
Events.clearDragAndDrop();
}
static cancelAll () {
if (timeoutEvent) {
clearTimeout(timeoutEvent);
}
timeoutEvent = undefined;
Events.clearEvents();
}
static clearEvents () {
if (isTablet) { // clearEvents
window.ontouchmove = undefined;
window.ontouchend = undefined;
} else {
window.onmousemove = function (e) {
e.preventDefault();
};
window.onmouseup = undefined;
}
}
static performMouseUpAction (e) {
if (fcnend) {
fcnend(e, dragcanvas);
}
}
static itIsAClick (e) {
if (fcnclick) {
fcnclick(e, dragthumbnail);
}
}
static moveThumbnail (el, dx, dy) {
if (!el) {
return;
}
el.top += dy;
el.left += dx;
el.style.top = el.top + 'px';
el.style.left = el.left + 'px';
}
static move3D (el, dx, dy) {
if (!el) {
return;
}
var mtx = new WebKitCSSMatrix(window.getComputedStyle(el).webkitTransform);
el.top = dy + mtx.m42;
el.left = dx + mtx.m41;
el.style.webkitTransform = 'translate3d(' + el.left + 'px,' + el.top + 'px, 0)';
}
/*
.m41 corresponds to the x value of a WebKitCSSMatrix
.m42 corresponds to the y value of a WebKitCSSMatrix
*/
static getTargetPoint (e) {
if (isTablet) {
if (e.touches && (e.touches.length > 0)) {
return {
x: e.touches[0].pageX,
y: e.touches[0].pageY
};
} else if (e.changedTouches) {
return {
x: e.changedTouches[0].pageX,
y: e.changedTouches[0].pageY
};
}
}
return {
x: e.clientX,
y: e.clientY
};
}
static updatePinchCenter (e) {
if (e.touches.length != 2) {
return;
}
var x1 = e.touches[0].clientX,
y1 = e.touches[0].clientY;
var x2 = e.touches[1].clientX,
y2 = e.touches[1].clientY;
var cx = x1 + (x2 - x1) / 2,
cy = y1 + (y2 - y1) / 2;
var d = Math.sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1));
pinchcenter = {
x: cx,
y: cy,
distance: d
};
}
static zoomScale (e) {
if (e.touches.length !== 2) {
return lastZoomScale;
}
var x1 = e.touches[0].clientX,
y1 = e.touches[0].clientY;
var x2 = e.touches[1].clientX,
y2 = e.touches[1].clientY;
var d = Math.sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1));
lastZoomScale = d / pinchcenter.distance;
return lastZoomScale;
}
}