Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Incorrect measurements for SVG elements #1231

Closed
3luyka opened this issue Dec 30, 2019 · 13 comments
Closed

Incorrect measurements for SVG elements #1231

3luyka opened this issue Dec 30, 2019 · 13 comments

Comments

@3luyka
Copy link

3luyka commented Dec 30, 2019

Bug

UIManager.measureInWindow returns incorrect values for (Circle) element on Android platform. (iOS is ok).

Environment info

System:
    OS: macOS 10.15.2
    CPU: (4) x64 Intel(R) Core(TM) i5-5257U CPU @ 2.70GHz
    Memory: 61.05 MB / 8.00 GB
    Shell: 5.7.1 - /bin/zsh
  Binaries:
    Node: 10.16.0 - /usr/local/bin/node
    Yarn: 1.21.1 - /usr/local/bin/yarn
    npm: 6.13.4 - /usr/local/bin/npm
    Watchman: 4.9.0 - /usr/local/bin/watchman
  SDKs:
    iOS SDK:
      Platforms: iOS 13.2, DriverKit 19.0, macOS 10.15, tvOS 13.2, watchOS 6.1
    Android SDK:
      API Levels: 23, 25, 26, 27, 28
      Build Tools: 23.0.1, 25.0.0, 26.0.2, 26.0.3, 27.0.3, 28.0.2, 28.0.3
      System Images: android-23 | Intel x86 Atom_64, android-23 | Google APIs Intel x86 Atom_64, android-24 | Google APIs Intel x86 Atom_64, android-26 | Google APIs Intel x86 Atom_64, android-28 | Google APIs Intel x86 Atom, android-28 | Google Play Intel x86 Atom_64
  IDEs:
    Android Studio: 3.4 AI-183.6156.11.34.5692245
    Xcode: 11.3/11C29 - /usr/bin/xcodebuild
  npmPackages:
    react: 16.9.0 => 16.9.0 
    react-native: ^0.61.5 => 0.61.5

Library version: 9.13.6

@msand
Copy link
Collaborator

msand commented Dec 30, 2019

Repro?

@3luyka
Copy link
Author

3luyka commented Dec 30, 2019

@3luyka
Copy link
Author

3luyka commented Jan 2, 2020

Hey @msand, did you had any chance to take a look?

@msand
Copy link
Collaborator

msand commented Jan 2, 2020

Not yet no

@msand
Copy link
Collaborator

msand commented Jan 3, 2020

Seems the issue is that the bounds aren't calculated in the measure phase, but only in the draw phase. You can use the onLayout nativeEvent layout property instead, it's called as soon as the bounds are known:

import React from 'react';
import {Svg, Circle} from 'react-native-svg';
export default () => (
  <Svg height="100%">
    <Circle
      x={50}
      y={70}
      r={65}
      onLayout={e => {
        console.log(e.nativeEvent.layout);
      }}
    />
  </Svg>
);

@3luyka
Copy link
Author

3luyka commented Jan 3, 2020

@msand the reason why I'm using "measureInWindow" is that I need to get absolute (not relative) positions of the element in "window".

@3luyka
Copy link
Author

3luyka commented Jan 3, 2020

That happens only on Android and only with SVG elements.

@msand
Copy link
Collaborator

msand commented Jan 3, 2020

It seems to me like it should be possible to achieve, by measuring the svg root / containing view, and using the layout values from the primitive you're interested in:

import React, {useRef, useCallback} from 'react';
import {View, findNodeHandle, UIManager} from 'react-native';
import {Svg, Circle} from 'react-native-svg';

const measureInWindow = handler =>
  new Promise(resolve => {
    UIManager.measureInWindow(handler, (x, y, width, height) => {
      resolve({x, y, width, height});
    });
  });

export default () => {
  const svg = useRef(null);

  const handleLayout = useCallback(async e => {
    console.log('circle', e.nativeEvent.layout);
    const handler = findNodeHandle(svg.current);
    if (handler === null) {
      return;
    }
    const result = await measureInWindow(handler);
    console.warn('measure', result);
  }, []);

  return (
    <View
      style={{flex: 1, justifyContent: 'center'}}
      onLayout={e => {
        console.log('view', e.nativeEvent.layout);
      }}>
      <Svg
        ref={svg}
        height="50%"
        onLayout={e => {
          console.log('svg', e.nativeEvent.layout);
        }}>
        <Circle x={50} y={70} r={65} onLayout={handleLayout} />
      </Svg>
    </View>
  );
};

@msand
Copy link
Collaborator

msand commented Jan 3, 2020

I think I have a fix now, can you try with the latest commit from the develop branch?

@msand
Copy link
Collaborator

msand commented Jan 3, 2020

I'm getting this output using android and this code now:

 LOG  Running "Awe" with {"rootTag":11}
 LOG  circle {"height": 0, "width": 256, "x": 0, "y": 0}
 LOG  svg {"height": 177.3333282470703, "width": 256, "x": 0, "y": 88.66666412353516}
 LOG  view {"height": 354.6666564941406, "width": 256, "x": 0, "y": 0}
 LOG  circle {"height": 130, "width": 130, "x": -15, "y": 5}
 WARN  measure {"height": 130, "width": 130, "x": -15, "y": 93.66666412353516}
 WARN  measure {"height": 130, "width": 130, "x": -15, "y": 93.66666412353516}

And ios:

 LOG  Running "Awe" with {"rootTag":51,"initialProps":{}}
 LOG  view {"height": 896, "width": 414, "x": 0, "y": 0}
 LOG  svg {"height": 448, "width": 414, "x": 0, "y": 224}
 LOG  circle {"height": 0, "width": 414, "x": 0, "y": 0}
 WARN  measure {"height": 130, "width": 130, "x": -15, "y": 229}
 LOG  circle {"height": 130, "width": 130, "x": -15, "y": 5}
 WARN  measure {"height": 130, "width": 130, "x": -15, "y": 229}
import React, {useRef, useCallback} from 'react';
import {View, findNodeHandle, UIManager} from 'react-native';
import {Svg, Circle} from 'react-native-svg';

export default () => {
  const svg = useRef(null);

  const handleLayout = useCallback(async e => {
    console.log('circle', e.nativeEvent.layout);
    const handle = findNodeHandle(svg.current);
    if (handle === null) {
      return;
    }
    UIManager.measureInWindow(handle, (x, y, width, height) => {
      console.warn('measure', {x, y, width, height});
    });
  }, []);

  return (
    <View
      style={{flex: 1, justifyContent: 'center'}}
      onLayout={e => {
        console.log('view', e.nativeEvent.layout);
      }}>
      <Svg
        height="50%"
        onLayout={e => {
          console.log('svg', e.nativeEvent.layout);
        }}>
        <Circle x={50} y={70} r={65} onLayout={handleLayout} ref={svg} />
      </Svg>
    </View>
  );
};

@msand msand closed this as completed in 3bf07f8 Jan 4, 2020
msand pushed a commit that referenced this issue Jan 4, 2020
# [9.14.0](v9.13.6...v9.14.0) (2020-01-04)

### Bug Fixes

* **android:** correct values for measureInWindow, fixes [#1231](#1231) ([3bf07f8](3bf07f8))
* **android:** elements not touchable if below opacity limit ([ebc7220](ebc7220)), closes [#1200](#1200)
* **android:** fix radial gradient vertical center offset scaling ([d5bddd5](d5bddd5))
* **ios:** crash when offset is outside range [#1201](#1201) ([a2ef51f](a2ef51f))
* **web:** fix gesture responder dimensions measurement ([36c20b3](36c20b3))
* extraction of clip rule, fixes [#1233](#1233) ([f93bdde](f93bdde))
* Text color doesn't work with inlineSize [#1225](#1225) ([027b8c1](027b8c1))

### Features

* **android:** support using other native views in e.g. masks ([15b4ac6](15b4ac6))
* **ios:** support using other native views in e.g. masks ([518a3b1](518a3b1))
* **web:** Implement support for event, touch & responder handlers ([60561ec](60561ec))
* **web:** Optimize: only set responders if press handler exists ([23250ad](23250ad))
* Implement display="none" ([3e3ad13](3e3ad13)), closes [#1220](#1220)
@msand
Copy link
Collaborator

msand commented Jan 4, 2020

🎉 This issue has been resolved in version 9.14.0 🎉

The release is available on:

Your semantic-release bot 📦🚀

@msand msand added the released label Jan 4, 2020
@msand
Copy link
Collaborator

msand commented Jan 4, 2020

Released in v10 (breaking change wasn't registered correctly by semantic-release and forgot to do dry-run first)

@3luyka
Copy link
Author

3luyka commented Jan 16, 2020

@msand Hey! Sorry for the late response.
Looks like everything is working as expected. Thanks a lot!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants