Skip to content

Instantly share code, notes, and snippets.

@axelchalon
Last active June 15, 2017 21:14
Show Gist options
  • Save axelchalon/bb64f2258d0de59e385c to your computer and use it in GitHub Desktop.
Save axelchalon/bb64f2258d0de59e385c to your computer and use it in GitHub Desktop.
Rotate an element with touch events
/**
* @param DOMElement touchElement The element whose center we use for the rotation, and on which the touch events occur; musn't be an svg element
* @param function callbacks {move: function, end (optional): function}
*/
var TouchRotate = function (touchElement, callbacks) {
// Does not work with SVG, hence touchElement mustn't be an SVG
function getElementCenterCoordinates(el) {
return {
centerX: el.offsetLeft + el.offsetWidth / 2,
centerY: el.offsetTop + el.offsetHeight / 2
}
}
// Get radian starting from standard CSS transform axis (vertical top axis: ((0,0),(0,1)))
function getRadian(currentX, currentY, centerX, centerY) {
var opp = centerY - currentY
var adj = currentX - centerX
var rad_starting_right = Math.atan2(opp, adj)
return Math.PI / 2 - rad_starting_right
}
// Handle mobile and desktop mouse events for rotation
['touchstart', 'mousedown', 'touchmove', 'mousedownmove'].forEach(function (eventName) {
touchElement.addEventListener(eventName, function (e) {
var currentX = e.touches ? e.touches[0].pageX : (e.pageX ? e.pageX : e.detail.pageX)
var currentY = e.touches ? e.touches[0].pageY : (e.pageY ? e.pageY : e.detail.pageY)
var {centerX, centerY} = getElementCenterCoordinates(touchElement)
var currentRadian = getRadian(currentX, currentY, centerX, centerY)
callbacks['move'](currentRadian)
event.preventDefault()
})
}); // do not remove the semi-colon
['touchend', 'mouseup'].forEach(function (eventName) {
console.log('up')
touchElement.addEventListener(eventName, function () {
if (typeof callbacks.end !== 'undefined')
callbacks['end']()
})
})
// Create custom "mousedownmove" event
var mousedown = false
touchElement.addEventListener('mousedown', () => {
console.log('mousedown')
mousedown = true
})
touchElement.addEventListener('mouseup', () => {
console.log('mouseup')
mousedown = false
})
touchElement.addEventListener('mousemove', (e) => {
if (mousedown) {
console.log('mousemove mousedown')
function triggerEvent(el, eventName, options) {
var event
if (window.CustomEvent) {
event = new CustomEvent(eventName, options)
} else {
event = document.createEvent('CustomEvent')
event.initCustomEvent(eventName, true, true, options)
}
el.dispatchEvent(event)
}
triggerEvent(touchElement, 'mousedownmove', {
detail: {
pageX: e.pageX,
pageY: e.pageY
}
})
}
})
}
var index = 0;
var TouchRotateCallbacks = function () {
var lastNotchRadian = false
return {
move: function (touchMoveRadian) { // closure isn't functional #todo
// Quick fix because touchMoveRadian abruptly switches from (+3/2 * PI) to (-1/2 * PI)
var radianDiff = touchMoveRadian - lastNotchRadian
if (radianDiff < -Math.PI)
radianDiff = touchMoveRadian + Math.PI * 2 - lastNotchRadian
else if (radianDiff > Math.PI)
radianDiff = lastNotchRadian - (touchMoveRadian + Math.PI * 2)
if (lastNotchRadian === false)
lastNotchRadian = touchMoveRadian
else if (radianDiff > Math.PI / MAX_VISIBLE_NUMBER_OF_NODES) {
lastNotchRadian = touchMoveRadian
index++
} else if (radianDiff < -Math.PI / MAX_VISIBLE_NUMBER_OF_NODES) {
lastNotchRadian = touchMoveRadian
index--
}
},
end: function () {
lastNotchRadian = false
}
}
}
var touchRotateCallbacks = TouchRotateCallbacks()
new TouchRotate(document.querySelector('#some-dom-element'), touchRotateCallbacks.move, touchRotateCallbacks.end)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment