react-native icon indicating copy to clipboard operation
react-native copied to clipboard

scaleX doesn't use same dp as width

Open Gregoirevda opened this issue 2 years ago • 3 comments

Description

This

<View style={{width: w}} />

doesn't always equal

<View style={{width: 1, transform: [{scaleX: w}, {translateX: w/2}]}} />

Width isn't always the same. (translateX is a side thing to mimic origin right)

From testing: When Pixel density is 2 on iPhone, iPad, Android tablet/phone: width === scaleX When Pixel density is 1.5, 1.8: width !== scaleX

Which means width is using density-independent pixels, but scaleX isn't?

I've managed to fix this with

// If pixel ratio is 1.5, it's 75% of pixel ratio 2 
// w * 0.75 
const ratioDiff = PixelRatio.get() / 2;
<View style={{width: 1, transform: [{scaleX: w * ratioDiff}, {translateX: w/2}]}} />

This was only validated on android devices with pixel ratio of 1.5 and 1.88. Will this work for 2+ pixel ratio's?

React Native Version

0.72.5

Output of npx react-native info

System:
  OS: macOS 13.5
  CPU: (12) arm64 Apple M2 Max
  Memory: 64.88 MB / 32.00 GB
  Shell:
    version: "5.9"
    path: /bin/zsh
Binaries:
  Node:
    version: 20.8.0
    path: ~/.nvm/versions/node/v20.8.0/bin/node
  Yarn:
    version: 1.22.19
    path: /usr/local/bin/yarn
  npm:
    version: 10.1.0
    path: ~/.nvm/versions/node/v20.8.0/bin/npm
  Watchman:
    version: 2023.10.02.00
    path: /opt/homebrew/bin/watchman
Managers:
  CocoaPods:
    version: 1.13.0
    path: /usr/local/bin/pod
SDKs:
  iOS SDK:
    Platforms:
      - DriverKit 23.0
      - iOS 17.0
      - macOS 14.0
      - tvOS 17.0
      - watchOS 10.0
  Android SDK: Not Found
IDEs:
  Android Studio: 2022.3 AI-223.8836.35.2231.10811636
  Xcode:
    version: 15.0/15A240d
    path: /usr/bin/xcodebuild
Languages:
  Java:
    version: 11.0.20.1
    path: /usr/bin/javac
  Ruby:
    version: 3.2.2
    path: /Users/gregoirevda/.rbenv/shims/ruby
npmPackages:
  "@react-native-community/cli": Not Found
  react: Not Found
  react-native: Not Found
  react-native-macos: Not Found
npmGlobalPackages:
  "*react-native*": Not Found
Android:
  hermesEnabled: Not found
  newArchEnabled: Not found
iOS:
  hermesEnabled: Not found
  newArchEnabled: Not found

Steps to reproduce

Compare both output on devices with pixel density !== 2

<View style={{width: 100, height: 100, backgroundColor: 'red'}} />
<View style={{height: 100, width: 1, backgroundColor: 'green', transform: [{scaleX: 100}, {translateX: 50}]}} />

Snack, screenshot, or link to a repository

https://snack.expo.dev/@gregoirevda/pixel-density-scalex

Gregoirevda avatar Nov 10 '23 08:11 Gregoirevda

:warning: Newer Version of React Native is Available!
:information_source: You are on a supported minor version, but it looks like there's a newer patch available - 0.72.6. Please upgrade to the highest patch for your minor or latest and verify if the issue persists (alternatively, create a new project and repro the issue in it). If it does not repro, please let us know so we can close out this issue. This helps us ensure we are looking at issues that still exist in the most recent releases.

github-actions[bot] avatar Nov 10 '23 08:11 github-actions[bot]

After testing on ldpi, mdpi, hdpi, xhdpi and xxhdpi I realised width !== scaleX only when pixel density is a decimal (could only find decimal dpi on android)

I've changed

const ratioDiff = PixelRatio.get() / 2;

to

const pixelRatio = PixelRatio.get();
const pixelRatioRounded = Math.round(pixelRatio);
const ratioDiff = pixelRatio / pixelRatioRounded;

When running this


const width = 200;

 return <View style={{marginLeft: 100, marginTop: 100}}>
    <View style={{width: width, height: 100, backgroundColor: 'red'}} />
    
    <View style={{height: 100, width: 1, backgroundColor: 'green', transform: [
      {translateX: width/2},
      { scaleX: width }
      ]}} />
      
      <View style={{height: 100, width: 1, backgroundColor: 'pink', transform: [
      {translateX: width/2},
      { scaleX: width * ratioDiff }
      ]}} />
    <Text>{PixelRatio.get()}</Text>
  </View>

Screenshot 2023-11-10 at 11 58 44 - fix XHDPI

Screenshot 2023-11-10 at 11 57 59 - fix XXHDPI Screenshot 2023-11-10 at 11 56 37 - fix HDPI Screenshot 2023-11-10 at 11 55 07 - fix XHDPI Screenshot 2023-11-10 at 11 54 17 - fix MDPI

You notice that the 3th option (pink) always equals the width (red)

Gregoirevda avatar Nov 10 '23 11:11 Gregoirevda

@Gregoirevda this worked perfectly, thank you!

ZacMossHK avatar Apr 23 '24 13:04 ZacMossHK