fix: convert scale config to data-ui's config correctly (#115)

This commit is contained in:
Krist Wongsuphasawat 2019-05-30 10:19:05 -07:00 committed by Yongjie Zhao
parent 8eaebc7c0c
commit 0dfaff8c2a
6 changed files with 77 additions and 9 deletions

View File

@ -13,6 +13,7 @@ import { PartialSpec } from '../encodeable/types/Specification';
import createMarginSelector, { DEFAULT_MARGIN } from '../utils/selectors/createMarginSelector';
import createXYChartLayoutSelector from '../utils/selectors/createXYChartLayoutSelector';
import { BoxPlotDataRow } from './types';
import convertScaleToDataUIScale from '../utils/convertScaleToDataUIScaleShape';
export interface TooltipProps {
datum: BoxPlotDataRow;
@ -116,8 +117,8 @@ export default class BoxPlot extends React.PureComponent<Props> {
)}
showYGrid
theme={theme}
xScale={channels.x.definition.scale}
yScale={channels.y.definition.scale}
xScale={convertScaleToDataUIScale(channels.x.scale!.config)}
yScale={convertScaleToDataUIScale(channels.y.scale!.config)}
>
{children}
{layout.renderXAxis()}

View File

@ -24,6 +24,7 @@ import { PartialSpec } from '../encodeable/types/Specification';
import DefaultTooltipRenderer from './DefaultTooltipRenderer';
import createMarginSelector, { DEFAULT_MARGIN } from '../utils/selectors/createMarginSelector';
import createXYChartLayoutSelector from '../utils/selectors/createXYChartLayoutSelector';
import convertScaleToDataUIScale from '../utils/convertScaleToDataUIScaleShape';
export interface TooltipProps {
encoder: Encoder;
@ -255,8 +256,8 @@ export default class LineChart extends PureComponent<Props> {
snapTooltipToDataX
theme={theme}
tooltipData={tooltipData}
xScale={channels.x.definition.scale}
yScale={channels.y.definition.scale}
xScale={convertScaleToDataUIScale(channels.x.scale!.config)}
yScale={convertScaleToDataUIScale(channels.y.scale!.config)}
>
{children}
{layout.renderXAxis()}

View File

@ -13,6 +13,7 @@ import { PartialSpec } from '../encodeable/types/Specification';
import createMarginSelector, { DEFAULT_MARGIN } from '../utils/selectors/createMarginSelector';
import createXYChartLayoutSelector from '../utils/selectors/createXYChartLayoutSelector';
import DefaultTooltipRenderer from './DefaultTooltipRenderer';
import convertScaleToDataUIScale from '../utils/convertScaleToDataUIScaleShape';
export interface TooltipProps {
datum: EncodedPoint;
@ -131,8 +132,8 @@ export default class ScatterPlot extends PureComponent<Props> {
)}
showYGrid
theme={theme}
xScale={channels.x.definition.scale}
yScale={channels.y.definition.scale}
xScale={convertScaleToDataUIScale(channels.x.scale!.config)}
yScale={convertScaleToDataUIScale(channels.y.scale!.config)}
>
{children}
{layout.renderXAxis()}

View File

@ -5,11 +5,13 @@ import { SchemeParams, ScaleType } from 'vega-lite/build/src/scale';
export interface Scale<Output extends Value = Value> {
type?: ScaleType;
domain?: number[] | string[] | boolean[] | DateTime[];
paddingInner?: number;
paddingOuter?: number;
range?: Output[];
clamp?: boolean;
nice?: boolean;
scheme?: string | SchemeParams;
// vega-lite does not have this
/** vega-lite does not have this */
namespace?: string;
}

View File

@ -12,6 +12,7 @@ import { AxisOrient } from '../encodeable/types/Axis';
import { XFieldDef, YFieldDef } from '../encodeable/types/ChannelDef';
import { PlainObject } from '../encodeable/types/Data';
import { DEFAULT_LABEL_ANGLE } from './constants';
import convertScaleToDataUIScale from './convertScaleToDataUIScaleShape';
// Additional margin to avoid content hidden behind scroll bar
const OVERFLOW_MARGIN = 8;
@ -71,8 +72,8 @@ export default class XYChartLayout {
width,
height,
margin,
xScale: xEncoder.definition.scale || {},
yScale: yEncoder.definition.scale || {},
xScale: convertScaleToDataUIScale(xEncoder.scale!.config || {}),
yScale: convertScaleToDataUIScale(yEncoder.scale!.config || {}),
theme,
children,
});

View File

@ -0,0 +1,62 @@
import { Value } from 'vega-lite/build/src/channeldef';
import { Scale } from '../encodeable/types/Scale';
type DataUIScaleType = 'time' | 'timeUtc' | 'linear' | 'band';
interface DataUIScale {
type: DataUIScaleType;
domain?: number[] | string[];
includeZero?: boolean;
nice?: boolean;
paddingInner?: number;
paddingOuter?: number;
range?: number[] | string[];
rangeRound?: number[] | string[];
}
function isCompatibleDomainOrRange(
array: Scale['domain'] | Scale['range'],
): array is number[] | string[] {
return (
typeof array !== 'undefined' &&
array.length > 0 &&
(typeof array[0] === 'string' || typeof array[0] === 'number')
);
}
/**
* Convert encodeable scale object into @data-ui's scale config
* @param scale
*/
export default function convertScaleToDataUIScale<Output extends Value>(scale: Scale<Output>) {
const { type, domain, range, nice, paddingInner, paddingOuter } = scale;
let outputType: DataUIScaleType;
if (type === 'linear' || type === 'time' || type === 'band') {
outputType = type;
} else if (type === 'utc') {
outputType = 'timeUtc';
} else {
throw new Error(`Unsupported scale type: ${type}`);
}
const output: DataUIScale = { type: outputType };
if (isCompatibleDomainOrRange(domain)) {
output.domain = domain;
}
if (isCompatibleDomainOrRange(range)) {
output.range = range;
}
if (typeof nice !== 'undefined') {
output.nice = nice;
}
if (typeof paddingInner !== 'undefined') {
output.paddingInner = paddingInner;
}
if (typeof paddingOuter !== 'undefined') {
output.paddingOuter = paddingOuter;
}
return output;
}