mirror of
https://github.com/zoriya/react-native-web.git
synced 2026-06-06 03:45:18 +00:00
[add] support directly requiring image assets
Thanks to IjzerenHein <hrutjes@gmail.com>. See #84
This commit is contained in:
@@ -16,6 +16,25 @@ module.exports = {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Image assets
|
||||||
|
|
||||||
|
In order to require image assets (e.g. `require('assets/myimage.png')`), add
|
||||||
|
the `url-loader` to the webpack config:
|
||||||
|
|
||||||
|
```js
|
||||||
|
// webpack.config.js
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
// ...
|
||||||
|
module: {
|
||||||
|
loaders: {
|
||||||
|
test: /\.(gif|jpe?g|png|svg)$/,
|
||||||
|
loader: 'url-loader',
|
||||||
|
query: { name: '[name].[hash:16].[ext]' }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
## Web-specific code
|
## Web-specific code
|
||||||
|
|
||||||
Minor platform differences can use the `Platform` module.
|
Minor platform differences can use the `Platform` module.
|
||||||
|
|||||||
@@ -36,6 +36,14 @@ suite('components/Image', () => {
|
|||||||
assert(backgroundImage.indexOf(defaultSource.uri) > -1)
|
assert(backgroundImage.indexOf(defaultSource.uri) > -1)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test('prop "defaultSource" with string value"', () => {
|
||||||
|
// emulate require-ed asset
|
||||||
|
const defaultSource = 'https://google.com/favicon.ico'
|
||||||
|
const dom = utils.renderToDOM(<Image defaultSource={defaultSource} />)
|
||||||
|
const backgroundImage = dom.style.backgroundImage
|
||||||
|
assert(backgroundImage.indexOf(defaultSource) > -1)
|
||||||
|
})
|
||||||
|
|
||||||
test('prop "onError"', function (done) {
|
test('prop "onError"', function (done) {
|
||||||
this.timeout(5000)
|
this.timeout(5000)
|
||||||
utils.render(<Image
|
utils.render(<Image
|
||||||
@@ -50,10 +58,7 @@ suite('components/Image', () => {
|
|||||||
|
|
||||||
test('prop "onLoad"', function (done) {
|
test('prop "onLoad"', function (done) {
|
||||||
this.timeout(5000)
|
this.timeout(5000)
|
||||||
utils.render(<Image
|
utils.render(<Image onLoad={onLoad} source={{ uri: 'https://google.com/favicon.ico' }} />)
|
||||||
onLoad={onLoad}
|
|
||||||
source={{ uri: 'https://google.com/favicon.ico' }}
|
|
||||||
/>)
|
|
||||||
function onLoad(e) {
|
function onLoad(e) {
|
||||||
assert.equal(e.nativeEvent.type, 'load')
|
assert.equal(e.nativeEvent.type, 'load')
|
||||||
done()
|
done()
|
||||||
@@ -91,7 +96,28 @@ suite('components/Image', () => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
test('prop "source"')
|
test('prop "source"', function (done) {
|
||||||
|
this.timeout(5000)
|
||||||
|
const source = { uri: 'https://google.com/favicon.ico' }
|
||||||
|
utils.render(<Image onLoad={onLoad} source={source} />)
|
||||||
|
function onLoad(e) {
|
||||||
|
const src = e.nativeEvent.target.src
|
||||||
|
assert.equal(src, source.uri)
|
||||||
|
done()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
test('prop "source" with string value', function (done) {
|
||||||
|
this.timeout(5000)
|
||||||
|
// emulate require-ed asset
|
||||||
|
const source = 'https://google.com/favicon.ico'
|
||||||
|
utils.render(<Image onLoad={onLoad} source={source} />)
|
||||||
|
function onLoad(e) {
|
||||||
|
const src = e.nativeEvent.target.src
|
||||||
|
assert.equal(src, source)
|
||||||
|
done()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
suite('prop "style"', () => {
|
suite('prop "style"', () => {
|
||||||
test('converts "resizeMode" property', () => {
|
test('converts "resizeMode" property', () => {
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
/* global window */
|
/* global window */
|
||||||
import { NativeMethodsDecorator } from '../../modules/NativeMethodsMixin'
|
import { NativeMethodsDecorator } from '../../modules/NativeMethodsMixin'
|
||||||
|
import resolveAssetSource from './resolveAssetSource'
|
||||||
import CoreComponent from '../CoreComponent'
|
import CoreComponent from '../CoreComponent'
|
||||||
import ImageResizeMode from './ImageResizeMode'
|
import ImageResizeMode from './ImageResizeMode'
|
||||||
import ImageStylePropTypes from './ImageStylePropTypes'
|
import ImageStylePropTypes from './ImageStylePropTypes'
|
||||||
@@ -14,27 +15,32 @@ const STATUS_LOADING = 'LOADING'
|
|||||||
const STATUS_PENDING = 'PENDING'
|
const STATUS_PENDING = 'PENDING'
|
||||||
const STATUS_IDLE = 'IDLE'
|
const STATUS_IDLE = 'IDLE'
|
||||||
|
|
||||||
|
const ImageSourcePropType = PropTypes.oneOfType([
|
||||||
|
PropTypes.shape({
|
||||||
|
uri: PropTypes.string.isRequired
|
||||||
|
}),
|
||||||
|
PropTypes.string
|
||||||
|
])
|
||||||
|
|
||||||
@NativeMethodsDecorator
|
@NativeMethodsDecorator
|
||||||
export default class Image extends Component {
|
export default class Image extends Component {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
accessibilityLabel: CoreComponent.propTypes.accessibilityLabel,
|
accessibilityLabel: CoreComponent.propTypes.accessibilityLabel,
|
||||||
accessible: CoreComponent.propTypes.accessible,
|
accessible: CoreComponent.propTypes.accessible,
|
||||||
children: PropTypes.any,
|
children: PropTypes.any,
|
||||||
defaultSource: PropTypes.object,
|
defaultSource: ImageSourcePropType,
|
||||||
onError: PropTypes.func,
|
onError: PropTypes.func,
|
||||||
onLoad: PropTypes.func,
|
onLoad: PropTypes.func,
|
||||||
onLoadEnd: PropTypes.func,
|
onLoadEnd: PropTypes.func,
|
||||||
onLoadStart: PropTypes.func,
|
onLoadStart: PropTypes.func,
|
||||||
resizeMode: PropTypes.oneOf(['contain', 'cover', 'none', 'stretch']),
|
resizeMode: PropTypes.oneOf(['contain', 'cover', 'none', 'stretch']),
|
||||||
source: PropTypes.object,
|
source: ImageSourcePropType,
|
||||||
style: StyleSheetPropType(ImageStylePropTypes),
|
style: StyleSheetPropType(ImageStylePropTypes),
|
||||||
testID: CoreComponent.propTypes.testID
|
testID: CoreComponent.propTypes.testID
|
||||||
};
|
};
|
||||||
|
|
||||||
static defaultProps = {
|
static defaultProps = {
|
||||||
accessible: true,
|
accessible: true,
|
||||||
defaultSource: {},
|
|
||||||
source: {},
|
|
||||||
style: {}
|
style: {}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -42,7 +48,7 @@ export default class Image extends Component {
|
|||||||
|
|
||||||
constructor(props, context) {
|
constructor(props, context) {
|
||||||
super(props, context)
|
super(props, context)
|
||||||
const { uri } = props.source
|
const uri = resolveAssetSource(props.source)
|
||||||
// state
|
// state
|
||||||
this.state = { status: uri ? STATUS_PENDING : STATUS_IDLE }
|
this.state = { status: uri ? STATUS_PENDING : STATUS_IDLE }
|
||||||
// autobinding
|
// autobinding
|
||||||
@@ -51,13 +57,13 @@ export default class Image extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_createImageLoader() {
|
_createImageLoader() {
|
||||||
const { source } = this.props
|
const uri = resolveAssetSource(this.props.source)
|
||||||
|
|
||||||
this._destroyImageLoader()
|
this._destroyImageLoader()
|
||||||
this.image = new window.Image()
|
this.image = new window.Image()
|
||||||
this.image.onerror = this._onError
|
this.image.onerror = this._onError
|
||||||
this.image.onload = this._onLoad
|
this.image.onload = this._onLoad
|
||||||
this.image.src = source.uri
|
this.image.src = uri
|
||||||
this._onLoadStart()
|
this._onLoadStart()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -113,9 +119,10 @@ export default class Image extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
componentWillReceiveProps(nextProps) {
|
componentWillReceiveProps(nextProps) {
|
||||||
if (this.props.source.uri !== nextProps.source.uri) {
|
const nextUri = resolveAssetSource(nextProps.source)
|
||||||
|
if (resolveAssetSource(this.props.source) !== nextUri) {
|
||||||
this.setState({
|
this.setState({
|
||||||
status: nextProps.source.uri ? STATUS_PENDING : STATUS_IDLE
|
status: nextUri ? STATUS_PENDING : STATUS_IDLE
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -135,8 +142,7 @@ export default class Image extends Component {
|
|||||||
} = this.props
|
} = this.props
|
||||||
|
|
||||||
const isLoaded = this.state.status === STATUS_LOADED
|
const isLoaded = this.state.status === STATUS_LOADED
|
||||||
const defaultImage = defaultSource.uri || null
|
const displayImage = resolveAssetSource(!isLoaded ? defaultSource : source)
|
||||||
const displayImage = !isLoaded ? defaultImage : source.uri
|
|
||||||
const backgroundImage = displayImage ? `url("${displayImage}")` : null
|
const backgroundImage = displayImage ? `url("${displayImage}")` : null
|
||||||
const style = StyleSheet.flatten(this.props.style)
|
const style = StyleSheet.flatten(this.props.style)
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
function resolveAssetSource(source) {
|
||||||
|
return ((typeof source === 'object') ? source.uri : source) || null
|
||||||
|
}
|
||||||
|
|
||||||
|
export default resolveAssetSource
|
||||||
Reference in New Issue
Block a user