var __assign = this && this.__assign || function () { __assign = Object.assign || function (t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; } return t; }; return __assign.apply(this, arguments); }; /** * 基于 G 的刻度时间轴组件 */ import { ext } from '@antv/matrix-util'; import { isNumber, isString } from '@antv/util'; import TimeBarTooltip from './timeBarTooltip'; import ControllerBtn from './controllerBtn'; import { VALUE_CHANGE, TIMELINE_START, TIMELINE_END, PLAY_PAUSE_BTN, NEXT_STEP_BTN, PRE_STEP_BTN, TIMEBAR_CONFIG_CHANGE } from './constant'; var transform = ext.transform; var DEFAULT_SELECTEDTICK_STYLE = { fill: '#5B8FF9' }; var DEFAULT_UNSELECTEDTICK_STYLE = { fill: '#e6e8e9' }; var TimeBarSlice = /** @class */function () { function TimeBarSlice(cfgs) { this.frameCount = 0; this.fontFamily = 'Arial, sans-serif'; var graph = cfgs.graph, canvas = cfgs.canvas, group = cfgs.group, width = cfgs.width, height = cfgs.height, padding = cfgs.padding, data = cfgs.data, start = cfgs.start, end = cfgs.end, _a = cfgs.x, x = _a === void 0 ? 0 : _a, _b = cfgs.y, y = _b === void 0 ? 0 : _b, tickLabelFormatter = cfgs.tickLabelFormatter, _c = cfgs.selectedTickStyle, selectedTickStyle = _c === void 0 ? DEFAULT_SELECTEDTICK_STYLE : _c, _d = cfgs.unselectedTickStyle, unselectedTickStyle = _d === void 0 ? DEFAULT_UNSELECTEDTICK_STYLE : _d, tooltipBackgroundColor = cfgs.tooltipBackgroundColor, tooltipFomatter = cfgs.tooltipFomatter, tickLabelStyle = cfgs.tickLabelStyle, _e = cfgs.controllerCfg, controllerCfg = _e === void 0 ? { speed: 1 } : _e; this.graph = graph; this.group = group; this.sliceGroup = group.addGroup({ name: 'slice-group' }); this.canvas = canvas; this.width = width; this.height = height; this.padding = padding; this.data = data; this.start = start; this.end = end; this.tickLabelFormatter = tickLabelFormatter; this.tickLabelStyle = tickLabelStyle || {}; this.selectedTickStyle = selectedTickStyle; this.unselectedTickStyle = unselectedTickStyle; this.controllerCfg = controllerCfg; this.currentSpeed = controllerCfg.speed || 1; this.x = x; this.y = y; this.tooltipBackgroundColor = tooltipBackgroundColor; this.tooltipFomatter = tooltipFomatter; // 初始化 fontFamily,如果有浏览器,取 body 上的字体,防止文字更新时局部渲染造成的重影 this.fontFamily = typeof window !== 'undefined' ? window.getComputedStyle(document.body, null).getPropertyValue('font-family') || 'Arial, sans-serif' : 'Arial, sans-serif'; this.renderSlices(); this.initEvent(); } TimeBarSlice.prototype.renderSlices = function () { var _this = this; var _a = this, width = _a.width, height = _a.height, padding = _a.padding, data = _a.data, start = _a.start, end = _a.end, tickLabelFormatter = _a.tickLabelFormatter, selectedTickStyle = _a.selectedTickStyle, unselectedTickStyle = _a.unselectedTickStyle, tickLabelStyle = _a.tickLabelStyle; var realWidth = width - 2 * padding; var fontSize = 10; var labelLineHeight = 4; var labelAreaHeight = 3 * padding + labelLineHeight + fontSize; var ticksAreaHeight = height - labelAreaHeight - 2 * padding; var gap = 2; var ticksLength = data.length; var tickWidth = (realWidth - gap * (ticksLength - 1)) / ticksLength; this.tickWidth = tickWidth; var sliceGroup = this.sliceGroup; var tickRects = []; var labels = []; var startTickId = Math.round(ticksLength * start); var endTickId = Math.round(ticksLength * end); this.startTickRectId = startTickId; this.endTickRectId = endTickId; var rotate = tickLabelStyle.rotate; delete tickLabelStyle.rotate; data.forEach(function (d, i) { // draw the tick rects var selected = i >= startTickId && i <= endTickId; var tickStyle = selected ? selectedTickStyle : unselectedTickStyle; var rect = sliceGroup.addShape('rect', { attrs: __assign({ x: padding + i * (tickWidth + gap), y: padding, width: tickWidth, height: ticksAreaHeight }, tickStyle), draggable: true, name: "tick-rect-".concat(i) }); // draw the pick tick rects var pickRect = sliceGroup.addShape('rect', { attrs: { x: padding + i * tickWidth + gap * (2 * i - 1) / 2, y: padding, width: i === 0 || i === ticksLength - 1 ? tickWidth + gap / 2 : tickWidth + gap, height: ticksAreaHeight, fill: '#fff', opacity: 0 }, draggable: true, name: "pick-rect-".concat(i) }); pickRect.toFront(); var rectBBox = rect.getBBox(); var centerX = (rectBBox.minX + rectBBox.maxX) / 2; tickRects.push({ rect: rect, pickRect: pickRect, value: d.date, x: centerX, y: rectBBox.minY }); var label; if (tickLabelFormatter) { label = tickLabelFormatter(d); if (!isString(label) && label) { // return true label = d.date; } } else if (i % Math.round(ticksLength / 10) === 0) { label = d.date; } if (label) { labels.push(label); // draw tick lines var lineStartY = rectBBox.maxY + padding * 2; sliceGroup.addShape('line', { attrs: { stroke: '#BFBFBF', x1: centerX, y1: lineStartY, x2: centerX, y2: lineStartY + labelLineHeight }, name: 'tick-line' }); var labelStartY = lineStartY + labelLineHeight + padding; var text = sliceGroup.addShape('text', { attrs: __assign({ fill: '#8c8c8c', stroke: '#fff', lineWidth: 1, x: centerX, y: labelStartY, textAlign: 'center', text: label, textBaseline: 'top', fontSize: 10, fontFamily: _this.fontFamily || 'Arial, sans-serif' }, tickLabelStyle), capture: false, name: 'tick-label' }); var textBBox = text.getBBox(); if (textBBox.maxX > width) { text.attr('textAlign', 'right'); } else if (textBBox.minX < 0) { text.attr('textAlign', 'left'); } if (isNumber(rotate) && labels.length !== 10) { var matrix = transform([1, 0, 0, 0, 1, 0, 0, 0, 1], [['t', -centerX, -labelStartY], ['r', rotate], ['t', centerX - 5, labelStartY + 2]]); text.attr({ textAlign: 'left', matrix: matrix }); } if (labels.length === 1) { text.attr({ textAlign: 'left' }); } else if (labels.length === 10) { text.attr({ textAlign: 'right' }); } // draw tick labels } }); this.tickRects = tickRects; // 渲染播放、快进和后退的控制按钮 var group = this.group; this.currentSpeed = 1; this.controllerBtnGroup = new ControllerBtn(__assign({ group: group, x: this.x, y: this.y + height + 5, width: width, height: 40, hideTimeTypeController: true, speed: this.currentSpeed, fontFamily: this.fontFamily || 'Arial, sans-serif' }, this.controllerCfg)); }; TimeBarSlice.prototype.initEvent = function () { var _this = this; var sliceGroup = this.sliceGroup; sliceGroup.on('click', function (e) { var targetRect = e.target; if (targetRect.get('type') !== 'rect' || !targetRect.get('name')) return; var id = parseInt(targetRect.get('name').split('-')[2], 10); if (!isNaN(id)) { var tickRects_1 = _this.tickRects; // cancel the selected ticks var unselectedTickStyle_1 = _this.unselectedTickStyle; tickRects_1.forEach(function (tickRect) { tickRect.rect.attr(unselectedTickStyle_1); }); var selectedTickStyle = _this.selectedTickStyle; tickRects_1[id].rect.attr(selectedTickStyle); _this.startTickRectId = id; _this.endTickRectId = id; var ticksLength = tickRects_1.length; var start = id / ticksLength; _this.graph.emit(VALUE_CHANGE, { value: [start, start] }); } }); sliceGroup.on('dragstart', function (e) { var tickRects = _this.tickRects; // cancel the selected ticks var unselectedTickStyle = _this.unselectedTickStyle; tickRects.forEach(function (tickRect) { tickRect.rect.attr(unselectedTickStyle); }); var targetRect = e.target; var id = parseInt(targetRect.get('name').split('-')[2], 10); var selectedTickStyle = _this.selectedTickStyle; tickRects[id].rect.attr(selectedTickStyle); _this.startTickRectId = id; var ticksLength = tickRects.length; var start = id / ticksLength; _this.graph.emit(VALUE_CHANGE, { value: [start, start] }); _this.dragging = true; }); sliceGroup.on('dragover', function (e) { if (!_this.dragging) return; if (e.target.get('type') !== 'rect') return; var id = parseInt(e.target.get('name').split('-')[2], 10); var startTickRectId = _this.startTickRectId; var tickRects = _this.tickRects; var selectedTickStyle = _this.selectedTickStyle; var unselectedTickStyle = _this.unselectedTickStyle; for (var i = 0; i < tickRects.length; i++) { var style = i >= startTickRectId && i <= id ? selectedTickStyle : unselectedTickStyle; tickRects[i].rect.attr(style); } var ticksLength = tickRects.length; _this.endTickRectId = id; var start = startTickRectId / ticksLength; var end = id / ticksLength; _this.graph.emit(VALUE_CHANGE, { value: [start, end] }); }); sliceGroup.on('drop', function (e) { if (!_this.dragging) return; _this.dragging = false; if (e.target.get('type') !== 'rect') return; var startTickRectId = _this.startTickRectId; var id = parseInt(e.target.get('name').split('-')[2], 10); if (id < startTickRectId) return; var selectedTickStyle = _this.selectedTickStyle; var tickRects = _this.tickRects; tickRects[id].rect.attr(selectedTickStyle); _this.endTickRectId = id; var ticksLength = tickRects.length; var start = startTickRectId / ticksLength; var end = id / ticksLength; _this.graph.emit(VALUE_CHANGE, { value: [start, end] }); }); // tooltip var _a = this, tooltipBackgroundColor = _a.tooltipBackgroundColor, tooltipFomatter = _a.tooltipFomatter, canvas = _a.canvas; var tooltip = new TimeBarTooltip({ container: canvas.get('container'), backgroundColor: tooltipBackgroundColor }); var tickRects = this.tickRects; tickRects.forEach(function (tickRect) { var pickRect = tickRect.pickRect; pickRect.on('mouseenter', function (e) { var rect = e.target; if (rect.get('type') !== 'rect') return; var id = parseInt(rect.get('name').split('-')[2], 10); var clientPoint = canvas.getClientByPoint(tickRects[id].x, tickRects[id].y); tooltip.show({ x: tickRects[id].x, y: tickRects[id].y, clientX: clientPoint.x, clientY: clientPoint.y, text: tooltipFomatter ? tooltipFomatter(tickRects[id].value) : tickRects[id].value }); }); pickRect.on('mouseleave', function (e) { tooltip.hide(); }); }); // play controller events var group = this.group; // 播放区按钮控制 /** 播放/暂停事件 */ group.on("".concat(PLAY_PAUSE_BTN, ":click"), function () { _this.isPlay = !_this.isPlay; _this.changePlayStatus(); }); // 处理前进一步的事件 group.on("".concat(NEXT_STEP_BTN, ":click"), function () { _this.updateStartEnd(1); }); // 处理后退一步的事件 group.on("".concat(PRE_STEP_BTN, ":click"), function () { _this.updateStartEnd(-1); }); group.on(TIMEBAR_CONFIG_CHANGE, function (_a) { var type = _a.type, speed = _a.speed; _this.currentSpeed = speed; }); }; TimeBarSlice.prototype.changePlayStatus = function (isSync) { if (isSync === void 0) { isSync = true; } this.controllerBtnGroup.playButton.update({ isPlay: this.isPlay }); if (this.isPlay) { // 开始播放 this.playHandler = this.startPlay(); this.graph.emit(TIMELINE_START, null); } else { // 结束播放 if (this.playHandler) { if (typeof window !== 'undefined') window.cancelAnimationFrame(this.playHandler); if (isSync) { this.graph.emit(TIMELINE_END, null); } } } }; TimeBarSlice.prototype.startPlay = function () { var _this = this; return typeof window !== 'undefined' ? window.requestAnimationFrame(function () { var speed = _this.currentSpeed; // 一分钟刷新一次 if (_this.frameCount % (60 / speed) === 0) { _this.frameCount = 0; _this.updateStartEnd(1); } _this.frameCount++; if (_this.isPlay) { _this.playHandler = _this.startPlay(); } }) : undefined; }; TimeBarSlice.prototype.updateStartEnd = function (sign) { var self = this; var tickRects = this.tickRects; var ticksLength = tickRects.length; var unselectedTickStyle = this.unselectedTickStyle; var selectedTickStyle = this.selectedTickStyle; var previousEndTickRectId = self.endTickRectId; if (sign > 0) { self.endTickRectId++; } else { tickRects[self.endTickRectId].rect.attr(unselectedTickStyle); self.endTickRectId--; } // 若此时 start 与 end 不同,范围前进/后退/播放 if (previousEndTickRectId !== self.startTickRectId) { if (self.endTickRectId < self.startTickRectId) { self.startTickRectId = self.endTickRectId; } } else { // 否则是单帧的前进/后退/播放 for (var i = self.startTickRectId; i <= self.endTickRectId - 1; i++) { tickRects[i].rect.attr(unselectedTickStyle); } self.startTickRectId = self.endTickRectId; } if (tickRects[self.endTickRectId]) { tickRects[self.endTickRectId].rect.attr(selectedTickStyle); var start = self.startTickRectId / ticksLength; var end = self.endTickRectId / ticksLength; this.graph.emit(VALUE_CHANGE, { value: [start, end] }); } }; TimeBarSlice.prototype.destory = function () { var group = this.sliceGroup; group.off('click'); group.off('dragstart'); group.off('dragover'); group.off('drop'); this.tickRects.forEach(function (tickRect) { var pickRect = tickRect.pickRect; pickRect.off('mouseenter'); pickRect.off('mouseleave'); }); this.tickRects.length = 0; group.off("".concat(PLAY_PAUSE_BTN, ":click")); group.off("".concat(NEXT_STEP_BTN, ":click")); group.off("".concat(PRE_STEP_BTN, ":click")); group.off(TIMEBAR_CONFIG_CHANGE); this.sliceGroup.destroy(); }; return TimeBarSlice; }(); export default TimeBarSlice;