Skip to content

Instantly share code, notes, and snippets.

@andreferi3
Created May 21, 2020 07:31
Show Gist options
  • Select an option

  • Save andreferi3/02e8d0aea646928c0a682c77f7f3c781 to your computer and use it in GitHub Desktop.

Select an option

Save andreferi3/02e8d0aea646928c0a682c77f7f3c781 to your computer and use it in GitHub Desktop.
import { Dimensions } from 'react-native';
import { utcParse } from 'd3';
export const { width } = Dimensions.get('screen')
export const GRAPH_MARGIN = 10
export const SVGHeight = 150
export const SVGWidth = width / 100 * 80
export const graphHeight = SVGHeight - 2 * GRAPH_MARGIN
export const graphWidth = SVGWidth - 5 * GRAPH_MARGIN
export const parseTime = utcParse("%Y-%m-%dT%H:%M:%S.%LZ")
export const xRange = [0, graphWidth - GRAPH_MARGIN]
export const yRange = [graphHeight - GRAPH_MARGIN, 0]
export function countGraphWidth(width) {
return width - 5 * GRAPH_MARGIN
}
export function countGraphHeight(height) {
return height - 2 * GRAPH_MARGIN
}
import React from 'react'
import { View, ViewPropTypes } from 'react-native'
import PropTypes from 'prop-types';
import { data1 } from '../example/Chart/dataScheme';
import { SVGHeight, SVGWidth, GRAPH_MARGIN, graphWidth, graphHeight, parseTime, xRange, yRange, countGraphHeight, countGraphWidth } from './helper/chartHelper';
import { utcParse, extent, min, max } from 'd3';
import * as shape from 'd3-shape';
import { scaleTime, scaleLinear } from 'd3-scale'
import Svg, { Defs, LinearGradient, Stop, Path, G, Line, Text } from 'react-native-svg';
import { Colors } from '../../../../assets/themes';
import moment from 'moment';
const viewPropTypes = View.propTypes || ViewPropTypes
const d3 = { shape }
/**
* @param {number} width
*/
function rangeX(width) {
let range = xRange
if (width) {
range = [0, countGraphWidth(width) - GRAPH_MARGIN]
}
return range
}
/**
* @param {number} height
*/
function rangeY(height) {
let range = yRange
if (height) {
range = [countGraphHeight(height) - GRAPH_MARGIN, 0]
}
return range
}
/**
* @param {string, arrayOfObject, string, string, View.Style, number, number} param0
*/
const NChart = ({ chartColor, data, x, y, containerStyle, height, width }) => {
const xDomain = extent(data, function (d) { return parseTime(d[x]) })
const scaleX = scaleTime().domain(xDomain).range(rangeX(width));
const yMinDomain = min(data, d => d[y])
const yMaxDomain = max(data, d => d[y])
const yBottomDomain = ((yMaxDomain - yMinDomain) < yMinDomain) ? (yMaxDomain - yMinDomain) : yMinDomain
const yTopDomain = ((yBottomDomain == yMinDomain)) ? yMaxDomain + 5 : yMaxDomain
const yDomain = [yMinDomain, yTopDomain]
const scaleY = scaleLinear().domain(yDomain).range(rangeY(height));
const yTicks = scaleLinear().domain(yDomain).ticks(5)
const line = d3.shape.line()
.x(function (d) { return scaleX(parseTime(d[x])) })
.y(function (d) { return scaleY(d[y]) })
.curve(d3.shape.curveBasis)(data)
/**
* @variation conditionalProperty
*/
const WIDTH = width ? width : SVGWidth
const HEIGHT = height ? height : SVGHeight
const GRAPH_HEIGHT = height ? countGraphHeight(height) : graphHeight
const GRAPH_WIDTH = width ? countGraphWidth(width) : graphWidth
const gradientColor = chartColor == 'green' ? Colors.colorScheme.$greenDark : Colors.colorScheme.$tertiaryDark
const lineColor = chartColor == 'green' ? Colors.colorScheme.$green : Colors.colorScheme.$red
return (
<View style={containerStyle}>
<Svg width={WIDTH} height={HEIGHT}>
<G>
<Defs>
<LinearGradient id="gradient" x1="50%" y1="0%" x2="50%" y2="100%">
<Stop offset="0%" stopColor={gradientColor} stopOpacity="0.7" />
<Stop offset="80%" stopColor={gradientColor} stopOpacity="0.2" />
<Stop offset="100%" stopColor={gradientColor} stopOpacity="0" />
</LinearGradient>
</Defs>
<Path d={`${line}L ${GRAPH_WIDTH - GRAPH_MARGIN} ${GRAPH_HEIGHT} L 0 ${GRAPH_HEIGHT}`} fill="url(#gradient)" />
<Path d={line} fill="transparent" stroke={lineColor} strokeWidth={3} />
<Line
x1={0}
y1={GRAPH_HEIGHT}
x2={GRAPH_WIDTH}
y2={GRAPH_HEIGHT}
stroke={Colors.colorScheme.$textSecondary}
strokeWidth={1}
translateY={-10}
/>
{
data.map((item, index) => (
<Line
key={index}
x1={scaleX(parseTime(item[x]))}
y1={GRAPH_HEIGHT - 2}
x2={scaleX(parseTime(item[x]))}
y2={GRAPH_HEIGHT - GRAPH_MARGIN}
stroke={Colors.colorScheme.$textSecondary}
strokeWidth={1}
/>
))
}
{
data.map((item, index) => {
return (
<Text
key={index}
x={scaleX(parseTime(item[x]))}
y={GRAPH_HEIGHT + GRAPH_MARGIN}
textAnchor="start"
fill={Colors.colorScheme.$textSecondary}
fontSize={12}
translateY={5}
>
{moment(item[x]).format('hh:mm')}
</Text>
)
})
}
{
yTicks.map((item, index) => (
<Line
key={index}
x1={GRAPH_WIDTH - 5}
y1={scaleY(item)}
x2={GRAPH_WIDTH + 7}
y2={scaleY(item)}
stroke={Colors.colorScheme.$textSecondary}
strokeWidth={1}
/>
))
}
{
yTicks.map((item, index) => (
<Line
key={index}
x1={0}
y1={scaleY(item)}
x2={GRAPH_WIDTH - 8}
y2={scaleY(item)}
stroke={Colors.colorScheme.$textSecondary}
strokeWidth={0.5}
strokeDasharray={[5, 5]}
/>
))
}
{
yTicks.map((item, index) => {
return (
<Text
key={index}
x={GRAPH_WIDTH + 10}
y={scaleY(item)}
textAnchor="start"
fontSize={12}
fill={Colors.colorScheme.$textSecondary}
>
{item + '%'}
</Text>
)
})
}
<Line
x1={GRAPH_WIDTH}
y1={scaleY(yMinDomain)}
x2={GRAPH_WIDTH}
y2={scaleY(yMaxDomain) - 15}
stroke={Colors.colorScheme.$textSecondary}
strokeWidth={1}
/>
</G>
</Svg>
</View>
)
}
NChart.propTypes = {
chartColor: PropTypes.oneOf(['red', 'green']),
containerStyle: viewPropTypes.style,
data: PropTypes.arrayOf(PropTypes.object).isRequired,
x: PropTypes.string,
y: PropTypes.string,
height: PropTypes.number,
width: PropTypes.number
}
NChart.defaultProps = {
data: data1,
chartColor: 'green',
x: 'x',
y: 'y'
}
export default NChart
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment