markerHelper.js 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254
  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. var zrUtil = require("zrender/lib/core/util");
  20. var numberUtil = require("../../util/number");
  21. var _dataStackHelper = require("../../data/helper/dataStackHelper");
  22. var isDimensionStacked = _dataStackHelper.isDimensionStacked;
  23. /*
  24. * Licensed to the Apache Software Foundation (ASF) under one
  25. * or more contributor license agreements. See the NOTICE file
  26. * distributed with this work for additional information
  27. * regarding copyright ownership. The ASF licenses this file
  28. * to you under the Apache License, Version 2.0 (the
  29. * "License"); you may not use this file except in compliance
  30. * with the License. You may obtain a copy of the License at
  31. *
  32. * http://www.apache.org/licenses/LICENSE-2.0
  33. *
  34. * Unless required by applicable law or agreed to in writing,
  35. * software distributed under the License is distributed on an
  36. * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  37. * KIND, either express or implied. See the License for the
  38. * specific language governing permissions and limitations
  39. * under the License.
  40. */
  41. var indexOf = zrUtil.indexOf;
  42. function hasXOrY(item) {
  43. return !(isNaN(parseFloat(item.x)) && isNaN(parseFloat(item.y)));
  44. }
  45. function hasXAndY(item) {
  46. return !isNaN(parseFloat(item.x)) && !isNaN(parseFloat(item.y));
  47. } // Make it simple, do not visit all stacked value to count precision.
  48. // function getPrecision(data, valueAxisDim, dataIndex) {
  49. // var precision = -1;
  50. // var stackedDim = data.mapDimension(valueAxisDim);
  51. // do {
  52. // precision = Math.max(
  53. // numberUtil.getPrecision(data.get(stackedDim, dataIndex)),
  54. // precision
  55. // );
  56. // var stackedOnSeries = data.getCalculationInfo('stackedOnSeries');
  57. // if (stackedOnSeries) {
  58. // var byValue = data.get(data.getCalculationInfo('stackedByDimension'), dataIndex);
  59. // data = stackedOnSeries.getData();
  60. // dataIndex = data.indexOf(data.getCalculationInfo('stackedByDimension'), byValue);
  61. // stackedDim = data.getCalculationInfo('stackedDimension');
  62. // }
  63. // else {
  64. // data = null;
  65. // }
  66. // } while (data);
  67. // return precision;
  68. // }
  69. function markerTypeCalculatorWithExtent(mlType, data, otherDataDim, targetDataDim, otherCoordIndex, targetCoordIndex) {
  70. var coordArr = [];
  71. var stacked = isDimensionStacked(data, targetDataDim
  72. /*, otherDataDim*/
  73. );
  74. var calcDataDim = stacked ? data.getCalculationInfo('stackResultDimension') : targetDataDim;
  75. var value = numCalculate(data, calcDataDim, mlType);
  76. var dataIndex = data.indicesOfNearest(calcDataDim, value)[0];
  77. coordArr[otherCoordIndex] = data.get(otherDataDim, dataIndex);
  78. coordArr[targetCoordIndex] = data.get(calcDataDim, dataIndex);
  79. var coordArrValue = data.get(targetDataDim, dataIndex); // Make it simple, do not visit all stacked value to count precision.
  80. var precision = numberUtil.getPrecision(data.get(targetDataDim, dataIndex));
  81. precision = Math.min(precision, 20);
  82. if (precision >= 0) {
  83. coordArr[targetCoordIndex] = +coordArr[targetCoordIndex].toFixed(precision);
  84. }
  85. return [coordArr, coordArrValue];
  86. }
  87. var curry = zrUtil.curry; // TODO Specified percent
  88. var markerTypeCalculator = {
  89. /**
  90. * @method
  91. * @param {module:echarts/data/List} data
  92. * @param {string} baseAxisDim
  93. * @param {string} valueAxisDim
  94. */
  95. min: curry(markerTypeCalculatorWithExtent, 'min'),
  96. /**
  97. * @method
  98. * @param {module:echarts/data/List} data
  99. * @param {string} baseAxisDim
  100. * @param {string} valueAxisDim
  101. */
  102. max: curry(markerTypeCalculatorWithExtent, 'max'),
  103. /**
  104. * @method
  105. * @param {module:echarts/data/List} data
  106. * @param {string} baseAxisDim
  107. * @param {string} valueAxisDim
  108. */
  109. average: curry(markerTypeCalculatorWithExtent, 'average')
  110. };
  111. /**
  112. * Transform markPoint data item to format used in List by do the following
  113. * 1. Calculate statistic like `max`, `min`, `average`
  114. * 2. Convert `item.xAxis`, `item.yAxis` to `item.coord` array
  115. * @param {module:echarts/model/Series} seriesModel
  116. * @param {module:echarts/coord/*} [coordSys]
  117. * @param {Object} item
  118. * @return {Object}
  119. */
  120. function dataTransform(seriesModel, item) {
  121. var data = seriesModel.getData();
  122. var coordSys = seriesModel.coordinateSystem; // 1. If not specify the position with pixel directly
  123. // 2. If `coord` is not a data array. Which uses `xAxis`,
  124. // `yAxis` to specify the coord on each dimension
  125. // parseFloat first because item.x and item.y can be percent string like '20%'
  126. if (item && !hasXAndY(item) && !zrUtil.isArray(item.coord) && coordSys) {
  127. var dims = coordSys.dimensions;
  128. var axisInfo = getAxisInfo(item, data, coordSys, seriesModel); // Clone the option
  129. // Transform the properties xAxis, yAxis, radiusAxis, angleAxis, geoCoord to value
  130. item = zrUtil.clone(item);
  131. if (item.type && markerTypeCalculator[item.type] && axisInfo.baseAxis && axisInfo.valueAxis) {
  132. var otherCoordIndex = indexOf(dims, axisInfo.baseAxis.dim);
  133. var targetCoordIndex = indexOf(dims, axisInfo.valueAxis.dim);
  134. var coordInfo = markerTypeCalculator[item.type](data, axisInfo.baseDataDim, axisInfo.valueDataDim, otherCoordIndex, targetCoordIndex);
  135. item.coord = coordInfo[0]; // Force to use the value of calculated value.
  136. // let item use the value without stack.
  137. item.value = coordInfo[1];
  138. } else {
  139. // FIXME Only has one of xAxis and yAxis.
  140. var coord = [item.xAxis != null ? item.xAxis : item.radiusAxis, item.yAxis != null ? item.yAxis : item.angleAxis]; // Each coord support max, min, average
  141. for (var i = 0; i < 2; i++) {
  142. if (markerTypeCalculator[coord[i]]) {
  143. coord[i] = numCalculate(data, data.mapDimension(dims[i]), coord[i]);
  144. }
  145. }
  146. item.coord = coord;
  147. }
  148. }
  149. return item;
  150. }
  151. function getAxisInfo(item, data, coordSys, seriesModel) {
  152. var ret = {};
  153. if (item.valueIndex != null || item.valueDim != null) {
  154. ret.valueDataDim = item.valueIndex != null ? data.getDimension(item.valueIndex) : item.valueDim;
  155. ret.valueAxis = coordSys.getAxis(dataDimToCoordDim(seriesModel, ret.valueDataDim));
  156. ret.baseAxis = coordSys.getOtherAxis(ret.valueAxis);
  157. ret.baseDataDim = data.mapDimension(ret.baseAxis.dim);
  158. } else {
  159. ret.baseAxis = seriesModel.getBaseAxis();
  160. ret.valueAxis = coordSys.getOtherAxis(ret.baseAxis);
  161. ret.baseDataDim = data.mapDimension(ret.baseAxis.dim);
  162. ret.valueDataDim = data.mapDimension(ret.valueAxis.dim);
  163. }
  164. return ret;
  165. }
  166. function dataDimToCoordDim(seriesModel, dataDim) {
  167. var data = seriesModel.getData();
  168. var dimensions = data.dimensions;
  169. dataDim = data.getDimension(dataDim);
  170. for (var i = 0; i < dimensions.length; i++) {
  171. var dimItem = data.getDimensionInfo(dimensions[i]);
  172. if (dimItem.name === dataDim) {
  173. return dimItem.coordDim;
  174. }
  175. }
  176. }
  177. /**
  178. * Filter data which is out of coordinateSystem range
  179. * [dataFilter description]
  180. * @param {module:echarts/coord/*} [coordSys]
  181. * @param {Object} item
  182. * @return {boolean}
  183. */
  184. function dataFilter(coordSys, item) {
  185. // Alwalys return true if there is no coordSys
  186. return coordSys && coordSys.containData && item.coord && !hasXOrY(item) ? coordSys.containData(item.coord) : true;
  187. }
  188. function dimValueGetter(item, dimName, dataIndex, dimIndex) {
  189. // x, y, radius, angle
  190. if (dimIndex < 2) {
  191. return item.coord && item.coord[dimIndex];
  192. }
  193. return item.value;
  194. }
  195. function numCalculate(data, valueDataDim, type) {
  196. if (type === 'average') {
  197. var sum = 0;
  198. var count = 0;
  199. data.each(valueDataDim, function (val, idx) {
  200. if (!isNaN(val)) {
  201. sum += val;
  202. count++;
  203. }
  204. });
  205. return sum / count;
  206. } else if (type === 'median') {
  207. return data.getMedian(valueDataDim);
  208. } else {
  209. // max & min
  210. return data.getDataExtent(valueDataDim, true)[type === 'max' ? 1 : 0];
  211. }
  212. }
  213. exports.dataTransform = dataTransform;
  214. exports.getAxisInfo = getAxisInfo;
  215. exports.dataFilter = dataFilter;
  216. exports.dimValueGetter = dimValueGetter;
  217. exports.numCalculate = numCalculate;