| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418 | 
/** 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 graphic = require("../../util/graphic");var modelUtil = require("../../util/model");var brushHelper = require("./brushHelper");/** 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 each = zrUtil.each;var indexOf = zrUtil.indexOf;var curry = zrUtil.curry;var COORD_CONVERTS = ['dataToPoint', 'pointToData']; // FIXME// how to genarialize to more coordinate systems.var INCLUDE_FINDER_MAIN_TYPES = ['grid', 'xAxis', 'yAxis', 'geo', 'graph', 'polar', 'radiusAxis', 'angleAxis', 'bmap'];/** * [option in constructor]: * { *     Index/Id/Name of geo, xAxis, yAxis, grid: See util/model#parseFinder. * } * * * [targetInfo]: * * There can be multiple axes in a single targetInfo. Consider the case * of `grid` component, a targetInfo represents a grid which contains one or more * cartesian and one or more axes. And consider the case of parallel system, * which has multiple axes in a coordinate system. * Can be { *     panelId: ..., *     coordSys: <a representitive cartesian in grid (first cartesian by default)>, *     coordSyses: all cartesians. *     gridModel: <grid component> *     xAxes: correspond to coordSyses on index *     yAxes: correspond to coordSyses on index * } * or { *     panelId: ..., *     coordSys: <geo coord sys> *     coordSyses: [<geo coord sys>] *     geoModel: <geo component> * } * * * [panelOpt]: * * Make from targetInfo. Input to BrushController. * { *     panelId: ..., *     rect: ... * } * * * [area]: * * Generated by BrushController or user input. * { *     panelId: Used to locate coordInfo directly. If user inpput, no panelId. *     brushType: determine how to convert to/from coord('rect' or 'polygon' or 'lineX/Y'). *     Index/Id/Name of geo, xAxis, yAxis, grid: See util/model#parseFinder. *     range: pixel range. *     coordRange: representitive coord range (the first one of coordRanges). *     coordRanges: <Array> coord ranges, used in multiple cartesian in one grid. * } *//** * @param {Object} option contains Index/Id/Name of xAxis/yAxis/geo/grid *        Each can be {number|Array.<number>}. like: {xAxisIndex: [3, 4]} * @param {module:echarts/model/Global} ecModel * @param {Object} [opt] * @param {Array.<string>} [opt.include] include coordinate system types. */function BrushTargetManager(option, ecModel, opt) {  /**   * @private   * @type {Array.<Object>}   */  var targetInfoList = this._targetInfoList = [];  var info = {};  var foundCpts = parseFinder(ecModel, option);  each(targetInfoBuilders, function (builder, type) {    if (!opt || !opt.include || indexOf(opt.include, type) >= 0) {      builder(foundCpts, targetInfoList, info);    }  });}var proto = BrushTargetManager.prototype;proto.setOutputRanges = function (areas, ecModel) {  this.matchOutputRanges(areas, ecModel, function (area, coordRange, coordSys) {    (area.coordRanges || (area.coordRanges = [])).push(coordRange); // area.coordRange is the first of area.coordRanges    if (!area.coordRange) {      area.coordRange = coordRange; // In 'category' axis, coord to pixel is not reversible, so we can not      // rebuild range by coordRange accrately, which may bring trouble when      // brushing only one item. So we use __rangeOffset to rebuilding range      // by coordRange. And this it only used in brush component so it is no      // need to be adapted to coordRanges.      var result = coordConvert[area.brushType](0, coordSys, coordRange);      area.__rangeOffset = {        offset: diffProcessor[area.brushType](result.values, area.range, [1, 1]),        xyMinMax: result.xyMinMax      };    }  });};proto.matchOutputRanges = function (areas, ecModel, cb) {  each(areas, function (area) {    var targetInfo = this.findTargetInfo(area, ecModel);    if (targetInfo && targetInfo !== true) {      zrUtil.each(targetInfo.coordSyses, function (coordSys) {        var result = coordConvert[area.brushType](1, coordSys, area.range);        cb(area, result.values, coordSys, ecModel);      });    }  }, this);};proto.setInputRanges = function (areas, ecModel) {  each(areas, function (area) {    var targetInfo = this.findTargetInfo(area, ecModel);    area.range = area.range || []; // convert coordRange to global range and set panelId.    if (targetInfo && targetInfo !== true) {      area.panelId = targetInfo.panelId; // (1) area.range shoule always be calculate from coordRange but does      // not keep its original value, for the sake of the dataZoom scenario,      // where area.coordRange remains unchanged but area.range may be changed.      // (2) Only support converting one coordRange to pixel range in brush      // component. So do not consider `coordRanges`.      // (3) About __rangeOffset, see comment above.      var result = coordConvert[area.brushType](0, targetInfo.coordSys, area.coordRange);      var rangeOffset = area.__rangeOffset;      area.range = rangeOffset ? diffProcessor[area.brushType](result.values, rangeOffset.offset, getScales(result.xyMinMax, rangeOffset.xyMinMax)) : result.values;    }  }, this);};proto.makePanelOpts = function (api, getDefaultBrushType) {  return zrUtil.map(this._targetInfoList, function (targetInfo) {    var rect = targetInfo.getPanelRect();    return {      panelId: targetInfo.panelId,      defaultBrushType: getDefaultBrushType && getDefaultBrushType(targetInfo),      clipPath: brushHelper.makeRectPanelClipPath(rect),      isTargetByCursor: brushHelper.makeRectIsTargetByCursor(rect, api, targetInfo.coordSysModel),      getLinearBrushOtherExtent: brushHelper.makeLinearBrushOtherExtent(rect)    };  });};proto.controlSeries = function (area, seriesModel, ecModel) {  // Check whether area is bound in coord, and series do not belong to that coord.  // If do not do this check, some brush (like lineX) will controll all axes.  var targetInfo = this.findTargetInfo(area, ecModel);  return targetInfo === true || targetInfo && indexOf(targetInfo.coordSyses, seriesModel.coordinateSystem) >= 0;};/** * If return Object, a coord found. * If reutrn true, global found. * Otherwise nothing found. * * @param {Object} area * @param {Array} targetInfoList * @return {Object|boolean} */proto.findTargetInfo = function (area, ecModel) {  var targetInfoList = this._targetInfoList;  var foundCpts = parseFinder(ecModel, area);  for (var i = 0; i < targetInfoList.length; i++) {    var targetInfo = targetInfoList[i];    var areaPanelId = area.panelId;    if (areaPanelId) {      if (targetInfo.panelId === areaPanelId) {        return targetInfo;      }    } else {      for (var i = 0; i < targetInfoMatchers.length; i++) {        if (targetInfoMatchers[i](foundCpts, targetInfo)) {          return targetInfo;        }      }    }  }  return true;};function formatMinMax(minMax) {  minMax[0] > minMax[1] && minMax.reverse();  return minMax;}function parseFinder(ecModel, option) {  return modelUtil.parseFinder(ecModel, option, {    includeMainTypes: INCLUDE_FINDER_MAIN_TYPES  });}var targetInfoBuilders = {  grid: function (foundCpts, targetInfoList) {    var xAxisModels = foundCpts.xAxisModels;    var yAxisModels = foundCpts.yAxisModels;    var gridModels = foundCpts.gridModels; // Remove duplicated.    var gridModelMap = zrUtil.createHashMap();    var xAxesHas = {};    var yAxesHas = {};    if (!xAxisModels && !yAxisModels && !gridModels) {      return;    }    each(xAxisModels, function (axisModel) {      var gridModel = axisModel.axis.grid.model;      gridModelMap.set(gridModel.id, gridModel);      xAxesHas[gridModel.id] = true;    });    each(yAxisModels, function (axisModel) {      var gridModel = axisModel.axis.grid.model;      gridModelMap.set(gridModel.id, gridModel);      yAxesHas[gridModel.id] = true;    });    each(gridModels, function (gridModel) {      gridModelMap.set(gridModel.id, gridModel);      xAxesHas[gridModel.id] = true;      yAxesHas[gridModel.id] = true;    });    gridModelMap.each(function (gridModel) {      var grid = gridModel.coordinateSystem;      var cartesians = [];      each(grid.getCartesians(), function (cartesian, index) {        if (indexOf(xAxisModels, cartesian.getAxis('x').model) >= 0 || indexOf(yAxisModels, cartesian.getAxis('y').model) >= 0) {          cartesians.push(cartesian);        }      });      targetInfoList.push({        panelId: 'grid--' + gridModel.id,        gridModel: gridModel,        coordSysModel: gridModel,        // Use the first one as the representitive coordSys.        coordSys: cartesians[0],        coordSyses: cartesians,        getPanelRect: panelRectBuilder.grid,        xAxisDeclared: xAxesHas[gridModel.id],        yAxisDeclared: yAxesHas[gridModel.id]      });    });  },  geo: function (foundCpts, targetInfoList) {    each(foundCpts.geoModels, function (geoModel) {      var coordSys = geoModel.coordinateSystem;      targetInfoList.push({        panelId: 'geo--' + geoModel.id,        geoModel: geoModel,        coordSysModel: geoModel,        coordSys: coordSys,        coordSyses: [coordSys],        getPanelRect: panelRectBuilder.geo      });    });  }};var targetInfoMatchers = [// gridfunction (foundCpts, targetInfo) {  var xAxisModel = foundCpts.xAxisModel;  var yAxisModel = foundCpts.yAxisModel;  var gridModel = foundCpts.gridModel;  !gridModel && xAxisModel && (gridModel = xAxisModel.axis.grid.model);  !gridModel && yAxisModel && (gridModel = yAxisModel.axis.grid.model);  return gridModel && gridModel === targetInfo.gridModel;}, // geofunction (foundCpts, targetInfo) {  var geoModel = foundCpts.geoModel;  return geoModel && geoModel === targetInfo.geoModel;}];var panelRectBuilder = {  grid: function () {    // grid is not Transformable.    return this.coordSys.grid.getRect().clone();  },  geo: function () {    var coordSys = this.coordSys;    var rect = coordSys.getBoundingRect().clone(); // geo roam and zoom transform    rect.applyTransform(graphic.getTransform(coordSys));    return rect;  }};var coordConvert = {  lineX: curry(axisConvert, 0),  lineY: curry(axisConvert, 1),  rect: function (to, coordSys, rangeOrCoordRange) {    var xminymin = coordSys[COORD_CONVERTS[to]]([rangeOrCoordRange[0][0], rangeOrCoordRange[1][0]]);    var xmaxymax = coordSys[COORD_CONVERTS[to]]([rangeOrCoordRange[0][1], rangeOrCoordRange[1][1]]);    var values = [formatMinMax([xminymin[0], xmaxymax[0]]), formatMinMax([xminymin[1], xmaxymax[1]])];    return {      values: values,      xyMinMax: values    };  },  polygon: function (to, coordSys, rangeOrCoordRange) {    var xyMinMax = [[Infinity, -Infinity], [Infinity, -Infinity]];    var values = zrUtil.map(rangeOrCoordRange, function (item) {      var p = coordSys[COORD_CONVERTS[to]](item);      xyMinMax[0][0] = Math.min(xyMinMax[0][0], p[0]);      xyMinMax[1][0] = Math.min(xyMinMax[1][0], p[1]);      xyMinMax[0][1] = Math.max(xyMinMax[0][1], p[0]);      xyMinMax[1][1] = Math.max(xyMinMax[1][1], p[1]);      return p;    });    return {      values: values,      xyMinMax: xyMinMax    };  }};function axisConvert(axisNameIndex, to, coordSys, rangeOrCoordRange) {  var axis = coordSys.getAxis(['x', 'y'][axisNameIndex]);  var values = formatMinMax(zrUtil.map([0, 1], function (i) {    return to ? axis.coordToData(axis.toLocalCoord(rangeOrCoordRange[i])) : axis.toGlobalCoord(axis.dataToCoord(rangeOrCoordRange[i]));  }));  var xyMinMax = [];  xyMinMax[axisNameIndex] = values;  xyMinMax[1 - axisNameIndex] = [NaN, NaN];  return {    values: values,    xyMinMax: xyMinMax  };}var diffProcessor = {  lineX: curry(axisDiffProcessor, 0),  lineY: curry(axisDiffProcessor, 1),  rect: function (values, refer, scales) {    return [[values[0][0] - scales[0] * refer[0][0], values[0][1] - scales[0] * refer[0][1]], [values[1][0] - scales[1] * refer[1][0], values[1][1] - scales[1] * refer[1][1]]];  },  polygon: function (values, refer, scales) {    return zrUtil.map(values, function (item, idx) {      return [item[0] - scales[0] * refer[idx][0], item[1] - scales[1] * refer[idx][1]];    });  }};function axisDiffProcessor(axisNameIndex, values, refer, scales) {  return [values[0] - scales[axisNameIndex] * refer[0], values[1] - scales[axisNameIndex] * refer[1]];} // We have to process scale caused by dataZoom manually,// although it might be not accurate.function getScales(xyMinMaxCurr, xyMinMaxOrigin) {  var sizeCurr = getSize(xyMinMaxCurr);  var sizeOrigin = getSize(xyMinMaxOrigin);  var scales = [sizeCurr[0] / sizeOrigin[0], sizeCurr[1] / sizeOrigin[1]];  isNaN(scales[0]) && (scales[0] = 1);  isNaN(scales[1]) && (scales[1] = 1);  return scales;}function getSize(xyMinMax) {  return xyMinMax ? [xyMinMax[0][1] - xyMinMax[0][0], xyMinMax[1][1] - xyMinMax[1][0]] : [NaN, NaN];}var _default = BrushTargetManager;module.exports = _default;
 |