visualEncoding.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283
  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. /**
  20. * AUTO-GENERATED FILE. DO NOT MODIFY.
  21. */
  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. import * as zrUtil from 'zrender/lib/core/util.js';
  41. import BoundingRect from 'zrender/lib/core/BoundingRect.js';
  42. import * as visualSolution from '../../visual/visualSolution.js';
  43. import { makeBrushCommonSelectorForSeries } from './selector.js';
  44. import * as throttleUtil from '../../util/throttle.js';
  45. import BrushTargetManager from '../helper/BrushTargetManager.js';
  46. var STATE_LIST = ['inBrush', 'outOfBrush'];
  47. var DISPATCH_METHOD = '__ecBrushSelect';
  48. var DISPATCH_FLAG = '__ecInBrushSelectEvent';
  49. ;
  50. export function layoutCovers(ecModel) {
  51. ecModel.eachComponent({
  52. mainType: 'brush'
  53. }, function (brushModel) {
  54. var brushTargetManager = brushModel.brushTargetManager = new BrushTargetManager(brushModel.option, ecModel);
  55. brushTargetManager.setInputRanges(brushModel.areas, ecModel);
  56. });
  57. }
  58. /**
  59. * Register the visual encoding if this modules required.
  60. */
  61. export default function brushVisual(ecModel, api, payload) {
  62. var brushSelected = [];
  63. var throttleType;
  64. var throttleDelay;
  65. ecModel.eachComponent({
  66. mainType: 'brush'
  67. }, function (brushModel) {
  68. payload && payload.type === 'takeGlobalCursor' && brushModel.setBrushOption(payload.key === 'brush' ? payload.brushOption : {
  69. brushType: false
  70. });
  71. });
  72. layoutCovers(ecModel);
  73. ecModel.eachComponent({
  74. mainType: 'brush'
  75. }, function (brushModel, brushIndex) {
  76. var thisBrushSelected = {
  77. brushId: brushModel.id,
  78. brushIndex: brushIndex,
  79. brushName: brushModel.name,
  80. areas: zrUtil.clone(brushModel.areas),
  81. selected: []
  82. }; // Every brush component exists in event params, convenient
  83. // for user to find by index.
  84. brushSelected.push(thisBrushSelected);
  85. var brushOption = brushModel.option;
  86. var brushLink = brushOption.brushLink;
  87. var linkedSeriesMap = [];
  88. var selectedDataIndexForLink = [];
  89. var rangeInfoBySeries = [];
  90. var hasBrushExists = false;
  91. if (!brushIndex) {
  92. // Only the first throttle setting works.
  93. throttleType = brushOption.throttleType;
  94. throttleDelay = brushOption.throttleDelay;
  95. } // Add boundingRect and selectors to range.
  96. var areas = zrUtil.map(brushModel.areas, function (area) {
  97. var builder = boundingRectBuilders[area.brushType];
  98. var selectableArea = zrUtil.defaults({
  99. boundingRect: builder ? builder(area) : void 0
  100. }, area);
  101. selectableArea.selectors = makeBrushCommonSelectorForSeries(selectableArea);
  102. return selectableArea;
  103. });
  104. var visualMappings = visualSolution.createVisualMappings(brushModel.option, STATE_LIST, function (mappingOption) {
  105. mappingOption.mappingMethod = 'fixed';
  106. });
  107. zrUtil.isArray(brushLink) && zrUtil.each(brushLink, function (seriesIndex) {
  108. linkedSeriesMap[seriesIndex] = 1;
  109. });
  110. function linkOthers(seriesIndex) {
  111. return brushLink === 'all' || !!linkedSeriesMap[seriesIndex];
  112. } // If no supported brush or no brush on the series,
  113. // all visuals should be in original state.
  114. function brushed(rangeInfoList) {
  115. return !!rangeInfoList.length;
  116. }
  117. /**
  118. * Logic for each series: (If the logic has to be modified one day, do it carefully!)
  119. *
  120. * ( brushed ┬ && ┬hasBrushExist ┬ && linkOthers ) => StepA: ┬record, ┬ StepB: ┬visualByRecord.
  121. * !brushed┘ ├hasBrushExist ┤ └nothing,┘ ├visualByRecord.
  122. * └!hasBrushExist┘ └nothing.
  123. * ( !brushed && ┬hasBrushExist ┬ && linkOthers ) => StepA: nothing, StepB: ┬visualByRecord.
  124. * └!hasBrushExist┘ └nothing.
  125. * ( brushed ┬ && !linkOthers ) => StepA: nothing, StepB: ┬visualByCheck.
  126. * !brushed┘ └nothing.
  127. * ( !brushed && !linkOthers ) => StepA: nothing, StepB: nothing.
  128. */
  129. // Step A
  130. ecModel.eachSeries(function (seriesModel, seriesIndex) {
  131. var rangeInfoList = rangeInfoBySeries[seriesIndex] = [];
  132. seriesModel.subType === 'parallel' ? stepAParallel(seriesModel, seriesIndex) : stepAOthers(seriesModel, seriesIndex, rangeInfoList);
  133. });
  134. function stepAParallel(seriesModel, seriesIndex) {
  135. var coordSys = seriesModel.coordinateSystem;
  136. hasBrushExists = hasBrushExists || coordSys.hasAxisBrushed();
  137. linkOthers(seriesIndex) && coordSys.eachActiveState(seriesModel.getData(), function (activeState, dataIndex) {
  138. activeState === 'active' && (selectedDataIndexForLink[dataIndex] = 1);
  139. });
  140. }
  141. function stepAOthers(seriesModel, seriesIndex, rangeInfoList) {
  142. if (!seriesModel.brushSelector || brushModelNotControll(brushModel, seriesIndex)) {
  143. return;
  144. }
  145. zrUtil.each(areas, function (area) {
  146. if (brushModel.brushTargetManager.controlSeries(area, seriesModel, ecModel)) {
  147. rangeInfoList.push(area);
  148. }
  149. hasBrushExists = hasBrushExists || brushed(rangeInfoList);
  150. });
  151. if (linkOthers(seriesIndex) && brushed(rangeInfoList)) {
  152. var data_1 = seriesModel.getData();
  153. data_1.each(function (dataIndex) {
  154. if (checkInRange(seriesModel, rangeInfoList, data_1, dataIndex)) {
  155. selectedDataIndexForLink[dataIndex] = 1;
  156. }
  157. });
  158. }
  159. } // Step B
  160. ecModel.eachSeries(function (seriesModel, seriesIndex) {
  161. var seriesBrushSelected = {
  162. seriesId: seriesModel.id,
  163. seriesIndex: seriesIndex,
  164. seriesName: seriesModel.name,
  165. dataIndex: []
  166. }; // Every series exists in event params, convenient
  167. // for user to find series by seriesIndex.
  168. thisBrushSelected.selected.push(seriesBrushSelected);
  169. var rangeInfoList = rangeInfoBySeries[seriesIndex];
  170. var data = seriesModel.getData();
  171. var getValueState = linkOthers(seriesIndex) ? function (dataIndex) {
  172. return selectedDataIndexForLink[dataIndex] ? (seriesBrushSelected.dataIndex.push(data.getRawIndex(dataIndex)), 'inBrush') : 'outOfBrush';
  173. } : function (dataIndex) {
  174. return checkInRange(seriesModel, rangeInfoList, data, dataIndex) ? (seriesBrushSelected.dataIndex.push(data.getRawIndex(dataIndex)), 'inBrush') : 'outOfBrush';
  175. }; // If no supported brush or no brush, all visuals are in original state.
  176. (linkOthers(seriesIndex) ? hasBrushExists : brushed(rangeInfoList)) && visualSolution.applyVisual(STATE_LIST, visualMappings, data, getValueState);
  177. });
  178. });
  179. dispatchAction(api, throttleType, throttleDelay, brushSelected, payload);
  180. }
  181. ;
  182. function dispatchAction(api, throttleType, throttleDelay, brushSelected, payload) {
  183. // This event will not be triggered when `setOpion`, otherwise dead lock may
  184. // triggered when do `setOption` in event listener, which we do not find
  185. // satisfactory way to solve yet. Some considered resolutions:
  186. // (a) Diff with prevoius selected data ant only trigger event when changed.
  187. // But store previous data and diff precisely (i.e., not only by dataIndex, but
  188. // also detect value changes in selected data) might bring complexity or fragility.
  189. // (b) Use spectial param like `silent` to suppress event triggering.
  190. // But such kind of volatile param may be weird in `setOption`.
  191. if (!payload) {
  192. return;
  193. }
  194. var zr = api.getZr();
  195. if (zr[DISPATCH_FLAG]) {
  196. return;
  197. }
  198. if (!zr[DISPATCH_METHOD]) {
  199. zr[DISPATCH_METHOD] = doDispatch;
  200. }
  201. var fn = throttleUtil.createOrUpdate(zr, DISPATCH_METHOD, throttleDelay, throttleType);
  202. fn(api, brushSelected);
  203. }
  204. function doDispatch(api, brushSelected) {
  205. if (!api.isDisposed()) {
  206. var zr = api.getZr();
  207. zr[DISPATCH_FLAG] = true;
  208. api.dispatchAction({
  209. type: 'brushSelect',
  210. batch: brushSelected
  211. });
  212. zr[DISPATCH_FLAG] = false;
  213. }
  214. }
  215. function checkInRange(seriesModel, rangeInfoList, data, dataIndex) {
  216. for (var i = 0, len = rangeInfoList.length; i < len; i++) {
  217. var area = rangeInfoList[i];
  218. if (seriesModel.brushSelector(dataIndex, data, area.selectors, area)) {
  219. return true;
  220. }
  221. }
  222. }
  223. function brushModelNotControll(brushModel, seriesIndex) {
  224. var seriesIndices = brushModel.option.seriesIndex;
  225. return seriesIndices != null && seriesIndices !== 'all' && (zrUtil.isArray(seriesIndices) ? zrUtil.indexOf(seriesIndices, seriesIndex) < 0 : seriesIndex !== seriesIndices);
  226. }
  227. var boundingRectBuilders = {
  228. rect: function (area) {
  229. return getBoundingRectFromMinMax(area.range);
  230. },
  231. polygon: function (area) {
  232. var minMax;
  233. var range = area.range;
  234. for (var i = 0, len = range.length; i < len; i++) {
  235. minMax = minMax || [[Infinity, -Infinity], [Infinity, -Infinity]];
  236. var rg = range[i];
  237. rg[0] < minMax[0][0] && (minMax[0][0] = rg[0]);
  238. rg[0] > minMax[0][1] && (minMax[0][1] = rg[0]);
  239. rg[1] < minMax[1][0] && (minMax[1][0] = rg[1]);
  240. rg[1] > minMax[1][1] && (minMax[1][1] = rg[1]);
  241. }
  242. return minMax && getBoundingRectFromMinMax(minMax);
  243. }
  244. };
  245. function getBoundingRectFromMinMax(minMax) {
  246. return new BoundingRect(minMax[0][0], minMax[1][0], minMax[0][1] - minMax[0][0], minMax[1][1] - minMax[1][0]);
  247. }