Working on tap behavior of scatter and flippables.
This commit is contained in:
+92
-7
@@ -931,7 +931,7 @@ export class DOMScatterContainer {
|
||||
context.stroke()
|
||||
}
|
||||
requestAnimationFrame(dt => {
|
||||
this.showTouches(dt)
|
||||
this.showTouches(dt, canvas)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1043,6 +1043,7 @@ export class DOMScatter extends AbstractScatter {
|
||||
height = null, // required
|
||||
resizable = false,
|
||||
clickOnTap = false,
|
||||
allowClickDistance = 44,
|
||||
verbose = true,
|
||||
onResize = null,
|
||||
touchAction = 'none',
|
||||
@@ -1106,7 +1107,8 @@ export class DOMScatter extends AbstractScatter {
|
||||
rotation: this.startRotationDegrees,
|
||||
transformOrigin: transformOrigin
|
||||
}
|
||||
|
||||
this.tapNodes = new Map()
|
||||
this.allowClickDistance = allowClickDistance
|
||||
|
||||
// For tweenlite we need initial values in _gsTransform
|
||||
TweenLite.set(element, this.initialValues)
|
||||
@@ -1299,16 +1301,99 @@ export class DOMScatter extends AbstractScatter {
|
||||
}
|
||||
|
||||
onTap(event, interaction, point) {
|
||||
|
||||
if (this.clickOnTap) {
|
||||
let p = Points.fromPageToNode(this.element, point)
|
||||
let element = document.elementFromPoint(p.x, p.y)
|
||||
if (element != null) {
|
||||
console.log('tap simulates click')
|
||||
element.click()
|
||||
let directNode = document.elementFromPoint(point.x, point.y)
|
||||
let nearestNode = this.nearestClickable(event)
|
||||
|
||||
console.log("onTap", directNode, nearestNode.tagName)
|
||||
if (directNode != null && this.isClickable(directNode)) {
|
||||
directNode.click()
|
||||
}
|
||||
else {
|
||||
if (nearestNode.tagName == 'svg' && this.isClickable(nearestNode)) {
|
||||
let handler = this.tapNodes.get(nearestNode)
|
||||
console.log("Clicking beneath SVG: to be done", handler)
|
||||
Events.stop(event)
|
||||
//nearestNode.click()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a click or tap behavior to the node. Uses
|
||||
* either the scatter clickOnTap version which requires click handlers
|
||||
* or uses the hammer.js driven tap handler.
|
||||
*
|
||||
* @param {*} node
|
||||
* @param {*} handler
|
||||
* @memberof DOMScatter
|
||||
*/
|
||||
|
||||
addTapListener(node, handler) {
|
||||
if (this.clickOnTap) {
|
||||
node.addEventListener('click', handler)
|
||||
this.tapNodes.set(node, handler)
|
||||
}
|
||||
else {
|
||||
InteractionMapper.on('tap', node, handler)
|
||||
}
|
||||
}
|
||||
|
||||
isClickable(node) {
|
||||
if (node.tagName == 'A')
|
||||
return true
|
||||
if (this.tapNodes.has(node))
|
||||
return true
|
||||
return false
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of all clickable nodes.
|
||||
* Unfortunately we cannot search for all nodes with an attached 'click' event listener
|
||||
* See https://stackoverflow.com/questions/11455515/how-to-check-whether-dynamically-attached-event-listener-exists-or-not
|
||||
* Therefore we can only detect the following standard cases:
|
||||
* I. All clickable objects like clickables
|
||||
* II. Objects that have been attached a click handler by the scatter itself via
|
||||
*/
|
||||
clickableNodes() {
|
||||
let result = []
|
||||
for (let node of this.element.querySelectorAll("*")) {
|
||||
if (this.isClickable(node))
|
||||
result.push(node)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
nearestClickable(event) {
|
||||
let element = this.element
|
||||
let clickables = this.clickableNodes()
|
||||
let globalClick = (event.center) ? event.center : { x: event.x, y: event.y }
|
||||
let localClick = Points.fromPageToNode(element, globalClick)
|
||||
|
||||
let clickRects = clickables.map(link => {
|
||||
let rect = link.getBoundingClientRect()
|
||||
let topLeft = Points.fromPageToNode(element, rect)
|
||||
let center = Points.fromPageToNode(element, { x: rect.x + rect.width / 2, y: rect.y + rect.height / 2 })
|
||||
return { x: topLeft.x, y: topLeft.y, width: rect.width, height: rect.height, center, link }
|
||||
})
|
||||
|
||||
let distances = []
|
||||
clickRects.forEach(rect => {
|
||||
let distance = Points.distanceToRect(localClick, rect)
|
||||
distances.push(parseInt(distance))
|
||||
})
|
||||
|
||||
let closestClickIndex = distances.indexOf(Math.min(...distances))
|
||||
let closestClickable = clickables[closestClickIndex]
|
||||
if (distances[closestClickIndex] < this.allowClickDistance) {
|
||||
console.log("found closest clickables", closestClickable)
|
||||
return closestClickable
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
isDescendant(parent, child) {
|
||||
let node = child.parentNode
|
||||
while (node != null) {
|
||||
|
||||
Reference in New Issue
Block a user