BrushController.js 25 KB

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