DataZoom.js 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329
  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 echarts = require("../../../echarts");
  20. var zrUtil = require("zrender/lib/core/util");
  21. var BrushController = require("../../helper/BrushController");
  22. var BrushTargetManager = require("../../helper/BrushTargetManager");
  23. var history = require("../../dataZoom/history");
  24. var sliderMove = require("../../helper/sliderMove");
  25. var lang = require("../../../lang");
  26. var featureManager = require("../featureManager");
  27. require("../../dataZoomSelect");
  28. /*
  29. * Licensed to the Apache Software Foundation (ASF) under one
  30. * or more contributor license agreements. See the NOTICE file
  31. * distributed with this work for additional information
  32. * regarding copyright ownership. The ASF licenses this file
  33. * to you under the Apache License, Version 2.0 (the
  34. * "License"); you may not use this file except in compliance
  35. * with the License. You may obtain a copy of the License at
  36. *
  37. * http://www.apache.org/licenses/LICENSE-2.0
  38. *
  39. * Unless required by applicable law or agreed to in writing,
  40. * software distributed under the License is distributed on an
  41. * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  42. * KIND, either express or implied. See the License for the
  43. * specific language governing permissions and limitations
  44. * under the License.
  45. */
  46. // Use dataZoomSelect
  47. var dataZoomLang = lang.toolbox.dataZoom;
  48. var each = zrUtil.each; // Spectial component id start with \0ec\0, see echarts/model/Global.js~hasInnerId
  49. var DATA_ZOOM_ID_BASE = '\0_ec_\0toolbox-dataZoom_';
  50. function DataZoom(model, ecModel, api) {
  51. /**
  52. * @private
  53. * @type {module:echarts/component/helper/BrushController}
  54. */
  55. (this._brushController = new BrushController(api.getZr())).on('brush', zrUtil.bind(this._onBrush, this)).mount();
  56. /**
  57. * @private
  58. * @type {boolean}
  59. */
  60. this._isZoomActive;
  61. }
  62. DataZoom.defaultOption = {
  63. show: true,
  64. filterMode: 'filter',
  65. // Icon group
  66. icon: {
  67. zoom: 'M0,13.5h26.9 M13.5,26.9V0 M32.1,13.5H58V58H13.5 V32.1',
  68. back: 'M22,1.4L9.9,13.5l12.3,12.3 M10.3,13.5H54.9v44.6 H10.3v-26'
  69. },
  70. // `zoom`, `back`
  71. title: zrUtil.clone(dataZoomLang.title),
  72. brushStyle: {
  73. borderWidth: 0,
  74. color: 'rgba(0,0,0,0.2)'
  75. }
  76. };
  77. var proto = DataZoom.prototype;
  78. proto.render = function (featureModel, ecModel, api, payload) {
  79. this.model = featureModel;
  80. this.ecModel = ecModel;
  81. this.api = api;
  82. updateZoomBtnStatus(featureModel, ecModel, this, payload, api);
  83. updateBackBtnStatus(featureModel, ecModel);
  84. };
  85. proto.onclick = function (ecModel, api, type) {
  86. handlers[type].call(this);
  87. };
  88. proto.remove = function (ecModel, api) {
  89. this._brushController.unmount();
  90. };
  91. proto.dispose = function (ecModel, api) {
  92. this._brushController.dispose();
  93. };
  94. /**
  95. * @private
  96. */
  97. var handlers = {
  98. zoom: function () {
  99. var nextActive = !this._isZoomActive;
  100. this.api.dispatchAction({
  101. type: 'takeGlobalCursor',
  102. key: 'dataZoomSelect',
  103. dataZoomSelectActive: nextActive
  104. });
  105. },
  106. back: function () {
  107. this._dispatchZoomAction(history.pop(this.ecModel));
  108. }
  109. };
  110. /**
  111. * @private
  112. */
  113. proto._onBrush = function (areas, opt) {
  114. if (!opt.isEnd || !areas.length) {
  115. return;
  116. }
  117. var snapshot = {};
  118. var ecModel = this.ecModel;
  119. this._brushController.updateCovers([]); // remove cover
  120. var brushTargetManager = new BrushTargetManager(retrieveAxisSetting(this.model.option), ecModel, {
  121. include: ['grid']
  122. });
  123. brushTargetManager.matchOutputRanges(areas, ecModel, function (area, coordRange, coordSys) {
  124. if (coordSys.type !== 'cartesian2d') {
  125. return;
  126. }
  127. var brushType = area.brushType;
  128. if (brushType === 'rect') {
  129. setBatch('x', coordSys, coordRange[0]);
  130. setBatch('y', coordSys, coordRange[1]);
  131. } else {
  132. setBatch({
  133. lineX: 'x',
  134. lineY: 'y'
  135. }[brushType], coordSys, coordRange);
  136. }
  137. });
  138. history.push(ecModel, snapshot);
  139. this._dispatchZoomAction(snapshot);
  140. function setBatch(dimName, coordSys, minMax) {
  141. var axis = coordSys.getAxis(dimName);
  142. var axisModel = axis.model;
  143. var dataZoomModel = findDataZoom(dimName, axisModel, ecModel); // Restrict range.
  144. var minMaxSpan = dataZoomModel.findRepresentativeAxisProxy(axisModel).getMinMaxSpan();
  145. if (minMaxSpan.minValueSpan != null || minMaxSpan.maxValueSpan != null) {
  146. minMax = sliderMove(0, minMax.slice(), axis.scale.getExtent(), 0, minMaxSpan.minValueSpan, minMaxSpan.maxValueSpan);
  147. }
  148. dataZoomModel && (snapshot[dataZoomModel.id] = {
  149. dataZoomId: dataZoomModel.id,
  150. startValue: minMax[0],
  151. endValue: minMax[1]
  152. });
  153. }
  154. function findDataZoom(dimName, axisModel, ecModel) {
  155. var found;
  156. ecModel.eachComponent({
  157. mainType: 'dataZoom',
  158. subType: 'select'
  159. }, function (dzModel) {
  160. var has = dzModel.getAxisModel(dimName, axisModel.componentIndex);
  161. has && (found = dzModel);
  162. });
  163. return found;
  164. }
  165. };
  166. /**
  167. * @private
  168. */
  169. proto._dispatchZoomAction = function (snapshot) {
  170. var batch = []; // Convert from hash map to array.
  171. each(snapshot, function (batchItem, dataZoomId) {
  172. batch.push(zrUtil.clone(batchItem));
  173. });
  174. batch.length && this.api.dispatchAction({
  175. type: 'dataZoom',
  176. from: this.uid,
  177. batch: batch
  178. });
  179. };
  180. function retrieveAxisSetting(option) {
  181. var setting = {}; // Compatible with previous setting: null => all axis, false => no axis.
  182. zrUtil.each(['xAxisIndex', 'yAxisIndex'], function (name) {
  183. setting[name] = option[name];
  184. setting[name] == null && (setting[name] = 'all');
  185. (setting[name] === false || setting[name] === 'none') && (setting[name] = []);
  186. });
  187. return setting;
  188. }
  189. function updateBackBtnStatus(featureModel, ecModel) {
  190. featureModel.setIconStatus('back', history.count(ecModel) > 1 ? 'emphasis' : 'normal');
  191. }
  192. function updateZoomBtnStatus(featureModel, ecModel, view, payload, api) {
  193. var zoomActive = view._isZoomActive;
  194. if (payload && payload.type === 'takeGlobalCursor') {
  195. zoomActive = payload.key === 'dataZoomSelect' ? payload.dataZoomSelectActive : false;
  196. }
  197. view._isZoomActive = zoomActive;
  198. featureModel.setIconStatus('zoom', zoomActive ? 'emphasis' : 'normal');
  199. var brushTargetManager = new BrushTargetManager(retrieveAxisSetting(featureModel.option), ecModel, {
  200. include: ['grid']
  201. });
  202. view._brushController.setPanels(brushTargetManager.makePanelOpts(api, function (targetInfo) {
  203. return targetInfo.xAxisDeclared && !targetInfo.yAxisDeclared ? 'lineX' : !targetInfo.xAxisDeclared && targetInfo.yAxisDeclared ? 'lineY' : 'rect';
  204. })).enableBrush(zoomActive ? {
  205. brushType: 'auto',
  206. brushStyle: featureModel.getModel('brushStyle').getItemStyle()
  207. } : false);
  208. }
  209. featureManager.register('dataZoom', DataZoom); // Create special dataZoom option for select
  210. // FIXME consider the case of merge option, where axes options are not exists.
  211. echarts.registerPreprocessor(function (option) {
  212. if (!option) {
  213. return;
  214. }
  215. var dataZoomOpts = option.dataZoom || (option.dataZoom = []);
  216. if (!zrUtil.isArray(dataZoomOpts)) {
  217. option.dataZoom = dataZoomOpts = [dataZoomOpts];
  218. }
  219. var toolboxOpt = option.toolbox;
  220. if (toolboxOpt) {
  221. // Assume there is only one toolbox
  222. if (zrUtil.isArray(toolboxOpt)) {
  223. toolboxOpt = toolboxOpt[0];
  224. }
  225. if (toolboxOpt && toolboxOpt.feature) {
  226. var dataZoomOpt = toolboxOpt.feature.dataZoom; // FIXME: If add dataZoom when setOption in merge mode,
  227. // no axis info to be added. See `test/dataZoom-extreme.html`
  228. addForAxis('xAxis', dataZoomOpt);
  229. addForAxis('yAxis', dataZoomOpt);
  230. }
  231. }
  232. function addForAxis(axisName, dataZoomOpt) {
  233. if (!dataZoomOpt) {
  234. return;
  235. } // Try not to modify model, because it is not merged yet.
  236. var axisIndicesName = axisName + 'Index';
  237. var givenAxisIndices = dataZoomOpt[axisIndicesName];
  238. if (givenAxisIndices != null && givenAxisIndices !== 'all' && !zrUtil.isArray(givenAxisIndices)) {
  239. givenAxisIndices = givenAxisIndices === false || givenAxisIndices === 'none' ? [] : [givenAxisIndices];
  240. }
  241. forEachComponent(axisName, function (axisOpt, axisIndex) {
  242. if (givenAxisIndices != null && givenAxisIndices !== 'all' && zrUtil.indexOf(givenAxisIndices, axisIndex) === -1) {
  243. return;
  244. }
  245. var newOpt = {
  246. type: 'select',
  247. $fromToolbox: true,
  248. // Default to be filter
  249. filterMode: dataZoomOpt.filterMode || 'filter',
  250. // Id for merge mapping.
  251. id: DATA_ZOOM_ID_BASE + axisName + axisIndex
  252. }; // FIXME
  253. // Only support one axis now.
  254. newOpt[axisIndicesName] = axisIndex;
  255. dataZoomOpts.push(newOpt);
  256. });
  257. }
  258. function forEachComponent(mainType, cb) {
  259. var opts = option[mainType];
  260. if (!zrUtil.isArray(opts)) {
  261. opts = opts ? [opts] : [];
  262. }
  263. each(opts, cb);
  264. }
  265. });
  266. var _default = DataZoom;
  267. module.exports = _default;