context.js 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282
  1. function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
  2. import { getTickMethod } from '../../scale';
  3. import { getRange } from '../../util/array';
  4. import { EVENT_AFTER_INIT, EVENT_AFTER_DATA_CHANGE } from '../../chart/const';
  5. import { toTimeStamp } from '../../util/common'; // 判断新老values是否相等,这里只要判断前后是否相等即可
  6. function isValuesEqual(values, newValues) {
  7. if (values.length !== newValues.length) {
  8. return false;
  9. }
  10. var lastIndex = values.length - 1;
  11. return values[0] === newValues[0] && values[lastIndex] === newValues[lastIndex];
  12. } // 不同交互之间共享的上下文
  13. var defaultRange = [0, 1];
  14. class Context {
  15. // 最开始的原始值
  16. // 当前显示的范围
  17. // 缩放最小的点数
  18. // 最小的缩放比例, 默认通过minCount计算
  19. // minScale = 0.01;
  20. // 交互开始时,ticks个数,主要为了每次缩放后,更新ticks个数
  21. // lastTickCount;
  22. constructor(chart) {
  23. var _this = this;
  24. _defineProperty(this, "chart", null);
  25. _defineProperty(this, "values", null);
  26. _defineProperty(this, "range", defaultRange);
  27. _defineProperty(this, "startRange", defaultRange);
  28. _defineProperty(this, "minCount", 10);
  29. _defineProperty(this, "_afterinit", function () {
  30. // 初始化value值
  31. var scale = _this.getPinchScale(); // 记录原始全量数据
  32. var values = [].concat(scale.values);
  33. _this.values = values; // 最小的缩放比例
  34. if (!_this.minScale) {
  35. _this.minScale = _this.minCount / values.length;
  36. } // 初始化的时候有设置range,则初始化成默认比例
  37. if (_this.range !== defaultRange) {
  38. _this.updateRange(_this.range);
  39. _this.updateTicks();
  40. }
  41. });
  42. _defineProperty(this, "_afterdatachange", function () {
  43. _this.updateRange(_this.range);
  44. });
  45. this.chart = chart;
  46. this._initEvent(chart);
  47. }
  48. _initEvent(chart) {
  49. // 在整体初始化后还需要设置一些初始状态
  50. chart.on(EVENT_AFTER_INIT, this._afterinit);
  51. chart.on(EVENT_AFTER_DATA_CHANGE, this._afterdatachange);
  52. } // 缩放的主轴scale
  53. getPinchScale() {
  54. var {
  55. chart
  56. } = this; // 默认缩放x轴
  57. var scale = chart.getXScale();
  58. return scale;
  59. } // 跟随轴的scale
  60. getFollowScale() {
  61. var {
  62. chart
  63. } = this; // 默认缩放x轴
  64. var scales = chart.getYScales() || [];
  65. return scales[0];
  66. }
  67. start() {
  68. var {
  69. range
  70. } = this;
  71. var scale = this.getPinchScale();
  72. var [start, end] = range; // 记录交互起始的范围
  73. this.startRange = [start, end]; // 记录开始时的ticks个数
  74. this.lastTickCount = scale.tickCount;
  75. }
  76. doZoom(leftScale, rightScale, zoom) {
  77. var {
  78. startRange: range,
  79. minScale
  80. } = this;
  81. var [start, end] = range;
  82. var zoomOffset = 1 - zoom;
  83. var rangeLen = end - start;
  84. var rangeOffset = rangeLen * zoomOffset;
  85. var leftOffset = rangeOffset * leftScale;
  86. var rightOffset = rangeOffset * rightScale;
  87. var newStart = Math.max(0, start - leftOffset);
  88. var newEnd = Math.min(1, end + rightOffset);
  89. var newRange = [newStart, newEnd]; // 如果已经到了最小比例,则不能再继续再放大
  90. if (newEnd - newStart < minScale) {
  91. return;
  92. }
  93. this.updateRange(newRange);
  94. }
  95. doMove(ratio) {
  96. // 不管是0, 还是其他,都不用处理
  97. if (!ratio) return;
  98. var {
  99. startRange: range
  100. } = this;
  101. var [start, end] = range;
  102. var rangeLen = end - start;
  103. var rangeOffset = rangeLen * ratio;
  104. var newStart = start - rangeOffset;
  105. var newEnd = end - rangeOffset; // 处理边界值
  106. var newRange;
  107. if (newStart < 0) {
  108. newRange = [0, rangeLen];
  109. } else if (newEnd > 1) {
  110. newRange = [1 - rangeLen, 1];
  111. } else {
  112. newRange = [newStart, newEnd];
  113. }
  114. this.updateRange(newRange);
  115. }
  116. updateRange(range) {
  117. var {
  118. values
  119. } = this; // 0, 1 的范围之间
  120. var [start, end] = range; // start 不能小于0
  121. start = Math.max(0, start); // end 不能大于1
  122. end = Math.min(1, end); // 设置当前的范围
  123. this.range = [start, end];
  124. var len = values.length;
  125. var valueStart = start * len;
  126. var valueEnd = end * len; // 从原始数据里截取需要显示的数据
  127. var newValues = values.slice(valueStart, valueEnd);
  128. this.repaint(newValues);
  129. }
  130. repaint(newValues) {
  131. var {
  132. chart
  133. } = this;
  134. var scale = this.getPinchScale();
  135. var {
  136. values: currentValues,
  137. ticks
  138. } = scale; // 如果新数组和当前显示的数组相同,则不更新
  139. if (isValuesEqual(currentValues, newValues)) {
  140. return;
  141. } // 更新主轴values
  142. this.updateScale(scale, {
  143. ticks,
  144. values: newValues
  145. });
  146. this.updateFollowScale(scale, newValues);
  147. chart.repaint();
  148. }
  149. updateFollowScale(pinchScale, pinchValues) {
  150. var {
  151. chart
  152. } = this;
  153. var followScale = this.getFollowScale();
  154. var {
  155. field: pinchField,
  156. type: pinchScaleType
  157. } = pinchScale;
  158. var {
  159. field: followField
  160. } = followScale; // 根据主轴的value值,找到所有从轴的value值
  161. var values = []; // 转成map,让查找性能更高
  162. var pinchValueMap = {};
  163. pinchValues.forEach(function (item) {
  164. pinchValueMap[item] = true;
  165. });
  166. var data = chart.get('data');
  167. data.forEach(function (item) {
  168. if (pinchScaleType === 'timeCat') {
  169. var value = toTimeStamp(item[pinchField]);
  170. if (pinchValueMap[value]) {
  171. values.push(item[followField]);
  172. }
  173. }
  174. });
  175. var {
  176. min,
  177. max
  178. } = getRange(values);
  179. this.updateScale(followScale, {
  180. min,
  181. max,
  182. nice: true
  183. });
  184. }
  185. updateScale(scale, cfg) {
  186. if (!scale) {
  187. return;
  188. }
  189. scale.change(cfg);
  190. } // 上一次的tick个数
  191. updateTicks() {
  192. var {
  193. chart,
  194. values
  195. } = this;
  196. var scale = this.getPinchScale();
  197. var {
  198. values: currentValues,
  199. tickCount
  200. } = scale; // 根据当前数据的比例,和定义的tickCount计算应该需要多少个ticks
  201. var newTickCount = Math.round(tickCount * values.length / currentValues.length);
  202. var catTicks = getTickMethod('cat');
  203. var ticks = catTicks({
  204. tickCount: newTickCount,
  205. values
  206. });
  207. this.updateScale(scale, {
  208. ticks,
  209. values: currentValues
  210. }); // 更新完后,需要重新绘制一次
  211. chart.repaint();
  212. }
  213. destroy() {
  214. var {
  215. chart
  216. } = this;
  217. chart.off(EVENT_AFTER_INIT, this._afterinit);
  218. chart.off(EVENT_AFTER_DATA_CHANGE, this._afterdatachange);
  219. }
  220. }
  221. export default Context;