BrushController.js 25 KB

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