recharts#ReferenceLine JavaScript Examples
The following examples show how to use
recharts#ReferenceLine.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: DashboardBarChart.js From crypto-red.github.io with MIT License | 5 votes |
render() {
const { classes, coins_markets } = this.state;
const data_bar = coins_markets.map(function(data, key, array){
return {
name: data.name,
changes: data.price_change_percentage_1y_in_currency
};
});
return (
<div className={classes.cardContainer}>
<Fade in>
<Card className={classes.performanceCard}>
<CardHeader title={t( "components.dashboard_bar_chart.title")} />
<CardContent>
{
data_bar.length ?
<Fade in>
<div className={classes.barChart}>
<ResponsiveContainer>
<BarChart
width={400}
height={475}
data={data_bar}
>
<CartesianGrid strokeDasharray="3 3" />
<XAxis dataKey="name" interval={0} angle={90} height={75} dy={10} textAnchor="start"/>
<YAxis tickFormatter={value => this._percent_formatter(value, true)} />
<Tooltip formatter={value => this._percent_formatter(value, true)} />
<ReferenceLine y={0} stroke="#000" />
<Bar dataKey="changes" fill="#131162" />
</BarChart>
</ResponsiveContainer>
</div>
</Fade>:
<Fade in timeout={300}>
<Skeleton height={475}/>
</Fade>
}
</CardContent>
</Card>
</Fade>
</div>
);
}
Example #2
Source File: GraphDeathProjection.js From covid-19 with MIT License | 5 votes |
GraphDeathProjectionRender = (props) => {
let data = props.data;
const max_date = props.max_date;
const data_keys = props.data_keys;
data = data.map(d => {
d.name = moment(d.fulldate, "MM/DD/YYYY").format("M/D");
return d;
});
data = data.sort((a, b) => moment(a.fulldate, "MM/DD/YYYY").toDate() - (moment(b.fulldate, "MM/DD/YYYY")).toDate());
const [state, setState] = React.useState({
showall: false,
});
const handleLogScaleToggle = event => {
setState({ ...state, showall: !state.showall });
};
const cutoff = moment().subtract(30, 'days')
const future = moment().add(30, 'days')
data = data.filter(d => {
let day = moment(d.fulldate, "MM/DD/YYYY");
return day.isAfter(cutoff) && day.isBefore(future);
});
const formatYAxis = (tickItem) => {
return myShortNumber(tickItem);
}
return <>
<Grid container alignItems="center" spacing={1}>
<Grid item onClick={handleLogScaleToggle}>
<Typography>
Daily
</Typography>
</Grid>
<Grid item>
<AntSwitch checked={state.showall} onClick={handleLogScaleToggle} />
</Grid>
<Grid item onClick={handleLogScaleToggle}>
<Typography>
Total
</Typography>
</Grid>
<Grid item></Grid>
</Grid>
<ResponsiveContainer height={300} >
<ComposedChart data={data} margin={{ top: 5, right: 30, left: 5, bottom: 5 }} >
<XAxis dataKey="name" />
<YAxis yAxisId={0} tickFormatter={formatYAxis} />
<ReferenceLine x={moment(max_date, "MM/DD/YYYY").format("M/D")} label={{ value: props.max_label, fill: '#a3a3a3' }} stroke="#e3e3e3" strokeWidth={3} />
<CartesianGrid stroke="#d5d5d5" strokeDasharray="5 5" />
<Line type="monotone" dataKey={data_keys.key_mean} stroke="#000000" dot={{ r: 1 }} yAxisId={0} strokeWidth={2} />
<Area type='monotone' dataKey={data_keys.key_lower} stackId="1" stroke='#8884d8' fill='#FFFFFF' />
<Area type='monotone' dataKey={data_keys.key_delta} stackId="1" stroke='#82ca9d' fill='#82ca9d' />
<Line type="monotone" dataKey="actualDeath_daily" stroke="#FF0000" dot={{ r: 1 }} strokeDasharray="2 2" yAxisId={0} strokeWidth={2} />
<Line type="monotone" dataKey="actualDeath_moving_avg" stroke="#FF0000" dot={{ r: 1 }} yAxisId={0} strokeWidth={3} />
{state.showall && <Line type="monotone" dataKey={data_keys.key_mean_cumulative} dot={{ r: 1 }} stroke="#000000" yAxisId={0} strokeWidth={1} />}
{state.showall && <Line type="monotone" dataKey="actualDeath_total" dot={{ r: 1 }} stroke="#ff0000" yAxisId={0} strokeWidth={2} />}
{state.showall && <Area type='monotone' dataKey={data_keys.key_lower_cumulative} stackId="2" stroke='#8884d8' fill='#FFFFFF' />}
{state.showall && <Area type='monotone' dataKey={data_keys.key_delta_cumulative} stackId="2" stroke='#82ca9d' fill='#82ca9d' />}
<Tooltip content={props.tooltip} />
<Legend verticalAlign="top" payload={[
{ value: 'Actual Death', type: 'line', color: '#ff0000' },
{ value: 'Projection', type: 'line', color: '#000000' },
]} />
</ComposedChart>
</ResponsiveContainer>
<Typography variant="body2">
Source: The Institute for Health Metrics and Evaluation
</Typography>
</>
}
Example #3
Source File: MultiLinePlot.jsx From covince with MIT License | 4 votes |
MainChart = React.memo((props) => {
const {
activeLineages,
chart,
dateRange,
darkMode,
precision,
preset,
stroke,
tooltipEnabled,
type,
xAxisProps,
yAxisConfig = {},
zoomArea,
...chartProps
} = props
const { lineages, data, dates } = chart
const yAxisDomain = useMemo(() => {
if (yAxisConfig && yAxisConfig.domain) {
return yAxisConfig.domain
}
if (preset === 'percentage' && type === 'area' && lineages.length === Object.keys(activeLineages).length) {
return [0, 100]
}
if (dateRange && data.length) {
if (type === 'area') {
const [minIndex, maxIndex] = xAxisProps.domain
const range = data.slice(minIndex, maxIndex + 1)
let { sumY: max } = range[0]
for (const { sumY } of range.slice(1)) {
max = Math.max(sumY, max)
}
return [0, Math.ceil(max)]
} else {
const [minIndex, maxIndex] = xAxisProps.domain
const range = data.slice(minIndex, maxIndex + 1)
let { maxY: max } = range[0]
for (const { maxY } of range.slice(1)) {
max = Math.max(maxY, max)
}
return [0, Math.ceil(max)]
}
}
if (preset === 'percentage' && type === 'area' && lineages.length) {
return [0, 1]
}
return [0, 'auto']
}, [preset, type, yAxisConfig, lineages, xAxisProps.domain, data])
const yAxisTicks = useMemo(() => {
if (preset === 'percentage') {
if (lineages.length === 0) {
return { ticks: false }
}
const fullScale = lineages.length === Object.keys(activeLineages).length
if (fullScale) {
return {
tickFormatter: value => `${Math.min(parseFloat(value), 100)}%`,
ticks: dateRange ? undefined : [0, 25, 50, 75, 100]
}
}
return {
tickFormatter: value => {
if (value === 0) return '0%'
if (value >= 100) return '100%'
if (!Number.isInteger(value)) return `${value.toFixed(1)}%`
return `${value}%`
}
}
}
return {
tickFormatter: value => {
const valueStr = value.toString()
if (valueStr.length > 4) {
const tripleFigureCount = Math.floor((valueStr.length - 1) / 3)
const prefix = (value / Math.pow(1000, tripleFigureCount))
const prefixStr = prefix.toString()
return (
(prefixStr.length < 4 ? prefixStr : prefix.toPrecision(3)) +
(tripleFigureLabel[tripleFigureCount] || '')
)
}
return value.toLocaleString()
},
ticks: dateRange ? undefined : yAxisConfig.ticks
}
}, [preset, lineages, activeLineages, yAxisConfig, dateRange])
const grid =
<CartesianGrid stroke={tailwindColors[stroke][darkMode ? 500 : 300]} />
const [highlightedLineage, setHighlightedLineage] = useState(null)
const tooltip = useMemo(() =>
(tooltipEnabled && lineages.length > 0)
? <Tooltip
content={ChartTooltip}
cursor={{ stroke: tailwindColors[stroke][darkMode ? 300 : 400] }}
dates={dates}
percentage={preset === 'percentage'}
precision={precision}
sortByValue={type !== 'area'}
highlightedItem={highlightedLineage}
/>
: null
, [tooltipEnabled, stroke, dates, preset, precision, highlightedLineage, type])
const xAxis = useMemo(() =>
<XAxis
{...xAxisProps}
fontSize='12'
tick={data.length}
tickFormatter={i => i in data ? format(new Date(data[i].date), 'd MMM') : ''}
tickMargin='4'
stroke='currentcolor'
/>
, [data, xAxisProps])
const yAxis =
<YAxis
type='number'
allowDataOverflow={dateRange || yAxisConfig.allow_data_overflow || false}
domain={yAxisDomain}
width={48}
stroke='currentcolor'
tickMargin='4'
tick={data.length}
allowDecimals={false}
{...yAxisTicks}
/>
const areas = useMemo(() => {
if (type === 'area') {
return lineages.map(({ lineage, colour = fallbackColour }) => (
<Area
key={lineage}
activeDot={{ stroke: tailwindColors[stroke][400] }}
dataKey={lineage}
dot={false}
fill={colour}
fillOpacity={highlightedLineage === lineage ? 0.8 : undefined}
name={lineage}
stackId='1'
stroke={colour}
type='monotone'
animationDuration={animationDuration}
isAnimationActive={true}
onMouseEnter={({ name }) => { setHighlightedLineage(name) }}
onMouseLeave={() => { setHighlightedLineage(null) }}
/>
))
}
return lineages
.filter(_ => _.average !== 0)
.map(({ lineage, colour = fallbackColour }) => {
const key = `${lineage}_range`
return (
<Area
key={key}
activeDot={false}
dataKey={key}
fill={colour}
name='_range'
strokeWidth={0}
type='monotone'
animationDuration={animationDuration}
isAnimationActive={true}
/>
)
})
}, [lineages, stroke, type, highlightedLineage])
const lines = useMemo(() => {
if (type === 'area') return null
return lineages.map(({ lineage, colour = fallbackColour }) =>
<Line
key={lineage}
activeDot={{ stroke: tailwindColors[stroke][400] }}
dataKey={lineage}
dot={false}
name={lineage}
stroke={colour}
type='monotone'
animationDuration={animationDuration}
isAnimationActive={true}
/>
)
}, [lineages, stroke, type])
const yReference = useMemo(() => {
if (yAxisConfig.reference_line === undefined) return null
return (
<ReferenceLine
y={yAxisConfig.reference_line}
stroke={tailwindColors[stroke][darkMode ? 400 : 600]}
strokeDasharray={[8, 8]}
label=''
strokeWidth={2}
style={{ mixBlendMode: darkMode ? 'screen' : 'multiply' }}
/>
)
}, [yAxisConfig.reference_line, stroke])
return (
<ComposedChart
{...chartProps}
data={[...data] /* new array required for animations */}
>
{grid}
{areas}
{xAxis}
{yAxis}
{tooltip}
{yReference}
{lines}
{zoomArea.start !== undefined
? <ReferenceArea x1={zoomArea.start} x2={zoomArea.end} strokeOpacity={0.3} />
: null}
</ComposedChart>
)
})
Example #4
Source File: MultiLinePlot.jsx From covince with MIT License | 4 votes |
MultiLinePlot = props => {
const {
activeLineages,
area_data,
chartZoom,
className,
darkMode,
date,
groupStackedColours = true,
height = 120,
parameter,
preset: deprecatedPreset,
setDate,
stroke = 'blueGray',
tooltipEnabled,
type,
width,
/* xAxis: xAxisConfig = {}, */
yAxis: yAxisConfig,
zoomEnabled
} = props
const preset = useMemo(() => {
if (parameter && parameter.format === 'percentage') return 'percentage'
// back compat
if (deprecatedPreset) return deprecatedPreset
if (parameter && parameter.id === 'p') return 'percentage'
return null
}, [parameter, deprecatedPreset])
const precision = useMemo(() => {
return parameter ? parameter.precision : undefined
}, [parameter])
const chart = useMemo(() => {
const dataByDate = {}
const lineageSum = {}
for (const d of area_data) {
if (d.parameter === parameter.id && d.lineage !== 'total') {
const next = {
...dataByDate[d.date],
date: d.date,
[d.lineage]: d.mean,
[`${d.lineage}_range`]: d.range
}
if (d.lineage in activeLineages && activeLineages[d.lineage].active) {
next.maxY = Math.max(next.maxY || 0, d.range[1] || d.mean)
next.sumY = (next.sumY || 0) + d.mean
}
dataByDate[d.date] = next
const sum = lineageSum[d.lineage] || 0
lineageSum[d.lineage] = (sum + d.mean)
}
}
const data =
orderBy(Object.values(dataByDate), 'date', 'asc')
.map((d, index) => ({ ...d, index }))
const dates = data.map(_ => _.date)
const lineages = []
for (const lineage of Object.keys(lineageSum)) {
const { active, colour } = activeLineages[lineage]
if (active) {
lineages.push({ lineage, colour, average: lineageSum[lineage] / dates.length })
}
}
const ordered = orderBy(lineages, 'average', 'asc')
let sorted
if (groupStackedColours) {
sorted = []
while (ordered.length > 0) {
const [item] = ordered.splice(0, 1)
if (sorted.includes(item)) continue
sorted.push(item)
for (let i = 0; i < ordered.length; i++) {
const other = ordered[i]
if (item.colour === other.colour) {
sorted.push(other)
}
}
}
} else {
sorted = ordered
}
return {
lineages: sorted,
data,
dates
}
}, [area_data, activeLineages, groupStackedColours])
const { data, dates } = chart
const chartProps = useMemo(() => ({
width,
height,
margin: { top: 12, left: 0, right: 24 }
}), [width, height])
const { dateRange, setChartZoom, clearChartZoom } = chartZoom
const xAxisDomain = useMemo(() => {
const minIndex = 0
const maxIndex = data.length - 1
if (dateRange && dates.length) {
const [minDate, maxDate] = dateRange
const min = minDate ? Math.max(dates.indexOf(minDate), minIndex) : minIndex
let max = maxDate ? dates.indexOf(maxDate) : maxIndex
if (max === -1) max = maxIndex
return min < max ? [min, max] : [max, min]
}
return [minIndex, maxIndex]
}, [dateRange, dates])
const xAxisProps = useMemo(() => {
const indices = Object.keys(dates)
let ticks = indices
if (dateRange) {
const [minIndex, maxIndex] = xAxisDomain
ticks = indices.slice(minIndex, maxIndex + 1)
}
return {
allowDataOverflow: true,
dataKey: 'index',
domain: xAxisDomain,
ticks,
type: 'number'
}
}, [xAxisDomain, dates])
const [zoomArea, setZoomArea] = React.useState({})
const [isHovering, setIsHovering] = React.useState(false)
const eventHandlers = useMemo(() => {
const clickHandlers = {
onClick: item => {
if (date && item && !zoomArea.dragged) { // do not set date if not visible on chart
setDate(data[item.activeLabel].date)
}
if (zoomEnabled) {
setZoomArea({ dragged: zoomArea.dragged })
}
},
onMouseDown: e => {
if (e && zoomEnabled) {
setZoomArea({ start: e.activeLabel, end: e.activeLabel, dragged: false })
}
},
onMouseMove: e => {
if (e) {
setIsHovering(e.activeLabel !== undefined)
if (zoomArea.start === undefined) return
let end = e.activeLabel
if (e.activeLabel === undefined) { // outside of axes
end = xAxisDomain[zoomArea.end >= data.length / 2 ? 1 : 0]
}
setZoomArea({ start: zoomArea.start, end, dragged: true })
}
},
onMouseLeave: e => {
setIsHovering(false)
},
onMouseUp: (_, e) => {
if (zoomArea.end !== zoomArea.start) {
const xStart = data[zoomArea.start].date
const xEnd = data[zoomArea.end].date
const args = xStart < xEnd ? [xStart, xEnd] : [xEnd, xStart]
setChartZoom(...args)
}
setZoomArea({ dragged: zoomArea.dragged })
}
}
if (!tooltipEnabled) { // touch handlers need to be replaced when tooltip is missing
return {
...clickHandlers,
onTouchStart: clickHandlers.onMouseDown,
onTouchMove: clickHandlers.onMouseMove,
onTouchEnd: clickHandlers.onMouseUp
}
}
return clickHandlers
}, [zoomEnabled, data, zoomArea, isHovering])
const cursor = useMemo(() => {
if (zoomArea.start) return 'ew-resize'
if (isHovering) return 'crosshair'
return undefined
}, [zoomArea, isHovering])
return (
<div
className={classNames('relative select-none focus:outline-none', className)}
onDoubleClick={clearChartZoom}
>
<MainChart
{...{
...chartProps,
...eventHandlers,
activeLineages,
chart,
dateRange,
cursor,
darkMode,
precision,
preset,
stroke,
tooltipEnabled,
type,
xAxisProps,
yAxisConfig,
zoomArea
}}
/>
<div className='absolute top-0 left-0 pointer-events-none'>
<ComposedChart {...chartProps} data={data}>
<XAxis
{...xAxisProps}
tick={false}
stroke='none'
/>
<YAxis
width={48}
tick={false}
stroke='none'
/>
<ReferenceLine
x={dates.indexOf(date)}
stroke={tailwindColors[stroke][darkMode ? 300 : 400]}
label=''
strokeWidth={2}
style={{ mixBlendMode: darkMode ? 'screen' : 'multiply' }}
/>
</ComposedChart>
</div>
</div>
)
}
Example #5
Source File: AdvancedGraph.js From covid-19 with MIT License | 4 votes |
Chart = (props) => {
const ordered = (props.specs || []).sort((a, b) => {
if (a.derived && !b.derived) {
return -1;
} else if (!a.derived && b.derived) {
return 1;
} else {
return a.label < b.label ? -1 : 1;
}
});
let YAxis0Color = "black";
let YAxis1Color = undefined;
for (const s of ordered) {
if (s.rightAxis) {
YAxis1Color = s.color;
} else {
YAxis0Color = s.color;
}
}
function getvRefLines(lines) {
let result = (lines || []).map((l, idx) => {
return <ReferenceLine key={`vrefline${idx}`}
x={l.date}
stroke="#e3e3e3"
strokeWidth={1}
>
<Label value={l.label} position={"insideTop"} fill="#b3b3b3" />
</ReferenceLine>
}
);
return result;
}
function getvRefAreas(lines) {
let result = (lines || []).map((l, idx) => {
const startdate = l.date;
const today = moment().unix();
let enddate = startdate + 14 * 24 * 60 * 60;
while (enddate > today) {
enddate -= 24 * 60 * 60;
}
return <ReferenceArea key={`vrefarea${idx}`}
x1={startdate} x2={enddate}
// stroke="red"
// strokeOpacity={0.3}
fillOpacity={0.15}
/>
}
);
return result;
}
function gethRefLines(lines) {
let result = (lines || []).map((l, idx) => {
return <ReferenceLine key={`hrefline${idx}`}
y={l.value}
stroke="#e3e3e3"
strokeWidth={1}
>
<Label value={l.label} position={"insideLeft"} ></Label>
</ReferenceLine>
}
);
return result;
}
let vRefLines = getvRefLines(props.vRefLines);
let hRefLines = gethRefLines(props.hRefLines);
return (
<ResponsiveContainer height={300}>
<LineChart data={props.data} margin={{ left: -4, right: 8 }}>
{vRefLines}
{hRefLines}
{getvRefAreas(props.vRefLines)}
<Tooltip
formatter={valueFormatter}
labelFormatter={props.timestampFormatter}
/>
<XAxis
dataKey="timestamp"
tickFormatter={props.timestampFormatter}
/>
<YAxis
yAxisId={0}
tick={{ fill: YAxis0Color }}
scale={props.scale === 'Log' ? logScale : props.scale}
width={50}
tickFormatter={props.yAxisFormatter}
/>
{YAxis1Color &&
<YAxis
yAxisId={1}
tickFormatter={props.yAxisFormatter}
width={35}
tick={{ fill: YAxis1Color }}
orientation="right"
/>
}
<CartesianGrid stroke="#d5d5d5" strokeDasharray="5 5" />
{ordered.flatMap(spec => specToElements(spec))}
</LineChart>
</ResponsiveContainer>
);
}