UNPKG

@visactor/vgrammar-core

Version:

VGrammar is a visual grammar library

348 lines (279 loc) 14.1 kB
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