الواجهة PixelRatio في React Native

من موسوعة حسوب

تسمح الواجهة PixelRatio بالوصول إلى كثافة البكسل (pixel density) ومقياس الخط الخاصّ بالجهاز.

جلب صورة مضبوطة الحجم

إذا كنّا نعمل على جهازٍ ذي كثافة بكسل عاليةٍ فإنّنا سنحصل على صورةٍ بدقّةٍ أعلى، ولقد وُجد تجريبيًّا أنّ ضرب حجم الصورة بمعدل البكسل (pixel ratio) هي أفضل قاعدةٍ لتحديد كثافة البكسل الضرورية لعرض صورةٍ ما.

var image = getImage({
  width: PixelRatio.getPixelSizeForLayoutSize(200),
  height: PixelRatio.getPixelSizeForLayoutSize(100)
});
<Image source={image} style={{ width: 200, height: 100 }} />;

التقاط شبكة البكسل

يمكن تحديد مواقع، وأبعاد العناصر بدقّةٍ كيفيّة على منصّة iOS، مثلًا 29.674825، إلّا أن الشاشة لها عددٌ محدّدٌ من البكسلات في النهاية، مثلًا 640x960 في جهاز iPhone 4، و750×1334 في جهاز iPhone 6، تحاول iOS الاتزام بالقيمة التي يريدها المستخدم قدْرَ الإمكان، وذلك بنشر بكسل أساسيٍّ واحدٍ إلى عدّة بكسلات لخداع العين، غير أنّ سلبية هذه الطّريقة تتمثّل في كون العنصر يبدو بشكلٍ ضبابيٍّ، وفي الواقع وُجد أنّ المطورين لا يرغبون بهذه الميّزة بل يقومون بتنفيذ عملية التقريب (rounding) هذه يدويًّا، لتجنّب الحصول على عناصر ضبابيّة تقرّب جميع البكسلات تلقائيًا على React Native.

عند تنفيذ عملية التّقريب هذه يجب الانتباه لكي لا نعمل على القيم المقرَّبة، وغير المقرًّبة في آنٍ واحدٍ، لأن ذلك سيؤدي إلى تراكم أخطاء التّقريب، فحصول خطأ تقريبٍ وحيد يُعدٍّ فادحًا، إذ سيؤدّي إلى اختفاء بكسل واحدٍ من الحوافّ، أو مضاعفته.

كل شيء مكتوب بلغة JavaScript ، وضمن محرك التخطيط (layout engine) على React Native يعمل بأرقام ضبطٍ كيفيّةٍ، وذلك عند تحديد موقع، وأبعاد العنصر الأصليّ الذي نقرّبه في المهمّة الرّئيسيّة (main thread) فقط، كما أنّ التقريب يتمّ متناسبًا مع الجذر أكثر من الأب (parent)، لتجنّب تراكم أخطاء التّقريب.

مثال

إليك المثال التالي (تجربة حية):

import React from "react";
import { Image, PixelRatio, ScrollView, StyleSheet, Text, TextInput, View } from "react-native";

const size = 50;
const cat = {
  uri: "https://reactnative.dev/docs/assets/p_cat1.png",
  width: size,
  height: size
};

const App = () => (
  <ScrollView style={styles.scrollContainer}>
    <View style={styles.container}>
      <Text>Current Pixel Ratio is:</Text>
      <Text style={styles.value}>{PixelRatio.get()}</Text>
    </View>
    <View style={styles.container}>
      <Text>Current Font Scale is:</Text>
      <Text style={styles.value}>{PixelRatio.getFontScale()}</Text>
    </View>
    <View style={styles.container}>
      <Text>On this device images with a layout width of</Text>
      <Text style={styles.value}>{size} px</Text>
      <Image source={cat} />
    </View>
    <View style={styles.container}>
      <Text>require images with a pixel width of</Text>
      <Text style={styles.value}>
        {PixelRatio.getPixelSizeForLayoutSize(size)} px
      </Text>
      <Image
        source={cat}
        style={{
          width: PixelRatio.getPixelSizeForLayoutSize(size),
          height: PixelRatio.getPixelSizeForLayoutSize(size)
        }}
      />
    </View>
  </ScrollView>
);

const styles = StyleSheet.create({
  scrollContainer: {
    flext: 1,
    marginTop: "2em",
    justifyContent: "center",
  },
  container: {
    justifyContent: "center",
    alignItems: "center"
  },
  value: {
    fontSize: 24,
    marginBottom: 12,
    marginTop: 4
  }
});

export default App;

التوابع

get()‎

static get()

يعيد كثافة البكسل الخاصّة بالجهاز، من أمثلة ذلك:

  • PixelRatio.get() === 1
  • PixelRatio.get() === 1.5
  • PixelRatio.get() === 2
    • لأجهزة iPhone SE, 6S, 7, 8
    • لأجهزة iPhone XR
    • لأجهزة iPhone 11
    • لأجهزة xhdpi Android
  • PixelRatio.get() === 3
    • لأجهزة iPhone 6S Plus, 7 Plus, 8 Plus
    • لأجهزة iPhone X, XS, XS Max
    • لأجهزة iPhone 11 Pro, 11 Pro Max
    • لأجهزة Pixel, Pixel 2
    • لأجهزة xxhdpi Android
  • PixelRatio.get() === 3.5
    • لأجهزة Nexus 6
    • لأجهزة Pixel XL, Pixel 2 XL
    • لأجهزة xxxhdpi Android

getFontScale()‎

static getFontScale(): number

يعيد معامل قياس حجوم الخط، وهو عبارة عن المعدَّل المستخدم لقياس حجم الخط المطلق، لذا يتوجب على العناصر التي تعتمد عليه بكثرة القيام بالحسابات باستخدام القيم التّالية:

  • على منصة Android نحصل على هذه القيمة من مجموعة تفضيلات المستخدم على المسار Settings > Display > Font size
  • على منصة iOS نحصل على هذه القيمة من مجموعة تفضيلات المستخدم على المسار Settings > Display & Brightness > Text Size، وأيضًا يمكن تحديثها على المسار Settings > Accessibilty > Display & Test Size > Larger Text.

ويعيد معدَّل البكسل للجهاز إذا لم يكن مقياس الخط محدّدًا.

getPixelSizeForLayoutSize()‎

static getPixelSizeForLayoutSize(layoutSize: number): number

يحوِّل حجم التخطيط (dp) إلى الحجم بالبكسل (px)، وذلك لضمان إعادة عددٍ صحيحٍ.

roundToNearestPixel()‎

static roundToNearestPixel(layoutSize: number): number

يقرّب حجم التّخطيط (dp) إلى أقرب حجم تخطيطٍ موافقٍ لعددٍ صحيحٍ من البكسلات، فمثلاً في الجهاز الذي يكون معدل البكسل (PixelRatio) فيه 3 يتمّ تقريب حجم التّخطيط 8.4 dp كما يلي: PixelRatio.roundToNearestPixel(8.4) = 8.33، والذي يوافق تمامًا (8.33 * 3) = 25 بكسل.

مصادر