base.ts 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. import { assign, isEmpty, isFunction, isNil, isNumber, isObject, isString, map } from '@antv/util';
  2. import { getTickMethod } from './tick-method/register';
  3. import { ScaleConfig, Tick } from './types';
  4. export default abstract class Scale {
  5. /**
  6. * 度量的类型
  7. */
  8. public type: string = 'base';
  9. /**
  10. * 是否分类类型的度量
  11. */
  12. public isCategory?: boolean = false;
  13. /**
  14. * 是否线性度量,有linear, time 度量
  15. */
  16. public isLinear?: boolean = false;
  17. /**
  18. * 是否连续类型的度量,linear,time,log, pow, quantile, quantize 都支持
  19. */
  20. public isContinuous?: boolean = false;
  21. /**
  22. * 是否是常量的度量,传入和传出一致
  23. */
  24. public isIdentity: boolean = false;
  25. public field?: ScaleConfig['field'];
  26. public alias?: ScaleConfig['alias'];
  27. public values: ScaleConfig['values'] = [];
  28. public min?: ScaleConfig['min'];
  29. public max?: ScaleConfig['max'];
  30. public minLimit?: ScaleConfig['minLimit'];
  31. public maxLimit?: ScaleConfig['maxLimit'];
  32. public range: ScaleConfig['range'] = [0, 1];
  33. public ticks: ScaleConfig['ticks'] = [];
  34. public tickCount: ScaleConfig['tickCount'];
  35. public tickInterval: ScaleConfig['tickInterval'];
  36. public formatter?: ScaleConfig['formatter'];
  37. public tickMethod?: ScaleConfig['tickMethod'];
  38. protected __cfg__: ScaleConfig; // 缓存的旧配置, 用于 clone
  39. constructor(cfg: ScaleConfig) {
  40. this.__cfg__ = cfg;
  41. this.initCfg();
  42. this.init();
  43. }
  44. // 对于原始值的必要转换,如分类、时间字段需转换成数值,用transform/map命名可能更好
  45. public translate(v: any) {
  46. return v;
  47. }
  48. /** 将定义域转换为值域 */
  49. public abstract scale(value: any): number;
  50. /** 将值域转换为定义域 */
  51. public abstract invert(scaled: number): any;
  52. /** 重新初始化 */
  53. public change(cfg: ScaleConfig) {
  54. // 覆盖配置项,而不替代
  55. assign(this.__cfg__, cfg);
  56. this.init();
  57. }
  58. public clone(): Scale {
  59. return this.constructor(this.__cfg__);
  60. }
  61. /** 获取坐标轴需要的ticks */
  62. public getTicks(): Tick[] {
  63. return map(this.ticks, (tick: any, idx: number) => {
  64. if (isObject(tick)) {
  65. // 仅当符合Tick类型时才有意义
  66. return tick as Tick;
  67. }
  68. return {
  69. text: this.getText(tick, idx),
  70. tickValue: tick, // 原始value
  71. value: this.scale(tick), // scaled
  72. };
  73. });
  74. }
  75. /** 获取Tick的格式化结果 */
  76. public getText(value: any, key?: number): string {
  77. const formatter = this.formatter;
  78. const res = formatter ? formatter(value, key) : value;
  79. if (isNil(res) || !isFunction(res.toString)) {
  80. return '';
  81. }
  82. return res.toString();
  83. }
  84. // 获取配置项中的值,当前 scale 上的值可能会被修改
  85. protected getConfig(key) {
  86. return this.__cfg__[key];
  87. }
  88. // scale初始化
  89. protected init(): void {
  90. assign(this, this.__cfg__);
  91. this.setDomain();
  92. if (isEmpty(this.getConfig('ticks'))) {
  93. this.ticks = this.calculateTicks();
  94. }
  95. }
  96. // 子类上覆盖某些属性,不能直接在类上声明,否则会被覆盖
  97. protected initCfg() {}
  98. protected setDomain(): void {}
  99. protected calculateTicks(): any[] {
  100. const tickMethod = this.tickMethod;
  101. let ticks = [];
  102. if (isString(tickMethod)) {
  103. const method = getTickMethod(tickMethod);
  104. if (!method) {
  105. throw new Error('There is no method to to calculate ticks!');
  106. }
  107. ticks = method(this);
  108. } else if (isFunction(tickMethod)) {
  109. ticks = tickMethod(this);
  110. }
  111. return ticks;
  112. }
  113. // range 的最小值
  114. protected rangeMin() {
  115. return this.range[0];
  116. }
  117. // range 的最大值
  118. protected rangeMax() {
  119. return this.range[1];
  120. }
  121. /** 定义域转 0~1 */
  122. protected calcPercent(value: any, min: number, max: number): number {
  123. if (isNumber(value)) {
  124. return (value - min) / (max - min);
  125. }
  126. return NaN;
  127. }
  128. /** 0~1转定义域 */
  129. protected calcValue(percent: number, min: number, max: number): number {
  130. return min + percent * (max - min);
  131. }
  132. }