[fix] use getBoundingClientRect to measure layout

Fix #1037
Fix #1151
This commit is contained in:
Nicolas Gallagher
2019-01-01 12:21:29 -08:00
parent e696e637bd
commit 21c3931b69
3 changed files with 35 additions and 25 deletions
+8 -12
View File
@@ -7,28 +7,24 @@
* @noflow * @noflow
*/ */
import getBoundingClientRect from '../../modules/getBoundingClientRect';
import setValueForStyles from '../../vendor/react-dom/setValueForStyles'; import setValueForStyles from '../../vendor/react-dom/setValueForStyles';
const getRect = node => { const getRect = node => {
const height = node.offsetHeight; // Unlike the DOM's getBoundingClientRect, React Native layout measurements
// for "height" and "width" ignore scale transforms.
// https://developer.mozilla.org/en-US/docs/Web/API/CSS_Object_Model/Determining_the_dimensions_of_elements
const { x, y, top, left } = getBoundingClientRect(node);
const width = node.offsetWidth; const width = node.offsetWidth;
let left = node.offsetLeft; const height = node.offsetHeight;
let top = node.offsetTop; return { x, y, width, height, top, left };
node = node.offsetParent;
while (node && node.nodeType === 1 /* Node.ELEMENT_NODE */) {
left += node.offsetLeft - node.scrollLeft;
top += node.offsetTop - node.scrollTop;
node = node.offsetParent;
}
return { height, left, top, width };
}; };
const measureLayout = (node, relativeToNativeNode, callback) => { const measureLayout = (node, relativeToNativeNode, callback) => {
const relativeNode = relativeToNativeNode || (node && node.parentNode); const relativeNode = relativeToNativeNode || (node && node.parentNode);
if (node && relativeNode) { if (node && relativeNode) {
setTimeout(() => { setTimeout(() => {
const relativeRect = getRect(relativeNode); const relativeRect = getBoundingClientRect(relativeNode);
const { height, left, top, width } = getRect(node); const { height, left, top, width } = getRect(node);
const x = left - relativeRect.left; const x = left - relativeRect.left;
const y = top - relativeRect.top; const y = top - relativeRect.top;
@@ -0,0 +1,21 @@
/**
* Copyright (c) 2015-present, Nicolas Gallagher.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow strict
*/
/* global HTMLElement */
const getBoundingClientRect = (node: HTMLElement) => {
if (node) {
const isElement = node.nodeType === 1; /* Node.ELEMENT_NODE */
if (isElement && typeof node.getBoundingClientRect === 'function') {
return node.getBoundingClientRect();
}
}
};
export default getBoundingClientRect;
@@ -7,18 +7,11 @@
* @flow * @flow
*/ */
import getBoundingClientRect from '../getBoundingClientRect';
const emptyArray = []; const emptyArray = [];
const emptyFunction = () => {}; 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 // Mobile Safari re-uses touch objects, so we copy the properties we want and normalize the identifier
const normalizeTouches = touches => { const normalizeTouches = touches => {
if (!touches) { if (!touches) {
@@ -35,13 +28,13 @@ const normalizeTouches = touches => {
clientY: touch.clientY, clientY: touch.clientY,
force: touch.force, force: touch.force,
get locationX() { get locationX() {
rect = rect || getRect(touch.target); rect = rect || getBoundingClientRect(touch.target);
if (rect) { if (rect) {
return touch.pageX - rect.left; return touch.pageX - rect.left;
} }
}, },
get locationY() { get locationY() {
rect = rect || getRect(touch.target); rect = rect || getBoundingClientRect(touch.target);
if (rect) { if (rect) {
return touch.pageY - rect.top; return touch.pageY - rect.top;
} }
@@ -121,13 +114,13 @@ function normalizeMouseEvent(nativeEvent) {
force: nativeEvent.force, force: nativeEvent.force,
identifier: 0, identifier: 0,
get locationX() { get locationX() {
rect = rect || getRect(nativeEvent.target); rect = rect || getBoundingClientRect(nativeEvent.target);
if (rect) { if (rect) {
return nativeEvent.pageX - rect.left; return nativeEvent.pageX - rect.left;
} }
}, },
get locationY() { get locationY() {
rect = rect || getRect(nativeEvent.target); rect = rect || getBoundingClientRect(nativeEvent.target);
if (rect) { if (rect) {
return nativeEvent.pageY - rect.top; return nativeEvent.pageY - rect.top;
} }