scale.js 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299
  1. import { getScale } from '../../scale';
  2. import { isNil, mix, isObject, each, isArray, isString, isNumber, Array } from '../../util/common';
  3. import Global from '../../global';
  4. function isFullCircle(coord) {
  5. if (!coord.isPolar) {
  6. return false;
  7. }
  8. var startAngle = coord.startAngle;
  9. var endAngle = coord.endAngle;
  10. if (!isNil(startAngle) && !isNil(endAngle) && endAngle - startAngle < Math.PI * 2) {
  11. return false;
  12. }
  13. return true;
  14. }
  15. function clearObj(obj) {
  16. Object.keys(obj).forEach(function (key) {
  17. delete obj[key];
  18. });
  19. }
  20. class ScaleController {
  21. constructor(cfg) {
  22. // defs 列定义
  23. this.defs = {}; // 已经实例化的scale
  24. this.scales = {};
  25. mix(this, cfg);
  26. }
  27. setFieldDef(field, cfg) {
  28. var {
  29. defs
  30. } = this;
  31. if (isObject(field)) {
  32. mix(defs, field);
  33. } else {
  34. defs[field] = cfg;
  35. } // 因为可能同时变更多个scale,所以要把所有已实例化的scale都更新下
  36. this.updateScales();
  37. }
  38. _getDef(field) {
  39. var defs = this.defs;
  40. var def = null;
  41. if (Global.scales[field] || defs[field]) {
  42. def = mix({}, Global.scales[field]);
  43. each(defs[field], function (v, k) {
  44. if (isNil(v)) {
  45. delete def[k];
  46. } else {
  47. def[k] = v;
  48. }
  49. });
  50. }
  51. return def;
  52. }
  53. _getDefaultType(field, data, def) {
  54. if (def && def.type) {
  55. return def.type;
  56. }
  57. var type = 'linear';
  58. var value = Array.firstValue(data, field);
  59. if (isArray(value)) {
  60. value = value[0];
  61. }
  62. if (isString(value)) {
  63. type = 'cat';
  64. }
  65. return type;
  66. }
  67. _getScaleDef(type, field, data, def) {
  68. var values;
  69. if (def && def.values) {
  70. values = def.values;
  71. } else {
  72. values = Array.values(data, field);
  73. }
  74. var cfg = {
  75. field,
  76. values
  77. };
  78. if (type !== 'cat' && type !== 'timeCat') {
  79. if (!def || !(def.min && def.max)) {
  80. var {
  81. min,
  82. max
  83. } = Array.getRange(values);
  84. cfg.min = min;
  85. cfg.max = max;
  86. cfg.nice = true;
  87. }
  88. } else {
  89. cfg.isRounding = false; // used for tickCount calculation
  90. }
  91. return cfg;
  92. } // 调整range,为了让图形居中
  93. _adjustRange(type, cfg) {
  94. var {
  95. range,
  96. values
  97. } = cfg; // 如果是线性, 或者有自定义range都不处理
  98. if (type === 'linear' || range || !values) {
  99. return cfg;
  100. }
  101. var count = values.length; // 单只有一条数据时,在中间显示
  102. if (count === 1) {
  103. cfg.range = [0.5, 1];
  104. } else {
  105. var {
  106. chart
  107. } = this;
  108. var coord = chart.get('coord');
  109. var widthRatio = Global.widthRatio.multiplePie;
  110. var offset = 0;
  111. if (isFullCircle(coord)) {
  112. if (!coord.transposed) {
  113. cfg.range = [0, 1 - 1 / count];
  114. } else {
  115. offset = 1 / count * widthRatio;
  116. cfg.range = [offset / 2, 1 - offset / 2];
  117. }
  118. } else {
  119. // 为了让图形居中,所以才设置range
  120. offset = 1 / count * 0.5; // 这里可能用0.25会更合理
  121. cfg.range = [offset, 1 - offset];
  122. }
  123. }
  124. return cfg;
  125. }
  126. _getScaleCfg(field, data) {
  127. var self = this;
  128. var def = self._getDef(field);
  129. if (!data || !data.length) {
  130. if (def && def.type) {
  131. def.field = field;
  132. return {
  133. type: def.type,
  134. cfg: def
  135. };
  136. }
  137. return {
  138. type: 'identity',
  139. cfg: {
  140. value: field,
  141. field: field.toString(),
  142. values: [field]
  143. }
  144. };
  145. }
  146. var firstObj = data[0];
  147. var firstValue = firstObj[field];
  148. if (firstValue === null) {
  149. firstValue = Array.firstValue(data, field);
  150. }
  151. if (isNumber(field) || isNil(firstValue) && !def) {
  152. return {
  153. type: 'identity',
  154. cfg: {
  155. value: field,
  156. field: field.toString(),
  157. values: [field]
  158. }
  159. };
  160. }
  161. var type = self._getDefaultType(field, data, def);
  162. var cfg = self._getScaleDef(type, field, data, def);
  163. def && mix(cfg, def);
  164. cfg = this._adjustRange(type, cfg);
  165. return {
  166. type,
  167. cfg
  168. };
  169. }
  170. createScale(field, data) {
  171. var {
  172. scales
  173. } = this;
  174. var {
  175. type,
  176. cfg
  177. } = this._getScaleCfg(field, data);
  178. var scale = scales[field]; // 如果已经存在,且类型相等时直接返回
  179. if (scale && scale.type === type) {
  180. scale.change(cfg);
  181. return scale;
  182. }
  183. var Scale = getScale(type);
  184. var newScale = new Scale(cfg);
  185. scales[field] = newScale;
  186. return newScale;
  187. }
  188. _updateScale(scale) {
  189. var {
  190. field
  191. } = scale; // 因为每个field的数据都会不同
  192. var data = this.chart._getScaleData(field);
  193. var {
  194. cfg
  195. } = this._getScaleCfg(field, data);
  196. scale.change(cfg);
  197. }
  198. updateScales() {
  199. var _this = this;
  200. var {
  201. scales
  202. } = this; // 修改完列定义后,需要更新已经实例化的scale
  203. // 如果是还没有实例化的,在geom初始化的时候会被实例化,所以这里可以不用更新
  204. each(scales, function (scale) {
  205. _this._updateScale(scale);
  206. });
  207. } // 调整scale从0开始
  208. adjustStartZero(scale) {
  209. var {
  210. defs
  211. } = this;
  212. var {
  213. field,
  214. min,
  215. max
  216. } = scale; // 如果有定义,则不处理
  217. if (defs[field] && defs[field].min) {
  218. return;
  219. }
  220. if (min > 0) {
  221. scale.change({
  222. min: 0
  223. });
  224. } else if (max < 0) {
  225. scale.change({
  226. max: 0
  227. });
  228. }
  229. }
  230. clear() {
  231. // this.defs = {};
  232. // this.scales = {};
  233. clearObj(this.defs);
  234. clearObj(this.scales);
  235. this.data = null;
  236. }
  237. }
  238. export default ScaleController;