图片
静态图片资源
¥Static Image Resources
React Native 提供了一种统一的方式来管理 Android 和 iOS 应用中的图片和其他媒体资源。要将静态图片添加到你的应用中,请将其放置在源代码树中的某个位置并像这样引用它:
¥React Native provides a unified way of managing images and other media assets in your Android and iOS apps. To add a static image to your app, place it somewhere in your source code tree and reference it like this:
<Image source={require('./my-icon.png')} />
图片名称的解析方式与 JS 模块的解析方式相同。在上面的示例中,打包程序将在需要它的组件所在的同一文件夹中查找 my-icon.png
。
¥The image name is resolved the same way JS modules are resolved. In the example above, the bundler will look for my-icon.png
in the same folder as the component that requires it.
你可以使用 @2x
和 @3x
后缀来提供不同屏幕密度的图片。如果你有以下文件结构:
¥You can use the @2x
and @3x
suffixes to provide images for different screen densities. If you have the following file structure:
.
├── button.js
└── img
├── check.png
├── check@2x.png
└── check@3x.png
...button.js
代码包含:
¥...and button.js
code contains:
<Image source={require('./img/check.png')} />
...打包器将打包并提供与设备屏幕密度相对应的图片。例如,check@2x.png
将用于 iPhone 7,而 check@3x.png
将用于 iPhone 7 Plus 或 Nexus 5。如果没有与屏幕密度匹配的图片,将选择最接近的最佳选项。
¥...the bundler will bundle and serve the image corresponding to device's screen density. For example, check@2x.png
, will be used on an iPhone 7, whilecheck@3x.png
will be used on an iPhone 7 Plus or a Nexus 5. If there is no image matching the screen density, the closest best option will be selected.
在 Windows 上,如果将新图片添加到项目中,你可能需要重新启动打包程序。
¥On Windows, you might need to restart the bundler if you add new images to your project.
以下是你可以获得的一些好处:
¥Here are some benefits that you get:
-
Android 和 iOS 系统相同。
¥Same system on Android and iOS.
-
图片与 JavaScript 代码位于同一文件夹中。组件是独立的。
¥Images live in the same folder as your JavaScript code. Components are self-contained.
-
没有全局名称空间,即你不必担心名称冲突。
¥No global namespace, i.e. you don't have to worry about name collisions.
-
只有实际使用的图片才会打包到你的应用中。
¥Only the images that are actually used will be packaged into your app.
-
添加和更改图片不需要重新编译应用,你可以像平常一样刷新模拟器。
¥Adding and changing images doesn't require app recompilation, you can refresh the simulator as you normally do.
-
打包器知道图片尺寸,无需在代码中重复它。
¥The bundler knows the image dimensions, no need to duplicate it in the code.
-
图片可以通过 npm 包分发。
¥Images can be distributed via npm packages.
为了使其工作,必须静态地知道 require
中的图片名称。
¥In order for this to work, the image name in require
has to be known statically.
// GOOD
<Image source={require('./my-icon.png')} />;
// BAD
const icon = this.props.active
? 'my-icon-active'
: 'my-icon-inactive';
<Image source={require('./' + icon + '.png')} />;
// GOOD
const icon = this.props.active
? require('./my-icon-active.png')
: require('./my-icon-inactive.png');
<Image source={icon} />;
请注意,这种方式所需的图片源包括图片的大小(宽度、高度)信息。如果你需要动态缩放图片(即通过 flex),你可能需要在样式属性上手动设置 {width: undefined, height: undefined}
。
¥Note that image sources required this way include size (width, height) info for the Image. If you need to scale the image dynamically (i.e. via flex), you may need to manually set {width: undefined, height: undefined}
on the style attribute.
静态非图片资源
¥Static Non-Image Resources
上述 require
语法也可用于在项目中静态包含音频、视频或文档文件。支持最常见的文件类型,包括 .mp3
、.wav
、.mp4
、.mov
、.html
和 .pdf
。完整列表请参见 打包器默认值。
¥The require
syntax described above can be used to statically include audio, video or document files in your project as well. Most common file types are supported including .mp3
, .wav
, .mp4
, .mov
, .html
and .pdf
. See bundler defaults for the full list.
你可以通过在 Metro 配置 中添加 assetExts
解析器选项 来添加对其他类型的支持。
¥You can add support for other types by adding an assetExts
resolver option in your Metro configuration.
需要注意的是,视频必须使用绝对定位而不是 flexGrow
,因为当前不为非图片资源传递大小信息。对于直接链接到 Xcode 或 Android 的 Assets 文件夹的视频,不会出现此限制。
¥A caveat is that videos must use absolute positioning instead of flexGrow
, since size info is not currently passed for non-image assets. This limitation doesn't occur for videos that are linked directly into Xcode or the Assets folder for Android.
来自混合应用资源的图片
¥Images From Hybrid App's Resources
如果你正在构建混合应用(React Native 中的一些 UI,平台代码中的一些 UI),你仍然可以使用已打包到应用中的图片。
¥If you are building a hybrid app (some UIs in React Native, some UIs in platform code) you can still use images that are already bundled into the app.
对于通过 Xcode 资源目录或 Android 可绘制文件夹中包含的图片,请使用不带扩展名的图片名称:
¥For images included via Xcode asset catalogs or in the Android drawable folder, use the image name without the extension:
<Image
source={{uri: 'app_icon'}}
style={{width: 40, height: 40}}
/>
对于 Android asset 文件夹中的图片,使用 asset:/
方案:
¥For images in the Android assets folder, use the asset:/
scheme:
<Image
source={{uri: 'asset:/app_icon.png'}}
style={{width: 40, height: 40}}
/>
这些方法不提供安全检查。你需要保证这些图片在应用中可用。你还必须手动指定图片尺寸。
¥These approaches provide no safety checks. It's up to you to guarantee that those images are available in the application. Also you have to specify image dimensions manually.
网络图片
¥Network Images
你将在应用中显示的许多图片在编译时将不可用,或者你将需要动态加载一些图片以减小二进制大小。与静态资源不同,你需要手动指定图片的尺寸。强烈建议你也使用 https 以满足 iOS 上的 应用传输安全 要求。
¥Many of the images you will display in your app will not be available at compile time, or you will want to load some dynamically to keep the binary size down. Unlike with static resources, you will need to manually specify the dimensions of your image. It's highly recommended that you use https as well in order to satisfy App Transport Security requirements on iOS.
// GOOD
<Image source={{uri: 'https://react.nodejs.cn/logo-og.png'}}
style={{width: 400, height: 400}} />
// BAD
<Image source={{uri: 'https://react.nodejs.cn/logo-og.png'}} />
图片网络请求
¥Network Requests for Images
如果你想在图片请求中设置 HTTP-Verb、Headers 或 Body 等内容,你可以通过在源对象上定义这些属性来实现:
¥If you would like to set such things as the HTTP-Verb, Headers or a Body along with the image request, you may do this by defining these properties on the source object:
<Image
source={{
uri: 'https://react.nodejs.cn/logo-og.png',
method: 'POST',
headers: {
Pragma: 'no-cache',
},
body: 'Your Body goes here',
}}
style={{width: 400, height: 400}}
/>
URI 数据图片
¥URI Data Images
有时,你可能会从 REST API 调用获取编码图片数据。你可以使用 'data:'
URI 方案来使用这些图片。与网络资源相同,你需要手动指定图片的尺寸。
¥Sometimes, you might be getting encoded image data from a REST API call. You can use the 'data:'
URI scheme to use these images. Same as for network resources, you will need to manually specify the dimensions of your image.
仅建议对非常小的动态图片(例如数据库列表中的图标)使用此方法。
¥This is recommended for very small and dynamic images only, like icons in a list from a DB.
// include at least width and height!
<Image
style={{
width: 51,
height: 51,
resizeMode: 'contain',
}}
source={{
uri: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADMAAAAzCAYAAAA6oTAqAAAAEXRFWHRTb2Z0d2FyZQBwbmdjcnVzaEB1SfMAAABQSURBVGje7dSxCQBACARB+2/ab8BEeQNhFi6WSYzYLYudDQYGBgYGBgYGBgYGBgYGBgZmcvDqYGBgmhivGQYGBgYGBgYGBgYGBgYGBgbmQw+P/eMrC5UTVAAAAABJRU5ErkJggg==',
}}
/>
缓存控制(仅限 iOS)
¥Cache Control (iOS Only)
在某些情况下,你可能只想显示本地缓存中已存在的图片,即低分辨率占位符,直到有更高分辨率可用为止。在其他情况下,你不关心图片是否过时,并且愿意显示过时的图片以节省带宽。cache
源属性使你可以控制网络层与缓存的交互方式。
¥In some cases you might only want to display an image if it is already in the local cache, i.e. a low resolution placeholder until a higher resolution is available. In other cases you do not care if the image is outdated and are willing to display an outdated image to save bandwidth. The cache
source property gives you control over how the network layer interacts with the cache.
-
default
:使用原生平台默认策略。¥
default
: Use the native platforms default strategy. -
reload
:URL 的数据将从原始源加载。不应使用现有的缓存数据来满足 URL 加载请求。¥
reload
: The data for the URL will be loaded from the originating source. No existing cache data should be used to satisfy a URL load request. -
force-cache
:现有的缓存数据将用于满足请求,无论其年龄或到期日期如何。如果缓存中没有对应请求的现有数据,则从原始源加载数据。¥
force-cache
: The existing cached data will be used to satisfy the request, regardless of its age or expiration date. If there is no existing data in the cache corresponding the request, the data is loaded from the originating source. -
only-if-cached
:现有的缓存数据将用于满足请求,无论其年龄或到期日期如何。如果缓存中不存在与 URL 加载请求对应的数据,则不会尝试从原始源加载数据,并且加载被认为失败。¥
only-if-cached
: The existing cache data will be used to satisfy a request, regardless of its age or expiration date. If there is no existing data in the cache corresponding to a URL load request, no attempt is made to load the data from the originating source, and the load is considered to have failed.
<Image
source={{
uri: 'https://react.nodejs.cn/logo-og.png',
cache: 'only-if-cached',
}}
style={{width: 400, height: 400}}
/>
本地文件系统映像
¥Local Filesystem Images
有关使用 Images.xcassets
之外的本地资源的示例,请参阅 CameraRoll。
¥See CameraRoll for an example of using local resources that are outside of Images.xcassets
.
最佳相机胶卷图片
¥Best Camera Roll Image
iOS 会在相机胶卷中为同一张图片保存多种尺寸,出于性能原因,选择尽可能接近的尺寸非常重要。在显示 200x200 缩略图时,你不会希望使用全质量 3264x2448 图片作为源。如果存在完全匹配,React Native 会选择它,否则它将使用第一个至少大 50% 的匹配,以避免在从接近尺寸调整大小时出现模糊。所有这些都是默认完成的,因此你不必担心编写繁琐(且容易出错)的代码来自己完成。
¥iOS saves multiple sizes for the same image in your Camera Roll, it is very important to pick the one that's as close as possible for performance reasons. You wouldn't want to use the full quality 3264x2448 image as source when displaying a 200x200 thumbnail. If there's an exact match, React Native will pick it, otherwise it's going to use the first one that's at least 50% bigger in order to avoid blur when resizing from a close size. All of this is done by default so you don't have to worry about writing the tedious (and error prone) code to do it yourself.
为什么不自动调整所有内容的大小?
¥Why Not Automatically Size Everything?
在浏览器中,如果你没有给图片指定大小,浏览器将渲染 0x0 元素,下载图片,然后根据正确的大小渲染图片。这种行为的一个大问题是,当图片加载时,你的 UI 会四处跳跃,这会导致非常糟糕的用户体验。这称为 累积布局偏移。
¥In the browser if you don't give a size to an image, the browser is going to render a 0x0 element, download the image, and then render the image based with the correct size. The big issue with this behavior is that your UI is going to jump all around as images load, this makes for a very bad user experience. This is called Cumulative Layout Shift.
在 React Native 中,这种行为是故意不实现的。开发者需要提前了解远程图片的尺寸(或长宽比),但我们相信这会带来更好的用户体验。通过 require('./my-icon.png')
语法从应用包加载的静态图片可以自动调整大小,因为它们的尺寸在安装时立即可用。
¥In React Native this behavior is intentionally not implemented. It is more work for the developer to know the dimensions (or aspect ratio) of the remote image in advance, but we believe that it leads to a better user experience. Static images loaded from the app bundle via the require('./my-icon.png')
syntax can be automatically sized because their dimensions are available immediately at the time of mounting.
例如,require('./my-icon.png')
的结果可能是:
¥For example, the result of require('./my-icon.png')
might be:
{"__packager_asset":true,"uri":"my-icon.png","width":591,"height":573}
源作为对象
¥Source as an object
在 React Native 中,一个有趣的决定是 src
属性被命名为 source
,并且不采用字符串,而是采用具有 uri
属性的对象。
¥In React Native, one interesting decision is that the src
attribute is named source
and doesn't take a string but an object with a uri
attribute.
<Image source={{uri: 'something.jpg'}} />
在基础设施方面,原因是它允许我们将元数据附加到该对象。例如,如果你使用的是 require('./my-icon.png')
,那么我们会添加有关其实际位置和大小的信息(不要依赖这一事实,它将来可能会发生变化!)。这也是面向未来的,例如我们可能希望在某个时候支持精灵,而不是输出 {uri: ...}
,我们可以输出 {uri: ..., crop: {left: 10, top: 50, width: 20, height: 40}}
并在所有现有调用站点上透明地支持精灵。
¥On the infrastructure side, the reason is that it allows us to attach metadata to this object. For example if you are using require('./my-icon.png')
, then we add information about its actual location and size (don't rely on this fact, it might change in the future!). This is also future proofing, for example we may want to support sprites at some point, instead of outputting {uri: ...}
, we can output {uri: ..., crop: {left: 10, top: 50, width: 20, height: 40}}
and transparently support spriting on all the existing call sites.
在用户方面,这使你可以使用有用的属性(例如图片的尺寸)来注释对象,以便计算它将显示的大小。请随意使用它作为你的数据结构来存储有关图片的更多信息。
¥On the user side, this lets you annotate the object with useful attributes such as the dimension of the image in order to compute the size it's going to be displayed in. Feel free to use it as your data structure to store more information about your image.
通过嵌套的背景图片
¥Background Image via Nesting
熟悉 Web 的开发者的常见功能请求是 background-image
。为了处理这个用例,你可以使用 <ImageBackground>
组件,它具有与 <Image>
相同的 props,并添加你想要在其之上分层的任何子组件。
¥A common feature request from developers familiar with the web is background-image
. To handle this use case, you can use the <ImageBackground>
component, which has the same props as <Image>
, and add whatever children to it you would like to layer on top of it.
在某些情况下你可能不想使用 <ImageBackground>
,因为实现是基本的。请参阅 <ImageBackground>
的 documentation 了解更多信息,并在需要时创建你自己的自定义组件。
¥You might not want to use <ImageBackground>
in some cases, since the implementation is basic. Refer to <ImageBackground>
's documentation for more insight, and create your own custom component when needed.
return (
<ImageBackground source={...} style={{width: '100%', height: '100%'}}>
<Text>Inside</Text>
</ImageBackground>
);
请注意,你必须指定一些宽度和高度样式属性。
¥Note that you must specify some width and height style attributes.
iOS 边框半径样式
¥iOS Border Radius Styles
请注意,iOS 的图片组件可能会忽略以下特定于角的边框半径样式属性:
¥Please note that the following corner specific, border radius style properties might be ignored by iOS's image component:
-
borderTopLeftRadius
-
borderTopRightRadius
-
borderBottomLeftRadius
-
borderBottomRightRadius
线程外解码
¥Off-thread Decoding
图片解码可能花费超过一帧的时间。这是网络上丢帧的主要来源之一,因为解码是在主线程中完成的。在 React Native 中,图片解码是在不同的线程中完成的。实际上,你已经需要处理尚未下载图片的情况,因此在解码时再显示几帧占位符不需要更改任何代码。
¥Image decoding can take more than a frame-worth of time. This is one of the major sources of frame drops on the web because decoding is done in the main thread. In React Native, image decoding is done in a different thread. In practice, you already need to handle the case when the image is not downloaded yet, so displaying the placeholder for a few more frames while it is decoding does not require any code change.
配置 iOS 图片缓存限制
¥Configuring iOS Image Cache Limits
在 iOS 上,我们公开了一个 API 来覆盖 React Native 的默认图片缓存限制。这应该从你的原生 AppDelegate 代码中调用(例如在 didFinishLaunchingWithOptions
中)。
¥On iOS, we expose an API to override React Native's default image cache limits. This should be called from within your native AppDelegate code (e.g. within didFinishLaunchingWithOptions
).
RCTSetImageCacheLimits(4*1024*1024, 200*1024*1024);
参数:
¥Parameters:
名称 | 类型 | 必需的 | 描述 |
---|---|---|---|
imageSizeLimit | number | 是的 | 图片缓存大小限制。 |
totalCostLimit | number | 是的 | 总缓存成本限制。 |
在上面的代码示例中,图片大小限制设置为 4 MB,总成本限制设置为 200 MB。
¥In the above code example the image size limit is set to 4 MB and the total cost limit is set to 200 MB.