How Can I Display SVG Data In React Native? - react-native

I have some SVG image data that I would like to import into my React Native App.
Is there any way to take my raw SVG image data and display it without saving it to a file?
I have an api that will create an image based from any given text (coolProgrammer123) and will return the SVG image data.
https://api.kwelo.com/v1/media/identicon/coolProgrammer123?format=base64
Any Ideas? Thanks.

I'll suggest you try out react-native-svg-uri
import SvgUri from 'react-native-svg-uri';
const TestSvgUri = () => (
<View style={styles.container}>
<SvgUri
width="200"
height="200"
source={{uri:'http://thenewcode.com/assets/images/thumbnails/homer-simpson.svg'}}
/>
</View>
);
UPDATE
Here is a code snippet on how you can use to use axios to get the SVG from the URL and pass it to the Image tag without using the above npm package.
import React, { Component } from 'react';
import { View, Image } from 'react-native';
import axios from 'axios';
class App extends Component {
constructor(props) {
super(props);
this.state = {
imageUri: ''
}
}
componentDidMount() {
this.getSvg();
}
getSvg = () => {
let image_base64;
axios.get('https://api.kwelo.com/v1/media/identicon/coolProgrammer123?format=base64')
.then(response => {
image_base64 = response.data;
this.setState({
...this.state,
imageUri: image_base64
})
})
.catch(function (error) {
console.log(error);
});
return image_base64;
}
render(){
return (
<View>
<Image
style={{
width: 81,
height: 81,
resizeMode: 'contain',
marginTop: 180,
marginLeft: 20,
marginRight: 20,
alignSelf: "center"
}}
source={{ uri: this.state.imageUri }}
/>
</View>
);
}
};
export default App;

Related

react-native-image-crop-tools CropView not showing image to be cropped

I am using react-native-image-crop-tools for cropping the image but CropView not showing the image to be cropped only a blank screen is showing. any solution regarding this?
import { CropView } from 'react-native-image-crop-tools';
const [uri, setUri] = useState('https://cdn.pixabay.com/photo/2015/04/23/22/00/tree-736885__480.jpg');
{uri !== undefined && <CropView
sourceUrl={uri}
style={{flex:1}}
ref={cropViewRef}
onImageCrop={(res) => console.warn(res)}
keepAspectRatio
aspectRatio={{ width: 16, height: 9 }}
/>}
Try this, I hope it will help you.
app.js
import React, { useState, useRef } from 'react';
import { Button, StyleSheet, View} from 'react-native';
import { CropView } from 'react-native-image-crop-tools';
import { launchImageLibrary } from 'react-native-image-picker';
export default function app() {
const [uri, setUri] = useState();
const cropViewRef = useRef();
let options = {
mediaType: 'photo',
quality: 1,
};
return (
<>
<View style={styles.container}>
<Button
title={'Pick Image'}
onPress={() => {
launchImageLibrary(options, response => {
setUri(response.assets[0].uri);
});
}}
/>
{uri !== undefined && <CropView
sourceUrl={uri}
style={styles.cropView}
ref={cropViewRef}
onImageCrop={(res) => console.log(res)}
keepAspectRatio
aspectRatio={{ width: 16, height: 9 }}
/>}
<Button
title={'Get Cropped View'}
onPress={() => {
cropViewRef.current.saveImage(true, 100);
}}
/>
</View>
</>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
},
cropView: {
flex: 1,
backgroundColor: '#000'
},
});
The library doesn't support remote images. It working in iOS is merely coincidental as might the native ios library supports for the cropping of network images.
If you want to crop a remote image please download it first using RNFetchBlob and then pass the local file path to it.
Supporting remote images directly is a somewhat complicated task and out of scope for this project.
You also can check out the closed issue in the library.
https://github.com/hhunaid/react-native-image-crop-tools/issues/16
You can have a try with the below example to crop the network images in the android platform:
For ex:
import React, {useCallback, useEffect, useState} from 'react';
import {View, Text} from 'react-native';
import {CropView} from 'react-native-image-crop-tools';
import RNFetchBlob from 'rn-fetch-blob';
export default () => {
const [uri, setUri] = useState('');
const getImage = useCallback(() => {
try {
RNFetchBlob.config({
fileCache: true,
// by adding this option, the temp files will have a file extension
appendExt: 'png',
})
.fetch(
'GET',
'https://cdn.pixabay.com/photo/2015/04/23/22/00/tree-736885__480.jpg',
)
.then(res => {
let status = res.info().status;
if (status === 200) {
setUri('file://' + res.path());
} else {
console.log(status);
}
})
// Something went wrong:
.catch((errorMessage, statusCode) => {
// error handling
console.log('Error : ', errorMessage);
});
} catch (err) {
console.log('Error : ', err.message);
}
}, []);
useEffect(() => {
getImage();
}, [getImage]);
if (uri === '') {
return (
<View style={{flex: 1, alignItems: 'center', justifyContent: 'center'}}>
<Text>{'processing...'}</Text>
</View>
);
}
return (
<CropView
sourceUrl={uri}
style={{flex: 1, height: '100%', width: '100%'}}
// ref={cropViewRef}
onImageCrop={res => console.warn(res)}
keepAspectRatio
aspectRatio={{width: 16, height: 9}}
/>
);
};

Selecting pictures in react native

I am using the react native camera roll function to retrieve videos from my phone's camera roll. I am able to get the videos to show up in a gallery in my app, but I can't seem to figure out how to make a button to open up this video and actually play it. Here is my code so far:
import React, {Component} from 'react';
import {
View,
Image,
FlatList,
PermissionsAndroid,
Platform,
} from 'react-native';
import CameraRoll from '#react-native-community/cameraroll';
class showVideo extends Component {
constructor(props) {
super(props);
this.state = {
data: '',
};
}
async componentDidMount() {
if (Platform.OS === 'android') {
const result = await PermissionsAndroid.request(
PermissionsAndroid.PERMISSIONS.READ_EXTERNAL_STORAGE,
{
title: 'Permission Explanation',
message: 'ReactNativeForYou would like to access your photos!',
},
);
if (result !== 'granted') {
console.log('Access to pictures was denied');
return;
}
}
CameraRoll.getPhotos({
first: 50,
assetType: 'All',
})
.then(res => {
this.setState({data: res.edges});
})
.catch(error => {
console.log(error);
});
}
render() {
return (
<View>
<FlatList
data={this.state.data}
numColumns={3}
renderItem={({item}) => (
<Image
style={{
width: '33%',
height: 150,
}}
source={{uri: item.node.image.uri}}
/>
)}
/>
</View>
);
}
}
export default showVideo;
Any pointers or recommendations? All I have is a static overview of videos pulled from my camera roll in my app.
I may suggest you to use <TouchableHighlight /> added outside the <Image/> tag to catch when onPress. Is this what you want? It could know just press on image.
import { TouchableHighlight } from "react-native";
<TouchableHighlight onPress={() => this.functionToPlayVideo(item.node.image.uri)}>
<Image
style={{
width: '33%',
height: 150,
}}
source={{uri: item.node.image.uri}}
/>
</TouchableHighlight>

How to show loading progress or spinner in the middle of the screen with React Native?

I am developing React Native app.
I was able to solve all problems by myself but this is exception.
I am going to load another screen with bottom tab navigator.
For example, after user login to the app, it should show main home screen which has many pictures and many style sheet effects, icons. Because of that, after login confirm ( I mean after alert of the login confirm), the main home screen appears after a few seconds.
So I want to show some spinner in the login screen while loading main home screen in the background and when it is ready to show, erase spinner and show main home screen.
How can I do this?
My bottom tab navigator was simply created with createBottomTabNavigator() method.
So in your case you can do several things
You can use React Native Activity Indicator -> View
You can use Overlay Library -> react-native-loading-spinner-overlay -> View GitHub
If you like to make loading like facebook / instagram -> then use react-native-easy-content-loader -> View GitHub
Assume that you are using React Native Activity Indicator :
import { ActivityIndicator } from "react-native";
export default class HomeScreen extends Component {
constructor(props) {
super(props);
this.state = {
isLoading: true
};
}
//Get Home Screen Data API Action
componentDidMount() {
this.loadAPI(); // Call home screen get data API function
}
//Login API Function
loadAPI = () => {
this.setState({ isLoading: true }); // Once You Call the API Action loading will be true
fetch(API_URL, {
method: "POST",
headers: {
"Content-Type": "application/json"
}
})
.then(response => response.json())
.then(responseText => {
// You can do anything accroding to your API response
this.setState({ isLoading: false }); // After getting response make loading to false
})
.catch(error => {});
};
render() {
return (
<View style={{ flex: 1, justifyContent: "center", alignItems: "center" }}>
{this.state.isLoading && <ActivityIndicator color={"#fff"} />}
</View>
);
}
}
If you want to hide all the view until loading finish like images, so you can use custom library instead of Activity Indicator.
I have created my custom Loader component. Using this you can display built in ActivityIndicator or your custom gif loader image with overlay.
Loader.js
import React, { Component } from 'react';
import {
StyleSheet,
View,
Modal,
Image,
ActivityIndicator
} from 'react-native';
class Loader extends Component {
constructor(props) {
super(props);
this.state = {
isLoading: this.props.isLoading
}
}
static getDerivedStateFromProps(nextProps) {
return {
isLoading: nextProps.isLoading
};
}
render() {
return (
<Modal
transparent={true}
animationType={'none'}
visible={this.state.isLoading}
style={{ zIndex: 1100 }}
onRequestClose={() => { }}>
<View style={styles.modalBackground}>
<View style={styles.activityIndicatorWrapper}>
<ActivityIndicator animating={this.state.isLoading} color="black" />
{/* If you want to image set source here */}
{/* <Image
source={require('../assets/images/loader.gif')}
style={{ height: 80, width: 80 }}
resizeMode="contain"
resizeMethod="resize"
/> */}
</View>
</View>
</Modal>
)
}
}
const styles = StyleSheet.create({
modalBackground: {
flex: 1,
alignItems: 'center',
flexDirection: 'column',
justifyContent: 'space-around',
backgroundColor: '#rgba(0, 0, 0, 0.5)',
zIndex: 1000
},
activityIndicatorWrapper: {
backgroundColor: '#FFFFFF',
height: 100,
width: 100,
borderRadius: 10,
display: 'flex',
alignItems: 'center',
justifyContent: 'space-around'
}
});
export default Loader
Now you can use it when you have to display loading indicator as below :
<Loader isLoading={this.state.isLoading} />
import { ActivityIndicator } from 'react-native';
export default class LoginScreen extends Component {
constructor(props) {
super(props);
this.state = {
spinner : true
}
}
render() {
return (
<View style={{flex : 1, justifyContent: 'center', alignItems: 'center',}}>
{
this.state.spinner &&
<ActivityIndicator color={'#fff'} />
}
</View>
)
}
}
So you can show the SPinner for suppose when you have to load an API or something and when you get the response of api, you can set spinner loading value to false.
For eg :
import {View, ActivityIndicator } from 'react-native';
export default class MainScreen extends React.Component {
constructor(props) {
super(props);
this.state = {
spinner : true
}
}
componentDidMount(){
this.loadApi();
}
loadApi = async() => {
let result = axios.get('url').then((data) =>{
this.setState({spinner:false});
}
).catch((err) => this.setState({spinner:false})
}
render() {
return (
<View style={{flex : 1, justifyContent: 'center', alignItems: 'center',}}>
{
this.state.spinner? <ActivityIndicator color={'#fff'} />:<View><Text>Data loaded</Text></View>
}
</View>
)
}
}
you have to use ActivityIndicator you can have to load this activityindicator before getting data from the server , you have to check below code hope you will understand
import React, {useEffect, useState} from 'react';
import {ActivityIndicator, View, Dimensions} from 'react-native';
import HomeScreen from './Home';
const DataViewer = () => {
const [data, setData] = useState([]);
const {height, width} = Dimensions.get('window');
useEffect(() => {
fetch('http://example.com/movies.json')
.then(response => {
return response.json();
})
.then(myJson => {
setData(myJson);
});
});
return data.length > 0 ? (
<HomeScreen data={data} />
) : (
<View
style={{justifyContent: 'center', alignItems: 'center', height, width}}>
<ActivityIndicator size="large" color="#0000ff" />
</View>
);
};
export default DataViewer;
You can use the Activity indicator as the default loading animation. But you can also use Lottie files to implement custom loading screen animation on your project by installing npm i lottie-react-native or yarn add lottie-react-native

React Native Loading image off API Fetch data

I am new to React Native! And having problems with properly loading the image off the JSON that I get from JsonPlaceHolder API. I set the state of the photos and the titles. The titles were able to load, however, photos were not be able to load properly. I did search and there are suggestions to replace http to https call would fix it. But No luck here. Please help! And Thank in Advance!
import React, { Component } from 'react';
import {
Image,
StyleSheet,
Text,
View,
} from 'react-native';
export default class App extends Component {
constructor(props){
super(props);
this.state = {
photos: '',
titles: ''
};
}
componentWillMount(){
this.fetchData();
}
fetchData = async () => {
let response = await fetch('http://jsonplaceholder.typicode.com/photos/1');
let json = await response.json();
this.setState({titles: json.title, photos: json.url.replace('http','https')});
};
render() {
console.log(this.state.photos)
return (
<View style={styles.container}>
<Image
source={{uri: this.state.photos}}
style={{height: 600, width: 600}}
resizeMode= 'cover'
/>
<Text>
Title: {this.state.titles}
</Text>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
backgroundColor: '#ecf0f1',
}
});
Hey so I ran your exact code except i replaced
this.setState({titles: json.title, photos: json.url.replace('http','https')});
with
this.setState( {
title: json.title,
photos: json.url,
} )
and it works fine for me, it simply gives me the error for not having an empty string as uri which is expected.

Displaying Images and text in ListView for React Native

I am trying to load images via a url and text using ListView and show data into List but when I populate it in a listview Image and text then my images are not show.
My code is:
import React, { Component } from "react";
import { ListView, Text, View, Image, StyleSheet } from "react-native";
const styles = Style.create({
container: {
flex: 1,
marginTop: 20
}
});
class ListViewDemo extends React.Component {
constructor(props) {
super(props);
const ds = new ListView.DataSource({
rowHasChanged: (r1, r2) => r1 !== r2
});
this.state = {
dataSource: ds.cloneWithRows(["row 1", "row 2"])
};
}
render() {
return (
<ListView
dataSource={this.state.dataSource}
renderRow={data => {
<View style={styles.container}>
<Image
source={{
uri:
"https://upload.wikimedia.org/wikipedia/commons/d/de/Bananavarieties.jpg"
}}
style={{ width: 193, height: 110 }}
/>
<Text> Asad </Text>
</View>;
}}
/>
);
}
} [enter image description here][1]
export default ListViewDemo;
Problem
The images would not render in your list view.
Solution
I have noticed sometimes having trouble getting images to show up when components render in react. Especially when they are loaded over a network call. I added a style to your image component, placed the image source into a variable and fixed some syntax errors you had in your code.
The biggest problem, and the reason it was not rendering the image was you added {} around your renderRow prop which would call for the need of a return statement. When you supply () around the return data, return is implied because your using a fat arrow function.
So this,
renderRow = { (data) => { }}
Became this,
renderRow={data => ( )}
Example
You can copy and paste this whole component into you code and it will work.
This has been tested,
import React, { Component } from 'react'; import { ListView, Text, View, Image, StyleSheet } from 'react-native';
const styles = StyleSheet.create({
container: {
flex: 1,
marginTop: 20,
},
img: {
width: 193,
height: 110,
},
});
class ListViewDemo extends Component {
constructor(props) {
super(props);
const ds = new ListView.DataSource({ rowHasChanged: (r1, r2) => r1 !== r2 });
this.state = {
dataSource: ds.cloneWithRows(['row 1', 'row 2']),
};
}
render() {
const imageSource = 'https://upload.wikimedia.org/wikipedia/commons/d/de/Bananavarieties.jpg';
return (
<ListView
dataSource={this.state.dataSource}
renderRow={data => (
<View style={styles.container}>
<Image
source={{ uri: imageSource }}
style={styles.img}
/>
<Text>{data}</Text>
</View>)}
/>
);
}
}
export default ListViewDemo;
Proof of Concept
Please see the image showing your component working now,
React Native provides a suite of components for presenting lists of data. Generally, you'll want to use either FlatList or SectionList first and then provide the image in the data source.
import React from 'react';
import { FlatList, StyleSheet, Text, View } from 'react-native';
const styles = StyleSheet.create({
container: {
flex: 1,
paddingTop: 22
},
item: {
padding: 10,
fontSize: 18,
height: 44,
},
img: {
width: 100,
height: 100
},
});
const FlatListBasics = () => {
return (
<View style={styles.container}>
<FlatList
data={[
{key: 'Devin', image: 'image1.png'},
{key: 'Dan', image:'image2.png'},
]}
renderItem={({item}) => <Image source={item.image} style={styles.img} /><Text style={styles.item}>{item.key}</Text>}
/>
</View>
);
}
export default FlatListBasics;
reference: https://reactnative.dev/docs/using-a-listview