UNPKG

victory-chart

Version:
119 lines (105 loc) 4.31 kB
import { sortBy, defaults, last } from "lodash"; import { Helpers, Log, Data, Domain, Scale } from "victory-core"; export default { getBaseProps(props, fallbackProps) { props = Helpers.modifyProps(props, fallbackProps, "line"); const defaultStyles = props.theme && props.theme.line && props.theme.line.style ? props.theme.line.style : {}; const calculatedValues = this.getCalculatedValues(props); const { scale, dataset, dataSegments } = calculatedValues; const style = Helpers.getStyles(props.style, defaultStyles, "auto", "100%"); const {interpolation, label, width, height, events, sharedEvents} = props; const dataStyle = Helpers.evaluateStyle(style.data, dataset); const childProps = { parent: { style: style.parent, scale, data: dataset, height, width }}; for (let index = 0, len = dataSegments.length; index < len; index++) { const dataProps = { scale, interpolation: Helpers.evaluateProp(interpolation, dataset), style: dataStyle, data: dataSegments[index] }; const text = index === dataSegments.length - 1 ? Helpers.evaluateProp(label, dataset) : undefined; const addLabels = (text !== undefined && text !== null) || events || sharedEvents; const labelProps = addLabels ? this.getLabelProps(dataProps, text, calculatedValues, style) : undefined; childProps[index] = { data: dataProps, labels: labelProps }; } return childProps; }, getLabelProps(dataProps, text, calculatedValues, style) { // eslint-disable-line max-params const { dataSegments, dataset, scale } = calculatedValues; const { style: dataStyle } = dataProps; const lastData = last(last(dataSegments)); const baseLabelStyle = Helpers.evaluateStyle(style.labels, dataset) || {}; const labelStyle = this.getLabelStyle(baseLabelStyle, dataStyle); return { x: lastData ? scale.x(lastData.x1 || lastData.x) + (labelStyle.padding || 0) : 0, y: lastData ? scale.y(lastData.y1 || lastData.y) : 0, style: labelStyle, textAnchor: labelStyle.textAnchor || "start", verticalAnchor: labelStyle.verticalAnchor || "middle", angle: labelStyle.angle, data: dataset, scale, text }; }, getScale(props, fallbackProps) { if (fallbackProps) { props = Helpers.modifyProps(props, fallbackProps); } const range = { x: Helpers.getRange(props, "x"), y: Helpers.getRange(props, "y") }; const domain = { x: Domain.getDomain(props, "x"), y: Domain.getDomain(props, "y") }; const scale = { x: Scale.getBaseScale(props, "x").domain(domain.x).range(range.x), y: Scale.getBaseScale(props, "y").domain(domain.y).range(range.y) }; return scale; }, getCalculatedValues(props) { let dataset = Data.getData(props); if (Data.getData(props).length < 2) { Log.warn("VictoryLine needs at least two data points to render properly."); dataset = []; } const dataSegments = this.getDataSegments(dataset, props.sortKey); const scale = this.getScale(props); return { dataset, dataSegments, scale }; }, getLabelStyle(labelStyle, dataStyle) { // match labels styles to data style by default (fill, opacity, others?) const opacity = dataStyle.opacity; // match label color to data color if it is not given. // use fill instead of stroke for text const fill = dataStyle.stroke; const padding = labelStyle.padding || 0; return defaults({}, labelStyle, {opacity, fill, padding}); }, getDataSegments(dataset, sortKey = "x") { const orderedData = sortBy(dataset, sortKey); const segments = []; let segmentStartIndex = 0; let segmentIndex = 0; for (let index = 0, len = orderedData.length; index < len; index++) { const datum = orderedData[index]; if (datum.y === null || typeof datum.y === "undefined") { segments[segmentIndex] = orderedData.slice(segmentStartIndex, index); segmentIndex++; segmentStartIndex = index + 1; } } segments[segmentIndex] = orderedData.slice(segmentStartIndex, orderedData.length); return segments.filter((segment) => { return Array.isArray(segment) && segment.length > 0; }); } };