mirror of
https://github.com/zoriya/react-native-web.git
synced 2026-06-02 18:41:17 +00:00
@@ -75,6 +75,23 @@ Example usage:
|
|||||||
<Image resizeMode={Image.resizeMode.contain} />
|
<Image resizeMode={Image.resizeMode.contain} />
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Methods
|
||||||
|
|
||||||
|
static **getSize**(uri: string, success: (width, height) => {}, failure: function)
|
||||||
|
|
||||||
|
Retrieve the width and height (in pixels) of an image prior to displaying it.
|
||||||
|
This method can fail if the image cannot be found, or fails to download.
|
||||||
|
|
||||||
|
(In order to retrieve the image dimensions, the image may first need to be
|
||||||
|
loaded or downloaded, after which it will be cached. This means that in
|
||||||
|
principle you could use this method to preload images, however it is not
|
||||||
|
optimized for that purpose, and may in future be implemented in a way that does
|
||||||
|
not fully load/download the image data.)
|
||||||
|
|
||||||
|
static **prefetch**(url: string): Promise
|
||||||
|
|
||||||
|
Prefetches a remote image for later use by downloading it.
|
||||||
|
|
||||||
## Examples
|
## Examples
|
||||||
|
|
||||||
```js
|
```js
|
||||||
|
|||||||
@@ -28,10 +28,9 @@ import { ActivityIndicator, Image, Platform, StyleSheet, Text, View } from 'reac
|
|||||||
var base64Icon = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEsAAABLCAQAAACSR7JhAAADtUlEQVR4Ac3YA2Bj6QLH0XPT1Fzbtm29tW3btm3bfLZtv7e2ObZnms7d8Uw098tuetPzrxv8wiISrtVudrG2JXQZ4VOv+qUfmqCGGl1mqLhoA52oZlb0mrjsnhKpgeUNEs91Z0pd1kvihA3ULGVHiQO2narKSHKkEMulm9VgUyE60s1aWoMQUbpZOWE+kaqs4eLEjdIlZTcFZB0ndc1+lhB1lZrIuk5P2aib1NBpZaL+JaOGIt0ls47SKzLC7CqrlGF6RZ09HGoNy1lYl2aRSWL5GuzqWU1KafRdoRp0iOQEiDzgZPnG6DbldcomadViflnl/cL93tOoVbsOLVM2jylvdWjXolWX1hmfZbGR/wjypDjFLSZIRov09BgYmtUqPQPlQrPapecLgTIy0jMgPKtTeob2zWtrGH3xvjUkPCtNg/tm1rjwrMa+mdUkPd3hWbH0jArPGiU9ufCsNNWFZ40wpwn+62/66R2RUtoso1OB34tnLOcy7YB1fUdc9e0q3yru8PGM773vXsuZ5YIZX+5xmHwHGVvlrGPN6ZSiP1smOsMMde40wKv2VmwPPVXNut4sVpUreZiLBHi0qln/VQeI/LTMYXpsJtFiclUN+5HVZazim+Ky+7sAvxWnvjXrJFneVtLWLyPJu9K3cXLWeOlbMTlrIelbMDlrLenrjEQOtIF+fuI9xRp9ZBFp6+b6WT8RrxEpdK64BuvHgDk+vUy+b5hYk6zfyfs051gRoNO1usU12WWRWL73/MMEy9pMi9qIrR4ZpV16Rrvduxazmy1FSvuFXRkqTnE7m2kdb5U8xGjLw/spRr1uTov4uOgQE+0N/DvFrG/Jt7i/FzwxbA9kDanhf2w+t4V97G8lrT7wc08aA2QNUkuTfW/KimT01wdlfK4yEw030VfT0RtZbzjeMprNq8m8tnSTASrTLti64oBNdpmMQm0eEwvfPwRbUBywG5TzjPCsdwk3IeAXjQblLCoXnDVeoAz6SfJNk5TTzytCNZk/POtTSV40NwOFWzw86wNJRpubpXsn60NJFlHeqlYRbslqZm2jnEZ3qcSKgm0kTli3zZVS7y/iivZTweYXJ26Y+RTbV1zh3hYkgyFGSTKPfRVbRqWWVReaxYeSLarYv1Qqsmh1s95S7G+eEWK0f3jYKTbV6bOwepjfhtafsvUsqrQvrGC8YhmnO9cSCk3yuY984F1vesdHYhWJ5FvASlacshUsajFt2mUM9pqzvKGcyNJW0arTKN1GGGzQlH0tXwLDgQTurS8eIQAAAABJRU5ErkJggg==';
|
var base64Icon = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEsAAABLCAQAAACSR7JhAAADtUlEQVR4Ac3YA2Bj6QLH0XPT1Fzbtm29tW3btm3bfLZtv7e2ObZnms7d8Uw098tuetPzrxv8wiISrtVudrG2JXQZ4VOv+qUfmqCGGl1mqLhoA52oZlb0mrjsnhKpgeUNEs91Z0pd1kvihA3ULGVHiQO2narKSHKkEMulm9VgUyE60s1aWoMQUbpZOWE+kaqs4eLEjdIlZTcFZB0ndc1+lhB1lZrIuk5P2aib1NBpZaL+JaOGIt0ls47SKzLC7CqrlGF6RZ09HGoNy1lYl2aRSWL5GuzqWU1KafRdoRp0iOQEiDzgZPnG6DbldcomadViflnl/cL93tOoVbsOLVM2jylvdWjXolWX1hmfZbGR/wjypDjFLSZIRov09BgYmtUqPQPlQrPapecLgTIy0jMgPKtTeob2zWtrGH3xvjUkPCtNg/tm1rjwrMa+mdUkPd3hWbH0jArPGiU9ufCsNNWFZ40wpwn+62/66R2RUtoso1OB34tnLOcy7YB1fUdc9e0q3yru8PGM773vXsuZ5YIZX+5xmHwHGVvlrGPN6ZSiP1smOsMMde40wKv2VmwPPVXNut4sVpUreZiLBHi0qln/VQeI/LTMYXpsJtFiclUN+5HVZazim+Ky+7sAvxWnvjXrJFneVtLWLyPJu9K3cXLWeOlbMTlrIelbMDlrLenrjEQOtIF+fuI9xRp9ZBFp6+b6WT8RrxEpdK64BuvHgDk+vUy+b5hYk6zfyfs051gRoNO1usU12WWRWL73/MMEy9pMi9qIrR4ZpV16Rrvduxazmy1FSvuFXRkqTnE7m2kdb5U8xGjLw/spRr1uTov4uOgQE+0N/DvFrG/Jt7i/FzwxbA9kDanhf2w+t4V97G8lrT7wc08aA2QNUkuTfW/KimT01wdlfK4yEw030VfT0RtZbzjeMprNq8m8tnSTASrTLti64oBNdpmMQm0eEwvfPwRbUBywG5TzjPCsdwk3IeAXjQblLCoXnDVeoAz6SfJNk5TTzytCNZk/POtTSV40NwOFWzw86wNJRpubpXsn60NJFlHeqlYRbslqZm2jnEZ3qcSKgm0kTli3zZVS7y/iivZTweYXJ26Y+RTbV1zh3hYkgyFGSTKPfRVbRqWWVReaxYeSLarYv1Qqsmh1s95S7G+eEWK0f3jYKTbV6bOwepjfhtafsvUsqrQvrGC8YhmnO9cSCk3yuY984F1vesdHYhWJ5FvASlacshUsajFt2mUM9pqzvKGcyNJW0arTKN1GGGzQlH0tXwLDgQTurS8eIQAAAABJRU5ErkJggg==';
|
||||||
|
|
||||||
//var ImageCapInsetsExample = require('./ImageCapInsetsExample');
|
//var ImageCapInsetsExample = require('./ImageCapInsetsExample');
|
||||||
//const IMAGE_PREFETCH_URL = 'http://facebook.github.io/origami/public/images/blog-hero.jpg?r=1&t=' + Date.now();
|
const IMAGE_PREFETCH_URL = 'http://origami.design/public/images/bird-logo.png?r=1&t=' + Date.now();
|
||||||
//var prefetchTask = Image.prefetch(IMAGE_PREFETCH_URL);
|
var prefetchTask = Image.prefetch(IMAGE_PREFETCH_URL);
|
||||||
|
|
||||||
/*
|
|
||||||
var NetworkImageCallbackExample = React.createClass({
|
var NetworkImageCallbackExample = React.createClass({
|
||||||
getInitialState: function() {
|
getInitialState: function() {
|
||||||
return {
|
return {
|
||||||
@@ -88,7 +87,6 @@ var NetworkImageCallbackExample = React.createClass({
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
*/
|
|
||||||
|
|
||||||
var NetworkImageExample = React.createClass({
|
var NetworkImageExample = React.createClass({
|
||||||
getInitialState: function() {
|
getInitialState: function() {
|
||||||
@@ -118,7 +116,6 @@ var NetworkImageExample = React.createClass({
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
/*
|
|
||||||
var ImageSizeExample = React.createClass({
|
var ImageSizeExample = React.createClass({
|
||||||
getInitialState: function() {
|
getInitialState: function() {
|
||||||
return {
|
return {
|
||||||
@@ -133,24 +130,25 @@ var ImageSizeExample = React.createClass({
|
|||||||
},
|
},
|
||||||
render: function() {
|
render: function() {
|
||||||
return (
|
return (
|
||||||
<View style={{flexDirection: 'row'}}>
|
<View>
|
||||||
<Image
|
|
||||||
style={{
|
|
||||||
width: 60,
|
|
||||||
height: 60,
|
|
||||||
backgroundColor: 'transparent',
|
|
||||||
marginRight: 10,
|
|
||||||
}}
|
|
||||||
source={this.props.source} />
|
|
||||||
<Text>
|
<Text>
|
||||||
Actual dimensions:{'\n'}
|
Actual dimensions:{'\n'}
|
||||||
Width: {this.state.width}, Height: {this.state.height}
|
width: {this.state.width}, height: {this.state.height}
|
||||||
</Text>
|
</Text>
|
||||||
|
<Image
|
||||||
|
source={this.props.source}
|
||||||
|
style={{
|
||||||
|
backgroundColor: '#eee',
|
||||||
|
height: 227,
|
||||||
|
marginTop: 10,
|
||||||
|
width: 323
|
||||||
|
}}
|
||||||
|
/>
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
*/
|
|
||||||
/*
|
/*
|
||||||
var MultipleSourcesExample = React.createClass({
|
var MultipleSourcesExample = React.createClass({
|
||||||
getInitialState: function() {
|
getInitialState: function() {
|
||||||
@@ -239,17 +237,17 @@ const examples = [
|
|||||||
);
|
);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
/*
|
|
||||||
{
|
{
|
||||||
title: 'Image Loading Events',
|
title: 'Image Loading Events',
|
||||||
render: function() {
|
render: function() {
|
||||||
return (
|
return (
|
||||||
<NetworkImageCallbackExample source={{uri: 'http://facebook.github.io/origami/public/images/blog-hero.jpg?r=1&t=' + Date.now()}}
|
<NetworkImageCallbackExample
|
||||||
prefetchedSource={{uri: IMAGE_PREFETCH_URL}}/>
|
source={{uri: 'http://origami.design/public/images/bird-logo.png?r=1&t=' + Date.now()}}
|
||||||
|
prefetchedSource={{uri: IMAGE_PREFETCH_URL}}
|
||||||
|
/>
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
*/
|
|
||||||
{
|
{
|
||||||
title: 'Error Handler',
|
title: 'Error Handler',
|
||||||
render: function() {
|
render: function() {
|
||||||
@@ -263,7 +261,7 @@ const examples = [
|
|||||||
title: 'Image Download Progress',
|
title: 'Image Download Progress',
|
||||||
render: function() {
|
render: function() {
|
||||||
return (
|
return (
|
||||||
<NetworkImageExample source={{uri: 'http://facebook.github.io/origami/public/images/blog-hero.jpg?r=1'}}/>
|
<NetworkImageExample source={{uri: 'http://origami.design/public/images/bird-logo.png?r=1'}}/>
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
platform: 'ios',
|
platform: 'ios',
|
||||||
@@ -567,14 +565,12 @@ const examples = [
|
|||||||
platform: 'ios',
|
platform: 'ios',
|
||||||
},
|
},
|
||||||
*/
|
*/
|
||||||
/*
|
|
||||||
{
|
{
|
||||||
title: 'Image Size',
|
title: 'Image Size',
|
||||||
render: function() {
|
render: function() {
|
||||||
return <ImageSizeExample source={fullImage} />;
|
return <ImageSizeExample source={{ uri: 'https://upload.wikimedia.org/wikipedia/commons/d/d7/Chestnut-mandibled_Toucan.jpg' }} />;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
*/
|
|
||||||
/*
|
/*
|
||||||
{
|
{
|
||||||
title: 'MultipleSourcesExample',
|
title: 'MultipleSourcesExample',
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
/* global window */
|
/* global window */
|
||||||
import applyNativeMethods from '../../modules/applyNativeMethods';
|
import applyNativeMethods from '../../modules/applyNativeMethods';
|
||||||
import ImageResizeMode from './ImageResizeMode';
|
import ImageResizeMode from './ImageResizeMode';
|
||||||
|
import ImageLoader from '../../modules/ImageLoader';
|
||||||
import ImageStylePropTypes from './ImageStylePropTypes';
|
import ImageStylePropTypes from './ImageStylePropTypes';
|
||||||
import requestAnimationFrame from 'fbjs/lib/requestAnimationFrame';
|
import requestAnimationFrame from 'fbjs/lib/requestAnimationFrame';
|
||||||
import StyleSheet from '../../apis/StyleSheet';
|
import StyleSheet from '../../apis/StyleSheet';
|
||||||
@@ -57,11 +58,19 @@ class Image extends Component {
|
|||||||
style: emptyObject
|
style: emptyObject
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static getSize(uri, success, failure) {
|
||||||
|
ImageLoader.getSize(uri, success, failure);
|
||||||
|
}
|
||||||
|
|
||||||
|
static prefetch(uri) {
|
||||||
|
return ImageLoader.prefetch(uri);
|
||||||
|
}
|
||||||
|
|
||||||
static resizeMode = ImageResizeMode;
|
static resizeMode = ImageResizeMode;
|
||||||
|
|
||||||
constructor(props, context) {
|
constructor(props, context) {
|
||||||
super(props, context);
|
super(props, context);
|
||||||
this.state = { isLoaded: false };
|
this.state = { shouldDisplaySource: false };
|
||||||
const uri = resolveAssetSource(props.source);
|
const uri = resolveAssetSource(props.source);
|
||||||
this._imageState = uri ? STATUS_PENDING : STATUS_IDLE;
|
this._imageState = uri ? STATUS_PENDING : STATUS_IDLE;
|
||||||
this._isMounted = false;
|
this._isMounted = false;
|
||||||
@@ -75,7 +84,7 @@ class Image extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
componentDidUpdate() {
|
componentDidUpdate() {
|
||||||
if (this._imageState === STATUS_PENDING && !this.image) {
|
if (this._imageState === STATUS_PENDING) {
|
||||||
this._createImageLoader();
|
this._createImageLoader();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -93,7 +102,7 @@ class Image extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { isLoaded } = this.state;
|
const { shouldDisplaySource } = this.state;
|
||||||
const {
|
const {
|
||||||
accessibilityLabel,
|
accessibilityLabel,
|
||||||
accessible,
|
accessible,
|
||||||
@@ -103,13 +112,17 @@ class Image extends Component {
|
|||||||
source,
|
source,
|
||||||
testID,
|
testID,
|
||||||
/* eslint-disable */
|
/* eslint-disable */
|
||||||
|
onError,
|
||||||
|
onLoad,
|
||||||
|
onLoadEnd,
|
||||||
|
onLoadStart,
|
||||||
resizeMode,
|
resizeMode,
|
||||||
/* eslint-enable */
|
/* eslint-enable */
|
||||||
...other
|
...other
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
const displayImage = resolveAssetSource(!isLoaded ? defaultSource : source);
|
const displayImage = resolveAssetSource(shouldDisplaySource ? source : defaultSource);
|
||||||
const imageSizeStyle = resolveAssetDimensions(!isLoaded ? defaultSource : source);
|
const imageSizeStyle = resolveAssetDimensions(shouldDisplaySource ? source : defaultSource);
|
||||||
const backgroundImage = displayImage ? `url("${displayImage}")` : null;
|
const backgroundImage = displayImage ? `url("${displayImage}")` : null;
|
||||||
const originalStyle = StyleSheet.flatten(this.props.style);
|
const originalStyle = StyleSheet.flatten(this.props.style);
|
||||||
const finalResizeMode = resizeMode || originalStyle.resizeMode || ImageResizeMode.cover;
|
const finalResizeMode = resizeMode || originalStyle.resizeMode || ImageResizeMode.cover;
|
||||||
@@ -139,28 +152,21 @@ class Image extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_createImageLoader() {
|
_createImageLoader() {
|
||||||
const uri = resolveAssetSource(this.props.source);
|
|
||||||
|
|
||||||
this._destroyImageLoader();
|
this._destroyImageLoader();
|
||||||
this.image = new window.Image();
|
const uri = resolveAssetSource(this.props.source);
|
||||||
this.image.onerror = this._onError;
|
this._imageRequestId = ImageLoader.load(uri, this._onLoad, this._onError);
|
||||||
this.image.onload = this._onLoad;
|
|
||||||
this.image.src = uri;
|
|
||||||
this._onLoadStart();
|
this._onLoadStart();
|
||||||
}
|
}
|
||||||
|
|
||||||
_destroyImageLoader() {
|
_destroyImageLoader() {
|
||||||
if (this.image) {
|
if (this._imageRequestId) {
|
||||||
this.image.onerror = null;
|
ImageLoader.abort(this._imageRequestId);
|
||||||
this.image.onload = null;
|
this._imageRequestId = null;
|
||||||
this.image = null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_onError = () => {
|
_onError = () => {
|
||||||
const { onError, source } = this.props;
|
const { onError, source } = this.props;
|
||||||
this._destroyImageLoader();
|
|
||||||
this._onLoadEnd();
|
|
||||||
this._updateImageState(STATUS_ERRORED);
|
this._updateImageState(STATUS_ERRORED);
|
||||||
if (onError) {
|
if (onError) {
|
||||||
onError({
|
onError({
|
||||||
@@ -169,13 +175,13 @@ class Image extends Component {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
this._onLoadEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
_onLoad = (e) => {
|
_onLoad = (e) => {
|
||||||
const { onLoad } = this.props;
|
const { onLoad } = this.props;
|
||||||
const event = { nativeEvent: e };
|
const event = { nativeEvent: e };
|
||||||
|
|
||||||
this._destroyImageLoader();
|
|
||||||
this._updateImageState(STATUS_LOADED);
|
this._updateImageState(STATUS_LOADED);
|
||||||
if (onLoad) { onLoad(event); }
|
if (onLoad) { onLoad(event); }
|
||||||
this._onLoadEnd();
|
this._onLoadEnd();
|
||||||
@@ -194,11 +200,12 @@ class Image extends Component {
|
|||||||
|
|
||||||
_updateImageState(status) {
|
_updateImageState(status) {
|
||||||
this._imageState = status;
|
this._imageState = status;
|
||||||
const isLoaded = this._imageState === STATUS_LOADED;
|
const shouldDisplaySource = this._imageState === STATUS_LOADED || this._imageState === STATUS_LOADING;
|
||||||
if (isLoaded !== this.state.isLoaded) {
|
// only triggers a re-render when the image is loading (to support PJEG), loaded, or failed
|
||||||
|
if (shouldDisplaySource !== this.state.shouldDisplaySource) {
|
||||||
requestAnimationFrame(() => {
|
requestAnimationFrame(() => {
|
||||||
if (this._isMounted) {
|
if (this._isMounted) {
|
||||||
this.setState({ isLoaded });
|
this.setState({ shouldDisplaySource });
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,48 @@
|
|||||||
|
let id = 0;
|
||||||
|
const requests = {};
|
||||||
|
|
||||||
|
const ImageLoader = {
|
||||||
|
abort(requestId: number) {
|
||||||
|
let image = requests[`${requestId}`];
|
||||||
|
if (image) {
|
||||||
|
image.onerror = image.onload = image = null;
|
||||||
|
delete requests[`${requestId}`];
|
||||||
|
}
|
||||||
|
},
|
||||||
|
getSize(uri, success, failure) {
|
||||||
|
let complete = false;
|
||||||
|
const interval = setInterval(callback, 16);
|
||||||
|
const requestId = ImageLoader.load(uri, callback, callback);
|
||||||
|
|
||||||
|
function callback() {
|
||||||
|
const image = requests[`${requestId}`];
|
||||||
|
if (image) {
|
||||||
|
const { naturalHeight, naturalWidth } = image;
|
||||||
|
if (naturalHeight && naturalWidth) {
|
||||||
|
success(naturalWidth, naturalHeight);
|
||||||
|
complete = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (complete) {
|
||||||
|
ImageLoader.abort(requestId);
|
||||||
|
clearInterval(interval);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
load(uri, onLoad, onError): number {
|
||||||
|
id += 1;
|
||||||
|
const image = new window.Image();
|
||||||
|
image.onerror = onError;
|
||||||
|
image.onload = onLoad;
|
||||||
|
image.src = uri;
|
||||||
|
requests[`${id}`] = image;
|
||||||
|
return id;
|
||||||
|
},
|
||||||
|
prefetch(uri): Promise {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
ImageLoader.load(uri, resolve, reject);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ImageLoader;
|
||||||
Reference in New Issue
Block a user