title.js 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  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. import * as zrUtil from 'zrender/src/core/util';
  20. import * as echarts from '../echarts';
  21. import * as graphic from '../util/graphic';
  22. import {getLayoutRect} from '../util/layout';
  23. import {windowOpen} from '../util/format';
  24. // Model
  25. echarts.extendComponentModel({
  26. type: 'title',
  27. layoutMode: {type: 'box', ignoreSize: true},
  28. defaultOption: {
  29. // 一级层叠
  30. zlevel: 0,
  31. // 二级层叠
  32. z: 6,
  33. show: true,
  34. text: '',
  35. // 超链接跳转
  36. // link: null,
  37. // 仅支持self | blank
  38. target: 'blank',
  39. subtext: '',
  40. // 超链接跳转
  41. // sublink: null,
  42. // 仅支持self | blank
  43. subtarget: 'blank',
  44. // 'center' ¦ 'left' ¦ 'right'
  45. // ¦ {number}(x坐标,单位px)
  46. left: 0,
  47. // 'top' ¦ 'bottom' ¦ 'center'
  48. // ¦ {number}(y坐标,单位px)
  49. top: 0,
  50. // 水平对齐
  51. // 'auto' | 'left' | 'right' | 'center'
  52. // 默认根据 left 的位置判断是左对齐还是右对齐
  53. // textAlign: null
  54. //
  55. // 垂直对齐
  56. // 'auto' | 'top' | 'bottom' | 'middle'
  57. // 默认根据 top 位置判断是上对齐还是下对齐
  58. // textVerticalAlign: null
  59. // textBaseline: null // The same as textVerticalAlign.
  60. backgroundColor: 'rgba(0,0,0,0)',
  61. // 标题边框颜色
  62. borderColor: '#ccc',
  63. // 标题边框线宽,单位px,默认为0(无边框)
  64. borderWidth: 0,
  65. // 标题内边距,单位px,默认各方向内边距为5,
  66. // 接受数组分别设定上右下左边距,同css
  67. padding: 5,
  68. // 主副标题纵向间隔,单位px,默认为10,
  69. itemGap: 10,
  70. textStyle: {
  71. fontSize: 18,
  72. fontWeight: 'bolder',
  73. color: '#333'
  74. },
  75. subtextStyle: {
  76. color: '#aaa'
  77. }
  78. }
  79. });
  80. // View
  81. echarts.extendComponentView({
  82. type: 'title',
  83. render: function (titleModel, ecModel, api) {
  84. this.group.removeAll();
  85. if (!titleModel.get('show')) {
  86. return;
  87. }
  88. var group = this.group;
  89. var textStyleModel = titleModel.getModel('textStyle');
  90. var subtextStyleModel = titleModel.getModel('subtextStyle');
  91. var textAlign = titleModel.get('textAlign');
  92. var textVerticalAlign = zrUtil.retrieve2(
  93. titleModel.get('textBaseline'), titleModel.get('textVerticalAlign')
  94. );
  95. var textEl = new graphic.Text({
  96. style: graphic.setTextStyle({}, textStyleModel, {
  97. text: titleModel.get('text'),
  98. textFill: textStyleModel.getTextColor()
  99. }, {disableBox: true}),
  100. z2: 10
  101. });
  102. var textRect = textEl.getBoundingRect();
  103. var subText = titleModel.get('subtext');
  104. var subTextEl = new graphic.Text({
  105. style: graphic.setTextStyle({}, subtextStyleModel, {
  106. text: subText,
  107. textFill: subtextStyleModel.getTextColor(),
  108. y: textRect.height + titleModel.get('itemGap'),
  109. textVerticalAlign: 'top'
  110. }, {disableBox: true}),
  111. z2: 10
  112. });
  113. var link = titleModel.get('link');
  114. var sublink = titleModel.get('sublink');
  115. var triggerEvent = titleModel.get('triggerEvent', true);
  116. textEl.silent = !link && !triggerEvent;
  117. subTextEl.silent = !sublink && !triggerEvent;
  118. if (link) {
  119. textEl.on('click', function () {
  120. windowOpen(link, '_' + titleModel.get('target'));
  121. });
  122. }
  123. if (sublink) {
  124. subTextEl.on('click', function () {
  125. windowOpen(sublink, '_' + titleModel.get('subtarget'));
  126. });
  127. }
  128. textEl.eventData = subTextEl.eventData = triggerEvent
  129. ? {
  130. componentType: 'title',
  131. componentIndex: titleModel.componentIndex
  132. }
  133. : null;
  134. group.add(textEl);
  135. subText && group.add(subTextEl);
  136. // If no subText, but add subTextEl, there will be an empty line.
  137. var groupRect = group.getBoundingRect();
  138. var layoutOption = titleModel.getBoxLayoutParams();
  139. layoutOption.width = groupRect.width;
  140. layoutOption.height = groupRect.height;
  141. var layoutRect = getLayoutRect(
  142. layoutOption, {
  143. width: api.getWidth(),
  144. height: api.getHeight()
  145. }, titleModel.get('padding')
  146. );
  147. // Adjust text align based on position
  148. if (!textAlign) {
  149. // Align left if title is on the left. center and right is same
  150. textAlign = titleModel.get('left') || titleModel.get('right');
  151. if (textAlign === 'middle') {
  152. textAlign = 'center';
  153. }
  154. // Adjust layout by text align
  155. if (textAlign === 'right') {
  156. layoutRect.x += layoutRect.width;
  157. }
  158. else if (textAlign === 'center') {
  159. layoutRect.x += layoutRect.width / 2;
  160. }
  161. }
  162. if (!textVerticalAlign) {
  163. textVerticalAlign = titleModel.get('top') || titleModel.get('bottom');
  164. if (textVerticalAlign === 'center') {
  165. textVerticalAlign = 'middle';
  166. }
  167. if (textVerticalAlign === 'bottom') {
  168. layoutRect.y += layoutRect.height;
  169. }
  170. else if (textVerticalAlign === 'middle') {
  171. layoutRect.y += layoutRect.height / 2;
  172. }
  173. textVerticalAlign = textVerticalAlign || 'top';
  174. }
  175. group.attr('position', [layoutRect.x, layoutRect.y]);
  176. var alignStyle = {
  177. textAlign: textAlign,
  178. textVerticalAlign: textVerticalAlign
  179. };
  180. textEl.setStyle(alignStyle);
  181. subTextEl.setStyle(alignStyle);
  182. // Render background
  183. // Get groupRect again because textAlign has been changed
  184. groupRect = group.getBoundingRect();
  185. var padding = layoutRect.margin;
  186. var style = titleModel.getItemStyle(['color', 'opacity']);
  187. style.fill = titleModel.get('backgroundColor');
  188. var rect = new graphic.Rect({
  189. shape: {
  190. x: groupRect.x - padding[3],
  191. y: groupRect.y - padding[0],
  192. width: groupRect.width + padding[1] + padding[3],
  193. height: groupRect.height + padding[0] + padding[2],
  194. r: titleModel.get('borderRadius')
  195. },
  196. style: style,
  197. subPixelOptimize: true,
  198. silent: true
  199. });
  200. group.add(rect);
  201. }
  202. });