@visactor/vchart
Version:
charts lib based @visactor/VGrammar
162 lines (156 loc) • 8.47 kB
JavaScript
import { isArray, isEmpty, isEqual, isNil } from "@visactor/vutils";
import { isContinuous } from "@visactor/vscale";
import { createScale } from "../util/scale";
import { isDataDomainSpec } from "../util/type";
import { mergeFields } from "../util/data";
export class GlobalScale {
constructor(spec, chart) {
this._scaleSpecMap = new Map, this._scaleMap = new Map, this._modelScaleSpecMap = new Map,
this._markAttributeScaleMap = new Map, this._spec = null, this._chart = null, this.getStatisticalFields = dataId => {
const result = [];
return this._scaleSpecMap.forEach(((v, k) => {
isDataDomainSpec(v.domain) && v.domain.forEach((spec => {
spec.dataId === dataId && spec.fields.forEach((key => {
mergeFields(result, [ {
key: key,
operations: isContinuous(v.type) ? [ "max", "min" ] : [ "values" ]
} ]);
}));
}));
})), this._markAttributeScaleMap.forEach(((specList, scaleName) => {
const scale = this.getScale(scaleName);
specList.forEach((spec => {
this._getSeriesBySeriesId(spec.seriesId).getRawData().name === dataId && spec.field && mergeFields(result, [ {
key: spec.field,
operations: isContinuous(scale.type) ? [ "max", "min" ] : [ "values" ]
} ]);
}));
})), result;
}, this._spec = spec, this._chart = chart, this._setAttrFromSpec();
}
_createFromSpec(s) {
if (!s.id) return null;
let scale = this._scaleMap.get(s.id);
return scale || (scale = "ordinal" === s.type && "color" === s.id ? createScale("colorOrdinal") : createScale(s.type)),
scale ? (isArray(s.range) && scale.range(s.range), isArray(s.domain) && (isDataDomainSpec(s.domain) || scale.domain(s.domain)),
s.specified && scale.specified && scale.specified(s.specified), s.clamp && scale.clamp && scale.clamp(s.clamp),
scale) : null;
}
_setAttrFromSpec() {
var _a;
if (!(null === (_a = this._spec) || void 0 === _a ? void 0 : _a.length)) return;
const newScaleMap = new Map, newScaleSpecMap = new Map;
this._spec.forEach((s => {
const scale = this._createFromSpec(s);
scale && (newScaleMap.set(s.id, scale), newScaleSpecMap.set(s.id, s));
})), this._modelScaleSpecMap.forEach((s => {
const scale = this._createFromSpec(s);
scale && (newScaleMap.set(s.id, scale), newScaleSpecMap.set(s.id, s));
})), this._scaleSpecMap = newScaleSpecMap, this._scaleMap = newScaleMap;
}
updateSpec(spec) {
const result = {
change: !1,
reMake: !1,
reRender: !1,
reSize: !1,
reCompile: !1
};
if (isEqual(spec, this._spec)) return result;
result.change = !0;
for (let i = 0; i < spec.length; i++) {
const s = spec[i], scale = this._scaleMap.get(s.id);
if (!scale) return result.reMake = !0, result;
const lastSpec = this._spec.find((_s => _s.id === s.id));
if (!lastSpec.id) return result.reMake = !0, result;
if (lastSpec.type !== s.type) return result.reMake = !0, result;
if (!isEqual(lastSpec.specified, s.specified)) return result.reMake = !0, result;
s.range && !isEqual(s.range, scale.range()) && (scale.range(s.range), result.reRender = !0),
isDataDomainSpec(s.domain) ? result.reRender = !0 : isEqual(s.domain, scale.domain()) || (scale.domain(s.domain),
result.reRender = !0), this._scaleSpecMap.set(s.id, s);
}
return this._spec = spec, result;
}
registerModelScale(spec) {
const scale = this._createFromSpec(spec);
scale && (this._modelScaleSpecMap.set(spec.id, spec), this._scaleSpecMap.set(spec.id, spec),
this._scaleMap.set(spec.id, scale));
}
removeModelScale(filter) {
this._modelScaleSpecMap.forEach((spec => {
filter(spec) && (this._modelScaleSpecMap.delete(spec.id), this._scaleSpecMap.delete(spec.id),
this._scaleMap.delete(spec.id));
}));
}
getScale(user_id) {
return this._scaleMap.get(user_id);
}
getScaleSpec(user_id) {
return this._scaleSpecMap.get(user_id);
}
_getSeriesByRawDataId(id) {
const series = this._chart.getAllSeries();
for (let i = 0; i < series.length; i++) {
const s = series[i];
if (s.getRawData().name === id) return s;
}
return null;
}
_getSeriesBySeriesId(id) {
const series = this._chart.getAllSeries();
for (let i = 0; i < series.length; i++) {
const s = series[i];
if (s.id === id) return s;
}
return null;
}
updateScaleDomain(defaultDomain) {
this._scaleSpecMap.forEach(((scaleSpec, id) => {
const scale = this._scaleMap.get(id);
if (!scale) return;
if (!isDataDomainSpec(scaleSpec.domain)) return scaleSpec.domain && 0 !== scaleSpec.domain.length || scale.domain(defaultDomain),
void this._updateMarkScale(id, scale, scale.domain().slice());
let domain;
domain = isContinuous(scaleSpec.type) ? [ null, null ] : new Set, scaleSpec.domain.forEach((spec => {
const series = this._getSeriesByRawDataId(spec.dataId);
if (!series) return;
const isContinuousField = isContinuous(scaleSpec.type);
spec.fields.forEach((key => {
const statistics = series.getRawDataStatisticsByField(key, isContinuousField);
statistics && (isContinuousField ? (isNil(domain[0]) ? domain[0] = statistics.min : domain[0] = Math.min(statistics.min, domain[0]),
isNil(domain[1]) ? domain[1] = statistics.max : domain[1] = Math.max(statistics.max, domain[1])) : statistics.values.forEach((value => {
domain.add(value);
})));
}));
}));
const scaleDomain = domain;
isContinuous(scaleSpec.type) || (domain = Array.from(domain)), scale.domain(domain),
this._updateMarkScale(id, scale, scaleDomain);
}));
}
_updateMarkScale(id, scale, domain) {
const list = this._markAttributeScaleMap.get(id);
list && 0 !== list.length && list.forEach((info => {
if (!info.field || !info.markScale || info.markScale === scale) return;
if (isNil(info.changeDomain) || "none" === info.changeDomain || isNil(info.seriesId)) return void (isContinuous(scale.type) ? info.markScale.domain(domain) : scale.domain(Array.from(domain)));
const series = this._getSeriesBySeriesId(info.seriesId), isContinuousScale = isContinuous(scale.type), statistics = series.getRawDataStatisticsByField(info.field, isContinuousScale);
if (!isEmpty(statistics)) return "expand" === info.changeDomain ? (isContinuousScale ? (domain[0] = Math.min(domain[0], statistics.min),
domain[1] = Math.max(domain[1], statistics.max)) : (statistics.values.forEach((value => {
domain.add(value);
})), domain = Array.from(domain)), void info.markScale.domain(domain)) : void ("replace" !== info.changeDomain || (isContinuousScale ? info.markScale.domain([ statistics.min, statistics.max ]) : info.markScale.domain(statistics.values)));
isContinuous(scale.type) ? info.markScale.domain(domain) : scale.domain(Array.from(domain));
}));
}
registerMarkAttributeScale(spec, seriesId) {
const scale = this._scaleMap.get(spec.scale);
let list = this._markAttributeScaleMap.get(spec.scale);
list || (list = [], this._markAttributeScaleMap.set(spec.scale, list));
let markScale = scale;
return (isNil(spec.field) || !isNil(spec.changeDomain) && "none" !== spec.changeDomain && !isNil(seriesId)) && (markScale = scale.clone()),
list.push(Object.assign(Object.assign({}, spec), {
seriesId: seriesId,
markScale: markScale
})), markScale;
}
}
//# sourceMappingURL=global-scale.js.map