CalendarView.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413
  1. var echarts = require("../../echarts");
  2. var zrUtil = require("zrender/lib/core/util");
  3. var graphic = require("../../util/graphic");
  4. var formatUtil = require("../../util/format");
  5. var numberUtil = require("../../util/number");
  6. var MONTH_TEXT = {
  7. EN: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
  8. CN: ['一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月']
  9. };
  10. var WEEK_TEXT = {
  11. EN: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
  12. CN: ['日', '一', '二', '三', '四', '五', '六']
  13. };
  14. var _default = echarts.extendComponentView({
  15. type: 'calendar',
  16. /**
  17. * top/left line points
  18. * @private
  19. */
  20. _tlpoints: null,
  21. /**
  22. * bottom/right line points
  23. * @private
  24. */
  25. _blpoints: null,
  26. /**
  27. * first day of month
  28. * @private
  29. */
  30. _firstDayOfMonth: null,
  31. /**
  32. * first day point of month
  33. * @private
  34. */
  35. _firstDayPoints: null,
  36. render: function (calendarModel, ecModel, api) {
  37. var group = this.group;
  38. group.removeAll();
  39. var coordSys = calendarModel.coordinateSystem; // range info
  40. var rangeData = coordSys.getRangeInfo();
  41. var orient = coordSys.getOrient();
  42. this._renderDayRect(calendarModel, rangeData, group); // _renderLines must be called prior to following function
  43. this._renderLines(calendarModel, rangeData, orient, group);
  44. this._renderYearText(calendarModel, rangeData, orient, group);
  45. this._renderMonthText(calendarModel, orient, group);
  46. this._renderWeekText(calendarModel, rangeData, orient, group);
  47. },
  48. // render day rect
  49. _renderDayRect: function (calendarModel, rangeData, group) {
  50. var coordSys = calendarModel.coordinateSystem;
  51. var itemRectStyleModel = calendarModel.getModel('itemStyle.normal').getItemStyle();
  52. var sw = coordSys.getCellWidth();
  53. var sh = coordSys.getCellHeight();
  54. for (var i = rangeData.start.time; i <= rangeData.end.time; i = coordSys.getNextNDay(i, 1).time) {
  55. var point = coordSys.dataToRect([i], false).tl; // every rect
  56. var rect = new graphic.Rect({
  57. shape: {
  58. x: point[0],
  59. y: point[1],
  60. width: sw,
  61. height: sh
  62. },
  63. cursor: 'default',
  64. style: itemRectStyleModel
  65. });
  66. group.add(rect);
  67. }
  68. },
  69. // render separate line
  70. _renderLines: function (calendarModel, rangeData, orient, group) {
  71. var self = this;
  72. var coordSys = calendarModel.coordinateSystem;
  73. var lineStyleModel = calendarModel.getModel('splitLine.lineStyle').getLineStyle();
  74. var show = calendarModel.get('splitLine.show');
  75. var lineWidth = lineStyleModel.lineWidth;
  76. this._tlpoints = [];
  77. this._blpoints = [];
  78. this._firstDayOfMonth = [];
  79. this._firstDayPoints = [];
  80. var firstDay = rangeData.start;
  81. for (var i = 0; firstDay.time <= rangeData.end.time; i++) {
  82. addPoints(firstDay.formatedDate);
  83. if (i === 0) {
  84. firstDay = coordSys.getDateInfo(rangeData.start.y + '-' + rangeData.start.m);
  85. }
  86. var date = firstDay.date;
  87. date.setMonth(date.getMonth() + 1);
  88. firstDay = coordSys.getDateInfo(date);
  89. }
  90. addPoints(coordSys.getNextNDay(rangeData.end.time, 1).formatedDate);
  91. function addPoints(date) {
  92. self._firstDayOfMonth.push(coordSys.getDateInfo(date));
  93. self._firstDayPoints.push(coordSys.dataToRect([date], false).tl);
  94. var points = self._getLinePointsOfOneWeek(calendarModel, date, orient);
  95. self._tlpoints.push(points[0]);
  96. self._blpoints.push(points[points.length - 1]);
  97. show && self._drawSplitline(points, lineStyleModel, group);
  98. } // render top/left line
  99. show && this._drawSplitline(self._getEdgesPoints(self._tlpoints, lineWidth, orient), lineStyleModel, group); // render bottom/right line
  100. show && this._drawSplitline(self._getEdgesPoints(self._blpoints, lineWidth, orient), lineStyleModel, group);
  101. },
  102. // get points at both ends
  103. _getEdgesPoints: function (points, lineWidth, orient) {
  104. var rs = [points[0].slice(), points[points.length - 1].slice()];
  105. var idx = orient === 'horizontal' ? 0 : 1; // both ends of the line are extend half lineWidth
  106. rs[0][idx] = rs[0][idx] - lineWidth / 2;
  107. rs[1][idx] = rs[1][idx] + lineWidth / 2;
  108. return rs;
  109. },
  110. // render split line
  111. _drawSplitline: function (points, lineStyleModel, group) {
  112. var poyline = new graphic.Polyline({
  113. z2: 20,
  114. shape: {
  115. points: points
  116. },
  117. style: lineStyleModel
  118. });
  119. group.add(poyline);
  120. },
  121. // render month line of one week points
  122. _getLinePointsOfOneWeek: function (calendarModel, date, orient) {
  123. var coordSys = calendarModel.coordinateSystem;
  124. date = coordSys.getDateInfo(date);
  125. var points = [];
  126. for (var i = 0; i < 7; i++) {
  127. var tmpD = coordSys.getNextNDay(date.time, i);
  128. var point = coordSys.dataToRect([tmpD.time], false);
  129. points[2 * tmpD.day] = point.tl;
  130. points[2 * tmpD.day + 1] = point[orient === 'horizontal' ? 'bl' : 'tr'];
  131. }
  132. return points;
  133. },
  134. _formatterLabel: function (formatter, params) {
  135. if (typeof formatter === 'string' && formatter) {
  136. return formatUtil.formatTplSimple(formatter, params);
  137. }
  138. if (typeof formatter === 'function') {
  139. return formatter(params);
  140. }
  141. return params.nameMap;
  142. },
  143. _yearTextPositionControl: function (textEl, point, orient, position, margin) {
  144. point = point.slice();
  145. var aligns = ['center', 'bottom'];
  146. if (position === 'bottom') {
  147. point[1] += margin;
  148. aligns = ['center', 'top'];
  149. } else if (position === 'left') {
  150. point[0] -= margin;
  151. } else if (position === 'right') {
  152. point[0] += margin;
  153. aligns = ['center', 'top'];
  154. } else {
  155. // top
  156. point[1] -= margin;
  157. }
  158. var rotate = 0;
  159. if (position === 'left' || position === 'right') {
  160. rotate = Math.PI / 2;
  161. }
  162. return {
  163. rotation: rotate,
  164. position: point,
  165. style: {
  166. textAlign: aligns[0],
  167. textVerticalAlign: aligns[1]
  168. }
  169. };
  170. },
  171. // render year
  172. _renderYearText: function (calendarModel, rangeData, orient, group) {
  173. var yearLabel = calendarModel.getModel('yearLabel');
  174. if (!yearLabel.get('show')) {
  175. return;
  176. }
  177. var margin = yearLabel.get('margin');
  178. var pos = yearLabel.get('position');
  179. if (!pos) {
  180. pos = orient !== 'horizontal' ? 'top' : 'left';
  181. }
  182. var points = [this._tlpoints[this._tlpoints.length - 1], this._blpoints[0]];
  183. var xc = (points[0][0] + points[1][0]) / 2;
  184. var yc = (points[0][1] + points[1][1]) / 2;
  185. var idx = orient === 'horizontal' ? 0 : 1;
  186. var posPoints = {
  187. top: [xc, points[idx][1]],
  188. bottom: [xc, points[1 - idx][1]],
  189. left: [points[1 - idx][0], yc],
  190. right: [points[idx][0], yc]
  191. };
  192. var name = rangeData.start.y;
  193. if (+rangeData.end.y > +rangeData.start.y) {
  194. name = name + '-' + rangeData.end.y;
  195. }
  196. var formatter = yearLabel.get('formatter');
  197. var params = {
  198. start: rangeData.start.y,
  199. end: rangeData.end.y,
  200. nameMap: name
  201. };
  202. var content = this._formatterLabel(formatter, params);
  203. var yearText = new graphic.Text({
  204. z2: 30
  205. });
  206. graphic.setTextStyle(yearText.style, yearLabel, {
  207. text: content
  208. }), yearText.attr(this._yearTextPositionControl(yearText, posPoints[pos], orient, pos, margin));
  209. group.add(yearText);
  210. },
  211. _monthTextPositionControl: function (point, isCenter, orient, position, margin) {
  212. var align = 'left';
  213. var vAlign = 'top';
  214. var x = point[0];
  215. var y = point[1];
  216. if (orient === 'horizontal') {
  217. y = y + margin;
  218. if (isCenter) {
  219. align = 'center';
  220. }
  221. if (position === 'start') {
  222. vAlign = 'bottom';
  223. }
  224. } else {
  225. x = x + margin;
  226. if (isCenter) {
  227. vAlign = 'middle';
  228. }
  229. if (position === 'start') {
  230. align = 'right';
  231. }
  232. }
  233. return {
  234. x: x,
  235. y: y,
  236. textAlign: align,
  237. textVerticalAlign: vAlign
  238. };
  239. },
  240. // render month and year text
  241. _renderMonthText: function (calendarModel, orient, group) {
  242. var monthLabel = calendarModel.getModel('monthLabel');
  243. if (!monthLabel.get('show')) {
  244. return;
  245. }
  246. var nameMap = monthLabel.get('nameMap');
  247. var margin = monthLabel.get('margin');
  248. var pos = monthLabel.get('position');
  249. var align = monthLabel.get('align');
  250. var termPoints = [this._tlpoints, this._blpoints];
  251. if (zrUtil.isString(nameMap)) {
  252. nameMap = MONTH_TEXT[nameMap.toUpperCase()] || [];
  253. }
  254. var idx = pos === 'start' ? 0 : 1;
  255. var axis = orient === 'horizontal' ? 0 : 1;
  256. margin = pos === 'start' ? -margin : margin;
  257. var isCenter = align === 'center';
  258. for (var i = 0; i < termPoints[idx].length - 1; i++) {
  259. var tmp = termPoints[idx][i].slice();
  260. var firstDay = this._firstDayOfMonth[i];
  261. if (isCenter) {
  262. var firstDayPoints = this._firstDayPoints[i];
  263. tmp[axis] = (firstDayPoints[axis] + termPoints[0][i + 1][axis]) / 2;
  264. }
  265. var formatter = monthLabel.get('formatter');
  266. var name = nameMap[+firstDay.m - 1];
  267. var params = {
  268. yyyy: firstDay.y,
  269. yy: (firstDay.y + '').slice(2),
  270. MM: firstDay.m,
  271. M: +firstDay.m,
  272. nameMap: name
  273. };
  274. var content = this._formatterLabel(formatter, params);
  275. var monthText = new graphic.Text({
  276. z2: 30
  277. });
  278. zrUtil.extend(graphic.setTextStyle(monthText.style, monthLabel, {
  279. text: content
  280. }), this._monthTextPositionControl(tmp, isCenter, orient, pos, margin));
  281. group.add(monthText);
  282. }
  283. },
  284. _weekTextPositionControl: function (point, orient, position, margin, cellSize) {
  285. var align = 'center';
  286. var vAlign = 'middle';
  287. var x = point[0];
  288. var y = point[1];
  289. var isStart = position === 'start';
  290. if (orient === 'horizontal') {
  291. x = x + margin + (isStart ? 1 : -1) * cellSize[0] / 2;
  292. align = isStart ? 'right' : 'left';
  293. } else {
  294. y = y + margin + (isStart ? 1 : -1) * cellSize[1] / 2;
  295. vAlign = isStart ? 'bottom' : 'top';
  296. }
  297. return {
  298. x: x,
  299. y: y,
  300. textAlign: align,
  301. textVerticalAlign: vAlign
  302. };
  303. },
  304. // render weeks
  305. _renderWeekText: function (calendarModel, rangeData, orient, group) {
  306. var dayLabel = calendarModel.getModel('dayLabel');
  307. if (!dayLabel.get('show')) {
  308. return;
  309. }
  310. var coordSys = calendarModel.coordinateSystem;
  311. var pos = dayLabel.get('position');
  312. var nameMap = dayLabel.get('nameMap');
  313. var margin = dayLabel.get('margin');
  314. var firstDayOfWeek = coordSys.getFirstDayOfWeek();
  315. if (zrUtil.isString(nameMap)) {
  316. nameMap = WEEK_TEXT[nameMap.toUpperCase()] || [];
  317. }
  318. var start = coordSys.getNextNDay(rangeData.end.time, 7 - rangeData.lweek).time;
  319. var cellSize = [coordSys.getCellWidth(), coordSys.getCellHeight()];
  320. margin = numberUtil.parsePercent(margin, cellSize[orient === 'horizontal' ? 0 : 1]);
  321. if (pos === 'start') {
  322. start = coordSys.getNextNDay(rangeData.start.time, -(7 + rangeData.fweek)).time;
  323. margin = -margin;
  324. }
  325. for (var i = 0; i < 7; i++) {
  326. var tmpD = coordSys.getNextNDay(start, i);
  327. var point = coordSys.dataToRect([tmpD.time], false).center;
  328. var day = i;
  329. day = Math.abs((i + firstDayOfWeek) % 7);
  330. var weekText = new graphic.Text({
  331. z2: 30
  332. });
  333. zrUtil.extend(graphic.setTextStyle(weekText.style, dayLabel, {
  334. text: nameMap[day]
  335. }), this._weekTextPositionControl(point, orient, pos, margin, cellSize));
  336. group.add(weekText);
  337. }
  338. }
  339. });
  340. module.exports = _default;