React Native Expo Image Resizing - javascript

I'm using react native expo to display images of various subjects. The images I'm using have a variety of widths, heights and aspect ratios. The images themselves come from google firebase storage and are retrieved from the currently selected subjects JSON data which contains the firebase storage Image URL.
Some subjects have no images at all, which is fine however I want the content below to therefore move up, so a fixed size/aspect ratio image or view in this case is not appropriate. And as I said Images are of various heights and widths (some landscape / some portrait.
Currently the styling for the image I'm attempting is like so:
Image: {
height: null,
width: "90%",
alignSelf: 'center',
resizeMode: 'contain'
},
Currently with the height set to null the image is not shown at all, and the content below sits above.
The width I want fixed at 90% of the screen's width which it currently is doing, however I'm having issues with the height. I've tried setting the height at 'undefined' and also percentages '40%' etc however this is not appropriate for the subjects missing images.
Another way I have tried is placing the image inside a view like so:
<View style={styles.ImageContainer}>
<Image style={styles.Image} source={{ url: subject.ImageUrl }}/>
</View>
...
// Styling:
Image: {
height: null,
width: "100%", // 100% of the image container which is 90% of screen.
alignSelf: 'center',
resizeMode: 'contain'
},
ImageContainer: {
width: '90%',
alignSelf: 'center',
justifyContent: 'center'
}
What I really want to achieve is setting the image container to the size of the image height, which is resized so it fills 90% of the screens width (without skewing/stretching the image).
Is there are way of doing this within the styling or do I have to attempt using a function? I'm sure I have had success achieving this through styling in the past.

You could use a minHeight for the image to make sure it shows, it should use the actual image height but setting a minimum will allow it to display.
OR
You could use Image.getSize() and use the exact height of the image. However, Image.getSize() is an async function so you would have to await it to get the size until you can display the image.

Related

How to make Nipple.js Joystick responsive?

I am currently using the javascript library nipple.js to add a joystick element to my vue.js-website.
The joystick is placed inside a resizeable parent-element but is of static size itself.
I was wondering how it would be possible to make the joystick element resize with its parent so it would have a fitting size when resizing the parent but also on different screen sizes in general.
This is how I initialize my Joystick in Vue right now
const options = {
zone: this.$refs.nippleRef,
mode: 'static',
position: { left: '25%', top: '50%' },
dynamicPage: true, // needed because of vue
size: 150,
restOpacity: 0.75,
};
I tried using e.g. a percentage in the place of the 150 at the size value. However only numbers are valid there.
I was wondering if there is a way to make the Joystick responsive either through javascript or with css?
And this is the template part of the vue file btw:
<v-col>
<div>
<div ref="nippleRef"></div>
</div>
</v-col>
Thank you in advance!

How can I efficiently render an Image Component in a React Native Header bar?

Overview
I am currently working on a React Native application that uses the React Navigation library. From the React Navigation library, I'm using the navigationOptions property to create a Header component in each of my screens. Each screen uses the exact same properties:
HomeScreen.navigationOptions = {
headerRight: (
<Ionicons
name={"md-menu"}
size={26}
style={{ marginBottom: -5, paddingRight: 15 }}
color={"#ccc"}
/>
),
headerTitle: (
<HeaderLogo/>
)
}
My Logo component is as such:
export default HeaderLogo = () => {
const logo = require("../../../assets/images/logo.png");
return (
<Image
style={{
resizeMode: "contain",
height: 40,
width: 85,
marginLeft: 85
}}
source={logo}
/>
)
}
The problem
The logo renders in the header correctly as expected; however, whenever I switch screens, the logo briefly disappears and reappears in a flash. Its noticeable and does not look good. I want the header to appear static no matter how many times I switch screens. I'm assuming this has something to with the require()method, where its pulling the image everytime. My question is:
How can I efficiently use an Image component in my Header, such that the header appears static?
Add headerMode: 'float' to the navigationOptions of the stack navigator that contains your screens.
From createStackNavigator documentation:
headerMode - Specifies how the header should be rendered:
float - Render a single header that stays at the top and animates as screens are changed. This is a common pattern on iOS.
screen - Each screen has a header attached to it and the header fades in and out together with the screen. This is a common pattern on Android.
none - No header will be rendered.

How to add text to an image in React Native?

I'm researching if it is easily possible with React Native or whether I should build a native app.
I want to edit an image from the photo library and add a text overlay to it. Think of it like a postcard with a greeting message on it.
How would I add text to and image and make a new copy of it in react native? I'm not looking for detailed code, just for an explanation on how to get started.
Update:
Would it be a good alternative to just save the coordinates of the message on the picture instead of generating a new image?
You can go with 2 ways. You can either render the text on an image component and save the position of that text or you can process the image and get a new image with the text.
The first option brings up the problem of that position is relative to image's size. Means that if the image renders on a different sized screen the position and size of text should also be moved accordingly. This option needs a good calculation algorithm. Also, another problem could be the rendering times. Text component will render instantly but Image component needs to load the image first. This option also needs a good way of render algorithm.
The second option is not possible without a 3rd party library or some level of native code since react-native doesn't support image processing beyond the limits of CSS. A good and maintained image processing library is gl-react-native-v2. This library helps you to process and manipulate the image as you wish and then save the result with captureFrame(config). This option is more capable of processing file but needs you to save a new image.
Either way is good if the way you go is appropriate for your use case. The decision really depends on your case and preference.
You could use react-native's ImageBackground tag since using the Image tag as a container would give you a yellow box warning.
The sample code for it with overlay is as shown below
<ImageBackground source={SomeImage} style= {SomeStyle} resizeMode='SomeMode'>
{loader}
</ImageBackground>
It would be efficient if you work on the same image by changing the flex property in the styles of the image or you may set the position: absolute to the main image container and assign top , bottom, left, right to the nested container.
Helpful link may be found here
<View style={{flex: 1, justifyContent: 'center', alignItems: 'center', marginTop: 20}}>
<Image
style={{
flex: 1,
width:100,
height:100,
}}
source={require('../imgs/star.png')}
/>
<Text style={{position: 'absolute', fontSize: 20}}>890</Text>
</View>
I'm researching if it is easily possible with React Native or whether I should build a native app.
This sounds very doable in react-native
I want to edit an image from the photo library and add a text overlay to it. Think of it like a postcard with a greeting message on it.
I think I would capture ALL the relevant metadata as an object...
{
image: {
uri: './assets/image.jpg',
height: 576,
width: 1024
},
message: {
fontFace: 'Calibri',
fontSize: 16,
text: 'Happy Holidays!'
boundingBox: {
height: '30%',
width: '30%',
top: 0,
left: 0
}
}
}
With the above detail (and maybe more), you'd then be able to reconstruct the design intent on any device, regardless of size (tablet vs mobile) or pixel depth. The boundingBox would be expressed in terms relative to the image's rendered dimensions. In the above example, the message would be contained in a text box no more than 30% of the image width, 30% of its height, and positioned in the top-left corner.
How would I add text to an image and make a new copy of it in react native?
This eliminates the need to do any screenshotting or actual image manipulation, etc. No need to "make a new copy". Just treat them as two separate and distinct assets, then merge them at render using the metadata you captured.
Final thought: if you "need" to "upload the finished photo to a server" as you stated in another comment to another solution, you can do this serverside using any number of technologies using the metadata as your guide.
You can use position: absolute since adding children to Image is deprecated. Following code will align text in middle (vertically and horizontally) over the image:
<View>
<Image
source={yourImageUrl}
resizeMode={'cover'}
style={{
width: 300,
height: 300
}}
/>
<View style={{ position: 'absolute', top: 0, left: 0, right: 0, height: 300, alignItems: 'center', justifyContent: 'center' }}>
<Text>Your overlay text</Text>
</View>
</View>
If you need to only show a text over the image you can wrap the image in a view and after the image insert a text element with position: 'absolute'. If you want a copy of the image containing the text then you can use the same approach but take a snapshot using react-native-view-shot
As far as I know, the image component can be used as a container so you can do something like this:
<Image>
<Text>{"some text"}</Text>
</Image>
Below code is what I used to add text on image at particular coordinates on image.
Xcode 8.3.2 Swift 3.1
func textToImage(drawText text: NSString, inImage image: UIImage, atPoint point: CGPoint) -> UIImage {
let textColor = UIColor.white
let textFont = UIFont(name: "Helvetica Bold", size: 10)!
let scale = UIScreen.main.scale
UIGraphicsBeginImageContextWithOptions(image.size, false, scale)
let textFontAttributes = [
NSFontAttributeName: textFont,
NSForegroundColorAttributeName: textColor,
] as [String : Any]
image.draw(in: CGRect(origin: CGPoint.zero, size: image.size))
let rect = CGRect(origin: point, size: image.size)
text.draw(in: rect, withAttributes: textFontAttributes)
let newImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return newImage!
}
And call above method as below
let imageWithText = textToImage(drawText: "textOnImage", inImage:yourImage, atPoint: CGPoint(x:9,y:11))
There are several libraries available for that. If you want to add a text to an image you can use: react-native-media-editor. This is quite a good option for adding text to an image but I recommend you react-native-image-tools. It provides so much flexibility. You can add a text and position it accordingly. Apart from that, there are filters, cropping option, light adjustments and so much more.
It depends on the use case but if you simply want to put a text on an image, using ImageBackground is a one of the good approach.
Do it like below.
<ImageBackground
source={{ uri: hoge }}
style={{
height: 105,
width: 95,
position: 'relative', // because it's parent
top: 7,
left: 5
}}
>
<Text
style={{
fontWeight: 'bold',
color: 'white',
position: 'absolute', // child
bottom: 0, // position where you want
left: 0
}}
>
hoge
</Text>
</ImageBackground>

Material UI GridTile height

I'm currently working with material ui and I'm running into an issue with GridLists. I have a GridList with multiple GridTiles and I don't see any way to change the height of each GridList separately. We are provided a prop for GridLists that let us specify the GridList cellHeight, but not for individual GridTiles. Does anyone know of a way to accomplish this?
GriList entry on material ui site Material Ui Grid List
I currently have the following (which does not work).
<GridList style={gridListStyle}>
<GridTile style={gridStyle1} titlePosition="bottom">
<div>
stuff
</div>
</GridTile>
<GridTile style={gridStyle2}>
<div>
junk
</div>
</GridTile>
</GridList>
While not an ideal solution, I ended up overriding the height of the GridTile component by adding 100% height !important. This allowed me to set the height to exactly what I needed.
var gridTileStyle= {
position: 'relative',
float: 'left',
width: '100%',
minHeight: '400px',
minWidth: '664px',
overflow: 'hidden',
height: '100% !important'
}
This allowed the component to dynamically resize in the window as the page got smaller, without the GridTile underneathe it overlapping it. Hopefully this helps someone else in the future.
You can also add some flex styling, which could help you with spacing your Tiles appropriately; for examples of flex settings available in Material-UI see https://material-ui.com/layout/grid/ (don't stop just because you see grid - I've successfully implemented these properties in a GridList too!).
Setting minHeight: '100vh'
helped me to get a grid element to height of 100%.
I tried all other elements and variants and did not help.

How to define width by percentage in react native?

I am trying to create a view with a border around it that is centered and fills 80% of the screen. I have come up with this:
<View style={{flexDirection: 'row'}}>
<View style={{flex: .1}} />
<View style={{flex: .8, borderWidth: 2}} />
<View style={{flex: .1}} />
</View>
which works, but seems awfully verbose.
Is there a better (more succinct) way to create a view that is a certain percentage of the screen width and centered in the page?
UPDATE:
Starting from React Native version 0.42 we now have a full percentage support for width, height , padding and so on, see the full list and examples here:
https://github.com/facebook/react-native/commit/3f49e743bea730907066677c7cbfbb1260677d11
Old method:
Consider using Dimensions, like:
import Dimensions from 'Dimensions';
and then in element's style:
width: Dimensions.get('window').width / 100 * 80,
Working example: https://rnplay.org/apps/4pdwlg

Categories

Resources