- Go backend (server/)
- Frontend (web/, server/static/)
- Database and deployment files
- Scripts and docs
Co-Authored-By: 狸花猫/Claude-Qwen3.6-Plus 🐾
784 lines
26 KiB
JavaScript
784 lines
26 KiB
JavaScript
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);
|
||
};
|
||
import { get, size, assign, each, isNumber } from '@antv/util';
|
||
import { ext } from '@antv/matrix-util';
|
||
import Trend from './trend';
|
||
import Handler from './handler';
|
||
import { isString } from '@antv/util';
|
||
import ControllerBtn, { TIME_TYPE } from './controllerBtn';
|
||
import { VALUE_CHANGE, TIMELINE_START, TIMEBAR_CONFIG_CHANGE, PLAY_PAUSE_BTN, NEXT_STEP_BTN, PRE_STEP_BTN, TIMELINE_END } from './constant';
|
||
var transform = ext.transform;
|
||
/**
|
||
* 一些默认的样式配置
|
||
*/
|
||
export var BACKGROUND_STYLE = {
|
||
fill: '#416180',
|
||
opacity: 0.05
|
||
};
|
||
var SIMPLE_BACKGROUND_STYLE = {
|
||
fill: '#416180',
|
||
opacity: 0.15,
|
||
radius: 5
|
||
};
|
||
export var FOREGROUND_STYLE = {
|
||
fill: '#5B8FF9',
|
||
opacity: 0.3,
|
||
cursor: 'grab'
|
||
};
|
||
export var DEFAULT_HANDLER_WIDTH = 2;
|
||
export var HANDLER_STYLE = {
|
||
width: DEFAULT_HANDLER_WIDTH,
|
||
height: 24
|
||
};
|
||
export var TEXT_STYLE = {
|
||
textBaseline: 'middle',
|
||
fill: '#000',
|
||
opacity: 0.45
|
||
};
|
||
export var TICK_LABEL_STYLE = {
|
||
textAlign: 'center',
|
||
textBaseline: 'top',
|
||
fill: '#607889',
|
||
opacity: 0.35
|
||
};
|
||
export var TICK_LINE_STYLE = {
|
||
lineWidth: 1,
|
||
stroke: '#ccc'
|
||
};
|
||
var TrendTimeBar = /** @class */function () {
|
||
function TrendTimeBar(cfg) {
|
||
var _this = this;
|
||
this.prevX = 0;
|
||
this.onMouseDown = function (handler) {
|
||
return function (e) {
|
||
// 1. 记录点击的滑块
|
||
_this.currentHandler = handler;
|
||
var event = e.originalEvent;
|
||
// 2. 存储当前点击位置
|
||
event.stopPropagation();
|
||
event.preventDefault();
|
||
// 兼容移动端获取数据
|
||
_this.prevX = get(event, 'touches.0.pageX', event.pageX);
|
||
// 3. 开始滑动的时候,绑定 move 和 up 事件
|
||
var containerDOM = _this.canvas.get('container');
|
||
containerDOM.addEventListener('mousemove', _this.onMouseMove);
|
||
containerDOM.addEventListener('mouseup', _this.onMouseUp);
|
||
containerDOM.addEventListener('mouseleave', _this.onMouseUp);
|
||
// 移动端事件
|
||
containerDOM.addEventListener('touchmove', _this.onMouseMove);
|
||
containerDOM.addEventListener('touchend', _this.onMouseUp);
|
||
containerDOM.addEventListener('touchcancel', _this.onMouseUp);
|
||
};
|
||
};
|
||
this.onMouseMove = function (e) {
|
||
// 滑动过程中,计算偏移,更新滑块,然后 emit 数据出去
|
||
e.stopPropagation();
|
||
e.preventDefault();
|
||
var x = get(e, 'touches.0.pageX', e.pageX);
|
||
// 横向的 slider 只处理 x
|
||
var offsetX = x - _this.prevX;
|
||
var offsetXRange = _this.adjustOffsetRange(offsetX / _this.width);
|
||
// 更新 start end range 范围
|
||
_this.updateStartEnd(offsetXRange);
|
||
// 更新 ui
|
||
_this.updateUI();
|
||
_this.prevX = x;
|
||
};
|
||
this.onMouseUp = function () {
|
||
// 结束之后,取消绑定的事件
|
||
if (_this.currentHandler) {
|
||
_this.currentHandler = undefined;
|
||
}
|
||
var containerDOM = _this.canvas.get('container');
|
||
if (containerDOM) {
|
||
containerDOM.removeEventListener('mousemove', _this.onMouseMove);
|
||
containerDOM.removeEventListener('mouseup', _this.onMouseUp);
|
||
// 防止滑动到 canvas 外部之后,状态丢失
|
||
containerDOM.removeEventListener('mouseleave', _this.onMouseUp);
|
||
// 移动端事件
|
||
containerDOM.removeEventListener('touchmove', _this.onMouseMove);
|
||
containerDOM.removeEventListener('touchend', _this.onMouseUp);
|
||
containerDOM.removeEventListener('touchcancel', _this.onMouseUp);
|
||
}
|
||
};
|
||
var _a = cfg.x,
|
||
x = _a === void 0 ? 0 : _a,
|
||
_b = cfg.y,
|
||
y = _b === void 0 ? 0 : _b,
|
||
_c = cfg.width,
|
||
width = _c === void 0 ? 100 : _c,
|
||
height = cfg.height,
|
||
_d = cfg.padding,
|
||
padding = _d === void 0 ? 10 : _d,
|
||
trendCfg = cfg.trendCfg,
|
||
_e = cfg.controllerCfg,
|
||
controllerCfg = _e === void 0 ? {
|
||
speed: 1
|
||
} : _e,
|
||
_f = cfg.backgroundStyle,
|
||
backgroundStyle = _f === void 0 ? {} : _f,
|
||
_g = cfg.foregroundStyle,
|
||
foregroundStyle = _g === void 0 ? {} : _g,
|
||
_h = cfg.handlerStyle,
|
||
handlerStyle = _h === void 0 ? {} : _h,
|
||
_j = cfg.textStyle,
|
||
textStyle = _j === void 0 ? {} : _j,
|
||
// 缩略轴的初始位置
|
||
_k = cfg.start,
|
||
// 缩略轴的初始位置
|
||
start = _k === void 0 ? 0 : _k,
|
||
_l = cfg.end,
|
||
end = _l === void 0 ? 1 : _l,
|
||
_m = cfg.minText,
|
||
minText = _m === void 0 ? '' : _m,
|
||
_o = cfg.maxText,
|
||
maxText = _o === void 0 ? '' : _o,
|
||
group = cfg.group,
|
||
graph = cfg.graph,
|
||
canvas = cfg.canvas,
|
||
_p = cfg.tick,
|
||
tick = _p === void 0 ? {
|
||
tickLabelStyle: {},
|
||
tickLineStyle: {},
|
||
tickLabelFormatter: function tickLabelFormatter(d) {
|
||
return d;
|
||
},
|
||
ticks: []
|
||
} : _p,
|
||
type = cfg.type;
|
||
this.graph = graph;
|
||
this.canvas = canvas;
|
||
this.group = group;
|
||
this.timeBarType = type;
|
||
// position size
|
||
this.x = x;
|
||
this.y = y;
|
||
this.width = width;
|
||
this.height = height;
|
||
this.padding = padding;
|
||
this.ticks = tick.ticks;
|
||
this.trendCfg = trendCfg;
|
||
this.controllerCfg = controllerCfg;
|
||
this.currentSpeed = controllerCfg.speed || 1;
|
||
this.tickLabelFormatter = tick.tickLabelFormatter;
|
||
// style
|
||
if (type === 'trend') {
|
||
this.backgroundStyle = __assign(__assign({}, BACKGROUND_STYLE), backgroundStyle);
|
||
} else if (type === 'simple') {
|
||
this.backgroundStyle = __assign(__assign({}, SIMPLE_BACKGROUND_STYLE), backgroundStyle);
|
||
}
|
||
this.foregroundStyle = __assign(__assign({}, FOREGROUND_STYLE), foregroundStyle);
|
||
this.handlerStyle = __assign(__assign({}, HANDLER_STYLE), handlerStyle);
|
||
this.textStyle = __assign(__assign({}, TEXT_STYLE), textStyle);
|
||
this.tickLabelStyle = __assign(__assign({}, TICK_LABEL_STYLE), tick.tickLabelStyle);
|
||
this.tickLineStyle = __assign(__assign({}, TICK_LINE_STYLE), tick.tickLineStyle);
|
||
this.currentMode = controllerCfg.defaultTimeType || TIME_TYPE.RANGE;
|
||
// 初始信息
|
||
this.start = start;
|
||
this.end = end;
|
||
this.minText = minText;
|
||
this.maxText = maxText;
|
||
// 初始化 fontFamily,如果有浏览器,取 body 上的字体,防止文字更新时局部渲染造成的重影
|
||
this.fontFamily = typeof window !== 'undefined' ? window.getComputedStyle(document.body, null).getPropertyValue('font-family') || 'Arial, sans-serif' : 'Arial, sans-serif';
|
||
this.renderSlider();
|
||
}
|
||
/**
|
||
* 更新配置
|
||
* @param cfg
|
||
*/
|
||
TrendTimeBar.prototype.update = function (cfg) {
|
||
var x = cfg.x,
|
||
y = cfg.y,
|
||
width = cfg.width,
|
||
height = cfg.height,
|
||
minText = cfg.minText,
|
||
maxText = cfg.maxText,
|
||
start = cfg.start,
|
||
end = cfg.end;
|
||
// start、end 只能是 0~1 范围
|
||
this.start = Math.min(1, Math.max(start, 0));
|
||
this.end = Math.min(1, Math.max(end, 0));
|
||
// 如果传了则更新,没有传则不更新
|
||
// @ts-ignore
|
||
assign(this, {
|
||
x: x,
|
||
y: y,
|
||
width: width,
|
||
height: height,
|
||
minText: minText,
|
||
maxText: maxText
|
||
});
|
||
// 更新 ui,不自动绘制
|
||
this.updateUI();
|
||
};
|
||
TrendTimeBar.prototype.setText = function (minText, maxText) {
|
||
this.minTextShape.attr('text', minText);
|
||
this.maxTextShape.attr('text', maxText);
|
||
};
|
||
/**
|
||
* 初始化组件结构
|
||
* @private
|
||
*/
|
||
TrendTimeBar.prototype.renderSlider = function () {
|
||
var _this = this;
|
||
var _a = this,
|
||
width = _a.width,
|
||
height = _a.height,
|
||
timeBarType = _a.timeBarType;
|
||
// 趋势图数据
|
||
if (timeBarType === 'trend' && size(get(this.trendCfg, 'data'))) {
|
||
var trendComponent = new Trend(__assign(__assign({
|
||
x: this.x,
|
||
y: this.y,
|
||
width: width,
|
||
height: height
|
||
}, this.trendCfg), {
|
||
group: this.group
|
||
}));
|
||
this.trendComponent = trendComponent;
|
||
}
|
||
var sliderGroup = this.group.addGroup({
|
||
name: 'slider-group'
|
||
});
|
||
// 1. 背景
|
||
sliderGroup.addShape('rect', {
|
||
attrs: __assign({
|
||
x: 0,
|
||
y: 0,
|
||
width: width,
|
||
height: height
|
||
}, this.backgroundStyle),
|
||
name: 'background'
|
||
});
|
||
var textGroup = this.group.addGroup();
|
||
// 2. 左右文字
|
||
if (timeBarType === 'trend') {
|
||
this.minTextShape = textGroup.addShape('text', {
|
||
attrs: __assign({
|
||
x: 0,
|
||
y: height / 2 + this.y,
|
||
textAlign: 'right',
|
||
text: this.minText,
|
||
silent: false,
|
||
fontFamily: this.fontFamily || 'Arial, sans-serif',
|
||
stroke: '#fff',
|
||
lineWidth: 5
|
||
}, this.textStyle),
|
||
capture: false,
|
||
name: 'min-text-shape'
|
||
});
|
||
this.maxTextShape = textGroup.addShape('text', {
|
||
attrs: __assign({
|
||
y: height / 2 + this.y,
|
||
textAlign: 'left',
|
||
text: this.maxText,
|
||
silent: false,
|
||
fontFamily: this.fontFamily || 'Arial, sans-serif',
|
||
stroke: '#fff',
|
||
lineWidth: 5
|
||
}, this.textStyle),
|
||
capture: false,
|
||
name: 'max-text-shape'
|
||
});
|
||
} else {
|
||
this.minTextShape = textGroup.addShape('text', {
|
||
attrs: __assign({
|
||
x: 0,
|
||
y: this.y - 10,
|
||
textAlign: 'center',
|
||
text: this.minText,
|
||
silent: false,
|
||
fontFamily: this.fontFamily || 'Arial, sans-serif',
|
||
stroke: '#fff',
|
||
lineWidth: 5
|
||
}, this.textStyle),
|
||
capture: false,
|
||
name: 'min-text-shape'
|
||
});
|
||
this.maxTextShape = textGroup.addShape('text', {
|
||
attrs: __assign({
|
||
y: this.y - 10,
|
||
textAlign: 'center',
|
||
text: this.maxText,
|
||
silent: false,
|
||
fontFamily: this.fontFamily || 'Arial, sans-serif',
|
||
stroke: '#fff',
|
||
lineWidth: 5
|
||
}, this.textStyle),
|
||
capture: false,
|
||
name: 'max-text-shape'
|
||
});
|
||
}
|
||
// 3. 前景 选中背景框
|
||
this.foregroundShape = this.group.addGroup().addShape('rect', {
|
||
attrs: __assign({
|
||
x: 0,
|
||
y: this.y,
|
||
height: height
|
||
}, this.foregroundStyle),
|
||
name: 'foreground-shape'
|
||
});
|
||
this.foregroundShape.on('mousedown', function (e) {
|
||
e.target.attr('cursor', 'grabbing');
|
||
});
|
||
this.foregroundShape.on('mouseup', function (e) {
|
||
e.target.attr('cursor', _this.foregroundStyle.cursor || 'grab');
|
||
});
|
||
// 滑块相关的大小信息
|
||
var handlerWidth = get(this.handlerStyle, 'width', 2);
|
||
var handlerHeight = get(this.handlerStyle, 'height', 24);
|
||
var minHandleGroup = this.group.addGroup({
|
||
name: 'minHandlerShape'
|
||
});
|
||
// 4. 左右滑块
|
||
this.minHandlerShape = new Handler({
|
||
name: 'minHandlerShape',
|
||
group: minHandleGroup,
|
||
type: timeBarType,
|
||
x: this.x,
|
||
y: this.y,
|
||
width: handlerWidth,
|
||
height: handlerHeight,
|
||
style: this.handlerStyle
|
||
});
|
||
var maxHandleGroup = this.group.addGroup({
|
||
name: 'maxHandlerShape'
|
||
});
|
||
this.maxHandlerShape = new Handler({
|
||
name: 'maxHandlerShape',
|
||
group: maxHandleGroup,
|
||
type: timeBarType,
|
||
x: this.x,
|
||
y: this.y,
|
||
width: handlerWidth,
|
||
height: handlerHeight,
|
||
style: this.handlerStyle
|
||
});
|
||
// 缩略图下面的时间刻度
|
||
var tickData = this.ticks;
|
||
var interval = width / (tickData.length - 1);
|
||
this.tickPosList = [];
|
||
if (this.textList && this.textList.length) {
|
||
this.textList.forEach(function (text) {
|
||
text.destroy();
|
||
});
|
||
}
|
||
var lastX = -Infinity;
|
||
var rotate = this.tickLabelStyle.rotate;
|
||
delete this.tickLabelStyle.rotate;
|
||
this.textList = tickData.map(function (data, index) {
|
||
_this.tickPosList.push(_this.x + index * interval);
|
||
var label;
|
||
if (_this.tickLabelFormatter) {
|
||
label = _this.tickLabelFormatter(data);
|
||
if (!isString(label) && label) {
|
||
// return true
|
||
label = data.date;
|
||
}
|
||
} else {
|
||
label = data.date;
|
||
}
|
||
// 文本刻度
|
||
var textX = _this.x + index * interval,
|
||
textY = _this.y + height + 5;
|
||
var text = _this.group.addShape('text', {
|
||
attrs: __assign({
|
||
x: textX,
|
||
y: textY,
|
||
text: label,
|
||
fontFamily: _this.fontFamily || 'Arial, sans-serif'
|
||
}, _this.tickLabelStyle),
|
||
name: 'tick-label'
|
||
});
|
||
if (isNumber(rotate) && index !== tickData.length - 1) {
|
||
var matrix = transform([1, 0, 0, 0, 1, 0, 0, 0, 1], [['t', -textX, -textY], ['r', rotate], ['t', textX - 5, textY + 2]]);
|
||
text.attr({
|
||
textAlign: 'left',
|
||
matrix: matrix
|
||
});
|
||
}
|
||
if (index === 0) {
|
||
text.attr({
|
||
textAlign: 'left'
|
||
});
|
||
} else if (index !== tickData.length - 1) {
|
||
text.attr({
|
||
textAlign: 'right'
|
||
});
|
||
}
|
||
// 文本刻度上面的竖线
|
||
var line = _this.group.addShape('line', {
|
||
attrs: __assign({
|
||
x1: _this.x + index * interval,
|
||
y1: _this.y + height + 2,
|
||
x2: _this.x + index * interval,
|
||
y2: _this.y + height + 6
|
||
}, _this.tickLineStyle),
|
||
name: 'tick-line'
|
||
});
|
||
line.toBack();
|
||
var bbox = text.getBBox();
|
||
// 抽样,标签与标签间距不小于 10
|
||
if (bbox.minX > lastX) {
|
||
text.show();
|
||
line.show();
|
||
lastX = bbox.minX + bbox.width + 10;
|
||
} else {
|
||
text.hide();
|
||
line.hide();
|
||
}
|
||
return text;
|
||
});
|
||
// 渲染播放、快进和后退的控制按钮
|
||
this.controllerBtnGroup = new ControllerBtn(__assign({
|
||
group: this.group,
|
||
x: this.x,
|
||
y: this.y + height + 25,
|
||
width: width,
|
||
height: 35
|
||
}, this.controllerCfg));
|
||
// 初始化 minText 和 maxText,方便计算它们的 bbox
|
||
this.updateStartEnd(0);
|
||
// 根据 start end 更新 ui 的位置信息
|
||
this.updateUI();
|
||
// 移动到对应的位置
|
||
sliderGroup.move(this.x, this.y);
|
||
// 绑定事件鼠标事件
|
||
this.bindEvents();
|
||
if (this.currentMode === TIME_TYPE.SINGLE) {
|
||
this.minHandlerShape.hide();
|
||
this.foregroundShape.hide();
|
||
this.minTextShape.hide();
|
||
}
|
||
};
|
||
/**
|
||
* 绑定事件:
|
||
* - 点击
|
||
* - 滑动
|
||
* - 拖拽
|
||
* - 滚动
|
||
* @private
|
||
*/
|
||
TrendTimeBar.prototype.bindEvents = function () {
|
||
var _this = this;
|
||
// 1. 左滑块的滑动
|
||
var minHandleShapeGroup = this.group.find(function (group) {
|
||
return group.get('name') === 'minHandlerShape';
|
||
});
|
||
if (minHandleShapeGroup) {
|
||
minHandleShapeGroup.on('minHandlerShape-handler:mousedown', this.onMouseDown(this.minHandlerShape));
|
||
minHandleShapeGroup.on('minHandlerShape-handler:touchstart', this.onMouseDown(this.minHandlerShape));
|
||
}
|
||
var maxHandleShapeGroup = this.group.find(function (group) {
|
||
return group.get('name') === 'maxHandlerShape';
|
||
});
|
||
// 2. 右滑块的滑动
|
||
if (maxHandleShapeGroup) {
|
||
maxHandleShapeGroup.on('maxHandlerShape-handler:mousedown', this.onMouseDown(this.maxHandlerShape));
|
||
maxHandleShapeGroup.on('maxHandlerShape-handler:touchstart', this.onMouseDown(this.maxHandlerShape));
|
||
}
|
||
// 3. 前景选中区域
|
||
this.foregroundShape.on('mousedown', this.onMouseDown(this.foregroundShape));
|
||
this.foregroundShape.on('touchstart', this.onMouseDown(this.foregroundShape));
|
||
// 播放区按钮控制
|
||
/** 播放/暂停事件 */
|
||
this.group.on("".concat(PLAY_PAUSE_BTN, ":click"), function () {
|
||
_this.isPlay = !_this.isPlay;
|
||
_this.currentHandler = _this.maxHandlerShape;
|
||
_this.changePlayStatus();
|
||
});
|
||
// 处理前进一步的事件
|
||
this.group.on("".concat(NEXT_STEP_BTN, ":click"), function () {
|
||
_this.currentHandler = _this.maxHandlerShape;
|
||
_this.updateStartEnd(0.01);
|
||
_this.updateUI();
|
||
});
|
||
// 处理后退一步的事件
|
||
this.group.on("".concat(PRE_STEP_BTN, ":click"), function () {
|
||
_this.currentHandler = _this.maxHandlerShape;
|
||
_this.updateStartEnd(-0.01);
|
||
_this.updateUI();
|
||
});
|
||
this.group.on(TIMEBAR_CONFIG_CHANGE, function (_a) {
|
||
var type = _a.type,
|
||
speed = _a.speed;
|
||
_this.currentSpeed = speed;
|
||
_this.currentMode = type;
|
||
if (type === TIME_TYPE.SINGLE) {
|
||
_this.minHandlerShape.hide();
|
||
_this.foregroundShape.hide();
|
||
_this.minTextShape.hide();
|
||
} else if (type === TIME_TYPE.RANGE) {
|
||
_this.minHandlerShape.show();
|
||
_this.foregroundShape.show();
|
||
_this.minTextShape.show();
|
||
}
|
||
});
|
||
};
|
||
/** 输入当前圆点位置,输出离哪个 tick 的位置最近 */
|
||
TrendTimeBar.prototype.adjustTickIndex = function (timeSelectX) {
|
||
for (var i = 0; i < this.tickPosList.length - 1; i++) {
|
||
if (this.tickPosList[i] <= timeSelectX && timeSelectX <= this.tickPosList[i + 1]) {
|
||
return Math.abs(this.tickPosList[i] - timeSelectX) < Math.abs(timeSelectX - this.tickPosList[i + 1]) ? i : i + 1;
|
||
}
|
||
}
|
||
return 0;
|
||
};
|
||
/**
|
||
* 调整 offsetRange,因为一些范围的限制
|
||
* @param offsetRange
|
||
*/
|
||
TrendTimeBar.prototype.adjustOffsetRange = function (offsetRange) {
|
||
// 针对不同的滑动组件,处理的方式不同
|
||
switch (this.currentHandler) {
|
||
case this.minHandlerShape:
|
||
{
|
||
var min = 0 - this.start;
|
||
var max = 1 - this.start;
|
||
return Math.min(max, Math.max(min, offsetRange));
|
||
}
|
||
case this.maxHandlerShape:
|
||
{
|
||
var min = 0 - this.end;
|
||
var max = 1 - this.end;
|
||
return Math.min(max, Math.max(min, offsetRange));
|
||
}
|
||
case this.foregroundShape:
|
||
{
|
||
var min = 0 - this.start;
|
||
var max = 1 - this.end;
|
||
return Math.min(max, Math.max(min, offsetRange));
|
||
}
|
||
default:
|
||
return 0;
|
||
}
|
||
};
|
||
/**
|
||
* 更新起始、结束的控制块位置、文本、范围值(原始值)
|
||
* @param offsetRange
|
||
*/
|
||
TrendTimeBar.prototype.updateStartEnd = function (offsetRange) {
|
||
var minData = this.ticks[this.adjustTickIndex(this.start * this.width)];
|
||
var maxData = this.ticks[this.adjustTickIndex(this.end * this.width)];
|
||
if (!this.currentHandler) {
|
||
this.minText = this.tickLabelFormatter ? this.tickLabelFormatter(minData) : minData === null || minData === void 0 ? void 0 : minData.date;
|
||
this.maxText = this.tickLabelFormatter ? this.tickLabelFormatter(maxData) : maxData === null || maxData === void 0 ? void 0 : maxData.date;
|
||
return;
|
||
}
|
||
// 操作不同的组件,反馈不一样
|
||
switch (this.currentHandler) {
|
||
case this.minHandlerShape:
|
||
// 拖动最小滑块时使用当前最大值设置最大值的文本,以便恢复到默认值
|
||
this.maxText = this.maxTextShape.attr('text');
|
||
this.start += offsetRange;
|
||
this.minText = this.tickLabelFormatter ? this.tickLabelFormatter(minData) : minData.date;
|
||
break;
|
||
case this.maxHandlerShape:
|
||
// 拖动最大滑块时使用当前最小值设置最小值的文本,以便恢复到默认值
|
||
this.minText = this.minTextShape.attr('text');
|
||
this.end += offsetRange;
|
||
this.maxText = this.tickLabelFormatter ? this.tickLabelFormatter(maxData) : maxData.date;
|
||
break;
|
||
case this.foregroundShape:
|
||
this.start += offsetRange;
|
||
this.end += offsetRange;
|
||
this.minText = this.tickLabelFormatter ? this.tickLabelFormatter(minData) : minData.date;
|
||
this.maxText = this.tickLabelFormatter ? this.tickLabelFormatter(maxData) : maxData.date;
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
};
|
||
/**
|
||
* 根据移动的比例来更新 ui,更新范围(0-1 范围的比例值)
|
||
* @private
|
||
*/
|
||
TrendTimeBar.prototype.updateUI = function () {
|
||
var _this = this;
|
||
if (this.start < 0) {
|
||
this.start = 0;
|
||
}
|
||
if (this.start > 1) {
|
||
this.start = 1;
|
||
}
|
||
if (this.end > 1) {
|
||
this.end = 1;
|
||
}
|
||
if (this.end < 0) {
|
||
this.end = 0;
|
||
}
|
||
var min = this.x + this.start * this.width;
|
||
var max = this.x + this.end * this.width;
|
||
// 1. foreground
|
||
this.foregroundShape.attr('x', min);
|
||
this.foregroundShape.attr('width', max - min);
|
||
// 滑块相关的大小信息
|
||
var handlerWidth = get(this.handlerStyle, 'width', DEFAULT_HANDLER_WIDTH);
|
||
// 设置文本
|
||
this.setText(this.minText, this.maxText);
|
||
var _a = this.dodgeText([min, max]),
|
||
minAttrs = _a[0],
|
||
maxAttrs = _a[1];
|
||
// 2. 左侧滑块和文字位置
|
||
this.minHandlerShape.setX(min - handlerWidth / 2);
|
||
each(minAttrs, function (v, k) {
|
||
return _this.minTextShape.attr(k, v);
|
||
});
|
||
// 3. 右侧滑块和文字位置
|
||
this.maxHandlerShape.setX(max - handlerWidth / 2);
|
||
each(maxAttrs, function (v, k) {
|
||
return _this.maxTextShape.attr(k, v);
|
||
});
|
||
if (this.currentMode === TIME_TYPE.RANGE) {
|
||
// 因为存储的 start、end 可能不一定是按大小存储的,所以排序一下,对外是 end >= start
|
||
this.graph.emit(VALUE_CHANGE, {
|
||
value: [this.start, this.end].sort()
|
||
});
|
||
} else if (this.currentMode === TIME_TYPE.SINGLE) {
|
||
this.graph.emit(VALUE_CHANGE, {
|
||
value: [this.end, this.end]
|
||
});
|
||
}
|
||
};
|
||
/**
|
||
* 调整 text 的位置,自动躲避
|
||
* 根据位置,调整返回新的位置
|
||
* @param range
|
||
*/
|
||
TrendTimeBar.prototype.dodgeText = function (range) {
|
||
var _a, _b;
|
||
var TEXTPADDING = 2;
|
||
var handlerWidth = get(this.handlerStyle, 'width', DEFAULT_HANDLER_WIDTH);
|
||
var minTextShape = this.minTextShape;
|
||
var maxTextShape = this.maxTextShape;
|
||
var min = range[0],
|
||
max = range[1];
|
||
var sorted = false;
|
||
// 如果交换了位置,则对应的 min max 也交换
|
||
if (min > max) {
|
||
_a = [max, min], min = _a[0], max = _a[1];
|
||
_b = [maxTextShape, minTextShape], minTextShape = _b[0], maxTextShape = _b[1];
|
||
sorted = true;
|
||
}
|
||
// 避让规则,优先显示在两侧,只有显示不下的时候,才显示在中间
|
||
var minBBox = minTextShape.getBBox();
|
||
var maxBBox = maxTextShape.getBBox();
|
||
var minAttrs = null;
|
||
var maxAttrs = null;
|
||
if (this.timeBarType === 'trend') {
|
||
minAttrs = min - minBBox.width < this.x + TEXTPADDING ? {
|
||
x: min + handlerWidth / 2 + TEXTPADDING,
|
||
textAlign: 'left'
|
||
} : {
|
||
x: min - handlerWidth / 2 - TEXTPADDING,
|
||
textAlign: 'right'
|
||
};
|
||
maxAttrs = max + maxBBox.width > this.x + this.width ? {
|
||
x: max - handlerWidth / 2 - TEXTPADDING,
|
||
textAlign: 'right'
|
||
} : {
|
||
x: max + handlerWidth / 2 + TEXTPADDING,
|
||
textAlign: 'left'
|
||
};
|
||
} else if (this.timeBarType === 'simple') {
|
||
minAttrs = minTextShape.attr('x') > minBBox.width // 左边滑块文本位置小于其宽度代表文字超过左边届
|
||
? {
|
||
x: min,
|
||
textAlign: 'center'
|
||
} : {
|
||
x: min,
|
||
textAlign: 'left'
|
||
};
|
||
maxAttrs = maxTextShape.attr('x') > this.width - maxBBox.width // 有边滑块文本位置大于宽度代表文字超过右边界
|
||
? {
|
||
x: max,
|
||
textAlign: 'right'
|
||
} : {
|
||
x: max,
|
||
textAlign: 'center'
|
||
};
|
||
}
|
||
return !sorted ? [minAttrs, maxAttrs] : [maxAttrs, minAttrs];
|
||
};
|
||
TrendTimeBar.prototype.startPlay = function () {
|
||
var _this = this;
|
||
return typeof window !== 'undefined' ? window.requestAnimationFrame(function () {
|
||
var _a = _this,
|
||
ticks = _a.ticks,
|
||
width = _a.width;
|
||
var speed = _this.currentSpeed;
|
||
var tickInterval = width / ticks.length;
|
||
var offsetX = tickInterval / ((10 - speed) * 1000 / 60);
|
||
var offsetXRange = _this.adjustOffsetRange(offsetX / _this.width);
|
||
_this.updateStartEnd(offsetXRange);
|
||
_this.updateUI();
|
||
if (_this.isPlay) {
|
||
_this.playHandler = _this.startPlay();
|
||
}
|
||
}) : undefined;
|
||
};
|
||
TrendTimeBar.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);
|
||
}
|
||
}
|
||
}
|
||
};
|
||
TrendTimeBar.prototype.destory = function () {
|
||
this.graph.off(VALUE_CHANGE, function () {});
|
||
var group = this.group;
|
||
var minHandleShapeGroup = group.find(function (g) {
|
||
return g.get('name') === 'minHandlerShape';
|
||
});
|
||
if (minHandleShapeGroup) {
|
||
minHandleShapeGroup.off('minHandlerShape-handler:mousedown');
|
||
minHandleShapeGroup.off('minHandlerShape-handler:touchstart');
|
||
minHandleShapeGroup.destroy();
|
||
}
|
||
var maxHandleShapeGroup = group.find(function (g) {
|
||
return g.get('name') === 'maxHandlerShape';
|
||
});
|
||
// 2. 右滑块的滑动
|
||
if (maxHandleShapeGroup) {
|
||
maxHandleShapeGroup.off('maxHandlerShape-handler:mousedown');
|
||
maxHandleShapeGroup.off('maxHandlerShape-handler:touchstart');
|
||
maxHandleShapeGroup.destroy();
|
||
}
|
||
// 3. 前景选中区域
|
||
this.foregroundShape.off('mousedown');
|
||
this.foregroundShape.off('touchstart');
|
||
this.foregroundShape.destroy();
|
||
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);
|
||
group.destroy();
|
||
if (this.trendComponent) {
|
||
this.trendComponent.destory();
|
||
}
|
||
};
|
||
return TrendTimeBar;
|
||
}();
|
||
export default TrendTimeBar; |