React native svg chart graphs - react-native

import React from 'react'
import { BarChart, Grid } from 'react-native-svg-charts'
import { Defs, LinearGradient, Stop } from "react-native-svg";
class ColorBarExample extends React.PureComponent {
render() {
const data = [
{
value: 50,
},
{
value: 10,
svg: {
fill: 'rgba(134, 65, 244, 0.5)',
},
},
{
value: 40,
svg: {
stroke: 'purple',
strokeWidth: 2,
fill: 'white',
strokeDasharray: [ 4, 2 ],
},
},
{
value: 95,
svg: {
fill: 'url(#gradient)',
},
},
{
value: 85,
svg: {
fill: 'green',
},
},
]
const Gradient = () => (
<Defs key={'gradient'}>
<LinearGradient id={'gradient'} x1={'0'} y={'0%'} x2={'100%'} y2={'0%'}>
<Stop offset={'0%'} stopColor={'rgb(134, 65, 244)'}/>
<Stop offset={'100%'} stopColor={'rgb(66, 194, 244)'}/>
</LinearGradient>
</Defs>
)
return (
<BarChart
style={{ height: 200 }}
data={data}
gridMin={0}
svg={{ fill: 'rgba(134, 65, 244, 0.8)' }}
yAccessor={({ item }) => item.value}
contentInset={{ top: 20, bottom: 20 }}
>
<Grid/>
<Gradient/>
</BarChart>
)
}
}
export default ColorBarExample
As this is giving me a simple gradient but i am need a gradient like this. How can i get it in this gradient .
Let me know how can i draw it like this image so that each gradient have some borderradius at the top and and have a custom gradient colors as per image and also can be of small width instead of long.

You can give vertical gradient by this x2={'0%'} y2={'100%'} in Gradient function and for rounded corners you can try this
To change width of bar you may try spacingInner property.
To give gradient to all bars, we should manage svg fill property of data array.
here is the link of your barchart code demo. Please check if it helps.

Related

How do I render vertical victory native legend to the right of chart?

I have the following code and the associated result. However, my goal is to render the pie chart to the left and the legend to the right. Sometimes, my categories are a lot, so I would like to make the legend scrollable.
In summary, what I need help with is displaying the two with 50-50 split of the screen
export default () => {
const { Layout } = useTheme()
return <View style={Layout.rowCenter}>
<VictoryContainer width={400} height={400} style={{ padding: 10 }}>
<VictoryLegend
standalone={false}
centerTitle
orientation="horizontal"
style={{ labels: { fontSize: 20, fill: "white" } }}
gutter={20}
width={400}
colorScale={colorScale || ["tomato", "lightgreen", "gold", "cyan", "navy", 'teal', 'magenta', 'green', 'orange', 'aqua', 'fuchsia', 'purple']}
data={[
{ name: "one" },
{ name: "Two", },
{ name: "Three", },
{ name: "four", },
{ name: "five", }
]}
/>
<VictoryPie
standalone={false}
margin={{
top: 20
}}
width={400}
height={400}
colorScale={colorScale || ["tomato", "lightgreen", "gold", "cyan", "navy", 'teal', 'magenta', 'green', 'orange', 'aqua', 'fuchsia', 'purple']}
labels={() => null}
data={[
{ x: "one", y: 35 },
{ x: "Two", y: 40 },
{ x: "Three", y: 25 },
{ x: "four", y: 55 },
{ x: "five", y: 55 }
]}
/>
</VictoryContainer>
</View>
}
use react native svg and adjust the height, width and distance from left and right using viewBox prop of react native svg, this way we can arrange and display the items in 50-50 split of the screen. Hope this answer helps.

react-native-chart-kit issue check the render method

I am testing the package react-native-chart-kit, I follow the tutorial just to see how it could look like but I can't get it work correctly. I tried with piechart and barchart also but still the same mistake. Could you guide me to check what's wrong with :
import React from 'react'
import { Text, View, TouchableOpacity, Dimensions } from 'react-native'
import LineChart from 'react-native-chart-kit'
const screenWidth = Dimensions.get("window").width;
const linedata = {
labels: ['January', 'February', 'March', 'April', 'May', 'June'],
datasets: [
{
data: [20, 45, 28, 80, 99, 43],
strokeWidth: 2, // optional
},
],
};
export default function Linechart() {
return (
<View>
<Text>
Bezier Line Chart
</Text>
<LineChart
data={linedata}
width={Dimensions.get('window').width} // from react-native
height={220}
yAxisLabel={'$'}
chartConfig={{
backgroundColor: '#e26a00',
backgroundGradientFrom: '#fb8c00',
backgroundGradientTo: '#ffa726',
decimalPlaces: 2, // optional, defaults to 2dp
color: (opacity = 1) => `rgba(255, 255, 255, ${opacity})`,
style: {
borderRadius: 16
}
}}
bezier
style={{
marginVertical: 8,
borderRadius: 16
}}
/>
</View>
);
}
Just import it inside the curly brackets.
import { LineChart } from 'react-native-chart-kit';
Anytime you see this error message, it is better to suspect an existence of a wrong import statement first.

Charts libraries are not working in React Native

I'm new to React native. I want to show some charts in my dashboard screen. I have tried both react-native-chart-kit and react-native-pie libraries. But, both are showing me same error. I followed everything as mentioned in the docs.
Here is the code and error. kindly share your ideas.
import React, { Component } from 'react';
import { View, Text } from 'react-native';
import {
LineChart,
BarChart,
PieChart,
ProgressChart,
ContributionGraph,
StackedBarChart
} from "react-native-chart-kit";
const App = props =>
{
return(
<View style={{flex:1, alignItems:'center', justifyContent:'center'}}>
<Text>Charts Container</Text>
<LineChart
data={{
labels: ["January", "February", "March", "April", "May", "June"],
datasets: [
{
data: [
Math.random() * 100,
Math.random() * 100,
Math.random() * 100,
Math.random() * 100,
Math.random() * 100,
Math.random() * 100
]
}
]
}}
width={Dimensions.get("window").width} // from react-native
height={220}
yAxisLabel="$"
yAxisSuffix="k"
yAxisInterval={1} // optional, defaults to 1
chartConfig={{
backgroundColor: "#e26a00",
backgroundGradientFrom: "#fb8c00",
backgroundGradientTo: "#ffa726",
decimalPlaces: 2, // optional, defaults to 2dp
color: (opacity = 1) => `rgba(255, 255, 255, ${opacity})`,
labelColor: (opacity = 1) => `rgba(255, 255, 255, ${opacity})`,
style: {
borderRadius: 16
},
propsForDots: {
r: "6",
strokeWidth: "2",
stroke: "#ffa726"
}
}}
bezier
style={{
marginVertical: 8,
borderRadius: 16
}}
/>
</View>
)
}
export default App;

how to implement React native countdown circle

someone, please help me implementing countdown circle in react-native
I want the timer to start at 300 seconds goes down to 0 with an animated circle and text(time) inside that.
I tried using https://github.com/MrToph/react-native-countdown-circle
but here the issue is that text(time) is updated after one complete animation.
You can also see the issue I have opened there.
Below is the code snippet, of my implementation
<CountdownCircle
seconds={300}
radius={25}
borderWidth={3}
color="#006400"
bgColor="#fff"
textStyle={{ fontSize: 15 }}
onTimeElapsed={() =>
console.log('time over!')}
/>
I have changed the library file which you mentioned in your question. I know it's not good but I have tried to solve your problem.
import CountdownCircle from 'react-native-countdown-circle'//you can make your own file and import from that
<CountdownCircle
seconds={30}
radius={30}
borderWidth={8}
color="#ff003f"
bgColor="#fff"
textStyle={{ fontSize: 20 }}
onTimeElapsed={() => console.log("Elapsed!")}
/>
Here is library file which now you can use it as a component also here is that react-native-countdown-circle library file code(modified code)
import React from "react";
import {
Easing,
Animated,
StyleSheet,
Text,
View,
ViewPropTypes
} from "react-native";
import PropTypes from "prop-types";
// compatability for react-native versions < 0.44
const ViewPropTypesStyle = ViewPropTypes
? ViewPropTypes.style
: View.propTypes.style;
const styles = StyleSheet.create({
outerCircle: {
justifyContent: "center",
alignItems: "center",
backgroundColor: "#e3e3e3"
},
innerCircle: {
overflow: "hidden",
justifyContent: "center",
alignItems: "center",
backgroundColor: "#fff"
},
leftWrap: {
position: "absolute",
top: 0,
left: 0
},
halfCircle: {
position: "absolute",
top: 0,
left: 0,
borderTopRightRadius: 0,
borderBottomRightRadius: 0,
backgroundColor: "#f00"
}
});
function calcInterpolationValuesForHalfCircle1(animatedValue, { shadowColor }) {
const rotate = animatedValue.interpolate({
inputRange: [0, 50, 50, 100],
outputRange: ["0deg", "180deg", "180deg", "180deg"]
});
const backgroundColor = shadowColor;
return { rotate, backgroundColor };
}
function calcInterpolationValuesForHalfCircle2(
animatedValue,
{ color, shadowColor }
) {
const rotate = animatedValue.interpolate({
inputRange: [0, 50, 50, 100],
outputRange: ["0deg", "0deg", "180deg", "360deg"]
});
const backgroundColor = animatedValue.interpolate({
inputRange: [0, 50, 50, 100],
outputRange: [color, color, shadowColor, shadowColor]
});
return { rotate, backgroundColor };
}
function getInitialState(props) {
console.log();
return {
circleProgress,
secondsElapsed: 0,
text: props.updateText(0, props.seconds),
interpolationValuesHalfCircle1: calcInterpolationValuesForHalfCircle1(
circleProgress,
props
),
interpolationValuesHalfCircle2: calcInterpolationValuesForHalfCircle2(
circleProgress,
props
)
};
}
const circleProgress = new Animated.Value(0);
export default class PercentageCircle extends React.PureComponent {
static propTypes = {
seconds: PropTypes.number.isRequired,
radius: PropTypes.number.isRequired,
color: PropTypes.string,
shadowColor: PropTypes.string, // eslint-disable-line react/no-unused-prop-types
bgColor: PropTypes.string,
borderWidth: PropTypes.number,
containerStyle: ViewPropTypesStyle,
textStyle: Text.propTypes.style,
updateText: PropTypes.func,
onTimeElapsed: PropTypes.func
};
static defaultProps = {
color: "#f00",
shadowColor: "#999",
bgColor: "#e9e9ef",
borderWidth: 2,
seconds: 10,
children: null,
containerStyle: null,
textStyle: null,
onTimeElapsed: () => null,
updateText: (elapsedSeconds, totalSeconds) =>
(totalSeconds - elapsedSeconds).toString()
};
constructor(props) {
super(props);
this.state = getInitialState(props);
this.restartAnimation();
}
componentWillReceiveProps(nextProps) {
if (this.props.seconds !== nextProps.seconds) {
this.setState(getInitialState(nextProps));
}
}
onCircleAnimated = ({ finished }) => {
// if animation was interrupted by stopAnimation don't restart it.
if (!finished) return;
const secondsElapsed = this.state.secondsElapsed + 1;
const callback =
secondsElapsed < this.props.seconds
? this.restartAnimation
: this.props.onTimeElapsed;
const updatedText = this.props.updateText(
secondsElapsed,
this.props.seconds
);
this.setState(
{
...getInitialState(this.props),
secondsElapsed,
text: updatedText
},
callback
);
};
restartAnimation = () => {
Animated.timing(this.state.circleProgress, {
toValue:
parseFloat(JSON.stringify(this.state.circleProgress)) +
100 / this.props.seconds,
duration: 1000,
easing: Easing.linear
}).start(this.onCircleAnimated);
};
renderHalfCircle({ rotate, backgroundColor }) {
const { radius } = this.props;
return (
<View
style={[
styles.leftWrap,
{
width: radius,
height: radius * 2
}
]}
>
<Animated.View
style={[
styles.halfCircle,
{
width: radius,
height: radius * 2,
borderRadius: radius,
backgroundColor,
transform: [
{ translateX: radius / 2 },
{ rotate },
{ translateX: -radius / 2 }
]
}
]}
/>
</View>
);
}
renderInnerCircle() {
const radiusMinusBorder = this.props.radius - this.props.borderWidth;
return (
<View
style={[
styles.innerCircle,
{
width: radiusMinusBorder * 2,
height: radiusMinusBorder * 2,
borderRadius: radiusMinusBorder,
backgroundColor: this.props.bgColor,
...this.props.containerStyle
}
]}
>
<Text style={this.props.textStyle}>{this.state.text}</Text>
</View>
);
}
render() {
const {
interpolationValuesHalfCircle1,
interpolationValuesHalfCircle2
} = this.state;
return (
<View
style={[
styles.outerCircle,
{
width: this.props.radius * 2,
height: this.props.radius * 2,
borderRadius: this.props.radius,
backgroundColor: this.props.color
}
]}
>
{this.renderHalfCircle(interpolationValuesHalfCircle1)}
{this.renderHalfCircle(interpolationValuesHalfCircle2)}
{this.renderInnerCircle()}
</View>
);
}
}

Flash of content before/after rotate transform animation (flip card animation)

I see this behavior on both iOS and Android. Do you know why the content within the card flashes (hides then reappears instantly) after the transform animation starts (and also right before the animation ends).
This only happens if I do rotate, rotateY, or rotateX (untested rotateZ). I have no idea why.
Here is screencast:
High quality webm - https://gfycat.com/SplendidCompetentEnglishpointer
Low quality gif:
My render code is this:
<View style={style}>
<Animated.View style={[styleCommon, styleFace]}><Text>front</Text></Animated.View>
<Animated.View style={[styleCommon, styleBack]}><Text>front</Text></Animated.View>
</View>
And my styles are:
const styleCommon = {
justifyContent: 'center',
alignItems: 'center',
borderRadius: 10,
elevation: 2,
shadowRadius: 2,
shadowOpacity: 0.4,
shadowOffset: { height:1 },
overflow: 'hidden',
width: '100%',
height: '100%',
position: 'absolute',
backgroundColor: '#FFFFFF'
}
const styleFace = {
opacity: anim.interpolate({ inputRange:[0,.5,.5,1], outputRange:[1,1,0,0] }),
transform: [
{ rotateY:anim.interpolate({ inputRange:[0,1], outputRange:['0deg', '180deg'] }) }
]
};
const styleBack = {
opacity: anim.interpolate({ inputRange:[0,.5,.5,1], outputRange:[0,0,1,1] }),
transform: [
{ rotateY:anim.interpolate({ inputRange:[0,1], outputRange:['-180deg', '0deg'] }) }
]
};
I found it should be a bug of transform in react-native, showing view from 0.1 deg to 0.4 deg, and from -0.1 deg to -0.4 deg. Everything disappears within these degree.
That can be easily proven, by set start degree to 0.1 ~ 0.4.
transform: [
{ rotateY:anim.interpolate({ inputRange:[0,1], outputRange:['0.1deg', '180deg'] }) }
]
A quick workaround for this could be bypassing those Bermuda Degree:
const styleFace = {
transform: [
{ rotateY:this.anim.interpolate({ inputRange:[0,0.01,0.01,1], outputRange:['0deg', '0deg', '0.4deg', '180deg'] }) }
]
};
const styleBack = {
transform: [
{ rotateY:this.anim.interpolate({ inputRange:[0,0.99,0.99,1], outputRange:['-180deg', '-0.4deg', '0deg', '0deg'] }) }
]
};
Result: