UNPKG

@antv/scale

Version:

Toolkit for mapping abstract data into visual representation.

133 lines 4.43 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Ordinal = exports.defaultUnknown = void 0; const base_1 = require("./base"); exports.defaultUnknown = Symbol('defaultUnknown'); /** * 更新 indexMap * * @param arr 初始的数组 * @param target 目标 map * @returns {Map<string, any>} 生成的 indexMap */ function updateIndexMap(target, arr, key) { for (let i = 0; i < arr.length; i += 1) { if (!target.has(arr[i])) { target.set(key(arr[i]), i); } } } /** * 基于 indexMap 进行映射 * * @param options 相关选项 * @see MapBetweenArrOptions * @return {any} 映射结果 */ function mapBetweenArrByMapIndex(options) { const { value, from, to, mapper, notFoundReturn } = options; let mappedIndex = mapper.get(value); // index 不存在时, // 如果用户显式设置了 unknown 的值,那么就返回 unknown 的值 // 否者我们将 value 添加到原数组, 并更新 Map if (mappedIndex === undefined) { if (notFoundReturn !== exports.defaultUnknown) { return notFoundReturn; } mappedIndex = from.push(value) - 1; mapper.set(value, mappedIndex); } return to[mappedIndex % to.length]; } function createKey(d) { if (d instanceof Date) return (d) => `${d}`; if (typeof d === 'object') return (d) => JSON.stringify(d); return (d) => d; } /** * Ordinal 比例尺 * * 该比例尺具有离散的域和范围,例如将一组命名类别映射到一组颜色 * * - 使用 for 替代一些基于 map 的遍历,for 循环性能远高于 forEach, map * - 阻止无意义的更新,只有到用户调用 map、invert 或者 update 之后才会进行相应的更新 * - 两个 map 只初始化一次,在之后的更新中复用他们,这样我们避免了重复 new Map 带来的性能问题 * 在大量调用 update 函数场景下,较 d3-scale 效率有质的提高 */ class Ordinal extends base_1.Base { // 覆盖默认配置 getDefaultOptions() { return { domain: [], range: [], unknown: exports.defaultUnknown, }; } // 显示指定 options 的类型为 OrdinalOptions,从而推断出 O 的类型 constructor(options) { super(options); } map(x) { if (this.domainIndexMap.size === 0) { updateIndexMap(this.domainIndexMap, this.getDomain(), this.domainKey); } return mapBetweenArrByMapIndex({ value: this.domainKey(x), mapper: this.domainIndexMap, from: this.getDomain(), to: this.getRange(), notFoundReturn: this.options.unknown, }); } invert(y) { if (this.rangeIndexMap.size === 0) { updateIndexMap(this.rangeIndexMap, this.getRange(), this.rangeKey); } return mapBetweenArrByMapIndex({ value: this.rangeKey(y), mapper: this.rangeIndexMap, from: this.getRange(), to: this.getDomain(), notFoundReturn: this.options.unknown, }); } // 因为 ordinal 比例尺更新内部状态的开销较大,所以按需更新 rescale(options) { const [d] = this.options.domain; const [r] = this.options.range; this.domainKey = createKey(d); this.rangeKey = createKey(r); // 如果 rangeIndexMap 没有初始化,说明是在初始化阶段 if (!this.rangeIndexMap) { this.rangeIndexMap = new Map(); this.domainIndexMap = new Map(); return; } // 否者是在更新阶段 if (!options || options.range) { this.rangeIndexMap.clear(); } if (!options || options.domain || options.compare) { this.domainIndexMap.clear(); this.sortedDomain = undefined; } } clone() { return new Ordinal(this.options); } getRange() { return this.options.range; } getDomain() { // 如果设置了比较器,就排序 if (this.sortedDomain) return this.sortedDomain; const { domain, compare } = this.options; this.sortedDomain = compare ? [...domain].sort(compare) : domain; return this.sortedDomain; } } exports.Ordinal = Ordinal; //# sourceMappingURL=ordinal.js.map