viewHelper.js 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. var zrUtil = require("zrender/lib/core/util");
  2. var graphic = require("../../util/graphic");
  3. var textContain = require("zrender/lib/contain/text");
  4. var formatUtil = require("../../util/format");
  5. var matrix = require("zrender/lib/core/matrix");
  6. var axisHelper = require("../../coord/axisHelper");
  7. var AxisBuilder = require("../axis/AxisBuilder");
  8. /**
  9. * @param {module:echarts/model/Model} axisPointerModel
  10. */
  11. function buildElStyle(axisPointerModel) {
  12. var axisPointerType = axisPointerModel.get('type');
  13. var styleModel = axisPointerModel.getModel(axisPointerType + 'Style');
  14. var style;
  15. if (axisPointerType === 'line') {
  16. style = styleModel.getLineStyle();
  17. style.fill = null;
  18. } else if (axisPointerType === 'shadow') {
  19. style = styleModel.getAreaStyle();
  20. style.stroke = null;
  21. }
  22. return style;
  23. }
  24. /**
  25. * @param {Function} labelPos {align, verticalAlign, position}
  26. */
  27. function buildLabelElOption(elOption, axisModel, axisPointerModel, api, labelPos) {
  28. var value = axisPointerModel.get('value');
  29. var text = getValueLabel(value, axisModel.axis, axisModel.ecModel, axisPointerModel.get('seriesDataIndices'), {
  30. precision: axisPointerModel.get('label.precision'),
  31. formatter: axisPointerModel.get('label.formatter')
  32. });
  33. var labelModel = axisPointerModel.getModel('label');
  34. var paddings = formatUtil.normalizeCssArray(labelModel.get('padding') || 0);
  35. var font = labelModel.getFont();
  36. var textRect = textContain.getBoundingRect(text, font);
  37. var position = labelPos.position;
  38. var width = textRect.width + paddings[1] + paddings[3];
  39. var height = textRect.height + paddings[0] + paddings[2]; // Adjust by align.
  40. var align = labelPos.align;
  41. align === 'right' && (position[0] -= width);
  42. align === 'center' && (position[0] -= width / 2);
  43. var verticalAlign = labelPos.verticalAlign;
  44. verticalAlign === 'bottom' && (position[1] -= height);
  45. verticalAlign === 'middle' && (position[1] -= height / 2); // Not overflow ec container
  46. confineInContainer(position, width, height, api);
  47. var bgColor = labelModel.get('backgroundColor');
  48. if (!bgColor || bgColor === 'auto') {
  49. bgColor = axisModel.get('axisLine.lineStyle.color');
  50. }
  51. elOption.label = {
  52. shape: {
  53. x: 0,
  54. y: 0,
  55. width: width,
  56. height: height,
  57. r: labelModel.get('borderRadius')
  58. },
  59. position: position.slice(),
  60. // TODO: rich
  61. style: {
  62. text: text,
  63. textFont: font,
  64. textFill: labelModel.getTextColor(),
  65. textPosition: 'inside',
  66. fill: bgColor,
  67. stroke: labelModel.get('borderColor') || 'transparent',
  68. lineWidth: labelModel.get('borderWidth') || 0,
  69. shadowBlur: labelModel.get('shadowBlur'),
  70. shadowColor: labelModel.get('shadowColor'),
  71. shadowOffsetX: labelModel.get('shadowOffsetX'),
  72. shadowOffsetY: labelModel.get('shadowOffsetY')
  73. },
  74. // Lable should be over axisPointer.
  75. z2: 10
  76. };
  77. } // Do not overflow ec container
  78. function confineInContainer(position, width, height, api) {
  79. var viewWidth = api.getWidth();
  80. var viewHeight = api.getHeight();
  81. position[0] = Math.min(position[0] + width, viewWidth) - width;
  82. position[1] = Math.min(position[1] + height, viewHeight) - height;
  83. position[0] = Math.max(position[0], 0);
  84. position[1] = Math.max(position[1], 0);
  85. }
  86. /**
  87. * @param {number} value
  88. * @param {module:echarts/coord/Axis} axis
  89. * @param {module:echarts/model/Global} ecModel
  90. * @param {Object} opt
  91. * @param {Array.<Object>} seriesDataIndices
  92. * @param {number|string} opt.precision 'auto' or a number
  93. * @param {string|Function} opt.formatter label formatter
  94. */
  95. function getValueLabel(value, axis, ecModel, seriesDataIndices, opt) {
  96. var text = axis.scale.getLabel( // If `precision` is set, width can be fixed (like '12.00500'), which
  97. // helps to debounce when when moving label.
  98. value, {
  99. precision: opt.precision
  100. });
  101. var formatter = opt.formatter;
  102. if (formatter) {
  103. var params = {
  104. value: axisHelper.getAxisRawValue(axis, value),
  105. seriesData: []
  106. };
  107. zrUtil.each(seriesDataIndices, function (idxItem) {
  108. var series = ecModel.getSeriesByIndex(idxItem.seriesIndex);
  109. var dataIndex = idxItem.dataIndexInside;
  110. var dataParams = series && series.getDataParams(dataIndex);
  111. dataParams && params.seriesData.push(dataParams);
  112. });
  113. if (zrUtil.isString(formatter)) {
  114. text = formatter.replace('{value}', text);
  115. } else if (zrUtil.isFunction(formatter)) {
  116. text = formatter(params);
  117. }
  118. }
  119. return text;
  120. }
  121. /**
  122. * @param {module:echarts/coord/Axis} axis
  123. * @param {number} value
  124. * @param {Object} layoutInfo {
  125. * rotation, position, labelOffset, labelDirection, labelMargin
  126. * }
  127. */
  128. function getTransformedPosition(axis, value, layoutInfo) {
  129. var transform = matrix.create();
  130. matrix.rotate(transform, transform, layoutInfo.rotation);
  131. matrix.translate(transform, transform, layoutInfo.position);
  132. return graphic.applyTransform([axis.dataToCoord(value), (layoutInfo.labelOffset || 0) + (layoutInfo.labelDirection || 1) * (layoutInfo.labelMargin || 0)], transform);
  133. }
  134. function buildCartesianSingleLabelElOption(value, elOption, layoutInfo, axisModel, axisPointerModel, api) {
  135. var textLayout = AxisBuilder.innerTextLayout(layoutInfo.rotation, 0, layoutInfo.labelDirection);
  136. layoutInfo.labelMargin = axisPointerModel.get('label.margin');
  137. buildLabelElOption(elOption, axisModel, axisPointerModel, api, {
  138. position: getTransformedPosition(axisModel.axis, value, layoutInfo),
  139. align: textLayout.textAlign,
  140. verticalAlign: textLayout.textVerticalAlign
  141. });
  142. }
  143. /**
  144. * @param {Array.<number>} p1
  145. * @param {Array.<number>} p2
  146. * @param {number} [xDimIndex=0] or 1
  147. */
  148. function makeLineShape(p1, p2, xDimIndex) {
  149. xDimIndex = xDimIndex || 0;
  150. return {
  151. x1: p1[xDimIndex],
  152. y1: p1[1 - xDimIndex],
  153. x2: p2[xDimIndex],
  154. y2: p2[1 - xDimIndex]
  155. };
  156. }
  157. /**
  158. * @param {Array.<number>} xy
  159. * @param {Array.<number>} wh
  160. * @param {number} [xDimIndex=0] or 1
  161. */
  162. function makeRectShape(xy, wh, xDimIndex) {
  163. xDimIndex = xDimIndex || 0;
  164. return {
  165. x: xy[xDimIndex],
  166. y: xy[1 - xDimIndex],
  167. width: wh[xDimIndex],
  168. height: wh[1 - xDimIndex]
  169. };
  170. }
  171. function makeSectorShape(cx, cy, r0, r, startAngle, endAngle) {
  172. return {
  173. cx: cx,
  174. cy: cy,
  175. r0: r0,
  176. r: r,
  177. startAngle: startAngle,
  178. endAngle: endAngle,
  179. clockwise: true
  180. };
  181. }
  182. exports.buildElStyle = buildElStyle;
  183. exports.buildLabelElOption = buildLabelElOption;
  184. exports.getValueLabel = getValueLabel;
  185. exports.getTransformedPosition = getTransformedPosition;
  186. exports.buildCartesianSingleLabelElOption = buildCartesianSingleLabelElOption;
  187. exports.makeLineShape = makeLineShape;
  188. exports.makeRectShape = makeRectShape;
  189. exports.makeSectorShape = makeSectorShape;