@visactor/vgrammar-core
Version:
VGrammar is a visual grammar library
348 lines (279 loc) • 14.1 kB
JavaScript
import { isArray, isFunction, isNil, isNumber, isString, isValidNumber, maxInArray, minInArray } from "@visactor/vutils";
import { LinearScale, BandScale, OrdinalScale, PointScale, isContinuous, TimeScale, ThresholdScale, SqrtScale, SymlogScale, QuantizeScale, QuantileScale, PowScale, LogScale, isDiscretizing, IdentityScale } from "@visactor/vscale";
import { getGrammarOutput, invokeFunctionType, parseFunctionType } from "./util";
import { field as getFieldAccessor } from "@visactor/vgrammar-util";
export function createScale(type) {
switch (type) {
case "band":
return new BandScale;
case "linear":
return new LinearScale;
case "log":
return new LogScale;
case "ordinal":
return new OrdinalScale;
case "point":
return new PointScale;
case "pow":
return new PowScale;
case "quantile":
return new QuantileScale;
case "quantize":
return new QuantizeScale;
case "sqrt":
return new SqrtScale;
case "symlog":
return new SymlogScale;
case "threshold":
return new ThresholdScale;
case "time":
return new TimeScale;
case "utc":
return new TimeScale(!0);
case "identity":
return new IdentityScale;
}
return new LinearScale;
}
function isScaleDataType(spec) {
return !isNil(null == spec ? void 0 : spec.data);
}
function parseScaleDataType(spec, view) {
var _a;
if (isString(spec.data)) {
const data = view.getGrammarById(spec.data);
return data ? [ data ] : [];
}
return "data" === (null === (_a = spec.data) || void 0 === _a ? void 0 : _a.grammarType) ? [ spec.data ] : [];
}
function isMultiScaleDataType(spec) {
return !isNil(null == spec ? void 0 : spec.datas);
}
function parseMultiScaleDataType(spec, view) {
if (spec && spec.datas && spec.datas.length) {
const res = [];
return spec.datas.forEach((data => {
const gramarBase = parseScaleDataType(data, view);
gramarBase.length && res.push(gramarBase[0]);
})), res;
}
return [];
}
function isScaleCoordinateType(spec) {
return !isNil(null == spec ? void 0 : spec.coordinate);
}
function parseScaleCoordinateType(spec, view) {
var _a;
if (isString(spec.coordinate)) {
const coordinate = view.getCoordinateById(spec.coordinate);
return coordinate ? [ coordinate ] : [];
}
return "coordinate" === (null === (_a = spec.coordinate) || void 0 === _a ? void 0 : _a.grammarType) ? [ spec.coordinate ] : [];
}
function parseLinearScale(spec, view) {
let dependencies = [];
return dependencies = dependencies.concat(parseFunctionType(spec.nice, view)), dependencies = dependencies.concat(parseFunctionType(spec.niceMin, view)),
dependencies = dependencies.concat(parseFunctionType(spec.niceMax, view)), dependencies = dependencies.concat(parseFunctionType(spec.min, view)),
dependencies = dependencies.concat(parseFunctionType(spec.max, view)), dependencies = dependencies.concat(parseFunctionType(spec.zero, view)),
dependencies = dependencies.concat(parseFunctionType(spec.roundRange, view)), dependencies;
}
function parsePowScale(spec, view) {
return parseLinearScale(spec, view).concat(parseFunctionType(spec.exponent, view));
}
function parseSymlogScale(spec, view) {
return parseLinearScale(spec, view).concat(parseFunctionType(spec.constant, view));
}
function parseLogScale(spec, view) {
let dependencies = [];
return dependencies = dependencies.concat(parseFunctionType(spec.nice, view)), dependencies = dependencies.concat(parseFunctionType(spec.min, view)),
dependencies = dependencies.concat(parseFunctionType(spec.max, view)), dependencies = dependencies.concat(parseFunctionType(spec.zero, view)),
dependencies = dependencies.concat(parseFunctionType(spec.roundRange, view)), dependencies;
}
function parseQuantizeScale(spec, view) {
let dependencies = [];
return dependencies = dependencies.concat(parseFunctionType(spec.nice, view)), dependencies = dependencies.concat(parseFunctionType(spec.niceMin, view)),
dependencies = dependencies.concat(parseFunctionType(spec.niceMax, view)), dependencies = dependencies.concat(parseFunctionType(spec.min, view)),
dependencies = dependencies.concat(parseFunctionType(spec.max, view)), dependencies = dependencies.concat(parseFunctionType(spec.zero, view)),
dependencies;
}
function parseOrdinalScale(spec, view) {
return [];
}
function parseBaseBandScale(spec, view) {
let dependencies = [];
return dependencies = dependencies.concat(parseFunctionType(spec.round, view)),
dependencies = dependencies.concat(parseFunctionType(spec.padding, view)), dependencies = dependencies.concat(parseFunctionType(spec.paddingInner, view)),
dependencies = dependencies.concat(parseFunctionType(spec.paddingOuter, view)),
dependencies = dependencies.concat(parseFunctionType(spec.align, view)), dependencies;
}
function parseBandScale(spec, view) {
return parseBaseBandScale(spec, view).concat(parseFunctionType(spec.paddingInner, view));
}
function parsePointScale(spec, view) {
return parseBaseBandScale(spec, view);
}
export function parseScaleDomainRange(domain, view) {
return isScaleDataType(domain) ? parseScaleDataType(domain, view) : isMultiScaleDataType(domain) ? parseMultiScaleDataType(domain, view) : isScaleCoordinateType(domain) ? parseScaleCoordinateType(domain, view) : parseFunctionType(domain, view);
}
export function parseScaleConfig(type, config, view) {
if (isNil(config)) return [];
const deps = parseFunctionType(config.unknown, view);
switch (type) {
case "linear":
case "sqrt":
return deps.concat(parseLinearScale(config, view));
case "ordinal":
return deps.concat(parseOrdinalScale(config, view));
case "band":
return deps.concat(parseBandScale(config, view));
case "point":
return deps.concat(parsePointScale(config, view));
case "pow":
return deps.concat(parsePowScale(config, view));
case "log":
case "time":
case "utc":
return deps.concat(parseLogScale(config, view));
case "symlog":
return deps.concat(parseSymlogScale(config, view));
case "quantize":
return deps.concat(parseQuantizeScale(config, view));
}
return deps;
}
function configureScaleNice(spec, scale, parameters) {
const nice = invokeFunctionType(spec.nice, parameters, scale);
!0 === nice ? scale.nice() : isValidNumber(nice) && scale.nice(nice);
}
function configureScaleNiceMinMax(spec, scale, parameters) {
const niceMax = invokeFunctionType(spec.niceMax, parameters, scale);
!0 === niceMax ? scale.niceMax() : isValidNumber(niceMax) && scale.niceMax(niceMax);
const niceMin = invokeFunctionType(spec.niceMin, parameters, scale);
!0 === niceMin ? scale.niceMin() : isValidNumber(niceMin) && scale.niceMin(niceMin);
}
function configureScaleDomain(spec, scale, parameters) {
const min = invokeFunctionType(spec.min, parameters, scale), max = invokeFunctionType(spec.max, parameters, scale), zero = invokeFunctionType(spec.zero, parameters, scale), hasValidMin = isValidNumber(min), hasValidmax = isValidNumber(max), prevDomain = scale.domain();
if (2 === prevDomain.length && (hasValidMin || hasValidmax || zero)) {
let newMin = Math.min(prevDomain[0], prevDomain[prevDomain.length - 1]), newMax = Math.max(prevDomain[0], prevDomain[prevDomain.length - 1]);
zero && newMin > 0 ? newMin = 0 : hasValidMin && (newMin = Math.min(newMin, min)),
zero && newMax < 0 ? newMax = 0 : hasValidmax && (newMax = Math.max(newMax, max)),
scale.domain([ newMin, newMax ], !0);
}
}
function configureContinuousScale(spec, scale, parameters) {
var _a;
invokeFunctionType(spec.roundRange, parameters, scale) && scale.rangeRound(scale.range(), !0);
const {interpolate: interpolate, clamp: clamp} = null !== (_a = invokeFunctionType(spec.config, parameters, scale)) && void 0 !== _a ? _a : {};
interpolate && scale.interpolate(interpolate, !0), isNil(clamp) || (isFunction(clamp) ? scale.clamp(!0, clamp, !0) : scale.clamp(clamp, void 0, !0));
const tickCount = invokeFunctionType(spec.tickCount, parameters, scale);
tickCount && scale.tickData(tickCount);
}
function configureLinearScale(spec, scale, parameters) {
configureScaleNice(spec, scale, parameters), configureScaleNiceMinMax(spec, scale, parameters),
configureScaleDomain(spec, scale, parameters), configureContinuousScale(spec, scale, parameters);
}
function configurePowScale(spec, scale, parameters) {
configureLinearScale(spec, scale, parameters);
const exponent = invokeFunctionType(spec.exponent, parameters, scale);
exponent > 0 && scale.exponent(exponent);
}
function configureLogScale(spec, scale, parameters) {
configureScaleNice(spec, scale, parameters), configureScaleDomain(spec, scale, parameters);
const base = invokeFunctionType(spec.base, parameters, scale);
base > 0 && scale.base(base), configureContinuousScale(spec, scale, parameters);
}
function configureSqrtScale(spec, scale, parameters) {
configureLinearScale(spec, scale, parameters);
}
function configureTimeScale(spec, scale, parameters) {
configureScaleNice(spec, scale, parameters), configureScaleDomain(spec, scale, parameters),
configureContinuousScale(spec, scale, parameters);
}
function configureSymlogScale(spec, scale, parameters) {
configureLinearScale(spec, scale, parameters);
const constant = invokeFunctionType(spec.constant, parameters, scale);
isValidNumber(constant) && scale.constant(constant);
}
function configureQuantizeScale(spec, scale, parameters) {
configureScaleNice(spec, scale, parameters), configureScaleNiceMinMax(spec, scale, parameters),
configureScaleDomain(spec, scale, parameters);
}
function configureBaseBandScale(spec, scale, parameters) {
spec.round && scale.round(invokeFunctionType(spec.round, parameters, scale), !0),
spec.padding && scale.padding(invokeFunctionType(spec.padding, parameters, scale), !0),
spec.paddingInner && scale.paddingInner(invokeFunctionType(spec.paddingInner, parameters, scale), !0),
spec.paddingOuter && scale.paddingOuter(invokeFunctionType(spec.paddingOuter, parameters, scale), !0),
spec.align && scale.align(invokeFunctionType(spec.align, parameters, scale), !0);
}
function configureBandScale(spec, scale, parameters) {
return configureBaseBandScale(spec, scale, parameters);
}
function configurePointScale(spec, scale, parameters) {
return configureBaseBandScale(spec, scale, parameters);
}
function parseFieldData(spec, parameters) {
const field = spec.field, refData = getGrammarOutput(spec.data, parameters), fieldData = [];
if (isArray(field)) field.forEach((entry => {
const getter = getFieldAccessor(entry);
refData && refData.forEach((datum => {
fieldData.push(getter(datum));
}));
})); else {
const getter = getFieldAccessor(field);
refData && refData.forEach((datum => {
fieldData.push(getter(datum));
}));
}
return fieldData;
}
function parseMultiFieldData(spec, parameters) {
let fieldData = [];
return spec.datas.forEach((entry => {
fieldData = fieldData.concat(parseFieldData(entry, parameters));
})), fieldData;
}
function parseScaleDataTypeValue(fieldData, scale, sort, filterNumber) {
return sort && fieldData.sort(sort), isContinuous(scale.type) ? (filterNumber && fieldData.filter((entry => isNumber(entry))),
[ minInArray(fieldData), maxInArray(fieldData) ]) : fieldData;
}
export function configureScale(spec, scale, parameters) {
if (isScaleDataType(spec.domain) ? scale.domain(parseScaleDataTypeValue(parseFieldData(spec.domain, parameters), scale, spec.domain.sort, !0), !0) : isMultiScaleDataType(spec.domain) ? scale.domain(parseScaleDataTypeValue(parseMultiFieldData(spec.domain, parameters), scale, spec.domain.sort, !0), !0) : scale.domain(invokeFunctionType(spec.domain, parameters, scale), !0),
"identity" !== spec.type) if (isScaleDataType(spec.range)) scale.range(parseScaleDataTypeValue(parseFieldData(spec.range, parameters), scale), !0); else if (isMultiScaleDataType(spec.range)) scale.range(parseScaleDataTypeValue(parseMultiFieldData(spec.range, parameters), scale), !0); else if (isScaleCoordinateType(spec.range)) {
const coord = getGrammarOutput(spec.range.coordinate, parameters);
!isDiscretizing(scale.type) && coord && scale.range(coord.getRangeByDimension(spec.range.dimension, spec.range.isSubshaft, spec.range.reversed));
} else scale.range(invokeFunctionType(spec.range, parameters, scale), !0);
switch (isNil(spec.unknown) || scale.unknown(invokeFunctionType(spec.unknown, parameters, scale)),
spec.type) {
case "linear":
configureLinearScale(spec, scale, parameters), scale.rescale();
break;
case "band":
configureBandScale(spec, scale, parameters), scale.rescale();
break;
case "point":
configurePointScale(spec, scale, parameters), scale.rescale();
break;
case "pow":
configurePowScale(spec, scale, parameters), scale.rescale();
break;
case "log":
configureLogScale(spec, scale, parameters), scale.rescale();
break;
case "sqrt":
configureSqrtScale(spec, scale, parameters), scale.rescale();
break;
case "symlog":
configureSymlogScale(spec, scale, parameters), scale.rescale();
break;
case "time":
case "utc":
configureTimeScale(spec, scale, parameters), scale.rescale();
break;
case "quantize":
configureQuantizeScale(spec, scale, parameters), scale.rescale();
break;
case "quantile":
scale.rescale();
}
}
//# sourceMappingURL=scale.js.map