roams.js 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. /*
  2. * Licensed to the Apache Software Foundation (ASF) under one
  3. * or more contributor license agreements. See the NOTICE file
  4. * distributed with this work for additional information
  5. * regarding copyright ownership. The ASF licenses this file
  6. * to you under the Apache License, Version 2.0 (the
  7. * "License"); you may not use this file except in compliance
  8. * with the License. You may obtain a copy of the License at
  9. *
  10. * http://www.apache.org/licenses/LICENSE-2.0
  11. *
  12. * Unless required by applicable law or agreed to in writing,
  13. * software distributed under the License is distributed on an
  14. * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  15. * KIND, either express or implied. See the License for the
  16. * specific language governing permissions and limitations
  17. * under the License.
  18. */
  19. var zrUtil = require("zrender/lib/core/util");
  20. var RoamController = require("../../component/helper/RoamController");
  21. var throttleUtil = require("../../util/throttle");
  22. /*
  23. * Licensed to the Apache Software Foundation (ASF) under one
  24. * or more contributor license agreements. See the NOTICE file
  25. * distributed with this work for additional information
  26. * regarding copyright ownership. The ASF licenses this file
  27. * to you under the Apache License, Version 2.0 (the
  28. * "License"); you may not use this file except in compliance
  29. * with the License. You may obtain a copy of the License at
  30. *
  31. * http://www.apache.org/licenses/LICENSE-2.0
  32. *
  33. * Unless required by applicable law or agreed to in writing,
  34. * software distributed under the License is distributed on an
  35. * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  36. * KIND, either express or implied. See the License for the
  37. * specific language governing permissions and limitations
  38. * under the License.
  39. */
  40. // Only create one roam controller for each coordinate system.
  41. // one roam controller might be refered by two inside data zoom
  42. // components (for example, one for x and one for y). When user
  43. // pan or zoom, only dispatch one action for those data zoom
  44. // components.
  45. var ATTR = '\0_ec_dataZoom_roams';
  46. /**
  47. * @public
  48. * @param {module:echarts/ExtensionAPI} api
  49. * @param {Object} dataZoomInfo
  50. * @param {string} dataZoomInfo.coordId
  51. * @param {Function} dataZoomInfo.containsPoint
  52. * @param {Array.<string>} dataZoomInfo.allCoordIds
  53. * @param {string} dataZoomInfo.dataZoomId
  54. * @param {Object} dataZoomInfo.getRange
  55. * @param {Function} dataZoomInfo.getRange.pan
  56. * @param {Function} dataZoomInfo.getRange.zoom
  57. * @param {Function} dataZoomInfo.getRange.scrollMove
  58. * @param {boolean} dataZoomInfo.dataZoomModel
  59. */
  60. function register(api, dataZoomInfo) {
  61. var store = giveStore(api);
  62. var theDataZoomId = dataZoomInfo.dataZoomId;
  63. var theCoordId = dataZoomInfo.coordId; // Do clean when a dataZoom changes its target coordnate system.
  64. // Avoid memory leak, dispose all not-used-registered.
  65. zrUtil.each(store, function (record, coordId) {
  66. var dataZoomInfos = record.dataZoomInfos;
  67. if (dataZoomInfos[theDataZoomId] && zrUtil.indexOf(dataZoomInfo.allCoordIds, theCoordId) < 0) {
  68. delete dataZoomInfos[theDataZoomId];
  69. record.count--;
  70. }
  71. });
  72. cleanStore(store);
  73. var record = store[theCoordId]; // Create if needed.
  74. if (!record) {
  75. record = store[theCoordId] = {
  76. coordId: theCoordId,
  77. dataZoomInfos: {},
  78. count: 0
  79. };
  80. record.controller = createController(api, record);
  81. record.dispatchAction = zrUtil.curry(dispatchAction, api);
  82. } // Update reference of dataZoom.
  83. !record.dataZoomInfos[theDataZoomId] && record.count++;
  84. record.dataZoomInfos[theDataZoomId] = dataZoomInfo;
  85. var controllerParams = mergeControllerParams(record.dataZoomInfos);
  86. record.controller.enable(controllerParams.controlType, controllerParams.opt); // Consider resize, area should be always updated.
  87. record.controller.setPointerChecker(dataZoomInfo.containsPoint); // Update throttle.
  88. throttleUtil.createOrUpdate(record, 'dispatchAction', dataZoomInfo.dataZoomModel.get('throttle', true), 'fixRate');
  89. }
  90. /**
  91. * @public
  92. * @param {module:echarts/ExtensionAPI} api
  93. * @param {string} dataZoomId
  94. */
  95. function unregister(api, dataZoomId) {
  96. var store = giveStore(api);
  97. zrUtil.each(store, function (record) {
  98. record.controller.dispose();
  99. var dataZoomInfos = record.dataZoomInfos;
  100. if (dataZoomInfos[dataZoomId]) {
  101. delete dataZoomInfos[dataZoomId];
  102. record.count--;
  103. }
  104. });
  105. cleanStore(store);
  106. }
  107. /**
  108. * @public
  109. */
  110. function generateCoordId(coordModel) {
  111. return coordModel.type + '\0_' + coordModel.id;
  112. }
  113. /**
  114. * Key: coordId, value: {dataZoomInfos: [], count, controller}
  115. * @type {Array.<Object>}
  116. */
  117. function giveStore(api) {
  118. // Mount store on zrender instance, so that we do not
  119. // need to worry about dispose.
  120. var zr = api.getZr();
  121. return zr[ATTR] || (zr[ATTR] = {});
  122. }
  123. function createController(api, newRecord) {
  124. var controller = new RoamController(api.getZr());
  125. zrUtil.each(['pan', 'zoom', 'scrollMove'], function (eventName) {
  126. controller.on(eventName, function (event) {
  127. var batch = [];
  128. zrUtil.each(newRecord.dataZoomInfos, function (info) {
  129. // Check whether the behaviors (zoomOnMouseWheel, moveOnMouseMove,
  130. // moveOnMouseWheel, ...) enabled.
  131. if (!event.isAvailableBehavior(info.dataZoomModel.option)) {
  132. return;
  133. }
  134. var method = (info.getRange || {})[eventName];
  135. var range = method && method(newRecord.controller, event);
  136. !info.dataZoomModel.get('disabled', true) && range && batch.push({
  137. dataZoomId: info.dataZoomId,
  138. start: range[0],
  139. end: range[1]
  140. });
  141. });
  142. batch.length && newRecord.dispatchAction(batch);
  143. });
  144. });
  145. return controller;
  146. }
  147. function cleanStore(store) {
  148. zrUtil.each(store, function (record, coordId) {
  149. if (!record.count) {
  150. record.controller.dispose();
  151. delete store[coordId];
  152. }
  153. });
  154. }
  155. /**
  156. * This action will be throttled.
  157. */
  158. function dispatchAction(api, batch) {
  159. api.dispatchAction({
  160. type: 'dataZoom',
  161. batch: batch
  162. });
  163. }
  164. /**
  165. * Merge roamController settings when multiple dataZooms share one roamController.
  166. */
  167. function mergeControllerParams(dataZoomInfos) {
  168. var controlType; // DO NOT use reserved word (true, false, undefined) as key literally. Even if encapsulated
  169. // as string, it is probably revert to reserved word by compress tool. See #7411.
  170. var prefix = 'type_';
  171. var typePriority = {
  172. 'type_true': 2,
  173. 'type_move': 1,
  174. 'type_false': 0,
  175. 'type_undefined': -1
  176. };
  177. var preventDefaultMouseMove = true;
  178. zrUtil.each(dataZoomInfos, function (dataZoomInfo) {
  179. var dataZoomModel = dataZoomInfo.dataZoomModel;
  180. var oneType = dataZoomModel.get('disabled', true) ? false : dataZoomModel.get('zoomLock', true) ? 'move' : true;
  181. if (typePriority[prefix + oneType] > typePriority[prefix + controlType]) {
  182. controlType = oneType;
  183. } // Prevent default move event by default. If one false, do not prevent. Otherwise
  184. // users may be confused why it does not work when multiple insideZooms exist.
  185. preventDefaultMouseMove &= dataZoomModel.get('preventDefaultMouseMove', true);
  186. });
  187. return {
  188. controlType: controlType,
  189. opt: {
  190. // RoamController will enable all of these functionalities,
  191. // and the final behavior is determined by its event listener
  192. // provided by each inside zoom.
  193. zoomOnMouseWheel: true,
  194. moveOnMouseMove: true,
  195. moveOnMouseWheel: true,
  196. preventDefaultMouseMove: !!preventDefaultMouseMove
  197. }
  198. };
  199. }
  200. exports.register = register;
  201. exports.unregister = unregister;
  202. exports.generateCoordId = generateCoordId;