candlestickLayout.js 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. var zrUtil = require("zrender/lib/core/util");
  2. var _number = require("../../util/number");
  3. var parsePercent = _number.parsePercent;
  4. var _graphic = require("../../util/graphic");
  5. var subPixelOptimize = _graphic.subPixelOptimize;
  6. var retrieve2 = zrUtil.retrieve2;
  7. function _default(ecModel) {
  8. ecModel.eachSeriesByType('candlestick', function (seriesModel) {
  9. var coordSys = seriesModel.coordinateSystem;
  10. var data = seriesModel.getData();
  11. var candleWidth = calculateCandleWidth(seriesModel, data);
  12. var chartLayout = seriesModel.get('layout');
  13. var variableDim = chartLayout === 'horizontal' ? 0 : 1;
  14. var constDim = 1 - variableDim;
  15. var coordDims = ['x', 'y'];
  16. var vDims = [];
  17. var cDim;
  18. zrUtil.each(data.dimensions, function (dimName) {
  19. var dimInfo = data.getDimensionInfo(dimName);
  20. var coordDim = dimInfo.coordDim;
  21. if (coordDim === coordDims[constDim]) {
  22. vDims.push(dimName);
  23. } else if (coordDim === coordDims[variableDim]) {
  24. cDim = dimName;
  25. }
  26. });
  27. if (cDim == null || vDims.length < 4) {
  28. return;
  29. }
  30. var dataIndex = 0;
  31. data.each([cDim].concat(vDims), function () {
  32. var args = arguments;
  33. var axisDimVal = args[0];
  34. var idx = args[vDims.length + 1];
  35. var openVal = args[1];
  36. var closeVal = args[2];
  37. var lowestVal = args[3];
  38. var highestVal = args[4];
  39. var ocLow = Math.min(openVal, closeVal);
  40. var ocHigh = Math.max(openVal, closeVal);
  41. var ocLowPoint = getPoint(ocLow);
  42. var ocHighPoint = getPoint(ocHigh);
  43. var lowestPoint = getPoint(lowestVal);
  44. var highestPoint = getPoint(highestVal);
  45. var whiskerEnds = [[subPixelOptimizePoint(highestPoint), subPixelOptimizePoint(ocHighPoint)], [subPixelOptimizePoint(lowestPoint), subPixelOptimizePoint(ocLowPoint)]];
  46. var bodyEnds = [];
  47. addBodyEnd(ocHighPoint, 0);
  48. addBodyEnd(ocLowPoint, 1);
  49. var sign;
  50. if (openVal > closeVal) {
  51. sign = -1;
  52. } else if (openVal < closeVal) {
  53. sign = 1;
  54. } else {
  55. // If close === open, compare with close of last record
  56. if (dataIndex > 0) {
  57. sign = data.getItemModel(dataIndex - 1).get()[2] <= closeVal ? 1 : -1;
  58. } else {
  59. // No record of previous, set to be positive
  60. sign = 1;
  61. }
  62. }
  63. data.setItemLayout(idx, {
  64. chartLayout: chartLayout,
  65. sign: sign,
  66. initBaseline: openVal > closeVal ? ocHighPoint[constDim] : ocLowPoint[constDim],
  67. // open point.
  68. bodyEnds: bodyEnds,
  69. whiskerEnds: whiskerEnds,
  70. brushRect: makeBrushRect()
  71. });
  72. ++dataIndex;
  73. function getPoint(val) {
  74. var p = [];
  75. p[variableDim] = axisDimVal;
  76. p[constDim] = val;
  77. return isNaN(axisDimVal) || isNaN(val) ? [NaN, NaN] : coordSys.dataToPoint(p);
  78. }
  79. function addBodyEnd(point, start) {
  80. var point1 = point.slice();
  81. var point2 = point.slice();
  82. point1[variableDim] = subPixelOptimize(point1[variableDim] + candleWidth / 2, 1, false);
  83. point2[variableDim] = subPixelOptimize(point2[variableDim] - candleWidth / 2, 1, true);
  84. start ? bodyEnds.push(point1, point2) : bodyEnds.push(point2, point1);
  85. }
  86. function makeBrushRect() {
  87. var pmin = getPoint(Math.min(openVal, closeVal, lowestVal, highestVal));
  88. var pmax = getPoint(Math.max(openVal, closeVal, lowestVal, highestVal));
  89. pmin[variableDim] -= candleWidth / 2;
  90. pmax[variableDim] -= candleWidth / 2;
  91. return {
  92. x: pmin[0],
  93. y: pmin[1],
  94. width: constDim ? candleWidth : pmax[0] - pmin[0],
  95. height: constDim ? pmax[1] - pmin[1] : candleWidth
  96. };
  97. }
  98. function subPixelOptimizePoint(point) {
  99. point[variableDim] = subPixelOptimize(point[variableDim], 1);
  100. return point;
  101. }
  102. }, true);
  103. });
  104. }
  105. function calculateCandleWidth(seriesModel, data) {
  106. var baseAxis = seriesModel.getBaseAxis();
  107. var extent;
  108. var bandWidth = baseAxis.type === 'category' ? baseAxis.getBandWidth() : (extent = baseAxis.getExtent(), Math.abs(extent[1] - extent[0]) / data.count());
  109. var barMaxWidth = parsePercent(retrieve2(seriesModel.get('barMaxWidth'), bandWidth), bandWidth);
  110. var barMinWidth = parsePercent(retrieve2(seriesModel.get('barMinWidth'), 1), bandWidth);
  111. var barWidth = seriesModel.get('barWidth');
  112. return barWidth != null ? parsePercent(barWidth, bandWidth) // Put max outer to ensure bar visible in spite of overlap.
  113. : Math.max(Math.min(bandWidth / 2, barMaxWidth), barMinWidth);
  114. }
  115. module.exports = _default;