| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923 | 
/** Licensed to the Apache Software Foundation (ASF) under one* or more contributor license agreements.  See the NOTICE file* distributed with this work for additional information* regarding copyright ownership.  The ASF licenses this file* to you under the Apache License, Version 2.0 (the* "License"); you may not use this file except in compliance* with the License.  You may obtain a copy of the License at**   http://www.apache.org/licenses/LICENSE-2.0** Unless required by applicable law or agreed to in writing,* software distributed under the License is distributed on an* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY* KIND, either express or implied.  See the License for the* specific language governing permissions and limitations* under the License.*/var _config = require("../../config");var __DEV__ = _config.__DEV__;var zrUtil = require("zrender/lib/core/util");var Eventful = require("zrender/lib/mixin/Eventful");var graphic = require("../../util/graphic");var interactionMutex = require("./interactionMutex");var DataDiffer = require("../../data/DataDiffer");/** Licensed to the Apache Software Foundation (ASF) under one* or more contributor license agreements.  See the NOTICE file* distributed with this work for additional information* regarding copyright ownership.  The ASF licenses this file* to you under the Apache License, Version 2.0 (the* "License"); you may not use this file except in compliance* with the License.  You may obtain a copy of the License at**   http://www.apache.org/licenses/LICENSE-2.0** Unless required by applicable law or agreed to in writing,* software distributed under the License is distributed on an* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY* KIND, either express or implied.  See the License for the* specific language governing permissions and limitations* under the License.*/var curry = zrUtil.curry;var each = zrUtil.each;var map = zrUtil.map;var mathMin = Math.min;var mathMax = Math.max;var mathPow = Math.pow;var COVER_Z = 10000;var UNSELECT_THRESHOLD = 6;var MIN_RESIZE_LINE_WIDTH = 6;var MUTEX_RESOURCE_KEY = 'globalPan';var DIRECTION_MAP = {  w: [0, 0],  e: [0, 1],  n: [1, 0],  s: [1, 1]};var CURSOR_MAP = {  w: 'ew',  e: 'ew',  n: 'ns',  s: 'ns',  ne: 'nesw',  sw: 'nesw',  nw: 'nwse',  se: 'nwse'};var DEFAULT_BRUSH_OPT = {  brushStyle: {    lineWidth: 2,    stroke: 'rgba(0,0,0,0.3)',    fill: 'rgba(0,0,0,0.1)'  },  transformable: true,  brushMode: 'single',  removeOnClick: false};var baseUID = 0;/** * @alias module:echarts/component/helper/BrushController * @constructor * @mixin {module:zrender/mixin/Eventful} * @event module:echarts/component/helper/BrushController#brush *        params: *            areas: Array.<Array>, coord relates to container group, *                                    If no container specified, to global. *            opt { *                isEnd: boolean, *                removeOnClick: boolean *            } * * @param {module:zrender/zrender~ZRender} zr */function BrushController(zr) {  Eventful.call(this);  /**   * @type {module:zrender/zrender~ZRender}   * @private   */  this._zr = zr;  /**   * @type {module:zrender/container/Group}   * @readOnly   */  this.group = new graphic.Group();  /**   * Only for drawing (after enabledBrush).   *     'line', 'rect', 'polygon' or false   *     If passing false/null/undefined, disable brush.   *     If passing 'auto', determined by panel.defaultBrushType   * @private   * @type {string}   */  this._brushType;  /**   * Only for drawing (after enabledBrush).   *   * @private   * @type {Object}   */  this._brushOption;  /**   * @private   * @type {Object}   */  this._panels;  /**   * @private   * @type {Array.<nubmer>}   */  this._track = [];  /**   * @private   * @type {boolean}   */  this._dragging;  /**   * @private   * @type {Array}   */  this._covers = [];  /**   * @private   * @type {moudule:zrender/container/Group}   */  this._creatingCover;  /**   * `true` means global panel   * @private   * @type {module:zrender/container/Group|boolean}   */  this._creatingPanel;  /**   * @private   * @type {boolean}   */  this._enableGlobalPan;  /**   * @private   * @type {boolean}   */  /**   * @private   * @type {string}   */  this._uid = 'brushController_' + baseUID++;  /**   * @private   * @type {Object}   */  this._handlers = {};  each(pointerHandlers, function (handler, eventName) {    this._handlers[eventName] = zrUtil.bind(handler, this);  }, this);}BrushController.prototype = {  constructor: BrushController,  /**   * If set to null/undefined/false, select disabled.   * @param {Object} brushOption   * @param {string|boolean} brushOption.brushType 'line', 'rect', 'polygon' or false   *                          If passing false/null/undefined, disable brush.   *                          If passing 'auto', determined by panel.defaultBrushType.   *                              ('auto' can not be used in global panel)   * @param {number} [brushOption.brushMode='single'] 'single' or 'multiple'   * @param {boolean} [brushOption.transformable=true]   * @param {boolean} [brushOption.removeOnClick=false]   * @param {Object} [brushOption.brushStyle]   * @param {number} [brushOption.brushStyle.width]   * @param {number} [brushOption.brushStyle.lineWidth]   * @param {string} [brushOption.brushStyle.stroke]   * @param {string} [brushOption.brushStyle.fill]   * @param {number} [brushOption.z]   */  enableBrush: function (brushOption) {    this._brushType && doDisableBrush(this);    brushOption.brushType && doEnableBrush(this, brushOption);    return this;  },  /**   * @param {Array.<Object>} panelOpts If not pass, it is global brush.   *        Each items: {   *            panelId, // mandatory.   *            clipPath, // mandatory. function.   *            isTargetByCursor, // mandatory. function.   *            defaultBrushType, // optional, only used when brushType is 'auto'.   *            getLinearBrushOtherExtent, // optional. function.   *        }   */  setPanels: function (panelOpts) {    if (panelOpts && panelOpts.length) {      var panels = this._panels = {};      zrUtil.each(panelOpts, function (panelOpts) {        panels[panelOpts.panelId] = zrUtil.clone(panelOpts);      });    } else {      this._panels = null;    }    return this;  },  /**   * @param {Object} [opt]   * @return {boolean} [opt.enableGlobalPan=false]   */  mount: function (opt) {    opt = opt || {};    this._enableGlobalPan = opt.enableGlobalPan;    var thisGroup = this.group;    this._zr.add(thisGroup);    thisGroup.attr({      position: opt.position || [0, 0],      rotation: opt.rotation || 0,      scale: opt.scale || [1, 1]    });    this._transform = thisGroup.getLocalTransform();    return this;  },  eachCover: function (cb, context) {    each(this._covers, cb, context);  },  /**   * Update covers.   * @param {Array.<Object>} brushOptionList Like:   *        [   *            {id: 'xx', brushType: 'line', range: [23, 44], brushStyle, transformable},   *            {id: 'yy', brushType: 'rect', range: [[23, 44], [23, 54]]},   *            ...   *        ]   *        `brushType` is required in each cover info. (can not be 'auto')   *        `id` is not mandatory.   *        `brushStyle`, `transformable` is not mandatory, use DEFAULT_BRUSH_OPT by default.   *        If brushOptionList is null/undefined, all covers removed.   */  updateCovers: function (brushOptionList) {    brushOptionList = zrUtil.map(brushOptionList, function (brushOption) {      return zrUtil.merge(zrUtil.clone(DEFAULT_BRUSH_OPT), brushOption, true);    });    var tmpIdPrefix = '\0-brush-index-';    var oldCovers = this._covers;    var newCovers = this._covers = [];    var controller = this;    var creatingCover = this._creatingCover;    new DataDiffer(oldCovers, brushOptionList, oldGetKey, getKey).add(addOrUpdate).update(addOrUpdate).remove(remove).execute();    return this;    function getKey(brushOption, index) {      return (brushOption.id != null ? brushOption.id : tmpIdPrefix + index) + '-' + brushOption.brushType;    }    function oldGetKey(cover, index) {      return getKey(cover.__brushOption, index);    }    function addOrUpdate(newIndex, oldIndex) {      var newBrushOption = brushOptionList[newIndex]; // Consider setOption in event listener of brushSelect,      // where updating cover when creating should be forbiden.      if (oldIndex != null && oldCovers[oldIndex] === creatingCover) {        newCovers[newIndex] = oldCovers[oldIndex];      } else {        var cover = newCovers[newIndex] = oldIndex != null ? (oldCovers[oldIndex].__brushOption = newBrushOption, oldCovers[oldIndex]) : endCreating(controller, createCover(controller, newBrushOption));        updateCoverAfterCreation(controller, cover);      }    }    function remove(oldIndex) {      if (oldCovers[oldIndex] !== creatingCover) {        controller.group.remove(oldCovers[oldIndex]);      }    }  },  unmount: function () {    this.enableBrush(false); // container may 'removeAll' outside.    clearCovers(this);    this._zr.remove(this.group);    return this;  },  dispose: function () {    this.unmount();    this.off();  }};zrUtil.mixin(BrushController, Eventful);function doEnableBrush(controller, brushOption) {  var zr = controller._zr; // Consider roam, which takes globalPan too.  if (!controller._enableGlobalPan) {    interactionMutex.take(zr, MUTEX_RESOURCE_KEY, controller._uid);  }  mountHandlers(zr, controller._handlers);  controller._brushType = brushOption.brushType;  controller._brushOption = zrUtil.merge(zrUtil.clone(DEFAULT_BRUSH_OPT), brushOption, true);}function doDisableBrush(controller) {  var zr = controller._zr;  interactionMutex.release(zr, MUTEX_RESOURCE_KEY, controller._uid);  unmountHandlers(zr, controller._handlers);  controller._brushType = controller._brushOption = null;}function mountHandlers(zr, handlers) {  each(handlers, function (handler, eventName) {    zr.on(eventName, handler);  });}function unmountHandlers(zr, handlers) {  each(handlers, function (handler, eventName) {    zr.off(eventName, handler);  });}function createCover(controller, brushOption) {  var cover = coverRenderers[brushOption.brushType].createCover(controller, brushOption);  cover.__brushOption = brushOption;  updateZ(cover, brushOption);  controller.group.add(cover);  return cover;}function endCreating(controller, creatingCover) {  var coverRenderer = getCoverRenderer(creatingCover);  if (coverRenderer.endCreating) {    coverRenderer.endCreating(controller, creatingCover);    updateZ(creatingCover, creatingCover.__brushOption);  }  return creatingCover;}function updateCoverShape(controller, cover) {  var brushOption = cover.__brushOption;  getCoverRenderer(cover).updateCoverShape(controller, cover, brushOption.range, brushOption);}function updateZ(cover, brushOption) {  var z = brushOption.z;  z == null && (z = COVER_Z);  cover.traverse(function (el) {    el.z = z;    el.z2 = z; // Consider in given container.  });}function updateCoverAfterCreation(controller, cover) {  getCoverRenderer(cover).updateCommon(controller, cover);  updateCoverShape(controller, cover);}function getCoverRenderer(cover) {  return coverRenderers[cover.__brushOption.brushType];} // return target panel or `true` (means global panel)function getPanelByPoint(controller, e, localCursorPoint) {  var panels = controller._panels;  if (!panels) {    return true; // Global panel  }  var panel;  var transform = controller._transform;  each(panels, function (pn) {    pn.isTargetByCursor(e, localCursorPoint, transform) && (panel = pn);  });  return panel;} // Return a panel or truefunction getPanelByCover(controller, cover) {  var panels = controller._panels;  if (!panels) {    return true; // Global panel  }  var panelId = cover.__brushOption.panelId; // User may give cover without coord sys info,  // which is then treated as global panel.  return panelId != null ? panels[panelId] : true;}function clearCovers(controller) {  var covers = controller._covers;  var originalLength = covers.length;  each(covers, function (cover) {    controller.group.remove(cover);  }, controller);  covers.length = 0;  return !!originalLength;}function trigger(controller, opt) {  var areas = map(controller._covers, function (cover) {    var brushOption = cover.__brushOption;    var range = zrUtil.clone(brushOption.range);    return {      brushType: brushOption.brushType,      panelId: brushOption.panelId,      range: range    };  });  controller.trigger('brush', areas, {    isEnd: !!opt.isEnd,    removeOnClick: !!opt.removeOnClick  });}function shouldShowCover(controller) {  var track = controller._track;  if (!track.length) {    return false;  }  var p2 = track[track.length - 1];  var p1 = track[0];  var dx = p2[0] - p1[0];  var dy = p2[1] - p1[1];  var dist = mathPow(dx * dx + dy * dy, 0.5);  return dist > UNSELECT_THRESHOLD;}function getTrackEnds(track) {  var tail = track.length - 1;  tail < 0 && (tail = 0);  return [track[0], track[tail]];}function createBaseRectCover(doDrift, controller, brushOption, edgeNames) {  var cover = new graphic.Group();  cover.add(new graphic.Rect({    name: 'main',    style: makeStyle(brushOption),    silent: true,    draggable: true,    cursor: 'move',    drift: curry(doDrift, controller, cover, 'nswe'),    ondragend: curry(trigger, controller, {      isEnd: true    })  }));  each(edgeNames, function (name) {    cover.add(new graphic.Rect({      name: name,      style: {        opacity: 0      },      draggable: true,      silent: true,      invisible: true,      drift: curry(doDrift, controller, cover, name),      ondragend: curry(trigger, controller, {        isEnd: true      })    }));  });  return cover;}function updateBaseRect(controller, cover, localRange, brushOption) {  var lineWidth = brushOption.brushStyle.lineWidth || 0;  var handleSize = mathMax(lineWidth, MIN_RESIZE_LINE_WIDTH);  var x = localRange[0][0];  var y = localRange[1][0];  var xa = x - lineWidth / 2;  var ya = y - lineWidth / 2;  var x2 = localRange[0][1];  var y2 = localRange[1][1];  var x2a = x2 - handleSize + lineWidth / 2;  var y2a = y2 - handleSize + lineWidth / 2;  var width = x2 - x;  var height = y2 - y;  var widtha = width + lineWidth;  var heighta = height + lineWidth;  updateRectShape(controller, cover, 'main', x, y, width, height);  if (brushOption.transformable) {    updateRectShape(controller, cover, 'w', xa, ya, handleSize, heighta);    updateRectShape(controller, cover, 'e', x2a, ya, handleSize, heighta);    updateRectShape(controller, cover, 'n', xa, ya, widtha, handleSize);    updateRectShape(controller, cover, 's', xa, y2a, widtha, handleSize);    updateRectShape(controller, cover, 'nw', xa, ya, handleSize, handleSize);    updateRectShape(controller, cover, 'ne', x2a, ya, handleSize, handleSize);    updateRectShape(controller, cover, 'sw', xa, y2a, handleSize, handleSize);    updateRectShape(controller, cover, 'se', x2a, y2a, handleSize, handleSize);  }}function updateCommon(controller, cover) {  var brushOption = cover.__brushOption;  var transformable = brushOption.transformable;  var mainEl = cover.childAt(0);  mainEl.useStyle(makeStyle(brushOption));  mainEl.attr({    silent: !transformable,    cursor: transformable ? 'move' : 'default'  });  each(['w', 'e', 'n', 's', 'se', 'sw', 'ne', 'nw'], function (name) {    var el = cover.childOfName(name);    var globalDir = getGlobalDirection(controller, name);    el && el.attr({      silent: !transformable,      invisible: !transformable,      cursor: transformable ? CURSOR_MAP[globalDir] + '-resize' : null    });  });}function updateRectShape(controller, cover, name, x, y, w, h) {  var el = cover.childOfName(name);  el && el.setShape(pointsToRect(clipByPanel(controller, cover, [[x, y], [x + w, y + h]])));}function makeStyle(brushOption) {  return zrUtil.defaults({    strokeNoScale: true  }, brushOption.brushStyle);}function formatRectRange(x, y, x2, y2) {  var min = [mathMin(x, x2), mathMin(y, y2)];  var max = [mathMax(x, x2), mathMax(y, y2)];  return [[min[0], max[0]], // x range  [min[1], max[1]] // y range  ];}function getTransform(controller) {  return graphic.getTransform(controller.group);}function getGlobalDirection(controller, localDirection) {  if (localDirection.length > 1) {    localDirection = localDirection.split('');    var globalDir = [getGlobalDirection(controller, localDirection[0]), getGlobalDirection(controller, localDirection[1])];    (globalDir[0] === 'e' || globalDir[0] === 'w') && globalDir.reverse();    return globalDir.join('');  } else {    var map = {      w: 'left',      e: 'right',      n: 'top',      s: 'bottom'    };    var inverseMap = {      left: 'w',      right: 'e',      top: 'n',      bottom: 's'    };    var globalDir = graphic.transformDirection(map[localDirection], getTransform(controller));    return inverseMap[globalDir];  }}function driftRect(toRectRange, fromRectRange, controller, cover, name, dx, dy, e) {  var brushOption = cover.__brushOption;  var rectRange = toRectRange(brushOption.range);  var localDelta = toLocalDelta(controller, dx, dy);  each(name.split(''), function (namePart) {    var ind = DIRECTION_MAP[namePart];    rectRange[ind[0]][ind[1]] += localDelta[ind[0]];  });  brushOption.range = fromRectRange(formatRectRange(rectRange[0][0], rectRange[1][0], rectRange[0][1], rectRange[1][1]));  updateCoverAfterCreation(controller, cover);  trigger(controller, {    isEnd: false  });}function driftPolygon(controller, cover, dx, dy, e) {  var range = cover.__brushOption.range;  var localDelta = toLocalDelta(controller, dx, dy);  each(range, function (point) {    point[0] += localDelta[0];    point[1] += localDelta[1];  });  updateCoverAfterCreation(controller, cover);  trigger(controller, {    isEnd: false  });}function toLocalDelta(controller, dx, dy) {  var thisGroup = controller.group;  var localD = thisGroup.transformCoordToLocal(dx, dy);  var localZero = thisGroup.transformCoordToLocal(0, 0);  return [localD[0] - localZero[0], localD[1] - localZero[1]];}function clipByPanel(controller, cover, data) {  var panel = getPanelByCover(controller, cover);  return panel && panel !== true ? panel.clipPath(data, controller._transform) : zrUtil.clone(data);}function pointsToRect(points) {  var xmin = mathMin(points[0][0], points[1][0]);  var ymin = mathMin(points[0][1], points[1][1]);  var xmax = mathMax(points[0][0], points[1][0]);  var ymax = mathMax(points[0][1], points[1][1]);  return {    x: xmin,    y: ymin,    width: xmax - xmin,    height: ymax - ymin  };}function resetCursor(controller, e, localCursorPoint) {  if ( // Check active  !controller._brushType // resetCursor should be always called when mouse is in zr area,  // but not called when mouse is out of zr area to avoid bad influence  // if `mousemove`, `mouseup` are triggered from `document` event.  || isOutsideZrArea(controller, e)) {    return;  }  var zr = controller._zr;  var covers = controller._covers;  var currPanel = getPanelByPoint(controller, e, localCursorPoint); // Check whether in covers.  if (!controller._dragging) {    for (var i = 0; i < covers.length; i++) {      var brushOption = covers[i].__brushOption;      if (currPanel && (currPanel === true || brushOption.panelId === currPanel.panelId) && coverRenderers[brushOption.brushType].contain(covers[i], localCursorPoint[0], localCursorPoint[1])) {        // Use cursor style set on cover.        return;      }    }  }  currPanel && zr.setCursorStyle('crosshair');}function preventDefault(e) {  var rawE = e.event;  rawE.preventDefault && rawE.preventDefault();}function mainShapeContain(cover, x, y) {  return cover.childOfName('main').contain(x, y);}function updateCoverByMouse(controller, e, localCursorPoint, isEnd) {  var creatingCover = controller._creatingCover;  var panel = controller._creatingPanel;  var thisBrushOption = controller._brushOption;  var eventParams;  controller._track.push(localCursorPoint.slice());  if (shouldShowCover(controller) || creatingCover) {    if (panel && !creatingCover) {      thisBrushOption.brushMode === 'single' && clearCovers(controller);      var brushOption = zrUtil.clone(thisBrushOption);      brushOption.brushType = determineBrushType(brushOption.brushType, panel);      brushOption.panelId = panel === true ? null : panel.panelId;      creatingCover = controller._creatingCover = createCover(controller, brushOption);      controller._covers.push(creatingCover);    }    if (creatingCover) {      var coverRenderer = coverRenderers[determineBrushType(controller._brushType, panel)];      var coverBrushOption = creatingCover.__brushOption;      coverBrushOption.range = coverRenderer.getCreatingRange(clipByPanel(controller, creatingCover, controller._track));      if (isEnd) {        endCreating(controller, creatingCover);        coverRenderer.updateCommon(controller, creatingCover);      }      updateCoverShape(controller, creatingCover);      eventParams = {        isEnd: isEnd      };    }  } else if (isEnd && thisBrushOption.brushMode === 'single' && thisBrushOption.removeOnClick) {    // Help user to remove covers easily, only by a tiny drag, in 'single' mode.    // But a single click do not clear covers, because user may have casual    // clicks (for example, click on other component and do not expect covers    // disappear).    // Only some cover removed, trigger action, but not every click trigger action.    if (getPanelByPoint(controller, e, localCursorPoint) && clearCovers(controller)) {      eventParams = {        isEnd: isEnd,        removeOnClick: true      };    }  }  return eventParams;}function determineBrushType(brushType, panel) {  if (brushType === 'auto') {    return panel.defaultBrushType;  }  return brushType;}var pointerHandlers = {  mousedown: function (e) {    if (this._dragging) {      // In case some browser do not support globalOut,      // and release mose out side the browser.      handleDragEnd(this, e);    } else if (!e.target || !e.target.draggable) {      preventDefault(e);      var localCursorPoint = this.group.transformCoordToLocal(e.offsetX, e.offsetY);      this._creatingCover = null;      var panel = this._creatingPanel = getPanelByPoint(this, e, localCursorPoint);      if (panel) {        this._dragging = true;        this._track = [localCursorPoint.slice()];      }    }  },  mousemove: function (e) {    var x = e.offsetX;    var y = e.offsetY;    var localCursorPoint = this.group.transformCoordToLocal(x, y);    resetCursor(this, e, localCursorPoint);    if (this._dragging) {      preventDefault(e);      var eventParams = updateCoverByMouse(this, e, localCursorPoint, false);      eventParams && trigger(this, eventParams);    }  },  mouseup: function (e) {    handleDragEnd(this, e);  }};function handleDragEnd(controller, e) {  if (controller._dragging) {    preventDefault(e);    var x = e.offsetX;    var y = e.offsetY;    var localCursorPoint = controller.group.transformCoordToLocal(x, y);    var eventParams = updateCoverByMouse(controller, e, localCursorPoint, true);    controller._dragging = false;    controller._track = [];    controller._creatingCover = null; // trigger event shoule be at final, after procedure will be nested.    eventParams && trigger(controller, eventParams);  }}function isOutsideZrArea(controller, x, y) {  var zr = controller._zr;  return x < 0 || x > zr.getWidth() || y < 0 || y > zr.getHeight();}/** * key: brushType * @type {Object} */var coverRenderers = {  lineX: getLineRenderer(0),  lineY: getLineRenderer(1),  rect: {    createCover: function (controller, brushOption) {      return createBaseRectCover(curry(driftRect, function (range) {        return range;      }, function (range) {        return range;      }), controller, brushOption, ['w', 'e', 'n', 's', 'se', 'sw', 'ne', 'nw']);    },    getCreatingRange: function (localTrack) {      var ends = getTrackEnds(localTrack);      return formatRectRange(ends[1][0], ends[1][1], ends[0][0], ends[0][1]);    },    updateCoverShape: function (controller, cover, localRange, brushOption) {      updateBaseRect(controller, cover, localRange, brushOption);    },    updateCommon: updateCommon,    contain: mainShapeContain  },  polygon: {    createCover: function (controller, brushOption) {      var cover = new graphic.Group(); // Do not use graphic.Polygon because graphic.Polyline do not close the      // border of the shape when drawing, which is a better experience for user.      cover.add(new graphic.Polyline({        name: 'main',        style: makeStyle(brushOption),        silent: true      }));      return cover;    },    getCreatingRange: function (localTrack) {      return localTrack;    },    endCreating: function (controller, cover) {      cover.remove(cover.childAt(0)); // Use graphic.Polygon close the shape.      cover.add(new graphic.Polygon({        name: 'main',        draggable: true,        drift: curry(driftPolygon, controller, cover),        ondragend: curry(trigger, controller, {          isEnd: true        })      }));    },    updateCoverShape: function (controller, cover, localRange, brushOption) {      cover.childAt(0).setShape({        points: clipByPanel(controller, cover, localRange)      });    },    updateCommon: updateCommon,    contain: mainShapeContain  }};function getLineRenderer(xyIndex) {  return {    createCover: function (controller, brushOption) {      return createBaseRectCover(curry(driftRect, function (range) {        var rectRange = [range, [0, 100]];        xyIndex && rectRange.reverse();        return rectRange;      }, function (rectRange) {        return rectRange[xyIndex];      }), controller, brushOption, [['w', 'e'], ['n', 's']][xyIndex]);    },    getCreatingRange: function (localTrack) {      var ends = getTrackEnds(localTrack);      var min = mathMin(ends[0][xyIndex], ends[1][xyIndex]);      var max = mathMax(ends[0][xyIndex], ends[1][xyIndex]);      return [min, max];    },    updateCoverShape: function (controller, cover, localRange, brushOption) {      var otherExtent; // If brushWidth not specified, fit the panel.      var panel = getPanelByCover(controller, cover);      if (panel !== true && panel.getLinearBrushOtherExtent) {        otherExtent = panel.getLinearBrushOtherExtent(xyIndex, controller._transform);      } else {        var zr = controller._zr;        otherExtent = [0, [zr.getWidth(), zr.getHeight()][1 - xyIndex]];      }      var rectRange = [localRange, otherExtent];      xyIndex && rectRange.reverse();      updateBaseRect(controller, cover, rectRange, brushOption);    },    updateCommon: updateCommon,    contain: mainShapeContain  };}var _default = BrushController;module.exports = _default;
 |