Skip to content
This repository has been archived by the owner on Apr 14, 2021. It is now read-only.

Added touch support and partial pinch zoom support #47

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
238 changes: 235 additions & 3 deletions globe/globe.js
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,227 @@ DAT.Globe = function(container, opts) {
var padding = 40;
var PI_HALF = Math.PI / 2;


var touchHandled;
var isPinchScaling;
var pinchStartX;
var clickTimer;

//disabled pinch zooming by default due to as weird bugs in Safari but leaving in, in case someone else can fix it
var pinchZoomEnabled = opts.pinchZoomEnabled || false;

/**
* (Modified from `jquery-ui-touchpunch`)
* Simulate a mouse event based on a corresponding touch event
* @param {Object} event A touch event
* @param {String} simulatedType The corresponding mouse event
*/
function simulateMouseEvent(event, simulatedType) {

var touch;

// Ignore multi-touch events
if(event.originalEvent){
touch = event.originalEvent.changedTouches[0];

if (event.originalEvent.touches.length == 2) {
//handle pinching
isPinchScaling = true;
pinchStartX = event.originalEvent.touches[0].clientX;
onPinch(event);

return;
}
else if (event.originalEvent.touches.length > 2){
return;
}
}
else if(event.touches){
touch = event.changedTouches[0];

if(event.touches.length == 2){
//handle pinching
isPinchScaling = true;
pinchStartX = event.touches[0].clientX;
onPinch(event);

return;
}
else if(event.touches.length > 2){
return;
}
}

event.preventDefault();

var simulatedEvent = document.createEvent('MouseEvents');

// Initialize the simulated mouse event using the touch event's coordinates
simulatedEvent.initMouseEvent(
simulatedType, // type
true, // bubbles
true, // cancelable
window, // view
1, // detail
touch.screenX, // screenX
touch.screenY, // screenY
touch.clientX, // clientX
touch.clientY, // clientY
false, // ctrlKey
false, // altKey
false, // shiftKey
false, // metaKey
0, // button
null // relatedTarget
);

// Dispatch the simulated event to the target element
event.target.dispatchEvent(simulatedEvent);
}

function resetZoomOnDoubleTap(event){
// check for double tap
if(pinchZoomEnabled) {
if ((event.originalEvent && event.originalEvent.touches.length == 1) ||
(event.touches && event.touches.length == 1)) {

if (clickTimer == null) {
clickTimer = setTimeout(function () {
clickTimer = null;
}, 500)
} else {
clearTimeout(clickTimer);
clickTimer = null;

//reset zoom
zoom(-5000);
}
}
}
}

function _onTouchStart (event) {

resetZoomOnDoubleTap(event);

var self = this;

// Ignore the event if another widget is already being handled
if (touchHandled){
return;
}

// Set the flag to prevent other widgets from inheriting the touch event
touchHandled = true;

// Track movement to determine if interaction was a click
self._touchMoved = false;

// Simulate the mouseover event
simulateMouseEvent(event, 'mouseover');

// Simulate the mousemove event
simulateMouseEvent(event, 'mousemove');

// Simulate the mousedown event
simulateMouseEvent(event, 'mousedown');
}


function _onTouchMove(event) {
if(isPinchScaling){
onPinch(event);
return;
}

// Ignore event if not handled
if (!touchHandled) {
return;
}

// Interaction was not a click
this._touchMoved = true;

// Simulate the mousemove event
simulateMouseEvent(event, 'mousemove');
}

function _onTouchEnd(event) {

if(isPinchScaling){
onPinch(event);
isPinchScaling = false
return;
}

// Ignore event if not handled
if (!touchHandled) {
return;
}

// Simulate the mouseup event
simulateMouseEvent(event, 'mouseup');

// Simulate the mouseout event
simulateMouseEvent(event, 'mouseout');

// If the touch interaction did not move, it should trigger a click
if (!this._touchMoved) {

// Simulate the click event
simulateMouseEvent(event, 'click');
}

// Unset the flag to allow other widgets to inherit the touch event
touchHandled = false;
}

function getPinchDistance(event){
var dist;

try{
dist = Math.sqrt(
(event.touches[0].clientX-event.touches[1].clientX) * (event.touches[0].clientX-event.touches[1].clientX) +
(event.touches[0].clientY-event.touches[1].clientY) * (event.touches[0].clientY-event.touches[1].clientY)
);

dist = dist * 0.1;
dist = Math.min(dist, 25);

var dir = (pinchStartX > event.touches[0].clientX) ? 1 : -1;

dist = dist * dir;
}
catch(e){
dist = null;
}

return dist;
}

function onPinch(event){
if(pinchZoomEnabled){
var dist = getPinchDistance(event)
if(dist != null){
zoom(dist);
}
}
}


function addTouchHandlers(container){

var touchSupport = 'ontouchend' in document;

//ignore browsers without touch
if(!touchSupport){
return;
}

container.addEventListener('touchstart', _onTouchStart, false);
}


function init() {

container.style.color = '#fff';
Expand Down Expand Up @@ -152,6 +373,8 @@ DAT.Globe = function(container, opts) {

container.addEventListener('mousewheel', onMouseWheel, false);

addTouchHandlers(container);

document.addEventListener('keydown', onDocumentKeyDown, false);

window.addEventListener('resize', onWindowResize, false);
Expand Down Expand Up @@ -277,6 +500,11 @@ DAT.Globe = function(container, opts) {
container.addEventListener('mouseup', onMouseUp, false);
container.addEventListener('mouseout', onMouseOut, false);

container.addEventListener('touchend', _onTouchEnd, false);
container.addEventListener('touchmove', _onTouchMove, false);



mouseOnDown.x = - event.clientX;
mouseOnDown.y = event.clientY;

Expand Down Expand Up @@ -333,10 +561,14 @@ DAT.Globe = function(container, opts) {
}
}


function onWindowResize( event ) {
camera.aspect = container.offsetWidth / container.offsetHeight;
camera.updateProjectionMatrix();
renderer.setSize( container.offsetWidth, container.offsetHeight );
// this method fights with pinch zooming, needs to be disabled if pinch zooming
if(pinchZoomEnabled){
camera.aspect = container.offsetWidth / container.offsetHeight;
camera.updateProjectionMatrix();
renderer.setSize( container.offsetWidth, container.offsetHeight );
}
}

function zoom(delta) {
Expand Down