In react-native-chart-kit, how to display the line chart with min-max values or "fromZero"? - react-native

Hi Stack Overflow Community,
I am creating a react native mobile application using expo. I would like to display the line chart of user-entered data using the library "react-native-chart-kit". I need to display the line chart with the minimum & maximum values or from "Zero" in the Y-axis. My questions/blockers are,
Is there any possible way to have minimum and maximum values of the Y-axis to display the line chart? I have tried the implementation in "https://stackoverflow.com/questions/65961180/react-native-chart-kit-min-and-max-value". It did not help me.
I need to display the line chart from 0 (Y-axis). But if I use the prop "fromZero" of react-native-chart-kit, the data points and the line are displaying separately in Android. Below is the code snippet,
<LineChart
data={{
labels: date,
datasets: [
{
data: systole,
strokeWidth: 2, // optional
},
{
data: diastole,
strokeWidth: 2, // optional
},
],
}}
withShadow={false}
width={Dimensions.get("window").width} // from react-native
height={205}
//yAxisLabel={"$"}
chartConfig={{
//backgroundColor: '#e26a00',
backgroundGradientFrom: "white",
backgroundGradientTo: "white",
decimalPlaces: 2, // optional, defaults to 2dp
color: (opacity = 0) => `rgba(2, 34, 82, ${opacity})`,
style: {
borderRadius: 16,
},
useShadowColorFromDataSet: false,
propsForDots: {
r: "6",
strokeWidth: "2",
stroke: "#ffa726",
},
}}
withInnerLines={false}
legend={["blut"]}
bezier
fromZero
style={{
marginVertical: 5,
borderRadius: 16,
}}
/>
Line Chart- Data points and line displaying seperately
Any helps will be appreciated :)

Related

VictoryLabel coordinates don't match VictoryChart domain

I'm displaying stock data in a VictoryChart where x is a number representing days (i.e. simply 0, 1, 2, 3... etc.) and y is the price for that day.
I've set a domain for the VictoryChart (from the lowest values to the highest) and I've got a VictoryLine that's displaying correctly.
I wanted to add some "floating" labels (not on image below) where the lowest and highest prices are and I'm having issues with the x and y coordinates of the labels as they don't seem to match the domain I've defined.
I notice that if I place a label into the chart with position x = 0, y = 0, then it's located at the top left corner (I expected bottom left). This is how it looks currently, with some test labels:
Code:
<VictoryChart
domain={{ x: [startPrice.x, endPrice.x], y: [Math.floor(lowestPrice.y), Math.ceil(highestPrice.y)] }}
>
<VictoryLine
style={{
data: { stroke: '#4CB872', strokeWidth: 4 },
}}
data={chartData}
animate={{
duration: 1000,
onLoad: { duration: 1000 },
}}
/>
<VictoryLine
style={{ data: { stroke: Colors.Beige, strokeDasharray: '2,5', strokeWidth: 1, opacity: 0.5 } }}
data={chartData.map((datum) => ({ x: datum.x, y: chartData[0].y }))}
animate={{
duration: 1000,
onLoad: { duration: 1000 },
}}
></VictoryLine>
<VictoryLabel text='x10 y10' x={10} y={10} />
<VictoryLabel text='x100 y100' x={100} y={100} />
<VictoryLabel text='x200 y200' x={200} y={200} />
</VictoryChart>
chartData is e.g.:
"chartData": [
{
"date": "2020-09-21",
"x": 0,
"y": 142.31579017,
},
{
"date": "2020-09-22",
"x": 1,
"y": 142.31420395,
},
{
"date": "2020-09-23",
"x": 2,
"y": 142.16096094,
},
{
"date": "2020-09-24",
"x": 3,
"y": 142.09860251,
},
...
How can I use x/y positioning on VictoryLabels to place them on the graph with regards to the domain I defined? E.g. the Label marked "x100 y100" should not be at position x=100,y=100 but instead x=5,y=142.5 or thereabouts.
Thanks to #boygirl from FormidableLabs I now have the solution, see (https://github.com/FormidableLabs/victory-native/issues/637)
As they wrote there:
The x, y, props on VictoryLabel correspond to svg coordinate space, not data coordinate space. You can create a custom label that uses the scale prop passed in by VictoryChart to translate data coordinates to svg coordinates
Your custom label might look something like this:
const MyLabel = props => {
const x = props.scale.x(props.x);
const y = props.scale.y(props.y)
return <VictoryLabel {...props} x={x} y={y}/>
}
and you would use it like this:
<VictoryChart>
<MyLabel x={10} y={10} />
</VictoryChart>

Legend not displaying for vue.js project using Echarts

I am working on a vue.js project and I am using the v-charts plugin. I cannot get the legend to display for any of the line graphs I am producing. I am able to produce the appropriate chart with x-axis and y-axis labels and a title for the chart. I have tried altering a ton of different options for the legend. I have also imported the legend component for e-charts individually.
I have tried multiple different formatting options for the legend.I have started a new project without any styling and still no luck. I'm sure there's something simple going on with my options object but I cannot figure it out.
Has anybody else ever run into this and found a solution?
I have been using this site as a resource for years and never asked a question. I can't figure this one out.
The chart options bar is being set in a function and the data is represented appropriately on the graph. I just need to be able to display the legend.
Code snippets and screenshot of graph below:
<template>
<div class="standard_div">
<!-- Begin chart component of graph -->
<v-chart v-if="showChart" :options="chartOptionsBar"/>
<!-- End chart component-->
</div>
</template>
<script>
// Import a different instance ECharts into the .vue file.
import ECharts from 'vue-echarts';
import 'echarts/lib/component/legend'
import 'echarts/lib/component/title'
</script>
chartOptionsBar = {
xAxis: {
// The data for the series
data: this.xAxisSeries,
// Parameters for the x axis
name: this.x_axis,
nameLocation: 'middle',
nameTextStyle: {
padding: [20, 20, 20, 20],
fontWeight: 'bold',
}
},
yAxis: {
// Parameters for the x axis
name: this.y_axis,
nameLocation: 'middle',
nameTextStyle:{
padding: [25, 25, 25, 25],
fontWeight: 'bold',
}
},
series: [
{type: 'line', data: this.yAxisSeries},
],
legend:{
top: 'auto',
left: 'auto',
right: 'auto',
bottom: 'auto',
width: '50%',
orient: 'horizontal',
lineHeight: '56',
padding: 25,
type: 'plain',
zlevel: 20,
data: ["item0"]
},
title:{
show: true,
text: this.graphTitle,
x: 'center',
textStyle: {
fontSize: 20,
}
},
};
The link includes an image of the graph that was produced from the options bar above.
I had the same problem and importing the legend using
import 'echarts/lib/component/legend'
in my component worked for me!
Try to play with positioning props

React Native Mapbox custom cluster pie chart

I'm using the package react-native-mapbox-gl/maps to generate a map with clustering. I need to be able to analyze each cluster and based on its contents generate a pie chart representing the different types of points within the cluster. Either it isn't possible or I can't figure it out given the different types of Layers and Sources. I'm honestly not even sure where to begin. Any help or pointing in the right direction is much appreciated!
I've been able to create my map using the react-native-maps package (Google Maps) and have custom clusters, but I find the memory usage of the Mapbox package to be so much better.
There is nothing special about how I'm generating my map but here is the code:
const mapStyles = {
icon: {
iconImage: ['get', 'icon'],
iconSize: [
'match',
['get', 'icon'],
'park', 0.9,
'parkLarge', 1.6,
'school', 0.9,
'schoolLarge', 1.6,
1, /* default */
],
iconAllowOverlap: true
},
clusteredPoints: {
circlePitchAlignment: 'map',
circleColor: [
'step',
['get', 'point_count'],
'#2A2E43',
100,
'#2A2E43',
750,
'#2A2E43',
],
circleRadius: ['step', ['get', 'point_count'], 20, 100, 30, 750, 40],
circleOpacity: 1,
circleStrokeWidth: 4,
circleStrokeColor: 'white',
},
clusterCount: {
textColor: 'white',
textField: '{point_count}',
textSize: 12,
textPitchAlignment: 'map',
},
};
<MapboxGL.MapView
ref={ref => (this.map = ref)}
style={{ flex: 1, zIndex: 100 }}
styleURL="mapbox://[hidden]"
onPress={() => this.props.onPressMap()}
onRegionDidChange={(region) => this.onRegionDidChange(region)}
onRegionWillChange={() => this.props.onRegionWillChange()}
pitchEnabled={false}
rotateEnabled={false}
localizeLabels={true}
>
<MapboxGL.UserLocation visible={true} />
<MapboxGL.Camera
ref={(c) => this.camera = c}
zoomLevel={this.props.zoomLevel}
centerCoordinate={this.props.location}
animationMode={'flyTo'}
animationDuration={200}
style={{ paddingBottom: 300 }}
/>
<MapboxGL.Images images={{ park: parkIcon, parkLarge: parkIcon, school: schoolIcon, schoolLarge: schoolIcon }} />
{
this.props.featureCollection && this.props.featureCollection.features && this.props.featureCollection.features.length > 0 ? (
<View>
<MapboxGL.ShapeSource
id="pointsSource"
shape={this.props.featureCollection}
onPress={(event) => this.props.onPressMarker(event)}
cluster
clusterRadius={80}
clusterMaxZoomLevel={14}
>
<MapboxGL.SymbolLayer
id="pointCount"
style={mapStyles.clusterCount}
/>
<MapboxGL.CircleLayer
id="clusteredPoints"
belowLayerID="pointCount"
filter={['has', 'point_count']}
// filter={['>', 'point_count', 1]}
style={mapStyles.clusteredPoints}
/>
<MapboxGL.SymbolLayer
id="favoritesIcons"
filter={['!', ['has', 'point_count']]}
// filter={['==', 'point_count', 1]}
style={mapStyles.icon}
/>
</MapboxGL.ShapeSource>
</View>
) : null
}
</MapboxGL.MapView>
Though the relevant example in our documentation is built with Mapbox GL JS rather than React Native, you might find this display HTML clusters with custom properties example to be a good starting point. It demonstrates how to make use of expressions to create pie chart-like SVGs for each cluster, depending on the properties of the data in the particular cluster.
A similar approach (manually synchronizing the clustered source with a pool of marker objects that updates continuously while the map view changes, rather than using a Mapbox GL layer to display the clusters) will likely be necessary in a React Native implementation as well.

How to set dynamic styles in Vue.js component from Vuex store

I'm trying to set an array of components styles directly from the store, so that when the store changes, the design of each component changes too.
I store a set of links in my Vuex store like this:
links: [
{id: 1, text: 'Banana is a test', design: {color: 'red', 'background-color': 'blue', padding: '51px', margin: '5px', 'border-width' : '10px', 'border-color': 'blue', 'font-weight' : 600, font: 'Arial'}},
{id: 2, text: 'This is a test', design: {color: 'red', 'background-color': 'blue', padding: '20px', margin: '10px', 'border-width' : '10px', 'border-color': 'green', 'font-weight' : 600, font: 'Arial'}},
{id: 3, text: 'Monkey is a test', design: {color: 'red', 'background-color': 'blue', padding: '5px', margin: '5px', 'border-width' : '10px', 'border-color': 'green', 'font-weight' : 600, font: 'Arial'}},
]
and this is how I try to render them
<a v-for="link in links" :key=link.id :href="link.destination" :id=link.id :style="link.design">
{{link.text}}
</a>
the trouble is, when the design objects changes in the Vuex store, the links styles are not subsequently updated as I would expect.
In my Vue component I've tried getting the links in different ways, assuming this would change the reactivity. Currently I get them using a computed method like so:
computed: {
getLinks: function() {
return this.$store.state.links
}
},
but whenever I change the value of a background-color, say from 'blue' to 'red', I have to reload the page to see the change. Do I need to force a rerender of the page everytime I call my mutation?
This is my mutation for reference:
setSelectedItemDesign (state, payload ) {
state.selectedItem.design[Object.keys(payload)[0]] = Object.values(payload)[0]
}
and I'd call it from my component like this:
this.$store.commit('setSelectedItemDesign', {'background-color' : this.rgbaValue})
Thats because you read value from store directly here return this.$store.state.links. This way it is not reactive and also anitpattern, because you should not access store like that.
You should create getter to get value and then it should be ok.
The problem was that I was not updating the array in my store in a way that Vue observes to trigger a view update, as nada correctly pointed out.
You can see here for more details: vuejs.org/v2/guide/list.html#Array-Change-Detection

Hide certain legend elements

I am using the names property to label a scatter chart legend. I have not been able to find a way to only show the legend for only data14, data15, data16 and data17 and hide the legend elements for data1 through data13.
data1 through data13 will always be the same, data14 through data17 could expand or collapse in number and the label text will change.
names: {
data1: '2%',
data2: '5%',
data3: '10%',
data4: '15%',
data5: '20%',
data6: '25%',
data7: '30%',
data8: '35%',
data9: '40%',
data10: '45%',
data11: '50%',
data12: '55%',
data13: '60%',
data14: 'Oracle',
data15: 'HP',
data16: 'MS',
data17: 'Oracle'
},
Set your chart legend not visible:
legend: {
show: false
}
Then, make the legend visible only with elements you want:
chart.legend.show(['data14', 'data15', 'data16', 'data17'])