├── .github └── workflows │ └── npmpublish.yml ├── .gitignore ├── .npmignore ├── README.md ├── example └── App.js ├── index.js ├── package-lock.json ├── package.json ├── react_logo.png ├── retina.png ├── screens ├── Simulator Screen Shot - iPhone X - 2017-12-05 at 03.11.16.png ├── iPad screen.jpg └── iPhone 8.jpg └── src ├── applyScale.js ├── device.android.js ├── device.ios.js └── react-native-responsive-image.js /.github/workflows/npmpublish.yml: -------------------------------------------------------------------------------- 1 | name: Node.js Package 2 | 3 | on: 4 | release: 5 | types: [published] 6 | 7 | jobs: 8 | build: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - uses: actions/checkout@v1 12 | - uses: actions/setup-node@v1 13 | with: 14 | node-version: 12 15 | registry-url: https://registry.npmjs.org/ 16 | - run: npm ci 17 | - run: npm publish --access public 18 | env: 19 | NODE_AUTH_TOKEN: ${{secrets.NPM_TOKEN}} 20 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | 3 | 4 | ### JetBrains template 5 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion 6 | 7 | *.iml 8 | 9 | ## Directory-based project format: 10 | .idea/ 11 | # if you remove the above rule, at least ignore the following: 12 | 13 | /ResponsiveImageExample/ 14 | /ResponsiveImageExample/node_modules 15 | 16 | 17 | # User-specific stuff: 18 | # .idea/workspace.xml 19 | # .idea/tasks.xml 20 | # .idea/dictionaries 21 | 22 | # Sensitive or high-churn files: 23 | # .idea/dataSources.ids 24 | # .idea/dataSources.xml 25 | # .idea/sqlDataSources.xml 26 | # .idea/dynamic.xml 27 | # .idea/uiDesigner.xml 28 | 29 | # Gradle: 30 | # .idea/gradle.xml 31 | # .idea/libraries 32 | 33 | # Mongo Explorer plugin: 34 | # .idea/mongoSettings.xml 35 | 36 | ## File-based project format: 37 | *.ipr 38 | *.iws 39 | 40 | ## Plugin-specific files: 41 | 42 | # IntelliJ 43 | /out/ 44 | 45 | # mpeltonen/sbt-idea plugin 46 | .idea_modules/ 47 | 48 | # JIRA plugin 49 | atlassian-ide-plugin.xml 50 | 51 | # Crashlytics plugin (for Android Studio and IntelliJ) 52 | com_crashlytics_export_strings.xml 53 | crashlytics.properties 54 | crashlytics-build.properties 55 | 56 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | 3 | 4 | ### JetBrains template 5 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion 6 | 7 | *.iml 8 | 9 | ## Directory-based project format: 10 | .idea/ 11 | # if you remove the above rule, at least ignore the following: 12 | 13 | /ResponsiveImageExample/ 14 | /ResponsiveImageExample/node_modules 15 | 16 | 17 | # User-specific stuff: 18 | # .idea/workspace.xml 19 | # .idea/tasks.xml 20 | # .idea/dictionaries 21 | 22 | # Sensitive or high-churn files: 23 | # .idea/dataSources.ids 24 | # .idea/dataSources.xml 25 | # .idea/sqlDataSources.xml 26 | # .idea/dynamic.xml 27 | # .idea/uiDesigner.xml 28 | 29 | # Gradle: 30 | # .idea/gradle.xml 31 | # .idea/libraries 32 | 33 | # Mongo Explorer plugin: 34 | # .idea/mongoSettings.xml 35 | 36 | ## File-based project format: 37 | *.ipr 38 | *.iws 39 | 40 | ## Plugin-specific files: 41 | 42 | # IntelliJ 43 | /out/ 44 | 45 | # mpeltonen/sbt-idea plugin 46 | .idea_modules/ 47 | 48 | # JIRA plugin 49 | atlassian-ide-plugin.xml 50 | 51 | # Crashlytics plugin (for Android Studio and IntelliJ) 52 | com_crashlytics_export_strings.xml 53 | crashlytics.properties 54 | crashlytics-build.properties 55 | 56 | react_logo.png 57 | retina.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # React Native Responsive Image 2 | 3 | [![David](https://david-dm.org/dharmoslap/react-native-responsive-image.svg)](https://david-dm.org/dharmoslap/react-native-responsive-image) 4 | [![npm](https://img.shields.io/npm/v/react-native-responsive-image.svg)](https://www.npmjs.com/package/react-native-responsive-image) 5 | [![GitHub commits](https://img.shields.io/github/commits-since/dharmoslap/react-native-responsive-image/2.1.0.svg?maxAge=2592000)]() 6 | [![npm](https://img.shields.io/npm/dt/react-native-responsive-image.svg?maxAge=2592000)](https://www.npmjs.com/package/react-native-responsive-image) 7 | 8 | ## Why? 9 | 10 | React Native's Image size is rendered with the same dimensions regardless of device screen size and screen resolution. That's bad. This component scales itself seemlesly on all iOS and Android devices. 11 | 12 | ## Installation 13 | 14 | `npm install react-native-responsive-image --save` 15 | 16 | ## Usage 17 | 18 | `` is expecting `initWidth` and `initHeight` props. 19 | 20 | These values are used to set image size on any device that has screen size iPhone Plus, or larger. 21 | Image is then scaled down for any smaller device. 22 | 23 | Optional prop `component` is used to pass down either an `Image` or `ImageBackground` imported react-native (defaults to `Image` if not provided) 24 | 25 | ## Example 26 | 27 | ```javascript 28 | import React, { Component } from "react"; 29 | import { AppRegistry, StyleSheet, View } from "react-native"; 30 | import ResponsiveImage from "react-native-responsive-image"; 31 | 32 | class App extends Component { 33 | render() { 34 | return ( 35 | 43 | 48 | 53 | 58 | 59 | ); 60 | } 61 | } 62 | 63 | AppRegistry.registerComponent("ResponsiveImageExample", () => App); 64 | ``` 65 | 66 | For `initWidth=138` it looks like this: 67 | 68 | | Device | Screen width | Scale | `` width | 69 | | -------------------- | ------------ | ----- | --------------- | 70 | | iPhone SE | 320 | 0.77 | 106 | 71 | | iPhone X | 375 | 0.902 | 117 | 72 | | iPhone8 Plus | 414 | 1 | 138 | 73 | | Nokia 5 | 360 | 0.87 | 120 | 74 | | iPad (or any tablet) | - | 1 | 138 | 75 | 76 | ## Just one image? 77 | 78 | It sounds like you could save some loading by delivering low resolution images to screens with lower resolution. The best way is to serve just one high-resolution (retina) well compressed image. It’s surprising how well they can be compressed, and the result looks the same. 79 | 80 | ![Retina Compression](https://raw.githubusercontent.com/Dharmoslap/react-native-responsive-image/master/retina.png) 81 | 82 | ## Example project 83 | 84 | ### Create project 85 | 86 | `expo init ResponsiveImageExample` 87 | 88 | - go with 'expo-template-blank' 89 | 90 | `cp ./example/App.js ./ResponsiveImageExample/App.js` 91 | 92 | `cp -R ./src ./ResponsiveImageExample` 93 | 94 | `cd ResponsiveImageExample` 95 | 96 | `yarn start` 97 | 98 | ## Development 99 | 100 | 1. Modify any files in ./src directory 101 | 102 | 2. Propagate changes by `cp -R ./src ./ResponsiveImageExample/src` 103 | -------------------------------------------------------------------------------- /example/App.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { StyleSheet, Text, View } from 'react-native'; 3 | import ResponsiveImage from './src/react-native-responsive-image'; 4 | 5 | export default class App extends React.Component { 6 | render() { 7 | return ( 8 | 9 | 10 | 11 | 12 | ); 13 | } 14 | } -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | import ResponsiveImage from './src/react-native-responsive-image'; 2 | 3 | export default ResponsiveImage -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-native-responsive-image", 3 | "version": "2.1.0", 4 | "lockfileVersion": 1 5 | } 6 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-native-responsive-image", 3 | "version": "2.3.1", 4 | "description": "Image component, that resizes itself appropriately on various screensizes.", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "git+https://github.com/Dharmoslap/react-native-responsive-images.git" 12 | }, 13 | "keywords": [ 14 | "React", 15 | "Native" 16 | ], 17 | "author": "Ladislav Maxa (https://github.com/Dharmoslap)", 18 | "license": "ISC", 19 | "bugs": { 20 | "url": "https://github.com/Dharmoslap/react-native-responsive-images/issues" 21 | }, 22 | "homepage": "https://github.com/Dharmoslap/react-native-responsive-images#readme", 23 | "installConfig": { 24 | "pnp": true 25 | } 26 | } -------------------------------------------------------------------------------- /react_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ladas-larry/react-native-responsive-image/bcaeeebbf38c825bd205ea25a4ca001a73ad84ff/react_logo.png -------------------------------------------------------------------------------- /retina.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ladas-larry/react-native-responsive-image/bcaeeebbf38c825bd205ea25a4ca001a73ad84ff/retina.png -------------------------------------------------------------------------------- /screens/Simulator Screen Shot - iPhone X - 2017-12-05 at 03.11.16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ladas-larry/react-native-responsive-image/bcaeeebbf38c825bd205ea25a4ca001a73ad84ff/screens/Simulator Screen Shot - iPhone X - 2017-12-05 at 03.11.16.png -------------------------------------------------------------------------------- /screens/iPad screen.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ladas-larry/react-native-responsive-image/bcaeeebbf38c825bd205ea25a4ca001a73ad84ff/screens/iPad screen.jpg -------------------------------------------------------------------------------- /screens/iPhone 8.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ladas-larry/react-native-responsive-image/bcaeeebbf38c825bd205ea25a4ca001a73ad84ff/screens/iPhone 8.jpg -------------------------------------------------------------------------------- /src/applyScale.js: -------------------------------------------------------------------------------- 1 | var Device = require('./device'); 2 | 3 | function applyScale(size) { 4 | return Math.ceil(size * Device.scale); 5 | } 6 | 7 | module.exports = applyScale; 8 | -------------------------------------------------------------------------------- /src/device.android.js: -------------------------------------------------------------------------------- 1 | var React = require('react'); 2 | var { Dimensions } = require('react-native'); 3 | 4 | var device = Dimensions.get('window'); 5 | var scale; 6 | 7 | if (device.width <= 414) { 8 | //Android smartphones 9 | scale = device.width / 414; 10 | } else{ 11 | //Android tablets 12 | scale = 1; 13 | } 14 | 15 | module.exports = { scale: scale }; 16 | -------------------------------------------------------------------------------- /src/device.ios.js: -------------------------------------------------------------------------------- 1 | var React = require('react'); 2 | var { Dimensions } = require('react-native'); 3 | 4 | var device = Dimensions.get('window'); 5 | var scale; 6 | 7 | switch (device.width) { 8 | //iPhone4/4S and iPhone5/5S 9 | case 320: 10 | scale = 0.77; 11 | break; 12 | //iPhone6/6S 13 | case 375: 14 | scale = 0.902; 15 | break; 16 | //iPhone6plus/6Splus 17 | case 414: 18 | scale = 1; 19 | break; 20 | //iPad 21 | default: 22 | scale = 1; 23 | } 24 | 25 | module.exports = { scale: scale }; 26 | -------------------------------------------------------------------------------- /src/react-native-responsive-image.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import { Image } from 'react-native'; 3 | import applyScale from './applyScale'; 4 | 5 | export default class ResponsiveImage extends Component { 6 | 7 | setNativeProps(nativeProps) { 8 | this._root.setNativeProps(nativeProps); 9 | } 10 | 11 | render() { 12 | var width = applyScale(this.props.initWidth); 13 | var height = applyScale(this.props.initHeight); 14 | const Component = this.props.component 15 | return ( 16 | this._root = component} 20 | resizeMode={this.props.resizeMode || 'cover'} 21 | onLoadStart={this.props.onLoadStart} 22 | onProgress={this.props.onProgress} 23 | onLoad={this.props.onLoad} 24 | onError={this.props.onError} 25 | onLoadEnd={this.props.onLoadEnd} 26 | defaultSource={this.props.defaultSource} 27 | borderRadius={this.props.borderRadius} 28 | > 29 | {this.props.children} 30 | 31 | ) 32 | } 33 | } 34 | 35 | ResponsiveImage.defaultProps = { 36 | component: Image 37 | } 38 | --------------------------------------------------------------------------------