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. };
  73. var proto = DataZoom.prototype;
  74. proto.render = function (featureModel, ecModel, api, payload) {
  75. this.model = featureModel;
  76. this.ecModel = ecModel;
  77. this.api = api;
  78. updateZoomBtnStatus(featureModel, ecModel, this, payload, api);
  79. updateBackBtnStatus(featureModel, ecModel);
  80. };
  81. proto.onclick = function (ecModel, api, type) {
  82. handlers[type].call(this);
  83. };
  84. proto.remove = function (ecModel, api) {
  85. this._brushController.unmount();
  86. };
  87. proto.dispose = function (ecModel, api) {
  88. this._brushController.dispose();
  89. };
  90. /**
  91. * @private
  92. */
  93. var handlers = {
  94. zoom: function () {
  95. var nextActive = !this._isZoomActive;
  96. this.api.dispatchAction({
  97. type: 'takeGlobalCursor',
  98. key: 'dataZoomSelect',
  99. dataZoomSelectActive: nextActive
  100. });
  101. },
  102. back: function () {
  103. this._dispatchZoomAction(history.pop(this.ecModel));
  104. }
  105. };
  106. /**
  107. * @private
  108. */
  109. proto._onBrush = function (areas, opt) {
  110. if (!opt.isEnd || !areas.length) {
  111. return;
  112. }
  113. var snapshot = {};
  114. var ecModel = this.ecModel;
  115. this._brushController.updateCovers([]); // remove cover
  116. var brushTargetManager = new BrushTargetManager(retrieveAxisSetting(this.model.option), ecModel, {
  117. include: ['grid']
  118. });
  119. brushTargetManager.matchOutputRanges(areas, ecModel, function (area, coordRange, coordSys) {
  120. if (coordSys.type !== 'cartesian2d') {
  121. return;
  122. }
  123. var brushType = area.brushType;
  124. if (brushType === 'rect') {
  125. setBatch('x', coordSys, coordRange[0]);
  126. setBatch('y', coordSys, coordRange[1]);
  127. } else {
  128. setBatch({
  129. lineX: 'x',
  130. lineY: 'y'
  131. }[brushType], coordSys, coordRange);
  132. }
  133. });
  134. history.push(ecModel, snapshot);
  135. this._dispatchZoomAction(snapshot);
  136. function setBatch(dimName, coordSys, minMax) {
  137. var axis = coordSys.getAxis(dimName);
  138. var axisModel = axis.model;
  139. var dataZoomModel = findDataZoom(dimName, axisModel, ecModel); // Restrict range.
  140. var minMaxSpan = dataZoomModel.findRepresentativeAxisProxy(axisModel).getMinMaxSpan();
  141. if (minMaxSpan.minValueSpan != null || minMaxSpan.maxValueSpan != null) {
  142. minMax = sliderMove(0, minMax.slice(), axis.scale.getExtent(), 0, minMaxSpan.minValueSpan, minMaxSpan.maxValueSpan);
  143. }
  144. dataZoomModel && (snapshot[dataZoomModel.id] = {
  145. dataZoomId: dataZoomModel.id,
  146. startValue: minMax[0],
  147. endValue: minMax[1]
  148. });
  149. }
  150. function findDataZoom(dimName, axisModel, ecModel) {
  151. var found;
  152. ecModel.eachComponent({
  153. mainType: 'dataZoom',
  154. subType: 'select'
  155. }, function (dzModel) {
  156. var has = dzModel.getAxisModel(dimName, axisModel.componentIndex);
  157. has && (found = dzModel);
  158. });
  159. return found;
  160. }
  161. };
  162. /**
  163. * @private
  164. */
  165. proto._dispatchZoomAction = function (snapshot) {
  166. var batch = []; // Convert from hash map to array.
  167. each(snapshot, function (batchItem, dataZoomId) {
  168. batch.push(zrUtil.clone(batchItem));
  169. });
  170. batch.length && this.api.dispatchAction({
  171. type: 'dataZoom',
  172. from: this.uid,
  173. batch: batch
  174. });
  175. };
  176. function retrieveAxisSetting(option) {
  177. var setting = {}; // Compatible with previous setting: null => all axis, false => no axis.
  178. zrUtil.each(['xAxisIndex', 'yAxisIndex'], function (name) {
  179. setting[name] = option[name];
  180. setting[name] == null && (setting[name] = 'all');
  181. (setting[name] === false || setting[name] === 'none') && (setting[name] = []);
  182. });
  183. return setting;
  184. }
  185. function updateBackBtnStatus(featureModel, ecModel) {
  186. featureModel.setIconStatus('back', history.count(ecModel) > 1 ? 'emphasis' : 'normal');
  187. }
  188. function updateZoomBtnStatus(featureModel, ecModel, view, payload, api) {
  189. var zoomActive = view._isZoomActive;
  190. if (payload && payload.type === 'takeGlobalCursor') {
  191. zoomActive = payload.key === 'dataZoomSelect' ? payload.dataZoomSelectActive : false;
  192. }
  193. view._isZoomActive = zoomActive;
  194. featureModel.setIconStatus('zoom', zoomActive ? 'emphasis' : 'normal');
  195. var brushTargetManager = new BrushTargetManager(retrieveAxisSetting(featureModel.option), ecModel, {
  196. include: ['grid']
  197. });
  198. view._brushController.setPanels(brushTargetManager.makePanelOpts(api, function (targetInfo) {
  199. return targetInfo.xAxisDeclared && !targetInfo.yAxisDeclared ? 'lineX' : !targetInfo.xAxisDeclared && targetInfo.yAxisDeclared ? 'lineY' : 'rect';
  200. })).enableBrush(zoomActive ? {
  201. brushType: 'auto',
  202. brushStyle: {
  203. // FIXME user customized?
  204. lineWidth: 0,
  205. fill: 'rgba(0,0,0,0.2)'
  206. }
  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;