[fix] consistency of nativeEvent.location{X,Y} between touch and mouse

Calculate `location{X,Y}` in the same way for both touch and mouse
events. Also defer the call to `getBoundingClientRect` to avoid
unnecessary DOM queries when the data is not used.
This commit is contained in:
Nicolas Gallagher
2018-03-07 19:55:16 -08:00
parent a67bf0f490
commit 2050730b77
2 changed files with 42 additions and 21 deletions

View File

@@ -51,8 +51,8 @@ Object {
"clientY": 100,
"force": false,
"identifier": 0,
"locationX": 100,
"locationY": 100,
"locationX": undefined,
"locationY": undefined,
"pageX": 300,
"pageY": 300,
"screenX": 400,
@@ -63,8 +63,8 @@ Object {
],
"defaultPrevented": undefined,
"identifier": 0,
"locationX": 200,
"locationY": 200,
"locationX": undefined,
"locationY": undefined,
"pageX": 300,
"pageY": 300,
"preventDefault": [Function],

View File

@@ -10,6 +10,15 @@
const emptyArray = [];
const emptyFunction = () => {};
const getRect = node => {
if (node) {
const isElement = node.nodeType === 1 /* Node.ELEMENT_NODE */;
if (isElement && typeof node.getBoundingClientRect === 'function') {
return node.getBoundingClientRect();
}
}
};
// Mobile Safari re-uses touch objects, so we copy the properties we want and normalize the identifier
const normalizeTouches = touches => {
if (!touches) {
@@ -18,25 +27,25 @@ const normalizeTouches = touches => {
return Array.prototype.slice.call(touches).map(touch => {
const identifier = touch.identifier > 20 ? touch.identifier % 20 : touch.identifier;
let locationX, locationY;
const node = touch.target;
if (node) {
const isElement = node.nodeType === 1 /* Node.ELEMENT_NODE */;
if (isElement && typeof node.getBoundingClientRect === 'function') {
const rect = node.getBoundingClientRect();
locationX = touch.pageX - rect.left;
locationY = touch.pageY - rect.top;
}
}
let rect;
return {
_normalized: true,
clientX: touch.clientX,
clientY: touch.clientY,
force: touch.force,
locationX: locationX,
locationY: locationY,
get locationX() {
rect = rect || getRect(touch.target);
if (rect) {
return touch.pageX - rect.left;
}
},
get locationY() {
rect = rect || getRect(touch.target);
if (rect) {
return touch.pageY - rect.top;
}
},
identifier: identifier,
pageX: touch.pageX,
pageY: touch.pageY,
@@ -105,15 +114,27 @@ function normalizeTouchEvent(nativeEvent) {
}
function normalizeMouseEvent(nativeEvent) {
let rect;
const touches = [
{
_normalized: true,
clientX: nativeEvent.clientX,
clientY: nativeEvent.clientY,
force: nativeEvent.force,
locationX: nativeEvent.clientX,
locationY: nativeEvent.clientY,
identifier: 0,
get locationX() {
rect = rect || getRect(nativeEvent.target);
if (rect) {
return nativeEvent.pageX - rect.left;
}
},
get locationY() {
rect = rect || getRect(nativeEvent.target);
if (rect) {
return nativeEvent.pageY - rect.top;
}
},
pageX: nativeEvent.pageX,
pageY: nativeEvent.pageY,
screenX: nativeEvent.screenX,
@@ -143,8 +164,8 @@ function normalizeMouseEvent(nativeEvent) {
changedTouches: touches,
defaultPrevented: nativeEvent.defaultPrevented,
identifier: touches[0].identifier,
locationX: nativeEvent.offsetX,
locationY: nativeEvent.offsetY,
locationX: touches[0].locationX,
locationY: touches[0].locationY,
pageX: nativeEvent.pageX,
pageY: nativeEvent.pageY,
preventDefault,