v1.js 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303
  1. /**
  2. * 计算分割线的值。
  3. * Calculates the value of the split line.
  4. *
  5. * @param number splitType
  6. * @param array splitValue
  7. * @param array axisData
  8. * @access public
  9. * @return string|number
  10. */
  11. function calculateMarkLine(splitType, splitValue, axisData)
  12. {
  13. if(splitType == 0)
  14. {
  15. const sum = axisData.reduce((accumulator, currentValue) => accumulator + currentValue, 0);
  16. return (sum / axisData.length).toFixed(2);
  17. }
  18. else
  19. {
  20. return splitValue[0] * 100;
  21. }
  22. }
  23. /**
  24. * 初始波士顿模型。
  25. * Initial Boston Model.
  26. *
  27. * @access public
  28. * @return void
  29. */
  30. window.initBcgModel = function()
  31. {
  32. $.getLib(config.webRoot + 'js/echarts/echarts.common.min.js', {root: false}, function()
  33. {
  34. const bcgEcharts = echarts.init($('.echarts-content>div')[0]);
  35. const colors = ['#2294FB', '#22C98D', '#8166EE', '#FF8058', '#FF9F46', '#FFCD6C', '#04D2CC', '#2B67E5', '#E08BE7', '#B2B9C5'];
  36. const data = $('.echarts-content').data('blocks');
  37. const configureDimension = data.runOptions.configureDimension;
  38. const prerelease = data.runOptions.prerelease;
  39. /* 分割线的计算。*/
  40. /* Calculation of the split line. */
  41. const markLineX = calculateMarkLine(prerelease.splitType[1], prerelease.splitValue[1], data.basicXAxis);
  42. const markLineY = calculateMarkLine(prerelease.splitType[0], prerelease.splitValue[0], data.basicYAxis);
  43. const maxX = Math.max(...data.basicXAxis);
  44. const minX = Math.min(...data.basicXAxis);
  45. const maxY = Math.max(...data.basicYAxis);
  46. const minY = Math.min(...data.basicYAxis);
  47. const minXAxis = markLineX <= minX ? markLineX : Math.max(minX * 0.3, 40);
  48. const maxXAxis = markLineX >= maxX ? markLineX : Math.max(maxX * 0.3, 40);
  49. const minYAxis = markLineY <= minY ? markLineY : Math.max(minY * 0.3, 40);
  50. const maxYAxis = markLineY >= maxY ? markLineY : Math.max(maxY * 0.3, 40);
  51. /* 划分的区域名称的展示。*/
  52. /* A display of the names of the zones delineated. */
  53. const graphicData = [];
  54. for(let i = 0; i < 4; i++)
  55. {
  56. let position = (i % 2 == 0) ? { left: '9%' } : { right: '14%' };
  57. position[(i < 2) ? 'top' : 'bottom'] = (i < 2) ? '4%' : '10%';
  58. graphicData.push({
  59. type: 'text',
  60. style: {
  61. text: prerelease.blocks[i] || '',
  62. width: 160,
  63. overflow: 'truncate',
  64. fontSize: 20,
  65. fontWeight: 600,
  66. fill: '#64758B',
  67. },
  68. ...position,
  69. onmouseover: function() {
  70. this.setStyle({overflow: 'break'});
  71. },
  72. onmouseout: function() {
  73. this.setStyle({overflow: 'truncate'});
  74. }
  75. });
  76. }
  77. const markLineLabel = {
  78. show: true,
  79. color: '#39485D',
  80. fontSize: 20
  81. };
  82. const series = [];
  83. data['series'].forEach((item, index) => {
  84. series.push({
  85. name: item[2],
  86. data: [item],
  87. type: 'scatter',
  88. zlevel: index + 1,
  89. symbolSize: function(itemData) {
  90. return itemData[3];
  91. },
  92. itemStyle: {
  93. opacity: 0.3,
  94. color: function(params) {
  95. return colors[params.seriesIndex];
  96. },
  97. emphasis: {
  98. opacity: 0.6
  99. }
  100. },
  101. emphasis: {
  102. label: {
  103. show: true,
  104. position: 'top',
  105. distance: 6,
  106. fontSize: 20,
  107. color: '#39485D',
  108. opacity: 1,
  109. formatter: function(param) {
  110. const dataX = param.data[0].toFixed(2);
  111. const dataY = param.data[1].toFixed(2);
  112. let text = `${param.data[2]} (${dataX}, ${dataY})`;
  113. if(text.length > 20) text = text.replace(/(.{20})/g, '$1\n');
  114. return text;
  115. }
  116. }
  117. }
  118. });
  119. });
  120. series.push({
  121. type: 'scatter',
  122. markLine: {
  123. silent: false,
  124. symbol: 'none',
  125. label: {
  126. show: false
  127. },
  128. lineStyle: {
  129. width: 2,
  130. color: 'rgba(100, 117, 139, 0.3)',
  131. type: 'solid'
  132. },
  133. emphasis: {
  134. lineStyle: {
  135. color: 'rgba(100, 117, 139, 0.3)'
  136. }
  137. },
  138. data: [
  139. {
  140. xAxis: markLineX,
  141. emphasis: {
  142. label: {
  143. ...markLineLabel,
  144. position: 'top',
  145. padding: configureDimension.yAxisOrder == 1 ? 0 : [-20, 0]
  146. }
  147. }
  148. },
  149. {
  150. yAxis: markLineY,
  151. emphasis: {
  152. label: {
  153. ...markLineLabel,
  154. position: 'right',
  155. padding: configureDimension.xAxisOrder == 1 ? 0 : [0, -60]
  156. }
  157. }
  158. }
  159. ]
  160. }
  161. });
  162. const legend = [];
  163. for(let key in data.products)
  164. {
  165. if(key >= 0 && key < colors.length)
  166. {
  167. legend.push({
  168. name: data.products[key],
  169. itemStyle: {
  170. color: colors[key]
  171. }
  172. });
  173. }
  174. }
  175. const option = {
  176. animationDuration: 0,
  177. grid: {
  178. left: '3%',
  179. right: '14%',
  180. bottom: '5%',
  181. containLabel: true
  182. },
  183. legend: {
  184. data: legend,
  185. formatter: function(name) {
  186. const reg = /[\u4E00-\u9FA5]/;
  187. const threshold = !reg.test(name) ? 14 : 7;
  188. if(name.length > threshold) return name.slice(0, threshold) + '...';
  189. return name;
  190. },
  191. textStyle: {
  192. color: '#4A577F',
  193. fontSize: 20
  194. },
  195. itemGap: 15,
  196. right: 10,
  197. bottom: 'center',
  198. orient: 'vertical'
  199. },
  200. graphic: graphicData,
  201. xAxis: {
  202. name: '%',
  203. nameLocation: configureDimension.xAxisOrder == 1 ? 'start' : 'end',
  204. nameTextStyle: {
  205. fontSize: 20,
  206. color: '#000'
  207. },
  208. inverse: configureDimension.xAxisOrder == 1,
  209. type: 'value',
  210. min: function(value) {
  211. const threshold = minXAxis < -1000 ? 500 : 90;
  212. return value.min - minXAxis - threshold;
  213. },
  214. max: function(value) {
  215. const threshold = maxXAxis > 1000 ? 500 : 90;
  216. return value.max + maxXAxis + threshold;
  217. },
  218. splitLine: {
  219. show: false,
  220. },
  221. axisTick: {
  222. show: true,
  223. inside: true,
  224. lineStyle: {
  225. width: 2
  226. }
  227. },
  228. axisLabel: {
  229. show: true,
  230. fontSize: 16,
  231. color: '#64758B',
  232. formatter: function(params) {
  233. return params.toFixed(2);
  234. }
  235. },
  236. axisLine: {
  237. show: true,
  238. onZero: false,
  239. symbol: ['none', 'arrow'],
  240. lineStyle: {
  241. width: 2,
  242. color: 'rgba(100, 117, 139, 0.7)',
  243. }
  244. }
  245. },
  246. yAxis: {
  247. name: '%',
  248. nameLocation: configureDimension.yAxisOrder == 1 ? 'start' : 'end',
  249. nameTextStyle: {
  250. fontSize: 20,
  251. color: '#000'
  252. },
  253. inverse: configureDimension.yAxisOrder == 1,
  254. type: 'value',
  255. min: function(value) {
  256. const threshold = minYAxis < -1000 ? 500 : 90;
  257. return value.min - minYAxis - threshold;
  258. },
  259. max: function(value) {
  260. const threshold = maxYAxis > 1000 ? 500 : 90;
  261. return value.max + maxYAxis + threshold;
  262. },
  263. splitLine: {
  264. show: false
  265. },
  266. axisTick: {
  267. show: true,
  268. inside: true,
  269. lineStyle: {
  270. width: 2
  271. }
  272. },
  273. axisLine: {
  274. show: true,
  275. onZero: false,
  276. symbol: ['none', 'arrow'],
  277. lineStyle: {
  278. width: 2,
  279. color: 'rgba(100, 117, 139, 0.7)',
  280. }
  281. },
  282. axisLabel: {
  283. show: true,
  284. fontSize: 16,
  285. color: '#64758B',
  286. formatter: function(params) {
  287. return params.toFixed(2);
  288. }
  289. }
  290. },
  291. series: series
  292. };
  293. bcgEcharts.setOption(option);
  294. });
  295. }