BrushController.js 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845
  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 { __extends } from "tslib";
  41. import { curry, each, map, bind, merge, clone, defaults, assert } from 'zrender/lib/core/util.js';
  42. import Eventful from 'zrender/lib/core/Eventful.js';
  43. import * as graphic from '../../util/graphic.js';
  44. import * as interactionMutex from './interactionMutex.js';
  45. import DataDiffer from '../../data/DataDiffer.js';
  46. var BRUSH_PANEL_GLOBAL = true;
  47. var mathMin = Math.min;
  48. var mathMax = Math.max;
  49. var mathPow = Math.pow;
  50. var COVER_Z = 10000;
  51. var UNSELECT_THRESHOLD = 6;
  52. var MIN_RESIZE_LINE_WIDTH = 6;
  53. var MUTEX_RESOURCE_KEY = 'globalPan';
  54. var DIRECTION_MAP = {
  55. w: [0, 0],
  56. e: [0, 1],
  57. n: [1, 0],
  58. s: [1, 1]
  59. };
  60. var CURSOR_MAP = {
  61. w: 'ew',
  62. e: 'ew',
  63. n: 'ns',
  64. s: 'ns',
  65. ne: 'nesw',
  66. sw: 'nesw',
  67. nw: 'nwse',
  68. se: 'nwse'
  69. };
  70. var DEFAULT_BRUSH_OPT = {
  71. brushStyle: {
  72. lineWidth: 2,
  73. stroke: 'rgba(210,219,238,0.3)',
  74. fill: '#D2DBEE'
  75. },
  76. transformable: true,
  77. brushMode: 'single',
  78. removeOnClick: false
  79. };
  80. var baseUID = 0;
  81. /**
  82. * params:
  83. * areas: Array.<Array>, coord relates to container group,
  84. * If no container specified, to global.
  85. * opt {
  86. * isEnd: boolean,
  87. * removeOnClick: boolean
  88. * }
  89. */
  90. var BrushController =
  91. /** @class */
  92. function (_super) {
  93. __extends(BrushController, _super);
  94. function BrushController(zr) {
  95. var _this = _super.call(this) || this;
  96. /**
  97. * @internal
  98. */
  99. _this._track = [];
  100. /**
  101. * @internal
  102. */
  103. _this._covers = [];
  104. _this._handlers = {};
  105. if (process.env.NODE_ENV !== 'production') {
  106. assert(zr);
  107. }
  108. _this._zr = zr;
  109. _this.group = new graphic.Group();
  110. _this._uid = 'brushController_' + baseUID++;
  111. each(pointerHandlers, function (handler, eventName) {
  112. this._handlers[eventName] = bind(handler, this);
  113. }, _this);
  114. return _this;
  115. }
  116. /**
  117. * If set to `false`, select disabled.
  118. */
  119. BrushController.prototype.enableBrush = function (brushOption) {
  120. if (process.env.NODE_ENV !== 'production') {
  121. assert(this._mounted);
  122. }
  123. this._brushType && this._doDisableBrush();
  124. brushOption.brushType && this._doEnableBrush(brushOption);
  125. return this;
  126. };
  127. BrushController.prototype._doEnableBrush = function (brushOption) {
  128. var zr = this._zr; // Consider roam, which takes globalPan too.
  129. if (!this._enableGlobalPan) {
  130. interactionMutex.take(zr, MUTEX_RESOURCE_KEY, this._uid);
  131. }
  132. each(this._handlers, function (handler, eventName) {
  133. zr.on(eventName, handler);
  134. });
  135. this._brushType = brushOption.brushType;
  136. this._brushOption = merge(clone(DEFAULT_BRUSH_OPT), brushOption, true);
  137. };
  138. BrushController.prototype._doDisableBrush = function () {
  139. var zr = this._zr;
  140. interactionMutex.release(zr, MUTEX_RESOURCE_KEY, this._uid);
  141. each(this._handlers, function (handler, eventName) {
  142. zr.off(eventName, handler);
  143. });
  144. this._brushType = this._brushOption = null;
  145. };
  146. /**
  147. * @param panelOpts If not pass, it is global brush.
  148. */
  149. BrushController.prototype.setPanels = function (panelOpts) {
  150. if (panelOpts && panelOpts.length) {
  151. var panels_1 = this._panels = {};
  152. each(panelOpts, function (panelOpts) {
  153. panels_1[panelOpts.panelId] = clone(panelOpts);
  154. });
  155. } else {
  156. this._panels = null;
  157. }
  158. return this;
  159. };
  160. BrushController.prototype.mount = function (opt) {
  161. opt = opt || {};
  162. if (process.env.NODE_ENV !== 'production') {
  163. this._mounted = true; // should be at first.
  164. }
  165. this._enableGlobalPan = opt.enableGlobalPan;
  166. var thisGroup = this.group;
  167. this._zr.add(thisGroup);
  168. thisGroup.attr({
  169. x: opt.x || 0,
  170. y: opt.y || 0,
  171. rotation: opt.rotation || 0,
  172. scaleX: opt.scaleX || 1,
  173. scaleY: opt.scaleY || 1
  174. });
  175. this._transform = thisGroup.getLocalTransform();
  176. return this;
  177. }; // eachCover(cb, context): void {
  178. // each(this._covers, cb, context);
  179. // }
  180. /**
  181. * Update covers.
  182. * @param coverConfigList
  183. * If coverConfigList is null/undefined, all covers removed.
  184. */
  185. BrushController.prototype.updateCovers = function (coverConfigList) {
  186. if (process.env.NODE_ENV !== 'production') {
  187. assert(this._mounted);
  188. }
  189. coverConfigList = map(coverConfigList, function (coverConfig) {
  190. return merge(clone(DEFAULT_BRUSH_OPT), coverConfig, true);
  191. });
  192. var tmpIdPrefix = '\0-brush-index-';
  193. var oldCovers = this._covers;
  194. var newCovers = this._covers = [];
  195. var controller = this;
  196. var creatingCover = this._creatingCover;
  197. new DataDiffer(oldCovers, coverConfigList, oldGetKey, getKey).add(addOrUpdate).update(addOrUpdate).remove(remove).execute();
  198. return this;
  199. function getKey(brushOption, index) {
  200. return (brushOption.id != null ? brushOption.id : tmpIdPrefix + index) + '-' + brushOption.brushType;
  201. }
  202. function oldGetKey(cover, index) {
  203. return getKey(cover.__brushOption, index);
  204. }
  205. function addOrUpdate(newIndex, oldIndex) {
  206. var newBrushInternal = coverConfigList[newIndex]; // Consider setOption in event listener of brushSelect,
  207. // where updating cover when creating should be forbiden.
  208. if (oldIndex != null && oldCovers[oldIndex] === creatingCover) {
  209. newCovers[newIndex] = oldCovers[oldIndex];
  210. } else {
  211. var cover = newCovers[newIndex] = oldIndex != null ? (oldCovers[oldIndex].__brushOption = newBrushInternal, oldCovers[oldIndex]) : endCreating(controller, createCover(controller, newBrushInternal));
  212. updateCoverAfterCreation(controller, cover);
  213. }
  214. }
  215. function remove(oldIndex) {
  216. if (oldCovers[oldIndex] !== creatingCover) {
  217. controller.group.remove(oldCovers[oldIndex]);
  218. }
  219. }
  220. };
  221. BrushController.prototype.unmount = function () {
  222. if (process.env.NODE_ENV !== 'production') {
  223. if (!this._mounted) {
  224. return;
  225. }
  226. }
  227. this.enableBrush(false); // container may 'removeAll' outside.
  228. clearCovers(this);
  229. this._zr.remove(this.group);
  230. if (process.env.NODE_ENV !== 'production') {
  231. this._mounted = false; // should be at last.
  232. }
  233. return this;
  234. };
  235. BrushController.prototype.dispose = function () {
  236. this.unmount();
  237. this.off();
  238. };
  239. return BrushController;
  240. }(Eventful);
  241. function createCover(controller, brushOption) {
  242. var cover = coverRenderers[brushOption.brushType].createCover(controller, brushOption);
  243. cover.__brushOption = brushOption;
  244. updateZ(cover, brushOption);
  245. controller.group.add(cover);
  246. return cover;
  247. }
  248. function endCreating(controller, creatingCover) {
  249. var coverRenderer = getCoverRenderer(creatingCover);
  250. if (coverRenderer.endCreating) {
  251. coverRenderer.endCreating(controller, creatingCover);
  252. updateZ(creatingCover, creatingCover.__brushOption);
  253. }
  254. return creatingCover;
  255. }
  256. function updateCoverShape(controller, cover) {
  257. var brushOption = cover.__brushOption;
  258. getCoverRenderer(cover).updateCoverShape(controller, cover, brushOption.range, brushOption);
  259. }
  260. function updateZ(cover, brushOption) {
  261. var z = brushOption.z;
  262. z == null && (z = COVER_Z);
  263. cover.traverse(function (el) {
  264. el.z = z;
  265. el.z2 = z; // Consider in given container.
  266. });
  267. }
  268. function updateCoverAfterCreation(controller, cover) {
  269. getCoverRenderer(cover).updateCommon(controller, cover);
  270. updateCoverShape(controller, cover);
  271. }
  272. function getCoverRenderer(cover) {
  273. return coverRenderers[cover.__brushOption.brushType];
  274. } // return target panel or `true` (means global panel)
  275. function getPanelByPoint(controller, e, localCursorPoint) {
  276. var panels = controller._panels;
  277. if (!panels) {
  278. return BRUSH_PANEL_GLOBAL; // Global panel
  279. }
  280. var panel;
  281. var transform = controller._transform;
  282. each(panels, function (pn) {
  283. pn.isTargetByCursor(e, localCursorPoint, transform) && (panel = pn);
  284. });
  285. return panel;
  286. } // Return a panel or true
  287. function getPanelByCover(controller, cover) {
  288. var panels = controller._panels;
  289. if (!panels) {
  290. return BRUSH_PANEL_GLOBAL; // Global panel
  291. }
  292. var panelId = cover.__brushOption.panelId; // User may give cover without coord sys info,
  293. // which is then treated as global panel.
  294. return panelId != null ? panels[panelId] : BRUSH_PANEL_GLOBAL;
  295. }
  296. function clearCovers(controller) {
  297. var covers = controller._covers;
  298. var originalLength = covers.length;
  299. each(covers, function (cover) {
  300. controller.group.remove(cover);
  301. }, controller);
  302. covers.length = 0;
  303. return !!originalLength;
  304. }
  305. function trigger(controller, opt) {
  306. var areas = map(controller._covers, function (cover) {
  307. var brushOption = cover.__brushOption;
  308. var range = clone(brushOption.range);
  309. return {
  310. brushType: brushOption.brushType,
  311. panelId: brushOption.panelId,
  312. range: range
  313. };
  314. });
  315. controller.trigger('brush', {
  316. areas: areas,
  317. isEnd: !!opt.isEnd,
  318. removeOnClick: !!opt.removeOnClick
  319. });
  320. }
  321. function shouldShowCover(controller) {
  322. var track = controller._track;
  323. if (!track.length) {
  324. return false;
  325. }
  326. var p2 = track[track.length - 1];
  327. var p1 = track[0];
  328. var dx = p2[0] - p1[0];
  329. var dy = p2[1] - p1[1];
  330. var dist = mathPow(dx * dx + dy * dy, 0.5);
  331. return dist > UNSELECT_THRESHOLD;
  332. }
  333. function getTrackEnds(track) {
  334. var tail = track.length - 1;
  335. tail < 0 && (tail = 0);
  336. return [track[0], track[tail]];
  337. }
  338. ;
  339. function createBaseRectCover(rectRangeConverter, controller, brushOption, edgeNameSequences) {
  340. var cover = new graphic.Group();
  341. cover.add(new graphic.Rect({
  342. name: 'main',
  343. style: makeStyle(brushOption),
  344. silent: true,
  345. draggable: true,
  346. cursor: 'move',
  347. drift: curry(driftRect, rectRangeConverter, controller, cover, ['n', 's', 'w', 'e']),
  348. ondragend: curry(trigger, controller, {
  349. isEnd: true
  350. })
  351. }));
  352. each(edgeNameSequences, function (nameSequence) {
  353. cover.add(new graphic.Rect({
  354. name: nameSequence.join(''),
  355. style: {
  356. opacity: 0
  357. },
  358. draggable: true,
  359. silent: true,
  360. invisible: true,
  361. drift: curry(driftRect, rectRangeConverter, controller, cover, nameSequence),
  362. ondragend: curry(trigger, controller, {
  363. isEnd: true
  364. })
  365. }));
  366. });
  367. return cover;
  368. }
  369. function updateBaseRect(controller, cover, localRange, brushOption) {
  370. var lineWidth = brushOption.brushStyle.lineWidth || 0;
  371. var handleSize = mathMax(lineWidth, MIN_RESIZE_LINE_WIDTH);
  372. var x = localRange[0][0];
  373. var y = localRange[1][0];
  374. var xa = x - lineWidth / 2;
  375. var ya = y - lineWidth / 2;
  376. var x2 = localRange[0][1];
  377. var y2 = localRange[1][1];
  378. var x2a = x2 - handleSize + lineWidth / 2;
  379. var y2a = y2 - handleSize + lineWidth / 2;
  380. var width = x2 - x;
  381. var height = y2 - y;
  382. var widtha = width + lineWidth;
  383. var heighta = height + lineWidth;
  384. updateRectShape(controller, cover, 'main', x, y, width, height);
  385. if (brushOption.transformable) {
  386. updateRectShape(controller, cover, 'w', xa, ya, handleSize, heighta);
  387. updateRectShape(controller, cover, 'e', x2a, ya, handleSize, heighta);
  388. updateRectShape(controller, cover, 'n', xa, ya, widtha, handleSize);
  389. updateRectShape(controller, cover, 's', xa, y2a, widtha, handleSize);
  390. updateRectShape(controller, cover, 'nw', xa, ya, handleSize, handleSize);
  391. updateRectShape(controller, cover, 'ne', x2a, ya, handleSize, handleSize);
  392. updateRectShape(controller, cover, 'sw', xa, y2a, handleSize, handleSize);
  393. updateRectShape(controller, cover, 'se', x2a, y2a, handleSize, handleSize);
  394. }
  395. }
  396. function updateCommon(controller, cover) {
  397. var brushOption = cover.__brushOption;
  398. var transformable = brushOption.transformable;
  399. var mainEl = cover.childAt(0);
  400. mainEl.useStyle(makeStyle(brushOption));
  401. mainEl.attr({
  402. silent: !transformable,
  403. cursor: transformable ? 'move' : 'default'
  404. });
  405. each([['w'], ['e'], ['n'], ['s'], ['s', 'e'], ['s', 'w'], ['n', 'e'], ['n', 'w']], function (nameSequence) {
  406. var el = cover.childOfName(nameSequence.join(''));
  407. var globalDir = nameSequence.length === 1 ? getGlobalDirection1(controller, nameSequence[0]) : getGlobalDirection2(controller, nameSequence);
  408. el && el.attr({
  409. silent: !transformable,
  410. invisible: !transformable,
  411. cursor: transformable ? CURSOR_MAP[globalDir] + '-resize' : null
  412. });
  413. });
  414. }
  415. function updateRectShape(controller, cover, name, x, y, w, h) {
  416. var el = cover.childOfName(name);
  417. el && el.setShape(pointsToRect(clipByPanel(controller, cover, [[x, y], [x + w, y + h]])));
  418. }
  419. function makeStyle(brushOption) {
  420. return defaults({
  421. strokeNoScale: true
  422. }, brushOption.brushStyle);
  423. }
  424. function formatRectRange(x, y, x2, y2) {
  425. var min = [mathMin(x, x2), mathMin(y, y2)];
  426. var max = [mathMax(x, x2), mathMax(y, y2)];
  427. return [[min[0], max[0]], [min[1], max[1]] // y range
  428. ];
  429. }
  430. function getTransform(controller) {
  431. return graphic.getTransform(controller.group);
  432. }
  433. function getGlobalDirection1(controller, localDirName) {
  434. var map = {
  435. w: 'left',
  436. e: 'right',
  437. n: 'top',
  438. s: 'bottom'
  439. };
  440. var inverseMap = {
  441. left: 'w',
  442. right: 'e',
  443. top: 'n',
  444. bottom: 's'
  445. };
  446. var dir = graphic.transformDirection(map[localDirName], getTransform(controller));
  447. return inverseMap[dir];
  448. }
  449. function getGlobalDirection2(controller, localDirNameSeq) {
  450. var globalDir = [getGlobalDirection1(controller, localDirNameSeq[0]), getGlobalDirection1(controller, localDirNameSeq[1])];
  451. (globalDir[0] === 'e' || globalDir[0] === 'w') && globalDir.reverse();
  452. return globalDir.join('');
  453. }
  454. function driftRect(rectRangeConverter, controller, cover, dirNameSequence, dx, dy) {
  455. var brushOption = cover.__brushOption;
  456. var rectRange = rectRangeConverter.toRectRange(brushOption.range);
  457. var localDelta = toLocalDelta(controller, dx, dy);
  458. each(dirNameSequence, function (dirName) {
  459. var ind = DIRECTION_MAP[dirName];
  460. rectRange[ind[0]][ind[1]] += localDelta[ind[0]];
  461. });
  462. brushOption.range = rectRangeConverter.fromRectRange(formatRectRange(rectRange[0][0], rectRange[1][0], rectRange[0][1], rectRange[1][1]));
  463. updateCoverAfterCreation(controller, cover);
  464. trigger(controller, {
  465. isEnd: false
  466. });
  467. }
  468. function driftPolygon(controller, cover, dx, dy) {
  469. var range = cover.__brushOption.range;
  470. var localDelta = toLocalDelta(controller, dx, dy);
  471. each(range, function (point) {
  472. point[0] += localDelta[0];
  473. point[1] += localDelta[1];
  474. });
  475. updateCoverAfterCreation(controller, cover);
  476. trigger(controller, {
  477. isEnd: false
  478. });
  479. }
  480. function toLocalDelta(controller, dx, dy) {
  481. var thisGroup = controller.group;
  482. var localD = thisGroup.transformCoordToLocal(dx, dy);
  483. var localZero = thisGroup.transformCoordToLocal(0, 0);
  484. return [localD[0] - localZero[0], localD[1] - localZero[1]];
  485. }
  486. function clipByPanel(controller, cover, data) {
  487. var panel = getPanelByCover(controller, cover);
  488. return panel && panel !== BRUSH_PANEL_GLOBAL ? panel.clipPath(data, controller._transform) : clone(data);
  489. }
  490. function pointsToRect(points) {
  491. var xmin = mathMin(points[0][0], points[1][0]);
  492. var ymin = mathMin(points[0][1], points[1][1]);
  493. var xmax = mathMax(points[0][0], points[1][0]);
  494. var ymax = mathMax(points[0][1], points[1][1]);
  495. return {
  496. x: xmin,
  497. y: ymin,
  498. width: xmax - xmin,
  499. height: ymax - ymin
  500. };
  501. }
  502. function resetCursor(controller, e, localCursorPoint) {
  503. if ( // Check active
  504. !controller._brushType // resetCursor should be always called when mouse is in zr area,
  505. // but not called when mouse is out of zr area to avoid bad influence
  506. // if `mousemove`, `mouseup` are triggered from `document` event.
  507. || isOutsideZrArea(controller, e.offsetX, e.offsetY)) {
  508. return;
  509. }
  510. var zr = controller._zr;
  511. var covers = controller._covers;
  512. var currPanel = getPanelByPoint(controller, e, localCursorPoint); // Check whether in covers.
  513. if (!controller._dragging) {
  514. for (var i = 0; i < covers.length; i++) {
  515. var brushOption = covers[i].__brushOption;
  516. if (currPanel && (currPanel === BRUSH_PANEL_GLOBAL || brushOption.panelId === currPanel.panelId) && coverRenderers[brushOption.brushType].contain(covers[i], localCursorPoint[0], localCursorPoint[1])) {
  517. // Use cursor style set on cover.
  518. return;
  519. }
  520. }
  521. }
  522. currPanel && zr.setCursorStyle('crosshair');
  523. }
  524. function preventDefault(e) {
  525. var rawE = e.event;
  526. rawE.preventDefault && rawE.preventDefault();
  527. }
  528. function mainShapeContain(cover, x, y) {
  529. return cover.childOfName('main').contain(x, y);
  530. }
  531. function updateCoverByMouse(controller, e, localCursorPoint, isEnd) {
  532. var creatingCover = controller._creatingCover;
  533. var panel = controller._creatingPanel;
  534. var thisBrushOption = controller._brushOption;
  535. var eventParams;
  536. controller._track.push(localCursorPoint.slice());
  537. if (shouldShowCover(controller) || creatingCover) {
  538. if (panel && !creatingCover) {
  539. thisBrushOption.brushMode === 'single' && clearCovers(controller);
  540. var brushOption = clone(thisBrushOption);
  541. brushOption.brushType = determineBrushType(brushOption.brushType, panel);
  542. brushOption.panelId = panel === BRUSH_PANEL_GLOBAL ? null : panel.panelId;
  543. creatingCover = controller._creatingCover = createCover(controller, brushOption);
  544. controller._covers.push(creatingCover);
  545. }
  546. if (creatingCover) {
  547. var coverRenderer = coverRenderers[determineBrushType(controller._brushType, panel)];
  548. var coverBrushOption = creatingCover.__brushOption;
  549. coverBrushOption.range = coverRenderer.getCreatingRange(clipByPanel(controller, creatingCover, controller._track));
  550. if (isEnd) {
  551. endCreating(controller, creatingCover);
  552. coverRenderer.updateCommon(controller, creatingCover);
  553. }
  554. updateCoverShape(controller, creatingCover);
  555. eventParams = {
  556. isEnd: isEnd
  557. };
  558. }
  559. } else if (isEnd && thisBrushOption.brushMode === 'single' && thisBrushOption.removeOnClick) {
  560. // Help user to remove covers easily, only by a tiny drag, in 'single' mode.
  561. // But a single click do not clear covers, because user may have casual
  562. // clicks (for example, click on other component and do not expect covers
  563. // disappear).
  564. // Only some cover removed, trigger action, but not every click trigger action.
  565. if (getPanelByPoint(controller, e, localCursorPoint) && clearCovers(controller)) {
  566. eventParams = {
  567. isEnd: isEnd,
  568. removeOnClick: true
  569. };
  570. }
  571. }
  572. return eventParams;
  573. }
  574. function determineBrushType(brushType, panel) {
  575. if (brushType === 'auto') {
  576. if (process.env.NODE_ENV !== 'production') {
  577. assert(panel && panel.defaultBrushType, 'MUST have defaultBrushType when brushType is "atuo"');
  578. }
  579. return panel.defaultBrushType;
  580. }
  581. return brushType;
  582. }
  583. var pointerHandlers = {
  584. mousedown: function (e) {
  585. if (this._dragging) {
  586. // In case some browser do not support globalOut,
  587. // and release mouse out side the browser.
  588. handleDragEnd(this, e);
  589. } else if (!e.target || !e.target.draggable) {
  590. preventDefault(e);
  591. var localCursorPoint = this.group.transformCoordToLocal(e.offsetX, e.offsetY);
  592. this._creatingCover = null;
  593. var panel = this._creatingPanel = getPanelByPoint(this, e, localCursorPoint);
  594. if (panel) {
  595. this._dragging = true;
  596. this._track = [localCursorPoint.slice()];
  597. }
  598. }
  599. },
  600. mousemove: function (e) {
  601. var x = e.offsetX;
  602. var y = e.offsetY;
  603. var localCursorPoint = this.group.transformCoordToLocal(x, y);
  604. resetCursor(this, e, localCursorPoint);
  605. if (this._dragging) {
  606. preventDefault(e);
  607. var eventParams = updateCoverByMouse(this, e, localCursorPoint, false);
  608. eventParams && trigger(this, eventParams);
  609. }
  610. },
  611. mouseup: function (e) {
  612. handleDragEnd(this, e);
  613. }
  614. };
  615. function handleDragEnd(controller, e) {
  616. if (controller._dragging) {
  617. preventDefault(e);
  618. var x = e.offsetX;
  619. var y = e.offsetY;
  620. var localCursorPoint = controller.group.transformCoordToLocal(x, y);
  621. var eventParams = updateCoverByMouse(controller, e, localCursorPoint, true);
  622. controller._dragging = false;
  623. controller._track = [];
  624. controller._creatingCover = null; // trigger event shoule be at final, after procedure will be nested.
  625. eventParams && trigger(controller, eventParams);
  626. }
  627. }
  628. function isOutsideZrArea(controller, x, y) {
  629. var zr = controller._zr;
  630. return x < 0 || x > zr.getWidth() || y < 0 || y > zr.getHeight();
  631. }
  632. /**
  633. * key: brushType
  634. */
  635. var coverRenderers = {
  636. lineX: getLineRenderer(0),
  637. lineY: getLineRenderer(1),
  638. rect: {
  639. createCover: function (controller, brushOption) {
  640. function returnInput(range) {
  641. return range;
  642. }
  643. return createBaseRectCover({
  644. toRectRange: returnInput,
  645. fromRectRange: returnInput
  646. }, controller, brushOption, [['w'], ['e'], ['n'], ['s'], ['s', 'e'], ['s', 'w'], ['n', 'e'], ['n', 'w']]);
  647. },
  648. getCreatingRange: function (localTrack) {
  649. var ends = getTrackEnds(localTrack);
  650. return formatRectRange(ends[1][0], ends[1][1], ends[0][0], ends[0][1]);
  651. },
  652. updateCoverShape: function (controller, cover, localRange, brushOption) {
  653. updateBaseRect(controller, cover, localRange, brushOption);
  654. },
  655. updateCommon: updateCommon,
  656. contain: mainShapeContain
  657. },
  658. polygon: {
  659. createCover: function (controller, brushOption) {
  660. var cover = new graphic.Group(); // Do not use graphic.Polygon because graphic.Polyline do not close the
  661. // border of the shape when drawing, which is a better experience for user.
  662. cover.add(new graphic.Polyline({
  663. name: 'main',
  664. style: makeStyle(brushOption),
  665. silent: true
  666. }));
  667. return cover;
  668. },
  669. getCreatingRange: function (localTrack) {
  670. return localTrack;
  671. },
  672. endCreating: function (controller, cover) {
  673. cover.remove(cover.childAt(0)); // Use graphic.Polygon close the shape.
  674. cover.add(new graphic.Polygon({
  675. name: 'main',
  676. draggable: true,
  677. drift: curry(driftPolygon, controller, cover),
  678. ondragend: curry(trigger, controller, {
  679. isEnd: true
  680. })
  681. }));
  682. },
  683. updateCoverShape: function (controller, cover, localRange, brushOption) {
  684. cover.childAt(0).setShape({
  685. points: clipByPanel(controller, cover, localRange)
  686. });
  687. },
  688. updateCommon: updateCommon,
  689. contain: mainShapeContain
  690. }
  691. };
  692. function getLineRenderer(xyIndex) {
  693. return {
  694. createCover: function (controller, brushOption) {
  695. return createBaseRectCover({
  696. toRectRange: function (range) {
  697. var rectRange = [range, [0, 100]];
  698. xyIndex && rectRange.reverse();
  699. return rectRange;
  700. },
  701. fromRectRange: function (rectRange) {
  702. return rectRange[xyIndex];
  703. }
  704. }, controller, brushOption, [[['w'], ['e']], [['n'], ['s']]][xyIndex]);
  705. },
  706. getCreatingRange: function (localTrack) {
  707. var ends = getTrackEnds(localTrack);
  708. var min = mathMin(ends[0][xyIndex], ends[1][xyIndex]);
  709. var max = mathMax(ends[0][xyIndex], ends[1][xyIndex]);
  710. return [min, max];
  711. },
  712. updateCoverShape: function (controller, cover, localRange, brushOption) {
  713. var otherExtent; // If brushWidth not specified, fit the panel.
  714. var panel = getPanelByCover(controller, cover);
  715. if (panel !== BRUSH_PANEL_GLOBAL && panel.getLinearBrushOtherExtent) {
  716. otherExtent = panel.getLinearBrushOtherExtent(xyIndex);
  717. } else {
  718. var zr = controller._zr;
  719. otherExtent = [0, [zr.getWidth(), zr.getHeight()][1 - xyIndex]];
  720. }
  721. var rectRange = [localRange, otherExtent];
  722. xyIndex && rectRange.reverse();
  723. updateBaseRect(controller, cover, rectRange, brushOption);
  724. },
  725. updateCommon: updateCommon,
  726. contain: mainShapeContain
  727. };
  728. }
  729. export default BrushController;