pinch.js 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303
  1. function _inheritsLoose(subClass, superClass) { subClass.prototype = Object.create(superClass.prototype); subClass.prototype.constructor = subClass; subClass.__proto__ = superClass; }
  2. function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }
  3. var Util = require('../util/common');
  4. var Helper = require('./helper');
  5. var Interaction = require('./base');
  6. var Chart = require('../chart/chart');
  7. var FilterPlugin = require('../plugin/filter');
  8. var PressTooltipMixin = require('./mixin/press-tooltip');
  9. var updateScaleMixin = require('./mixin/update-scale');
  10. var Pinch =
  11. /*#__PURE__*/
  12. function (_Interaction) {
  13. _inheritsLoose(Pinch, _Interaction);
  14. var _proto = Pinch.prototype;
  15. _proto.getDefaultCfg = function getDefaultCfg() {
  16. var defaultCfg = _Interaction.prototype.getDefaultCfg.call(this);
  17. return Util.mix({}, defaultCfg, {
  18. startEvent: 'pinchstart',
  19. processEvent: 'pinch',
  20. endEvent: 'pinchend',
  21. resetEvent: 'touchend',
  22. pressThreshold: 9,
  23. // Minimal movement that is allowed while pressing
  24. pressTime: 251,
  25. // Minimal press time in ms
  26. mode: 'x',
  27. currentPinchScaling: null,
  28. originValues: null,
  29. minScale: null,
  30. maxScale: null,
  31. limitRange: {},
  32. sensitivity: 1,
  33. _pinchCumulativeDelta: 0,
  34. _timestamp: 0
  35. });
  36. };
  37. function Pinch(cfg, chart) {
  38. var _this;
  39. _this = _Interaction.call(this, cfg, chart) || this;
  40. var self = _assertThisInitialized(_assertThisInitialized(_this));
  41. var hammer = self.hammer;
  42. hammer.get('pinch').set({
  43. // open pinch recognizer
  44. enable: true
  45. });
  46. chart.registerPlugins([FilterPlugin, {
  47. changeData: function changeData() {
  48. self.limitRange = {};
  49. self.originTicks = null;
  50. },
  51. clear: function clear() {
  52. self.limitRange = {};
  53. self.originTicks = null;
  54. }
  55. }]);
  56. Util.mix(self, PressTooltipMixin, updateScaleMixin);
  57. self._bindPress();
  58. return _this;
  59. }
  60. _proto.start = function start() {
  61. if (this.pressed) return;
  62. this.currentPinchScaling = 1;
  63. };
  64. _proto.process = function process(e) {
  65. if (this.pressed) return;
  66. this._handlePinch(e);
  67. };
  68. _proto.end = function end(e) {
  69. if (this.pressed) return;
  70. this._handlePinch(e);
  71. this.currentPinchScaling = null; // reset
  72. this.pinchCumulativeDelta = 0;
  73. };
  74. _proto._handlePinch = function _handlePinch(e) {
  75. var currentPinchScaling = this.currentPinchScaling;
  76. var diff = 1 / currentPinchScaling * e.scale;
  77. var rect = e.target.getBoundingClientRect();
  78. var offsetX = e.center.x - rect.left;
  79. var offsetY = e.center.y - rect.top;
  80. var center = {
  81. x: offsetX,
  82. y: offsetY
  83. }; // fingers position difference
  84. var x = Math.abs(e.pointers[0].clientX - e.pointers[1].clientX);
  85. var y = Math.abs(e.pointers[0].clientY - e.pointers[1].clientY); // diagonal fingers will change both (xy) axes
  86. var p = x / y;
  87. var xy;
  88. if (p > 0.3 && p < 1.7) {
  89. xy = 'xy';
  90. } else if (x > y) {
  91. xy = 'x';
  92. } else {
  93. xy = 'y';
  94. }
  95. var lastTimestamp = this._timestamp;
  96. var now = +new Date();
  97. if (now - lastTimestamp > 16) {
  98. this._doZoom(diff, center, xy);
  99. this._timestamp = now;
  100. } // Keep track of overall scale
  101. this.currentPinchScaling = e.scale;
  102. };
  103. _proto._doZoom = function _doZoom(diff, center, whichAxes) {
  104. var self = this;
  105. var mode = self.mode,
  106. chart = self.chart,
  107. limitRange = self.limitRange; // Which axe should be modified when figers were used.
  108. var _whichAxes;
  109. if (mode === 'xy' && whichAxes !== undefined) {
  110. // based on fingers positions
  111. _whichAxes = whichAxes;
  112. } else {
  113. _whichAxes = 'xy';
  114. }
  115. var data = chart.get('data');
  116. if (Util.directionEnabled(mode, 'x') && Util.directionEnabled(_whichAxes, 'x')) {
  117. // x
  118. var xScale = chart.getXScale();
  119. var xField = xScale.field;
  120. if (!limitRange[xField]) {
  121. limitRange[xField] = Helper.getLimitRange(data, xScale);
  122. }
  123. if (xScale.isCategory) {
  124. // 横轴为分类类型
  125. self._zoomCatScale(xScale, diff, center);
  126. } else if (xScale.isLinear) {
  127. self._zoomLinearScale(xScale, diff, center, 'x');
  128. }
  129. var xDef = Helper.getColDef(chart, xField);
  130. this.xRange = Helper.getFieldRange(xDef, limitRange[xField], xScale.type);
  131. }
  132. if (Util.directionEnabled(mode, 'y') && Util.directionEnabled(_whichAxes, 'y')) {
  133. // y
  134. var yScales = chart.getYScales();
  135. Util.each(yScales, function (yScale) {
  136. var yField = yScale.field;
  137. if (!limitRange[yField]) {
  138. limitRange[yField] = Helper.getLimitRange(data, yScale);
  139. }
  140. yScale.isLinear && self._zoomLinearScale(yScale, diff, center, 'y');
  141. });
  142. var yDef = Helper.getColDef(chart, yScales[0].field);
  143. this.yRange = Helper.getFieldRange(yDef, limitRange[yScales[0].field], yScales[0].type);
  144. }
  145. chart.repaint();
  146. };
  147. _proto._zoomLinearScale = function _zoomLinearScale(scale, zoom, center, flag) {
  148. var chart = this.chart;
  149. var min = scale.min,
  150. max = scale.max,
  151. field = scale.field;
  152. var valueRange = max - min;
  153. var limitRange = this.limitRange;
  154. var originRange = limitRange[field].max - limitRange[field].min;
  155. var coord = chart.get('coord');
  156. var newDiff = valueRange * (zoom - 1);
  157. if (this.minScale && zoom < 1) {
  158. // zoom in
  159. var maxRange = originRange / this.minScale;
  160. newDiff = Math.max(valueRange - maxRange, newDiff);
  161. }
  162. if (this.maxScale && zoom >= 1) {
  163. // zoom out
  164. var minRange = originRange / this.maxScale;
  165. newDiff = Math.min(valueRange - minRange, newDiff);
  166. }
  167. var offsetPoint = coord.invertPoint(center);
  168. var percent = flag === 'x' ? offsetPoint.x : offsetPoint.y;
  169. var minDelta = newDiff * percent;
  170. var maxDelta = newDiff * (1 - percent);
  171. var newMax = max - maxDelta;
  172. var newMin = min + minDelta;
  173. this.updateLinearScale(field, newMin, newMax);
  174. }; // 针对分类类型
  175. _proto._zoomCatScale = function _zoomCatScale(scale, zoom, center) {
  176. var pinchCumulativeDelta = this._pinchCumulativeDelta;
  177. var sensitivity = this.sensitivity;
  178. pinchCumulativeDelta = zoom > 1 ? pinchCumulativeDelta + 1 : pinchCumulativeDelta - 1;
  179. this._pinchCumulativeDelta = pinchCumulativeDelta;
  180. var field = scale.field,
  181. values = scale.values;
  182. var chart = this.chart;
  183. var coord = chart.get('coord');
  184. if (!this.originTicks) {
  185. this.originTicks = scale.ticks;
  186. }
  187. var originValues = this.limitRange[field];
  188. var originValuesLen = originValues.length;
  189. var minScale = this.minScale || 1;
  190. var maxScale = this.maxScale || 5;
  191. var minCount = parseInt(originValuesLen / maxScale);
  192. var maxCount = parseInt(originValuesLen / minScale);
  193. var currentLen = values.length;
  194. if (pinchCumulativeDelta > 0 && currentLen <= minCount) {
  195. return null;
  196. }
  197. if (pinchCumulativeDelta < 0 && currentLen >= maxCount) {
  198. return null;
  199. }
  200. var lastLabelIndex = originValuesLen - 1;
  201. var firstValue = values[0];
  202. var lastValue = values[currentLen - 1];
  203. var minIndex = originValues.indexOf(firstValue);
  204. var maxIndex = originValues.indexOf(lastValue);
  205. var chartCenter = (coord.start.x + coord.end.x) / 2;
  206. var centerPointer = center.x;
  207. if (Math.abs(pinchCumulativeDelta) > sensitivity) {
  208. var deltaCount = Math.max(1, parseInt(currentLen * Math.abs(zoom - 1)));
  209. if (pinchCumulativeDelta < 0) {
  210. if (centerPointer >= chartCenter) {
  211. if (minIndex <= 0) {
  212. maxIndex = Math.min(lastLabelIndex, maxIndex + deltaCount);
  213. } else {
  214. minIndex = Math.max(0, minIndex - deltaCount);
  215. }
  216. } else if (centerPointer < chartCenter) {
  217. if (maxIndex >= lastLabelIndex) {
  218. minIndex = Math.max(0, minIndex - deltaCount);
  219. } else {
  220. maxIndex = Math.min(lastLabelIndex, maxIndex + deltaCount);
  221. }
  222. }
  223. this._pinchCumulativeDelta = 0;
  224. } else if (pinchCumulativeDelta > 0) {
  225. if (centerPointer >= chartCenter) {
  226. minIndex = minIndex < maxIndex ? minIndex = Math.min(maxIndex, minIndex + deltaCount) : minIndex;
  227. } else if (centerPointer < chartCenter) {
  228. maxIndex = maxIndex > minIndex ? maxIndex = Math.max(minIndex, maxIndex - deltaCount) : maxIndex;
  229. }
  230. this._pinchCumulativeDelta = 0;
  231. }
  232. var newValues = originValues.slice(minIndex, maxIndex + 1);
  233. this.updateCatScale(field, newValues, this.originTicks, originValues, minIndex, maxIndex);
  234. }
  235. };
  236. return Pinch;
  237. }(Interaction);
  238. Chart.registerInteraction('pinch', Pinch);
  239. module.exports = Pinch;