Image图片加载
在RN中,用Image标签来渲染图片,图片的来源有两种:本地静态图片和网络图片(或Base64格式数据,如手机相册),针对不同的方式有不同的数据源写法,它们之间的区别如下:
// 渲染本地静态图片
<Image source={require('../../assets/images/watch.jpg')} />
// 渲染网络图片
<Image source={{uri:'http://www.helloui.net/assets/watch.jpg'}} />
渲染图片时,必须给图片设置一个带有width和height的样式,即宽和高,否则图片将显示不出来。下面是Image的属性和方法:
属性 | 描述 |
---|---|
style | 显示样式,若要图片正常显示,必须设置width和height值 |
source | 图片数据源,数据源的方式有两种:本地静态图片和网络图片,它们之间写法会有区别 |
blurRadius | 整型,为图片添加一个模糊滤镜(类似于高斯模糊),值越大图片越模糊,默认值为0 |
onLayout | 当元素加载完成或者布局改变的时候调用,获取图片的信息坐标和宽高。 回调参数为:{nativeEvent: {layout: {x, y, width, height}}}. |
onLoadStart | 开始加载时触发该函数 |
onLoadEnd | 加载结束后,不论成功还是失败,都触发该函数 |
onLoad | 加载成功时触发该函数 |
onError | 加载失败时触发该函数 |
resizeMode | 决定当组件尺寸和图片尺寸不成比例的时候如何调整图片的大小 值为枚举类型:enum('cover', 'contain', 'stretch', 'repeat', 'center') |
defaultSource | 在读取图片时默认显示的图片,只能是本地静态图片。在android上调试模式将不会生效 |
这里要想要说明一下resizeMode属性,这个属性在有些场景上使用会很关键:
- cover 在保持图片宽高比的前提下缩放图片,直到宽度和高度都大于等于容器视图的尺寸。这样图片完全覆盖甚至超出容器,容器中不留任何空白。
- contain 在保持图片宽高比的前提下缩放图片,直到宽度和高度都小于等于容器视图的尺寸。这样图片完全被包裹在容器中,容器中可能留有空白。
- stretch 拉伸图片且不维持宽高比,直到宽高都刚好填满容器。
- repeat 重复平铺图片直到填满容器。图片会维持原始尺寸,但是当尺寸超过容器时会在保持宽高比的前提下缩放到能被容器包裹。
- center 居中不拉伸。
方法 | 描述 |
---|---|
getSize(uri, success, [failure]); | 该方法用于获取网络图片的尺寸,而且会缓存图片至本地 |
resolveAssetSource | 该方法用于获取本地静态图片的尺寸 |
prefetch | 预加载图片一个远程图片,返回一个Promise对象 |
贴上代码:
import React, { Component } from 'react';
import { View, Image, StyleSheet, Button } from 'react-native';
class ImageComp extends Component {
// Image.getSize(uri, success, [failure]);
// 该方法用于获取网络图片的尺寸,而且会缓存图片至本地
_getSize = () => {
Image.getSize('http://www.helloui.net/assets/watch.jpg',(width,height)=>{
console.log(width);
console.log(height);
},(error)=>{
console.log(error);
});
};
// 该方法用于获取本地静态图片的尺寸
_resolveAssetSource = () => {
const localImageInfo = Image.resolveAssetSource(require('../../assets/images/watch.jpg'));
console.log(localImageInfo);
}
// 预加载图片一个远程图片,返回一个Promise对象
_prefetch = () => {
Image.prefetch('http://www.helloui.net/assets/watch1.jpg').then((response)=>{
console.log('预加载成功:',response);
},(error)=>{
console.log('预加载失败:',error);
});
}
render(){
return(
<View style={styles.viewStyle}>
<Image
style={{width:200, height:200}}
// source={require('../../assets/images/watch.jpg')} // 图片源数据(远程 URL 地址或本地数据)
source={{uri:'http://www.helloui.net/assets/watch.jpg'}}
blurRadius={0} // 为图片添加一个模糊滤镜,值越大图片越模糊,默认值为0
onLayout={(e)=>{console.log(e.nativeEvent);}} // 当元素加载完成或者布局改变的时候调用,获取图片的信息坐标和宽高。参数为:{nativeEvent: {layout: {x, y, width, height}}}.
onLoadStart={()=>{}} // 开始加载时触发该函数
onLoadEnd={()=>{}} // 加载结束后,不论成功还是失败,都触发该函数
onLoad={()=>{}} // 加载成功时触发该函数
onError={()=>{}} // 加载失败时触发该函数
resizeMode='contain' // 决定当组件尺寸和图片尺寸不成比例的时候如何调整图片的大小,值为枚举类型:enum('cover', 'contain', 'stretch', 'repeat', 'center')
defaultSource={require('../../assets/images/watch-loading.jpg')} // 在读取图片时默认显示的图片,只能是本地静态图片。在android上调试模式将不会生效
/>
<Button
title='获取网络图片尺寸并预加载'
onPress={this._getSize}
/>
<Button
title='获取本地图片尺寸'
onPress={this._resolveAssetSource}
/>
<Button
title='仅预加载'
onPress={this._prefetch}
/>
</View>
);
}
}
const styles = StyleSheet.create({
viewStyle: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#E4E4E4'
}
});
export default ImageComp;
效果:
还有一个标签和Image的属性一样,那就是ImageBackground标签,它本身也是一个容器,同时会把图片作为背景图自动填充满整个容器。如
<ImageBackground
source={require('../../assets/images/watch.jpg')}
style={{width: '100%', height: '100%'}}>
<View />
</ImageBackground
ImageEditor图片剪切
做过H5网页动画或游戏开发的都知道,需要的图片资源是非常多的,往往为了优化加载,会把多张图片合并成一张图片,这样只需要加载一次就足够了。那么这种情况,就必须对这样合成的图片进行剪切。在RN中,使用ImageEditor来剪切图片,目前仅支持网络图片的剪切。ImageEditor是一个静态对象,其剪切功能可直接调用:
static cropImage(uri, cropData, success, failure)
贴上代码:
import React from 'react';
import { View, Text, Image, StyleSheet, ImageEditor } from 'react-native';
const cropData = {
offset: {x: 10, y: 30},//从原图裁剪的起始坐标
size: {width: 250, height: 250},//裁剪的宽高
displaySize: {width: 250, height: 250},//裁剪后生成图片的大小
resizeMode: 'contain', //缩放图像时使用的调整大小模式
//cover模式只求在显示比例不失真的情况下填充整个显示区域。可以对图片进行放大或者缩小,超出显示区域的部分不显示, 也就是说,图片可能部分会显示不了。
//contain模式是要求显示整张图片, 可以对它进行等比缩小, 图片会显示完整,可能会露出Image控件的底色。
//stretch模式不考虑保持图片原来的宽,高比.填充整个Image定义的显示区域,这种模式显示的图片可能会畸形和失真。
};
// 只能用于远程图片
class ImageEditorAPI extends React.Component {
state = {
imgURI: 'https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1551718648408&di=e5c78eb153cac2a1ec7a077f0df5190c&imgtype=0&src=http%3A%2F%2Fimgsrc.baidu.com%2Fimgad%2Fpic%2Fitem%2F279759ee3d6d55fb567c04ef67224f4a21a4dd45.jpg',
cropImgURI: null
}
componentDidMount(){
ImageEditor.cropImage(this.state.imgURI, cropData, this.cropSuccess, this.cropFail);
}
cropSuccess = (corpImgURI) => {
console.log('图片剪辑成功');
this.setState({cropImgURI:corpImgURI});
}
cropFail = () => {
console.log('图片剪辑失败');
}
render(){
return(
<View style={styles.viewStyle}>
<Text>剪辑前:</Text>
<Image
source={{ uri: this.state.imgURI }}
style={styles.imgStyle}
/>
<Text>剪辑后:</Text>
<Image
source={{ uri: this.state.cropImgURI }}
style={styles.imgStyle}
resizeMode="contain"
/>
</View>
);
}
}
const styles = StyleSheet.create({
viewStyle: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#E4E4E4'
},
imgStyle: {
width: 200,
height: 200
}
});
export default ImageEditorAPI;
效果: