圖片

2019-08-14 14:22 更新

一個 react 的組件用以顯示不同類型的圖片,包括網(wǎng)絡(luò)圖片,靜態(tài)資源,臨時的本地圖片,還有本地磁盤的圖片,比如手機照片。

舉例:

renderImages: function() {  return (
    <View>
      <Image
        style={styles.icon}
        source={require('image!myIcon')}
      />
      <Image
        style={styles.logo}
        source={{uri: 'http://facebook.github.io/react/img/logo_og.png'}}
      />
    </View>
  );
},

支撐工具

onLayout 函數(shù)
在進行裝載和布局改變的時候使用{nativeEvent: {layout: {x, y, width, height}}}調(diào)用。

resizeMode 枚舉 ('cover', 'contain', 'stretch')
當(dāng)幀與原始圖像尺寸不匹配時用于確定如何調(diào)整圖像的大小。

source {uri: string},編號 uri 是一個代表圖片資源標識符的字符串,它可以是 http 地址、 本地文件路徑或靜態(tài)圖像資源的名稱 (它被包含在 require('image!name') 函數(shù)中) 。

style 樣式
Flexbox......
Transforms...
resizeMode Object.keys(ImageResizeMode)
backgroundColor 字符串
borderColor 字符串
borderWidth 數(shù)字
borderRadius 數(shù)字
overflow 枚舉('visible', 'hidden')
tintColor 字符串
opacity 數(shù)字

testID 字符串 一個在 UI 自動測試腳本中使用此元素的唯一標識符。

ios accessibilityLabel 字符串

在用戶與圖像交互時,該文本會由屏幕閱讀器讀取。

ios accessible 布爾值
當(dāng)為 true 的時候,指示圖像是可訪問的元素。

ios capInsets {top: number, left: number, bottom: number, right: number}
當(dāng)圖像的大小被重新調(diào)整時,由 capInsets 指定的角落的大小將保持在一個固定的值,但中心內(nèi)容和圖像的邊界將被拉伸。這用于創(chuàng)建可調(diào)整大小的圓形按鈕、 陰影和其他可調(diào)整大小的資源。更多關(guān)于蘋果的文檔請點擊此處。

ios defaultSource {uri: string}
在下載最終圖像并且網(wǎng)絡(luò)斷開的時候用來顯示的靜態(tài)圖像。

ios onError 函數(shù)
在加載錯誤的時候使用 {nativeEvent: {error}} 進行調(diào)用。

ios onLoadEndr 函數(shù)
當(dāng)完全加載成功時進行調(diào)用。

ios onLoadEnd 函數(shù)
不管加載成功還是失敗都會調(diào)用。

ios onLoadStart 函數(shù)
加載成功的時候調(diào)用。

ios onProgress 函數(shù)
在下載進程中使用 {nativeEvent: {loaded, total}} 進行調(diào)用。

描述

靜態(tài)資源

在項目的進程中,添加并且移除和處理那些在應(yīng)用程序不是經(jīng)常使用的圖片是很常見的情況。為了處理這種情況,我們需要找到一個方法來靜態(tài)地定位那些被用在應(yīng)用程序里的圖片。因此,我們使用了一個標記器。唯一允許的指向 bundle 里的圖片的方法就是在源文件中遍歷地搜索 require('image!name-of-the-asset') 。

// GOOD<Image source={require('image!my-icon')} />// BADvar icon = this.props.active ? 'my-icon-active' : 'my-icon-inactive';<Image source={require('image!' + icon)} />// GOOD
var icon = this.props.active ? require('image!my-icon-active') : require('image!my-icon-inactive');<Image source={icon} />

當(dāng)主要的代碼執(zhí)行到這里,你就可以做一些有趣的事情,比如自動將那些用于應(yīng)用程序的 assets 打包。注意,這些代碼不是強制實施的,但不代表將來也不會。

使用 Images.xcassets 將靜態(tài)資源添加到你的 iOS 應(yīng)用程序中

NOTE: 生成應(yīng)用程序所需的新資源

無論在什么時候,您想把新的資源添加到 Images.xcassets 中,您都需要在使用它之前通過 Xcode 來重新構(gòu)建您的應(yīng)用程序 — — 僅在模擬器內(nèi)重新加載它是不夠的。

這一進程正在被改進,不久就會提供更好的工作流程。

將靜態(tài)資源添加到您的 Android 應(yīng)用程序中

將您的圖像作為位圖畫板添加到 android 項目中(<yourapp>/android/app/src/main/res)。 為了給您的 assets 文件提供不同的分辨率,使用 配置限定符進行檢查。 通常情況下,您將想要把您的 assets 文件放在下列目錄 (如果它們不存在,那么在 res 下創(chuàng)建它們):

  • drawable-mdpi (1x)

  • drawable-hdpi (1.5x)

  • drawable-xhdpi (2x)

  • drawable-xxhdpi (3x)

如果您的 asset 文件丟失了一種分辨率,那么 Android 將采取下一個最好的分辨率并且為您調(diào)整它的大小。

NOTE: 生成應(yīng)用程序所需的新資源

無論在什么時候您把新的資源添加到您的畫板中您都需要在使用它之前通過運行 react-native run-android 重新構(gòu)建您的應(yīng)用程序 - 僅重新加載 JS 是不夠的。

這一進程正在被改進,不久就會提供更好的工作流程。

網(wǎng)絡(luò)資源

在您進行編譯的時候,許多您的應(yīng)用程序中需要展示的圖片都不能使用,或者你會想要通過加載一些動態(tài)圖片來保持二進制大小在較低的狀態(tài)。不像靜態(tài)資源那樣,您將需要手動指定圖像的尺寸。

// GOOD<Image source={{uri: 'https://facebook.github.io/react/img/logo_og.png'}}
       style={{width: 400, height: 400}} />// BAD<Image source={{uri: 'https://facebook.github.io/react/img/logo_og.png'}} />

本地文件系統(tǒng)資源

請在 CameraRoll 中查看使用 Images.xcassets 之外的本地資源示例 。

最好的相片冊圖片

iOS 的相片冊可以讓你將同一張圖片保存為不同的尺寸,對于選擇那張接近你想要尺寸的圖片來說,這很重要。你不會想用一張 3264x2448 分辨率的圖片作為資源來顯示一個 200x200 的縮略圖。如果確實有符合你要求的尺寸, React Native 會自動選擇它,否則它會使用第一張比特定尺寸大 50% 的圖片來避免重新定義尺寸時帶來的模糊失真。這些工作 React Native 自動幫你完成了,所以你不必再自己編寫乏味和容易出錯的代碼。

為什么不自動調(diào)整所有事物?

在瀏覽器中 如果你不給一個圖像規(guī)定大小,那么瀏覽器會呈現(xiàn)一個 0x0 的元素、 隨后下載圖像,然后再以正確的尺寸呈現(xiàn)圖像。這種行為最大的問題是,您的 UI 會在正在加載的圖像四周跳動,這會造成一個非常糟糕的用戶體驗。

在 React Native 中故意不實施該行為。它的目的是讓開發(fā)人員可以提前知道遠程圖像的尺寸 (或圖形比例),我們認為這樣做的話可以實現(xiàn)更好的用戶體驗。通過使用 require('image!x') 語法從應(yīng)用程序包中加載的靜態(tài)圖片可以自動的調(diào)整大小,因為它們的尺寸在安裝時立即可用。

例如,上述使用 'require('image!logo')' 屏幕截圖的結(jié)果:

{"__packager_asset":true,"isStatic":true,"path":"/Users/react/HelloWorld/iOS/Images.xcassets/react.imageset/logo.png","uri":"logo","width":591,"height":573}

Source 是一個對象類型

在 React Native 中,一個有趣的決定是 src 特性將會被命名為 source,并且不作為一個字符串而是一個 uri 特性的對象類型。

<Image source={{uri: 'something.jpg'}} />

站在底層來看,這樣做的原因是它允許將元數(shù)據(jù)依附到這個對象中。舉個例子,你正在使用 require('image!icon'),我們將添加 isStatic 作為一個 flag 來標識本地文件(不要依賴這例子,將來這可能會改變?。?。這在將來同時也會成為可能,比如我們可能會支持子畫面,并用它來取代輸出 {uri: ...},我們可以輸出 {uri: ..., crop: {left: 10, top: 50, width: 20, height: 40}} 同時支持在所有已經(jīng)存在的網(wǎng)站中透明地顯示子畫面。

在用戶角度上,這會讓你用有用的特性比如圖片的幾何尺寸來注釋對象類型,從而計算出將要顯示出來的尺寸。盡情地使用這種數(shù)據(jù)類型來儲存你的圖片吧。

背景圖片疊加

一個對于 web 開發(fā)者們很常見的需求是 background-image。這種情況下,創(chuàng)建一個簡單的 <Image> 組件然后將它作為子 layer 添加到你想要添加的 layer 上面。

return (  <Image source={...}>
    <Text>Inside</Text>
  </Image>);

非主線程加載

圖片的解析會花費很多的時間。這是導(dǎo)致網(wǎng)頁的幀數(shù)下降的其中一個重要的原因,因為解析工作會被執(zhí)行在主線程中。在 React Native 中,圖片的解析會在不同的線程中執(zhí)行。在實際操作中,你已經(jīng)處理好這種情況,當(dāng)圖片還沒有下載完成,因此需要將 placeholder 顯示出來,這不用你寫任何代碼。

舉例

'use strict';

var React = require('react-native');
var {
  Image,
  StyleSheet,
  Text,
  View,
  ActivityIndicatorIOS
} = React;

var ImageCapInsetsExample = require('./ImageCapInsetsExample');

var NetworkImageExample = React.createClass({
  watchID: (null: ?number),

  getInitialState: function() {    return {
      error: false,
      loading: false,
      progress: 0
    };
  },
  render: function() {
    var loader = this.state.loading ?
      <View style={styles.progress}>
        <Text>{this.state.progress}%</Text>
        <ActivityIndicatorIOS style={{marginLeft:5}}/>
      </View> : null;    return this.state.error ?
      <Text>{this.state.error}</Text> :
      <Image
        source={this.props.source}
        style={[styles.base, {overflow: 'visible'}]}
        onLoadStart={(e) => this.setState({loading: true})}
        onError={(e) => this.setState({error: e.nativeEvent.error, loading: false})}
        onProgress={(e) => this.setState({progress: Math.round(100 * e.nativeEvent.loaded / e.nativeEvent.total)})}
        onLoad={() => this.setState({loading: false, error: false})}>
        {loader}
      </Image>;
  }
});

exports.displayName = (undefined: ?string);
exports.framework = 'React';
exports.title = '<Image>';
exports.description = 'Base component for displaying different types of images.';

exports.examples = [
  {
    title: 'Plain Network Image',
    description: 'If the `source` prop `uri` property is prefixed with ' +    '"http", then it will be downloaded from the network.',
    render: function() {      return (
        <Image
          source={{uri: 'http://facebook.github.io/react/img/logo_og.png'}}
          style={styles.base}
        />
      );
    },
  },
  {
    title: 'Plain Static Image',
    description: 'Static assets should be required by prefixing with `image!` ' +      'and are located in the app bundle.',
    render: function() {      return (
        <View style={styles.horizontal}>
          <Image source={require('image!uie_thumb_normal')} style={styles.icon} />
          <Image source={require('image!uie_thumb_selected')} style={styles.icon} />
          <Image source={require('image!uie_comment_normal')} style={styles.icon} />
          <Image source={require('image!uie_comment_highlighted')} style={styles.icon} />
        </View>
      );
    },
  },
  {
    title: 'Error Handler',
    render: function() {      return (
        <NetworkImageExample source={{uri: 'http://TYPO_ERROR_facebook.github.io/react/img/logo_og.png'}} />
      );
    },
    platform: 'ios',
  },
  {
    title: 'Image Download Progress',
    render: function() {      return (
        <NetworkImageExample source={{uri: 'http://facebook.github.io/origami/public/images/blog-hero.jpg?r=1'}}/>
      );
    },
    platform: 'ios',
  },
  {
    title: 'Border Color',
    render: function() {      return (
        <View style={styles.horizontal}>
          <Image
            source={smallImage}
            style={[
              styles.base,
              styles.background,
              {borderWidth: 3, borderColor: '#f099f0'}
            ]}
          />
        </View>
      );
    },
    platform: 'ios',
  },
  {
    title: 'Border Width',
    render: function() {      return (
        <View style={styles.horizontal}>
          <Image
            source={smallImage}
            style={[
              styles.base,
              styles.background,
              {borderWidth: 5, borderColor: '#f099f0'}
            ]}
          />
        </View>
      );
    },
    platform: 'ios',
  },
  {
    title: 'Border Radius',
    render: function() {      return (
        <View style={styles.horizontal}>
          <Image
            style={[styles.base, {borderRadius: 5}]}
            source={fullImage}
          />
          <Image
            style={[styles.base, styles.leftMargin, {borderRadius: 19}]}
            source={fullImage}
          />
        </View>
      );
    },
  },
  {
    title: 'Background Color',
    render: function() {      return (
        <View style={styles.horizontal}>
          <Image source={smallImage} style={styles.base} />
          <Image
            style={[
              styles.base,
              styles.leftMargin,
              {backgroundColor: 'rgba(0, 0, 100, 0.25)'}
            ]}
            source={smallImage}
          />
          <Image
            style={[styles.base, styles.leftMargin, {backgroundColor: 'red'}]}
            source={smallImage}
          />
          <Image
            style={[styles.base, styles.leftMargin, {backgroundColor: 'black'}]}
            source={smallImage}
          />
        </View>
      );
    },
  },
  {
    title: 'Opacity',
    render: function() {      return (
        <View style={styles.horizontal}>
          <Image
            style={[styles.base, {opacity: 1}]}
            source={fullImage}
          />
          <Image
            style={[styles.base, styles.leftMargin, {opacity: 0.8}]}
            source={fullImage}
          />
          <Image
            style={[styles.base, styles.leftMargin, {opacity: 0.6}]}
            source={fullImage}
          />
          <Image
            style={[styles.base, styles.leftMargin, {opacity: 0.4}]}
            source={fullImage}
          />
          <Image
            style={[styles.base, styles.leftMargin, {opacity: 0.2}]}
            source={fullImage}
          />
          <Image
            style={[styles.base, styles.leftMargin, {opacity: 0}]}
            source={fullImage}
          />
        </View>
      );
    },
  },
  {
    title: 'Nesting',
    render: function() {      return (
        <Image
          style={{width: 60, height: 60, backgroundColor: 'transparent'}}
          source={fullImage}>
          <Text style={styles.nestedText}>
            React
          </Text>
        </Image>
      );
    },
  },
  {
    title: 'Tint Color',
    description: 'The `tintColor` style prop changes all the non-alpha ' +      'pixels to the tint color.',
    render: function() {      return (
        <View>
          <View style={styles.horizontal}>
            <Image
              source={require('image!uie_thumb_normal')}
              style={[styles.icon, {borderRadius: 5, tintColor: '#5ac8fa' }]}
            />
            <Image
              source={require('image!uie_thumb_normal')}
              style={[styles.icon, styles.leftMargin, {borderRadius: 5, tintColor: '#4cd964' }]}
            />
            <Image
              source={require('image!uie_thumb_normal')}
              style={[styles.icon, styles.leftMargin, {borderRadius: 5, tintColor: '#ff2d55' }]}
            />
            <Image
              source={require('image!uie_thumb_normal')}
              style={[styles.icon, styles.leftMargin, {borderRadius: 5, tintColor: '#8e8e93' }]}
            />
          </View>
          <Text style={styles.sectionText}>
            It also works with downloaded images:
          </Text>
          <View style={styles.horizontal}>
            <Image
              source={smallImage}
              style={[styles.base, {borderRadius: 5, tintColor: '#5ac8fa' }]}
            />
            <Image
              source={smallImage}
              style={[styles.base, styles.leftMargin, {borderRadius: 5, tintColor: '#4cd964' }]}
            />
            <Image
              source={smallImage}
              style={[styles.base, styles.leftMargin, {borderRadius: 5, tintColor: '#ff2d55' }]}
            />
            <Image
              source={smallImage}
              style={[styles.base, styles.leftMargin, {borderRadius: 5, tintColor: '#8e8e93' }]}
            />
          </View>
        </View>
      );
    },
  },
  {
    title: 'Resize Mode',
    description: 'The `resizeMode` style prop controls how the image is ' +      'rendered within the frame.',
    render: function() {      return (
        <View style={styles.horizontal}>
          <View>
            <Text style={[styles.resizeModeText]}>
              Contain
            </Text>
            <Image
              style={styles.resizeMode}
              resizeMode={Image.resizeMode.contain}
              source={fullImage}
            />
          </View>
          <View style={styles.leftMargin}>
            <Text style={[styles.resizeModeText]}>
              Cover
            </Text>
            <Image
              style={styles.resizeMode}
              resizeMode={Image.resizeMode.cover}
              source={fullImage}
            />
          </View>
          <View style={styles.leftMargin}>
            <Text style={[styles.resizeModeText]}>
              Stretch
            </Text>
            <Image
              style={styles.resizeMode}
              resizeMode={Image.resizeMode.stretch}
              source={fullImage}
            />
          </View>
        </View>
      );
    },
  },
  {
    title: 'Animated GIF',
    render: function() {      return (
        <Image
          style={styles.gif}
          source={{uri: 'http://38.media.tumblr.com/9e9bd08c6e2d10561dd1fb4197df4c4e/tumblr_mfqekpMktw1rn90umo1_500.gif'}}
        />
      );
    },
    platform: 'ios',
  },
  {
    title: 'Cap Insets',
    description:      'When the image is resized, the corners of the size specified ' +      'by capInsets will stay a fixed size, but the center content and ' +      'borders of the image will be stretched. This is useful for creating ' +      'resizable rounded buttons, shadows, and other resizable assets.',
    render: function() {      return <ImageCapInsetsExample />;
    },
    platform: 'ios',
  },
];

var fullImage = {uri: 'http://facebook.github.io/react/img/logo_og.png'};
var smallImage = {uri: 'http://facebook.github.io/react/img/logo_small_2x.png'};

var styles = StyleSheet.create({
  base: {
    width: 38,
    height: 38,
  },
  progress: {
    flex: 1,
    alignItems: 'center',
    flexDirection: 'row',
    width: 100
  },
  leftMargin: {
    marginLeft: 10,
  },
  background: {
    backgroundColor: '#222222'
  },
  sectionText: {
    marginVertical: 6,
  },
  nestedText: {
    marginLeft: 12,
    marginTop: 20,
    backgroundColor: 'transparent',
    color: 'white'
  },
  resizeMode: {
    width: 90,
    height: 60,
    borderWidth: 0.5,
    borderColor: 'black'
  },
  resizeModeText: {
    fontSize: 11,
    marginBottom: 3,
  },
  icon: {
    width: 15,
    height: 15,
  },
  horizontal: {
    flexDirection: 'row',
  },
  gif: {
    flex: 1,
    height: 200,
  },
});


以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號