markerHelper.js 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. var zrUtil = require("zrender/lib/core/util");
  2. var numberUtil = require("../../util/number");
  3. var indexOf = zrUtil.indexOf;
  4. function hasXOrY(item) {
  5. return !(isNaN(parseFloat(item.x)) && isNaN(parseFloat(item.y)));
  6. }
  7. function hasXAndY(item) {
  8. return !isNaN(parseFloat(item.x)) && !isNaN(parseFloat(item.y));
  9. }
  10. function getPrecision(data, valueAxisDim, dataIndex) {
  11. var precision = -1;
  12. do {
  13. precision = Math.max(numberUtil.getPrecision(data.get(valueAxisDim, dataIndex)), precision);
  14. data = data.stackedOn;
  15. } while (data);
  16. return precision;
  17. }
  18. function markerTypeCalculatorWithExtent(mlType, data, otherDataDim, targetDataDim, otherCoordIndex, targetCoordIndex) {
  19. var coordArr = [];
  20. var value = numCalculate(data, targetDataDim, mlType);
  21. var dataIndex = data.indicesOfNearest(targetDataDim, value, true)[0];
  22. coordArr[otherCoordIndex] = data.get(otherDataDim, dataIndex, true);
  23. coordArr[targetCoordIndex] = data.get(targetDataDim, dataIndex, true);
  24. var precision = getPrecision(data, targetDataDim, dataIndex);
  25. precision = Math.min(precision, 20);
  26. if (precision >= 0) {
  27. coordArr[targetCoordIndex] = +coordArr[targetCoordIndex].toFixed(precision);
  28. }
  29. return coordArr;
  30. }
  31. var curry = zrUtil.curry; // TODO Specified percent
  32. var markerTypeCalculator = {
  33. /**
  34. * @method
  35. * @param {module:echarts/data/List} data
  36. * @param {string} baseAxisDim
  37. * @param {string} valueAxisDim
  38. */
  39. min: curry(markerTypeCalculatorWithExtent, 'min'),
  40. /**
  41. * @method
  42. * @param {module:echarts/data/List} data
  43. * @param {string} baseAxisDim
  44. * @param {string} valueAxisDim
  45. */
  46. max: curry(markerTypeCalculatorWithExtent, 'max'),
  47. /**
  48. * @method
  49. * @param {module:echarts/data/List} data
  50. * @param {string} baseAxisDim
  51. * @param {string} valueAxisDim
  52. */
  53. average: curry(markerTypeCalculatorWithExtent, 'average')
  54. };
  55. /**
  56. * Transform markPoint data item to format used in List by do the following
  57. * 1. Calculate statistic like `max`, `min`, `average`
  58. * 2. Convert `item.xAxis`, `item.yAxis` to `item.coord` array
  59. * @param {module:echarts/model/Series} seriesModel
  60. * @param {module:echarts/coord/*} [coordSys]
  61. * @param {Object} item
  62. * @return {Object}
  63. */
  64. function dataTransform(seriesModel, item) {
  65. var data = seriesModel.getData();
  66. var coordSys = seriesModel.coordinateSystem; // 1. If not specify the position with pixel directly
  67. // 2. If `coord` is not a data array. Which uses `xAxis`,
  68. // `yAxis` to specify the coord on each dimension
  69. // parseFloat first because item.x and item.y can be percent string like '20%'
  70. if (item && !hasXAndY(item) && !zrUtil.isArray(item.coord) && coordSys) {
  71. var dims = coordSys.dimensions;
  72. var axisInfo = getAxisInfo(item, data, coordSys, seriesModel); // Clone the option
  73. // Transform the properties xAxis, yAxis, radiusAxis, angleAxis, geoCoord to value
  74. item = zrUtil.clone(item);
  75. if (item.type && markerTypeCalculator[item.type] && axisInfo.baseAxis && axisInfo.valueAxis) {
  76. var otherCoordIndex = indexOf(dims, axisInfo.baseAxis.dim);
  77. var targetCoordIndex = indexOf(dims, axisInfo.valueAxis.dim);
  78. item.coord = markerTypeCalculator[item.type](data, axisInfo.baseDataDim, axisInfo.valueDataDim, otherCoordIndex, targetCoordIndex); // Force to use the value of calculated value.
  79. item.value = item.coord[targetCoordIndex];
  80. } else {
  81. // FIXME Only has one of xAxis and yAxis.
  82. var coord = [item.xAxis != null ? item.xAxis : item.radiusAxis, item.yAxis != null ? item.yAxis : item.angleAxis]; // Each coord support max, min, average
  83. for (var i = 0; i < 2; i++) {
  84. if (markerTypeCalculator[coord[i]]) {
  85. var dataDim = seriesModel.coordDimToDataDim(dims[i])[0];
  86. coord[i] = numCalculate(data, dataDim, coord[i]);
  87. }
  88. }
  89. item.coord = coord;
  90. }
  91. }
  92. return item;
  93. }
  94. function getAxisInfo(item, data, coordSys, seriesModel) {
  95. var ret = {};
  96. if (item.valueIndex != null || item.valueDim != null) {
  97. ret.valueDataDim = item.valueIndex != null ? data.getDimension(item.valueIndex) : item.valueDim;
  98. ret.valueAxis = coordSys.getAxis(seriesModel.dataDimToCoordDim(ret.valueDataDim));
  99. ret.baseAxis = coordSys.getOtherAxis(ret.valueAxis);
  100. ret.baseDataDim = seriesModel.coordDimToDataDim(ret.baseAxis.dim)[0];
  101. } else {
  102. ret.baseAxis = seriesModel.getBaseAxis();
  103. ret.valueAxis = coordSys.getOtherAxis(ret.baseAxis);
  104. ret.baseDataDim = seriesModel.coordDimToDataDim(ret.baseAxis.dim)[0];
  105. ret.valueDataDim = seriesModel.coordDimToDataDim(ret.valueAxis.dim)[0];
  106. }
  107. return ret;
  108. }
  109. /**
  110. * Filter data which is out of coordinateSystem range
  111. * [dataFilter description]
  112. * @param {module:echarts/coord/*} [coordSys]
  113. * @param {Object} item
  114. * @return {boolean}
  115. */
  116. function dataFilter(coordSys, item) {
  117. // Alwalys return true if there is no coordSys
  118. return coordSys && coordSys.containData && item.coord && !hasXOrY(item) ? coordSys.containData(item.coord) : true;
  119. }
  120. function dimValueGetter(item, dimName, dataIndex, dimIndex) {
  121. // x, y, radius, angle
  122. if (dimIndex < 2) {
  123. return item.coord && item.coord[dimIndex];
  124. }
  125. return item.value;
  126. }
  127. function numCalculate(data, valueDataDim, type) {
  128. if (type === 'average') {
  129. var sum = 0;
  130. var count = 0;
  131. data.each(valueDataDim, function (val, idx) {
  132. if (!isNaN(val)) {
  133. sum += val;
  134. count++;
  135. }
  136. }, true);
  137. return sum / count;
  138. } else {
  139. return data.getDataExtent(valueDataDim, true)[type === 'max' ? 1 : 0];
  140. }
  141. }
  142. exports.dataTransform = dataTransform;
  143. exports.getAxisInfo = getAxisInfo;
  144. exports.dataFilter = dataFilter;
  145. exports.dimValueGetter = dimValueGetter;
  146. exports.numCalculate = numCalculate;