roams.js 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. var zrUtil = require("zrender/lib/core/util");
  2. var RoamController = require("../../component/helper/RoamController");
  3. var throttleUtil = require("../../util/throttle");
  4. // Only create one roam controller for each coordinate system.
  5. // one roam controller might be refered by two inside data zoom
  6. // components (for example, one for x and one for y). When user
  7. // pan or zoom, only dispatch one action for those data zoom
  8. // components.
  9. var curry = zrUtil.curry;
  10. var ATTR = '\0_ec_dataZoom_roams';
  11. /**
  12. * @public
  13. * @param {module:echarts/ExtensionAPI} api
  14. * @param {Object} dataZoomInfo
  15. * @param {string} dataZoomInfo.coordId
  16. * @param {Function} dataZoomInfo.containsPoint
  17. * @param {Array.<string>} dataZoomInfo.allCoordIds
  18. * @param {string} dataZoomInfo.dataZoomId
  19. * @param {number} dataZoomInfo.throttleRate
  20. * @param {Function} dataZoomInfo.panGetRange
  21. * @param {Function} dataZoomInfo.zoomGetRange
  22. * @param {boolean} [dataZoomInfo.zoomLock]
  23. * @param {boolean} [dataZoomInfo.disabled]
  24. */
  25. function register(api, dataZoomInfo) {
  26. var store = giveStore(api);
  27. var theDataZoomId = dataZoomInfo.dataZoomId;
  28. var theCoordId = dataZoomInfo.coordId; // Do clean when a dataZoom changes its target coordnate system.
  29. // Avoid memory leak, dispose all not-used-registered.
  30. zrUtil.each(store, function (record, coordId) {
  31. var dataZoomInfos = record.dataZoomInfos;
  32. if (dataZoomInfos[theDataZoomId] && zrUtil.indexOf(dataZoomInfo.allCoordIds, theCoordId) < 0) {
  33. delete dataZoomInfos[theDataZoomId];
  34. record.count--;
  35. }
  36. });
  37. cleanStore(store);
  38. var record = store[theCoordId]; // Create if needed.
  39. if (!record) {
  40. record = store[theCoordId] = {
  41. coordId: theCoordId,
  42. dataZoomInfos: {},
  43. count: 0
  44. };
  45. record.controller = createController(api, record);
  46. record.dispatchAction = zrUtil.curry(dispatchAction, api);
  47. } // Update reference of dataZoom.
  48. !record.dataZoomInfos[theDataZoomId] && record.count++;
  49. record.dataZoomInfos[theDataZoomId] = dataZoomInfo;
  50. var controllerParams = mergeControllerParams(record.dataZoomInfos);
  51. record.controller.enable(controllerParams.controlType, controllerParams.opt); // Consider resize, area should be always updated.
  52. record.controller.setPointerChecker(dataZoomInfo.containsPoint); // Update throttle.
  53. throttleUtil.createOrUpdate(record, 'dispatchAction', dataZoomInfo.throttleRate, 'fixRate');
  54. }
  55. /**
  56. * @public
  57. * @param {module:echarts/ExtensionAPI} api
  58. * @param {string} dataZoomId
  59. */
  60. function unregister(api, dataZoomId) {
  61. var store = giveStore(api);
  62. zrUtil.each(store, function (record) {
  63. record.controller.dispose();
  64. var dataZoomInfos = record.dataZoomInfos;
  65. if (dataZoomInfos[dataZoomId]) {
  66. delete dataZoomInfos[dataZoomId];
  67. record.count--;
  68. }
  69. });
  70. cleanStore(store);
  71. }
  72. /**
  73. * @public
  74. */
  75. function shouldRecordRange(payload, dataZoomId) {
  76. if (payload && payload.type === 'dataZoom' && payload.batch) {
  77. for (var i = 0, len = payload.batch.length; i < len; i++) {
  78. if (payload.batch[i].dataZoomId === dataZoomId) {
  79. return false;
  80. }
  81. }
  82. }
  83. return true;
  84. }
  85. /**
  86. * @public
  87. */
  88. function generateCoordId(coordModel) {
  89. return coordModel.type + '\0_' + coordModel.id;
  90. }
  91. /**
  92. * Key: coordId, value: {dataZoomInfos: [], count, controller}
  93. * @type {Array.<Object>}
  94. */
  95. function giveStore(api) {
  96. // Mount store on zrender instance, so that we do not
  97. // need to worry about dispose.
  98. var zr = api.getZr();
  99. return zr[ATTR] || (zr[ATTR] = {});
  100. }
  101. function createController(api, newRecord) {
  102. var controller = new RoamController(api.getZr());
  103. controller.on('pan', curry(onPan, newRecord));
  104. controller.on('zoom', curry(onZoom, newRecord));
  105. return controller;
  106. }
  107. function cleanStore(store) {
  108. zrUtil.each(store, function (record, coordId) {
  109. if (!record.count) {
  110. record.controller.dispose();
  111. delete store[coordId];
  112. }
  113. });
  114. }
  115. function onPan(record, dx, dy, oldX, oldY, newX, newY) {
  116. wrapAndDispatch(record, function (info) {
  117. return info.panGetRange(record.controller, dx, dy, oldX, oldY, newX, newY);
  118. });
  119. }
  120. function onZoom(record, scale, mouseX, mouseY) {
  121. wrapAndDispatch(record, function (info) {
  122. return info.zoomGetRange(record.controller, scale, mouseX, mouseY);
  123. });
  124. }
  125. function wrapAndDispatch(record, getRange) {
  126. var batch = [];
  127. zrUtil.each(record.dataZoomInfos, function (info) {
  128. var range = getRange(info);
  129. !info.disabled && range && batch.push({
  130. dataZoomId: info.dataZoomId,
  131. start: range[0],
  132. end: range[1]
  133. });
  134. });
  135. record.dispatchAction(batch);
  136. }
  137. /**
  138. * This action will be throttled.
  139. */
  140. function dispatchAction(api, batch) {
  141. api.dispatchAction({
  142. type: 'dataZoom',
  143. batch: batch
  144. });
  145. }
  146. /**
  147. * Merge roamController settings when multiple dataZooms share one roamController.
  148. */
  149. function mergeControllerParams(dataZoomInfos) {
  150. var controlType;
  151. var opt = {};
  152. var typePriority = {
  153. 'true': 2,
  154. 'move': 1,
  155. 'false': 0,
  156. 'undefined': -1
  157. };
  158. zrUtil.each(dataZoomInfos, function (dataZoomInfo) {
  159. var oneType = dataZoomInfo.disabled ? false : dataZoomInfo.zoomLock ? 'move' : true;
  160. typePriority[oneType] > typePriority[controlType] && (controlType = oneType); // Do not support that different 'shift'/'ctrl'/'alt' setting used in one coord sys.
  161. zrUtil.extend(opt, dataZoomInfo.roamControllerOpt);
  162. });
  163. return {
  164. controlType: controlType,
  165. opt: opt
  166. };
  167. }
  168. exports.register = register;
  169. exports.unregister = unregister;
  170. exports.shouldRecordRange = shouldRecordRange;
  171. exports.generateCoordId = generateCoordId;