xanderdeseyn / react-native-responsive-linechart

A customizable and responsive line or area chart for react-native
https://react-native-responsive-linechart.surge.sh
MIT License
202 stars 46 forks source link

Question - plotting dates in X-axis #45

Closed olympiawoj closed 3 years ago

olympiawoj commented 3 years ago

Hello! I've come across this library after trying a few other solutions for React Native charting. I am trying to adapt one of the area + line chart demos to fit my needs plotting a history of stock price over time.. I see that the value for the x-axis requires a number. Do you have any recommendations for how to best translate date -> number in order to plot this in the chart while also being able to control the x-axis labels? e.g x: dateFns.format(new Date(key), 'M') and only plotting x-axis labels of Jan, Feb, March, etc through December? I originally tried just converting the date to a month, and then quickly realized, that would not work at all. I'll try converting every date to an integer and plotting that over time.

stockData is an array of objects where:

Object {
    "x": "Dec 30", // formatted date
    "y": 121,
  }

import React, { useEffect, useState } from 'react'
import {Chart, VerticalAxis, HorizontalAxis, Area, Line, Tooltip} from 'react-native-responsive-linechart'
import * as dateFns from 'date-fns'

export const ResponsiveStockChart = ({data}:any)=>{
    const [stockData, setStockData] = useState<any[]>([])
    console.log('ResponsiveStockChart', stockData)
    useEffect(()=>{
        const stockDataArr:any[] = []
        for (let [key, value] of Object.entries(data)) {
            let newPrice = parseInt(value["close"]).toFixed(2) 
            const newObj  = {
                dateFns.format(new Date(key), 'MMM-dd'), // Dec-31, Dec30
                //@ts-ignore
                y: newPrice
            }
            newObj.y && stockDataArr.unshift(newObj)
          }
         setStockData(stockDataArr.slice(70, 100))
    }, [data])

    return (
        <Chart
        style={{ height: 200, width: '100%' }}
        data={stockData}
        padding={{ left: 40, bottom: 20, right: 20, top: 20 }}
        xDomain={{ min: -2, max: 1 }}
        yDomain={{ min: -4, max: 150 }}
      >
        <VerticalAxis tickCount={10} theme={{ labels: { formatter: (v) => v.toFixed(2) } }} />
        <HorizontalAxis tickCount={3} />
        <Area theme={{ gradient: { from: { color: '#44bd32' }, to: { color: '#44bd32', opacity: 0.2 } } }} />
        <Line
          tooltipComponent={<Tooltip />}
          theme={{ stroke: { color: '#44bd32', width: 5 }, scatter: { default: { width: 8, height: 8, rx: 4, color: '#44ad32' }, selected: { color: 'red' } } }}
        />
      </Chart>
    )
}
xanderdeseyn commented 3 years ago

Hi there, converting to a number will probably be your best bet indeed. Optionally, you can pass the date or any other info you need in the labelFormatter in the meta prop of the chart datapoints.

olympiawoj commented 3 years ago

Thanks for confirming. I was able to plot a chart by converting the x-axis values to index numbers - but how can I access the meta tag in the formatter function?

If newObj looks like this:

           const newObj:MyObject  = {
                x: i.toString(),
                y: newPrice,
                meta: dateFns.format(new Date(key), 'MMM-dd')

            }

I've tried a few variations of the formatter function here, but haven't been able to get one working: <HorizontalAxis tickCount={10} theme={{ labels: { formatter: (meta) => meta.toString() , label: {color: colors.manatee}}, ticks: {visible: false} }}/>

xanderdeseyn commented 3 years ago

I just realized I confused tooltip with axis label. On the axis you don't have a datapoint of course. So you would need to convert the number you receive on the axis to a date, much you like did there for meta in MyObject.

olympiawoj commented 3 years ago

Thanks for your help @N1ghtly! I was able to put together this chart I'm pretty happy with so far - will keep adapting it to my needs, but thanks again for taking the time to respond -

IMG_3892

xanderdeseyn commented 3 years ago

Looks really cool! Good luck with the project :)

SamuelFairbrass commented 3 years ago

@olympiawoj in what format did you set the x-datapoint? Currently trying to do this myself and can't figure it out

adrian-burkhart commented 2 years ago

In case anyone else comes across this:

You can format the labels of any of the axis by passing a formatter function to the theme prop. Using that function, you can then swap out the numbers for any kind of strings.

To display dates as labels on an axis, you could for instance create an array of dates (as strings) and then pass a formatter function like this:

<HorizontalAxis
              theme={{
                labels: {
                  visible: true,
                  formatter: (v: number) => dates[v - 1],
                },
              }}
            />