util.js 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", { value: true });
  3. exports.getRegressionEquation = exports.getMeta = exports.getPath = exports.getQuadrantDefaultConfig = void 0;
  4. var tslib_1 = require("tslib");
  5. var util_1 = require("@antv/util");
  6. var d3_regression_1 = require("d3-regression");
  7. var utils_1 = require("../../utils");
  8. var REGRESSION_MAP = {
  9. exp: d3_regression_1.regressionExp,
  10. linear: d3_regression_1.regressionLinear,
  11. loess: d3_regression_1.regressionLoess,
  12. log: d3_regression_1.regressionLog,
  13. poly: d3_regression_1.regressionPoly,
  14. pow: d3_regression_1.regressionPow,
  15. quad: d3_regression_1.regressionQuad,
  16. };
  17. /**
  18. * 获取四象限默认配置
  19. * @param {number} xBaseline
  20. * @param {number} yBaseline
  21. */
  22. function getQuadrantDefaultConfig(xBaseline, yBaseline) {
  23. // 文本便宜距离
  24. var textOffset = 10;
  25. // 四象限默认样式
  26. var defaultConfig = {
  27. regionStyle: [
  28. {
  29. position: {
  30. start: [xBaseline, 'max'],
  31. end: ['max', yBaseline],
  32. },
  33. style: {
  34. fill: '#d8d0c0',
  35. opacity: 0.4,
  36. },
  37. },
  38. {
  39. position: {
  40. start: ['min', 'max'],
  41. end: [xBaseline, yBaseline],
  42. },
  43. style: {
  44. fill: '#a3dda1',
  45. opacity: 0.4,
  46. },
  47. },
  48. {
  49. position: {
  50. start: ['min', yBaseline],
  51. end: [xBaseline, 'min'],
  52. },
  53. style: {
  54. fill: '#d8d0c0',
  55. opacity: 0.4,
  56. },
  57. },
  58. {
  59. position: {
  60. start: [xBaseline, yBaseline],
  61. end: ['max', 'min'],
  62. },
  63. style: {
  64. fill: '#a3dda1',
  65. opacity: 0.4,
  66. },
  67. },
  68. ],
  69. lineStyle: {
  70. stroke: '#9ba29a',
  71. lineWidth: 1,
  72. },
  73. labelStyle: [
  74. {
  75. position: ['max', yBaseline],
  76. offsetX: -textOffset,
  77. offsetY: -textOffset,
  78. style: {
  79. textAlign: 'right',
  80. textBaseline: 'bottom',
  81. fontSize: 14,
  82. fill: '#ccc',
  83. },
  84. },
  85. {
  86. position: ['min', yBaseline],
  87. offsetX: textOffset,
  88. offsetY: -textOffset,
  89. style: {
  90. textAlign: 'left',
  91. textBaseline: 'bottom',
  92. fontSize: 14,
  93. fill: '#ccc',
  94. },
  95. },
  96. {
  97. position: ['min', yBaseline],
  98. offsetX: textOffset,
  99. offsetY: textOffset,
  100. style: {
  101. textAlign: 'left',
  102. textBaseline: 'top',
  103. fontSize: 14,
  104. fill: '#ccc',
  105. },
  106. },
  107. {
  108. position: ['max', yBaseline],
  109. offsetX: -textOffset,
  110. offsetY: textOffset,
  111. style: {
  112. textAlign: 'right',
  113. textBaseline: 'top',
  114. fontSize: 14,
  115. fill: '#ccc',
  116. },
  117. },
  118. ],
  119. };
  120. return defaultConfig;
  121. }
  122. exports.getQuadrantDefaultConfig = getQuadrantDefaultConfig;
  123. var splinePath = function (data, config) {
  124. var view = config.view, _a = config.options, xField = _a.xField, yField = _a.yField;
  125. var xScaleView = view.getScaleByField(xField);
  126. var yScaleView = view.getScaleByField(yField);
  127. var pathData = data.map(function (d) {
  128. return view.getCoordinate().convert({ x: xScaleView.scale(d[0]), y: yScaleView.scale(d[1]) });
  129. });
  130. return (0, utils_1.getSplinePath)(pathData, false);
  131. };
  132. var getPath = function (config) {
  133. var options = config.options;
  134. var xField = options.xField, yField = options.yField, data = options.data, regressionLine = options.regressionLine;
  135. var _a = regressionLine.type, type = _a === void 0 ? 'linear' : _a, algorithm = regressionLine.algorithm, customEquation = regressionLine.equation;
  136. var pathData;
  137. var equation = null;
  138. if (algorithm) {
  139. pathData = (0, util_1.isArray)(algorithm) ? algorithm : algorithm(data);
  140. equation = customEquation;
  141. }
  142. else {
  143. var reg = REGRESSION_MAP[type]()
  144. .x(function (d) { return d[xField]; })
  145. .y(function (d) { return d[yField]; });
  146. pathData = reg(data);
  147. equation = getRegressionEquation(type, pathData);
  148. }
  149. return [splinePath(pathData, config), equation];
  150. };
  151. exports.getPath = getPath;
  152. /**
  153. * 调整散点图 meta: { min, max } ① data.length === 1 ② 所有数据 y 值相等 ③ 所有数据 x 值相等
  154. * @param options
  155. * @returns
  156. */
  157. var getMeta = function (options) {
  158. var _a;
  159. var _b = options.meta, meta = _b === void 0 ? {} : _b, xField = options.xField, yField = options.yField, data = options.data;
  160. var xFieldValue = data[0][xField];
  161. var yFieldValue = data[0][yField];
  162. var xIsPositiveNumber = xFieldValue > 0;
  163. var yIsPositiveNumber = yFieldValue > 0;
  164. /**
  165. * 获得对应字段的 min max scale 配置
  166. */
  167. function getMetaMinMax(field, axis) {
  168. var fieldMeta = (0, util_1.get)(meta, [field]);
  169. function getCustomValue(type) {
  170. return (0, util_1.get)(fieldMeta, type);
  171. }
  172. var range = {};
  173. if (axis === 'x') {
  174. if ((0, util_1.isNumber)(xFieldValue)) {
  175. if (!(0, util_1.isNumber)(getCustomValue('min'))) {
  176. range['min'] = xIsPositiveNumber ? 0 : xFieldValue * 2;
  177. }
  178. if (!(0, util_1.isNumber)(getCustomValue('max'))) {
  179. range['max'] = xIsPositiveNumber ? xFieldValue * 2 : 0;
  180. }
  181. }
  182. return range;
  183. }
  184. if ((0, util_1.isNumber)(yFieldValue)) {
  185. if (!(0, util_1.isNumber)(getCustomValue('min'))) {
  186. range['min'] = yIsPositiveNumber ? 0 : yFieldValue * 2;
  187. }
  188. if (!(0, util_1.isNumber)(getCustomValue('max'))) {
  189. range['max'] = yIsPositiveNumber ? yFieldValue * 2 : 0;
  190. }
  191. }
  192. return range;
  193. }
  194. return tslib_1.__assign(tslib_1.__assign({}, meta), (_a = {}, _a[xField] = tslib_1.__assign(tslib_1.__assign({}, meta[xField]), getMetaMinMax(xField, 'x')), _a[yField] = tslib_1.__assign(tslib_1.__assign({}, meta[yField]), getMetaMinMax(yField, 'y')), _a));
  195. };
  196. exports.getMeta = getMeta;
  197. /**
  198. * 获取回归函数表达式
  199. * @param {string} type - 回归函数类型
  200. * @param {D3RegressionResult} res - 回归计算结果集
  201. * @return {string}
  202. */
  203. function getRegressionEquation(type, res) {
  204. var _a, _b, _c;
  205. var roundByPrecision = function (n, p) {
  206. if (p === void 0) { p = 4; }
  207. return Math.round(n * Math.pow(10, p)) / Math.pow(10, p);
  208. };
  209. var safeFormat = function (value) { return (Number.isFinite(value) ? roundByPrecision(value) : '?'); };
  210. switch (type) {
  211. case 'linear':
  212. // y = ax + b
  213. return "y = ".concat(safeFormat(res.a), "x + ").concat(safeFormat(res.b), ", R^2 = ").concat(safeFormat(res.rSquared));
  214. case 'exp':
  215. // y = ae^(bx)
  216. return "y = ".concat(safeFormat(res.a), "e^(").concat(safeFormat(res.b), "x), R^2 = ").concat(safeFormat(res.rSquared));
  217. case 'log':
  218. // y = a · ln(x) + b
  219. return "y = ".concat(safeFormat(res.a), "ln(x) + ").concat(safeFormat(res.b), ", R^2 = ").concat(safeFormat(res.rSquared));
  220. case 'quad':
  221. // y = ax^2 + bx + c
  222. return "y = ".concat(safeFormat(res.a), "x^2 + ").concat(safeFormat(res.b), "x + ").concat(safeFormat(res.c), ", R^2 = ").concat(safeFormat(res.rSquared));
  223. case 'poly':
  224. // y = anx^n + ... + a1x + a0
  225. // eslint-disable-next-line no-case-declarations
  226. var temp = "y = ".concat(safeFormat((_a = res.coefficients) === null || _a === void 0 ? void 0 : _a[0]), " + ").concat(safeFormat((_b = res.coefficients) === null || _b === void 0 ? void 0 : _b[1]), "x + ").concat(safeFormat((_c = res.coefficients) === null || _c === void 0 ? void 0 : _c[2]), "x^2");
  227. for (var i = 3; i < res.coefficients.length; ++i) {
  228. temp += " + ".concat(safeFormat(res.coefficients[i]), "x^").concat(i);
  229. }
  230. return "".concat(temp, ", R^2 = ").concat(safeFormat(res.rSquared));
  231. case 'pow':
  232. // y = ax^b
  233. return "y = ".concat(safeFormat(res.a), "x^").concat(safeFormat(res.b), ", R^2 = ").concat(safeFormat(res.rSquared));
  234. }
  235. return null;
  236. }
  237. exports.getRegressionEquation = getRegressionEquation;
  238. //# sourceMappingURL=util.js.map