diff --git a/packages/react-native-web/src/exports/Image/__tests__/index-test.js b/packages/react-native-web/src/exports/Image/__tests__/index-test.js
index 17b7718b..c7f81d9b 100644
--- a/packages/react-native-web/src/exports/Image/__tests__/index-test.js
+++ b/packages/react-native-web/src/exports/Image/__tests__/index-test.js
@@ -5,10 +5,13 @@ import Image from '../';
import ImageLoader from '../../../modules/ImageLoader';
import ImageUriCache from '../ImageUriCache';
import React from 'react';
+import StyleSheet from '../../StyleSheet';
import { mount, shallow } from 'enzyme';
const originalImage = window.Image;
+const findImageSurfaceStyle = wrapper => StyleSheet.flatten(wrapper.childAt(0).prop('style'));
+
describe('components/Image', () => {
beforeEach(() => {
window.Image = jest.fn(() => ({}));
@@ -37,14 +40,14 @@ describe('components/Image', () => {
test('sets background image when value is an object', () => {
const defaultSource = { uri: 'https://google.com/favicon.ico' };
const component = shallow();
- expect(component.prop('style').backgroundImage).toMatchSnapshot();
+ expect(findImageSurfaceStyle(component).backgroundImage).toMatchSnapshot();
});
test('sets background image when value is a string', () => {
// emulate require-ed asset
const defaultSource = 'https://google.com/favicon.ico';
const component = shallow();
- expect(component.prop('style').backgroundImage).toMatchSnapshot();
+ expect(findImageSurfaceStyle(component).backgroundImage).toMatchSnapshot();
});
test('sets "height" and "width" styles if missing', () => {
@@ -54,7 +57,7 @@ describe('components/Image', () => {
width: 20
};
const component = shallow();
- const { height, width } = component.prop('style');
+ const { height, width } = StyleSheet.flatten(component.prop('style'));
expect(height).toBe(10);
expect(width).toBe(20);
});
@@ -68,7 +71,7 @@ describe('components/Image', () => {
const component = shallow(
);
- const { height, width } = component.prop('style');
+ const { height, width } = StyleSheet.flatten(component.prop('style'));
expect(height).toBe(20);
expect(width).toBe(40);
});
@@ -141,7 +144,7 @@ describe('components/Image', () => {
].forEach(resizeMode => {
test(`value "${resizeMode}"`, () => {
const component = shallow();
- expect(component.prop('style').backgroundSize).toMatchSnapshot();
+ expect(findImageSurfaceStyle(component).backgroundSize).toMatchSnapshot();
});
});
});
@@ -206,7 +209,7 @@ describe('components/Image', () => {
describe('prop "style"', () => {
test('correctly supports "resizeMode" property', () => {
const component = shallow();
- expect(component.prop('style').backgroundSize).toMatchSnapshot();
+ expect(findImageSurfaceStyle(component).backgroundSize).toMatchSnapshot();
});
test('removes other unsupported View styles', () => {
diff --git a/packages/react-native-web/src/exports/Image/index.js b/packages/react-native-web/src/exports/Image/index.js
index 8b488c98..8e4216b5 100644
--- a/packages/react-native-web/src/exports/Image/index.js
+++ b/packages/react-native-web/src/exports/Image/index.js
@@ -188,37 +188,6 @@ class Image extends Component<*, State> {
...other
} = this.props;
- const displayImage = resolveAssetUri(shouldDisplaySource ? source : defaultSource);
- const imageSizeStyle = resolveAssetDimensions(shouldDisplaySource ? source : defaultSource);
- const backgroundImage = displayImage ? `url("${displayImage}")` : null;
- const originalStyle = StyleSheet.flatten(this.props.style);
- const finalResizeMode = resizeMode || originalStyle.resizeMode || ImageResizeMode.cover;
-
- const style = StyleSheet.flatten([
- styles.initial,
- imageSizeStyle,
- originalStyle,
- resizeModeStyles[finalResizeMode],
- this.context.isInAParentText && styles.inline,
- backgroundImage && { backgroundImage }
- ]);
- // View doesn't support these styles
- delete style.overlayColor;
- delete style.resizeMode;
- delete style.tintColor;
-
- // Allows users to trigger the browser's image context menu
- const hiddenImage = displayImage
- ? createElement('img', {
- alt: accessibilityLabel || '',
- decode: 'async',
- draggable: draggable || false,
- ref: this._setImageRef,
- src: displayImage,
- style: styles.img
- })
- : null;
-
if (process.env.NODE_ENV !== 'production') {
if (this.props.src) {
console.warn('The component requires a `source` property rather than `src`.');
@@ -231,15 +200,49 @@ class Image extends Component<*, State> {
}
}
+ const selectedSource = shouldDisplaySource ? source : defaultSource;
+ const displayImageUri = resolveAssetUri(selectedSource);
+ const imageSizeStyle = resolveAssetDimensions(selectedSource);
+ const backgroundImage = displayImageUri ? `url("${displayImageUri}")` : null;
+ const flatStyle = { ...StyleSheet.flatten(this.props.style) };
+ const finalResizeMode = resizeMode || flatStyle.resizeMode || ImageResizeMode.cover;
+ // View doesn't support these styles
+ delete flatStyle.overlayColor;
+ delete flatStyle.resizeMode;
+ delete flatStyle.tintColor;
+
+ // Accessibility image allows users to trigger the browser's image context menu
+ const hiddenImage = displayImageUri
+ ? createElement('img', {
+ alt: accessibilityLabel || '',
+ draggable: draggable || false,
+ ref: this._setImageRef,
+ src: displayImageUri,
+ style: styles.accessibilityImage
+ })
+ : null;
+
return (
+
{hiddenImage}
);
@@ -317,17 +320,25 @@ class Image extends Component<*, State> {
}
const styles = StyleSheet.create({
- initial: {
- backgroundColor: 'transparent',
- backgroundPosition: 'center',
- backgroundRepeat: 'no-repeat',
- backgroundSize: 'cover',
+ root: {
+ flexBasis: 'auto',
+ overflow: 'hidden',
zIndex: 0
},
inline: {
display: 'inline-flex'
},
- img: {
+ image: {
+ ...StyleSheet.absoluteFillObject,
+ backgroundColor: 'transparent',
+ backgroundPosition: 'center',
+ backgroundRepeat: 'no-repeat',
+ backgroundSize: 'cover',
+ height: '100%',
+ width: '100%',
+ zIndex: -1
+ },
+ accessibilityImage: {
...StyleSheet.absoluteFillObject,
height: '100%',
opacity: 0,
@@ -338,8 +349,7 @@ const styles = StyleSheet.create({
const resizeModeStyles = StyleSheet.create({
center: {
- backgroundSize: 'auto',
- backgroundPosition: 'center'
+ backgroundSize: 'auto'
},
contain: {
backgroundSize: 'contain'
@@ -348,11 +358,13 @@ const resizeModeStyles = StyleSheet.create({
backgroundSize: 'cover'
},
none: {
+ backgroundPosition: '0 0',
backgroundSize: 'auto'
},
repeat: {
- backgroundSize: 'auto',
- backgroundRepeat: 'repeat'
+ backgroundPosition: '0 0',
+ backgroundRepeat: 'repeat',
+ backgroundSize: 'auto'
},
stretch: {
backgroundSize: '100% 100%'