Implement color as function of point on SingleValueHistoryChart
This commit is contained in:
parent
9bddae17bb
commit
63cc319b3a
|
@ -20,10 +20,12 @@ import {
|
|||
AreaWithTopStroke,
|
||||
Point,
|
||||
TooltipComponent,
|
||||
computeColorStops,
|
||||
formatPct,
|
||||
} from './helpers'
|
||||
import { useEvent } from 'web/hooks/use-event'
|
||||
import { formatMoney } from 'common/util/format'
|
||||
import { nanoid } from 'nanoid'
|
||||
|
||||
export type MultiPoint<T = unknown> = Point<Date, number[], T>
|
||||
export type HistoryPoint<T = unknown> = Point<Date, number, T>
|
||||
|
@ -161,7 +163,7 @@ export const MultiValueHistoryChart = <P extends MultiPoint>(props: {
|
|||
const series = useMemo(() => {
|
||||
const d3Stack = stack<P, number>()
|
||||
.keys(range(0, Math.max(...data.map(({ y }) => y.length))))
|
||||
.value(({ y }, o) => y[o])
|
||||
.value(({ y }, k) => y[k])
|
||||
.order(stackOrderReverse)
|
||||
return d3Stack(data)
|
||||
}, [data])
|
||||
|
@ -214,7 +216,7 @@ export const SingleValueHistoryChart = <P extends HistoryPoint>(props: {
|
|||
data: P[]
|
||||
w: number
|
||||
h: number
|
||||
color: string
|
||||
color: string | ((p: P) => string)
|
||||
margin: Margin
|
||||
xScale: ScaleTime<number, number>
|
||||
yScale: ScaleContinuousNumeric<number, number>
|
||||
|
@ -269,6 +271,13 @@ export const SingleValueHistoryChart = <P extends HistoryPoint>(props: {
|
|||
}
|
||||
})
|
||||
|
||||
const gradientId = useMemo(() => nanoid(), [])
|
||||
const stops = useMemo(
|
||||
() =>
|
||||
typeof color !== 'string' ? computeColorStops(data, color, px) : null,
|
||||
[color, data, px]
|
||||
)
|
||||
|
||||
return (
|
||||
<SVGChart
|
||||
w={w}
|
||||
|
@ -280,8 +289,17 @@ export const SingleValueHistoryChart = <P extends HistoryPoint>(props: {
|
|||
onMouseOver={onMouseOver}
|
||||
Tooltip={Tooltip}
|
||||
>
|
||||
{stops && (
|
||||
<defs>
|
||||
<linearGradient gradientUnits="userSpaceOnUse" id={gradientId}>
|
||||
{stops.map((s, i) => (
|
||||
<stop key={i} offset={`${s.x / w}`} stopColor={s.color} />
|
||||
))}
|
||||
</linearGradient>
|
||||
</defs>
|
||||
)}
|
||||
<AreaWithTopStroke
|
||||
color={color}
|
||||
color={typeof color === 'string' ? color : `url(#${gradientId})`}
|
||||
data={data}
|
||||
px={px}
|
||||
py0={py0}
|
||||
|
|
|
@ -99,14 +99,14 @@ const AreaPathInternal = <P,>(
|
|||
export const AreaPath = memo(AreaPathInternal) as typeof AreaPathInternal
|
||||
|
||||
export const AreaWithTopStroke = <P,>(props: {
|
||||
color: string
|
||||
data: P[]
|
||||
color: string
|
||||
px: number | ((p: P) => number)
|
||||
py0: number | ((p: P) => number)
|
||||
py1: number | ((p: P) => number)
|
||||
curve: CurveFactory
|
||||
}) => {
|
||||
const { color, data, px, py0, py1, curve } = props
|
||||
const { data, color, px, py0, py1, curve } = props
|
||||
return (
|
||||
<g>
|
||||
<AreaPath
|
||||
|
@ -308,6 +308,33 @@ export const TooltipContainer = (props: {
|
|||
)
|
||||
}
|
||||
|
||||
export const computeColorStops = <P,>(
|
||||
data: P[],
|
||||
pc: (p: P) => string,
|
||||
px: (p: P) => number
|
||||
) => {
|
||||
const segments: { x: number; color: string }[] = []
|
||||
let currOffset = 0
|
||||
let currColor = pc(data[0])
|
||||
for (const p of data) {
|
||||
const c = pc(p)
|
||||
if (c !== currColor) {
|
||||
segments.push({ x: currOffset, color: currColor })
|
||||
currOffset = px(p)
|
||||
currColor = c
|
||||
}
|
||||
}
|
||||
segments.push({ x: currOffset, color: currColor })
|
||||
|
||||
const stops: { x: number; color: string }[] = []
|
||||
stops.push({ x: segments[0].x, color: segments[0].color })
|
||||
for (const s of segments.slice(1)) {
|
||||
stops.push({ x: s.x, color: stops[stops.length - 1].color })
|
||||
stops.push({ x: s.x, color: s.color })
|
||||
}
|
||||
return stops
|
||||
}
|
||||
|
||||
export const getDateRange = (contract: Contract) => {
|
||||
const { createdTime, closeTime, resolutionTime } = contract
|
||||
const isClosed = !!closeTime && Date.now() > closeTime
|
||||
|
|
Loading…
Reference in New Issue
Block a user