- Go backend (server/)
- Frontend (web/, server/static/)
- Database and deployment files
- Scripts and docs
Co-Authored-By: 狸花猫/Claude-Qwen3.6-Plus 🐾
400 lines
15 KiB
JavaScript
400 lines
15 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 { deepMix } from '@antv/util';
|
||
import { ext } from '@antv/matrix-util';
|
||
import Button from './timeButton';
|
||
import { TIMEBAR_CONFIG_CHANGE, PRE_STEP_BTN, NEXT_STEP_BTN } from './constant';
|
||
var transform = ext.transform;
|
||
var DEFAULT_RECT_FILL = '#aaa';
|
||
var DEFAULT_RECT_STROKE = 'green';
|
||
var DEFAULT_PLAYBTN_STYLE = {
|
||
fill: '#aaa',
|
||
fillOpacity: 0.35,
|
||
stroke: '#aaa'
|
||
};
|
||
var DEFAULT_PREBTN_STYLE = {
|
||
fill: '#fff'
|
||
};
|
||
var DEFAULT_NEXTBTN_STYLE = {
|
||
fill: 'green'
|
||
};
|
||
var DEFAULT_SPEED_CONTROLLER_STYLE = {
|
||
pointer: {
|
||
fill: '#aaa',
|
||
lineWidth: 0
|
||
},
|
||
scroller: {
|
||
stroke: '#aaa',
|
||
fill: '#aaa',
|
||
lineWidth: 1,
|
||
lineAppendWidth: 5,
|
||
cursor: 'pointer'
|
||
},
|
||
text: {
|
||
fill: '#aaa',
|
||
textBaseline: 'top'
|
||
}
|
||
};
|
||
var DEFAULT_TIMETYPE_CONTROLLER_STYLE = {
|
||
check: {
|
||
stroke: 'green',
|
||
lineWidth: 3
|
||
},
|
||
box: {
|
||
fill: '#fff',
|
||
stroke: '#aaa',
|
||
lineWidth: 2,
|
||
radius: 3,
|
||
width: 12,
|
||
height: 12
|
||
},
|
||
text: {
|
||
fill: '#aaa',
|
||
fontSize: 12,
|
||
textBaseline: 'top'
|
||
}
|
||
};
|
||
var DEFAULT_CONTROLLER_CONFIG = {
|
||
speed: 1,
|
||
loop: false,
|
||
fill: '#fff',
|
||
stroke: '#fff',
|
||
hideTimeTypeController: false,
|
||
preBtnStyle: {
|
||
fill: '#aaa',
|
||
stroke: '#aaa'
|
||
},
|
||
nextBtnStyle: {
|
||
fill: '#aaa',
|
||
stroke: '#aaa'
|
||
},
|
||
playBtnStyle: {
|
||
fill: '#aaa',
|
||
stroke: '#aaa',
|
||
fillOpacity: 0.05
|
||
},
|
||
speedControllerStyle: DEFAULT_SPEED_CONTROLLER_STYLE,
|
||
timeTypeControllerStyle: DEFAULT_TIMETYPE_CONTROLLER_STYLE
|
||
};
|
||
var SPEED_CONTROLLER_OFFSET = 110;
|
||
var TOGGLE_MODEL_OFFSET = 50;
|
||
export var TIME_TYPE = {
|
||
SINGLE: 'single',
|
||
RANGE: 'range'
|
||
};
|
||
var ControllerBtn = /** @class */function () {
|
||
function ControllerBtn(cfg) {
|
||
this.controllerCfg = deepMix({}, DEFAULT_CONTROLLER_CONFIG, cfg);
|
||
this.group = cfg.group;
|
||
this.controllerGroup = this.group.addGroup({
|
||
name: 'controller-group'
|
||
});
|
||
this.speedAxisY = [];
|
||
this.currentSpeed = this.controllerCfg.speed;
|
||
this.currentType = this.controllerCfg.defaultTimeType || TIME_TYPE.RANGE;
|
||
this.fontFamily = cfg.fontFamily || 'Arial, sans-serif';
|
||
this.init();
|
||
}
|
||
ControllerBtn.prototype.init = function () {
|
||
this.renderPlayButton();
|
||
};
|
||
/** 获取播放键 marker path */
|
||
ControllerBtn.prototype.getNextMarkerPath = function (x, y, len) {
|
||
return [['M', x, y - len], ['L', x + len, y], ['L', x, y + len], ['Z', x, y - len], ['M', x, y], ['L', x - len, y - len], ['L', x - len, y + len], ['Z']];
|
||
};
|
||
ControllerBtn.prototype.getPreMarkerPath = function (x, y, len) {
|
||
return [['M', x, y - len], ['L', x - len, y], ['L', x, y + len], ['L', x, y - len], ['M', x, y], ['L', x + len, y - len], ['L', x + len, y + len], ['Z']];
|
||
};
|
||
ControllerBtn.prototype.renderPlayButton = function () {
|
||
var controllerCfg = this.controllerCfg;
|
||
var width = controllerCfg.width,
|
||
height = controllerCfg.height,
|
||
x = controllerCfg.x,
|
||
y = controllerCfg.y,
|
||
hideTimeTypeController = controllerCfg.hideTimeTypeController,
|
||
_a = controllerCfg.fill,
|
||
fill = _a === void 0 ? DEFAULT_RECT_FILL : _a,
|
||
_b = controllerCfg.stroke,
|
||
stroke = _b === void 0 ? DEFAULT_RECT_STROKE : _b,
|
||
_c = controllerCfg.containerStyle,
|
||
containerStyle = _c === void 0 ? {} : _c;
|
||
var playBtnStyle = __assign(__assign({}, DEFAULT_PLAYBTN_STYLE), controllerCfg.playBtnStyle || {});
|
||
var preBtnStyle = __assign(__assign({}, DEFAULT_PREBTN_STYLE), controllerCfg.preBtnStyle || {});
|
||
var nextBtnStyle = __assign(__assign({}, DEFAULT_NEXTBTN_STYLE), controllerCfg.nextBtnStyle || {});
|
||
var r = height / 2 - 5;
|
||
var realY = y + 10;
|
||
// 绘制最外层的矩形包围框
|
||
var container = this.controllerGroup.addShape('rect', {
|
||
attrs: __assign({
|
||
x: x,
|
||
y: realY,
|
||
width: width,
|
||
height: height,
|
||
stroke: stroke,
|
||
fill: fill
|
||
}, containerStyle),
|
||
name: 'container-rect'
|
||
});
|
||
if (this.playButton) {
|
||
this.playButton.update({
|
||
x: width / 2,
|
||
y: realY,
|
||
r: r
|
||
});
|
||
} else {
|
||
this.playButton = new Button({
|
||
group: this.controllerGroup,
|
||
x: width / 2,
|
||
y: realY + r + 5,
|
||
r: r,
|
||
isPlay: this.isPlay,
|
||
style: playBtnStyle
|
||
});
|
||
}
|
||
// 后退按钮
|
||
var prePaddingX = preBtnStyle.offsetX || 0;
|
||
var prePaddingY = preBtnStyle.offsetY || 0;
|
||
var preR = (preBtnStyle.scale || 1) * r;
|
||
this.controllerGroup.addShape('path', {
|
||
attrs: __assign({
|
||
path: this.getPreMarkerPath(width / 2 - 5 * r + prePaddingX, realY + r + 5 + prePaddingY, preR * 0.5)
|
||
}, preBtnStyle),
|
||
name: PRE_STEP_BTN
|
||
});
|
||
// 前进按钮
|
||
var nxtPaddingX = nextBtnStyle.offsetX || 0;
|
||
var nxtPaddingY = nextBtnStyle.offsetY || 0;
|
||
var nxtR = (nextBtnStyle.scale || 1) * r;
|
||
this.controllerGroup.addShape('path', {
|
||
attrs: __assign({
|
||
path: this.getNextMarkerPath(width / 2 + 5 * r + nxtPaddingX, realY + r + 5 + nxtPaddingY, nxtR * 0.5)
|
||
}, nextBtnStyle),
|
||
name: NEXT_STEP_BTN
|
||
});
|
||
container.toBack();
|
||
// 调节speed的按钮
|
||
this.renderSpeedBtn();
|
||
if (!hideTimeTypeController) {
|
||
this.renderToggleTime();
|
||
}
|
||
this.bindEvent();
|
||
// 根据配置的 scale、offsetX,offsetY 缩放和移动控制栏
|
||
var _d = this.controllerCfg.scale,
|
||
scale = _d === void 0 ? 1 : _d;
|
||
var currentBBox = this.controllerGroup.getCanvasBBox();
|
||
var centerX = (currentBBox.maxX + currentBBox.minX) / 2;
|
||
var centerY = (currentBBox.maxY + currentBBox.minY) / 2;
|
||
var matrix = transform([1, 0, 0, 0, 1, 0, 0, 0, 1], [['t', -centerX, -centerY], ['s', scale, scale], ['t', centerX, centerY]]);
|
||
this.controllerGroup.setMatrix(matrix);
|
||
};
|
||
ControllerBtn.prototype.renderSpeedBtn = function () {
|
||
var _a = this.controllerCfg,
|
||
y = _a.y,
|
||
width = _a.width,
|
||
hideTimeTypeController = _a.hideTimeTypeController;
|
||
var speedControllerStyle = __assign(__assign({}, DEFAULT_SPEED_CONTROLLER_STYLE), this.controllerCfg.speedControllerStyle || {});
|
||
var _b = speedControllerStyle.scroller,
|
||
scroller = _b === void 0 ? {} : _b,
|
||
_c = speedControllerStyle.text,
|
||
text = _c === void 0 ? {} : _c,
|
||
_d = speedControllerStyle.pointer,
|
||
pointer = _d === void 0 ? {} : _d,
|
||
_e = speedControllerStyle.scale,
|
||
scale = _e === void 0 ? 1 : _e,
|
||
_f = speedControllerStyle.offsetX,
|
||
offsetX = _f === void 0 ? 0 : _f,
|
||
_g = speedControllerStyle.offsetY,
|
||
offsetY = _g === void 0 ? 0 : _g;
|
||
var speedGroup = this.controllerGroup.addGroup({
|
||
name: 'speed-group'
|
||
});
|
||
this.speedGroup = speedGroup;
|
||
var speedNum = [];
|
||
var maxSpeed = 5;
|
||
this.speedAxisY = [19, 22, 26, 32, 39];
|
||
// 增加speed刻度
|
||
for (var i = 0; i < 5; i++) {
|
||
var axisY = y + this.speedAxisY[i];
|
||
// 灰色刻度
|
||
var startX = width - (!hideTimeTypeController ? SPEED_CONTROLLER_OFFSET : TOGGLE_MODEL_OFFSET);
|
||
speedGroup.addShape('line', {
|
||
attrs: __assign({
|
||
x1: startX,
|
||
x2: startX + 15,
|
||
y1: axisY,
|
||
y2: axisY
|
||
}, scroller),
|
||
speed: maxSpeed,
|
||
name: 'speed-rect'
|
||
});
|
||
this.speedAxisY[i] = axisY;
|
||
speedNum.push(maxSpeed);
|
||
maxSpeed = maxSpeed - 1;
|
||
}
|
||
// 速度文本
|
||
this.speedText = speedGroup.addShape('text', {
|
||
attrs: __assign({
|
||
x: width - (!hideTimeTypeController ? SPEED_CONTROLLER_OFFSET : TOGGLE_MODEL_OFFSET) + 20,
|
||
y: this.speedAxisY[0] + 4,
|
||
text: "1.0X",
|
||
fontFamily: this.fontFamily || 'Arial, sans-serif'
|
||
}, text),
|
||
name: 'speed-text'
|
||
});
|
||
this.speedPoint = speedGroup.addShape('path', {
|
||
attrs: __assign({
|
||
path: this.getPointerPath(width - (!hideTimeTypeController ? SPEED_CONTROLLER_OFFSET : TOGGLE_MODEL_OFFSET), 0),
|
||
matrix: [1, 0, 0, 0, 1, 0, 0, this.speedAxisY[4], 1]
|
||
}, pointer),
|
||
name: 'speed-pointer'
|
||
});
|
||
// 根据配置在 speedControllerStyle 中的 scale offsetX offsetY 缩放和移动速度控制器
|
||
var currentBBox = this.speedGroup.getCanvasBBox();
|
||
var centerX = (currentBBox.maxX + currentBBox.minX) / 2;
|
||
var centerY = (currentBBox.maxY + currentBBox.minY) / 2;
|
||
var matrix = this.speedGroup.getMatrix() || [1, 0, 0, 0, 1, 0, 0, 0, 1];
|
||
matrix = transform(matrix, [['t', -centerX, -centerY], ['s', scale, scale], ['t', centerX + offsetX * scale, centerY + offsetY * scale]]);
|
||
this.speedGroup.setMatrix(matrix);
|
||
};
|
||
ControllerBtn.prototype.getPointerPath = function (x, y) {
|
||
return [['M', x, y], ['L', x - 10, y - 4], ['L', x - 10, y + 4], ['Z']];
|
||
};
|
||
ControllerBtn.prototype.renderToggleTime = function () {
|
||
var _a, _b;
|
||
var _c = this.controllerCfg,
|
||
width = _c.width,
|
||
defaultTimeType = _c.defaultTimeType;
|
||
var timeTypeControllerStyle = __assign(__assign({}, DEFAULT_TIMETYPE_CONTROLLER_STYLE), this.controllerCfg.timeTypeControllerStyle || {});
|
||
var _d = timeTypeControllerStyle.scale,
|
||
scale = _d === void 0 ? 1 : _d,
|
||
_e = timeTypeControllerStyle.offsetX,
|
||
offsetX = _e === void 0 ? 0 : _e,
|
||
_f = timeTypeControllerStyle.offsetY,
|
||
offsetY = _f === void 0 ? 0 : _f,
|
||
_g = timeTypeControllerStyle.box,
|
||
box = _g === void 0 ? {} : _g,
|
||
_h = timeTypeControllerStyle.check,
|
||
check = _h === void 0 ? {} : _h,
|
||
_j = timeTypeControllerStyle.text,
|
||
text = _j === void 0 ? {} : _j;
|
||
this.toggleGroup = this.controllerGroup.addGroup({
|
||
name: 'toggle-group'
|
||
});
|
||
var isChecked = defaultTimeType === TIME_TYPE.SINGLE;
|
||
this.toggleGroup.addShape('rect', {
|
||
attrs: __assign({
|
||
x: width - TOGGLE_MODEL_OFFSET,
|
||
y: this.speedAxisY[0] + 3.5
|
||
}, box),
|
||
isChecked: isChecked,
|
||
name: 'toggle-model'
|
||
});
|
||
this.checkedIcon = this.toggleGroup.addShape('path', {
|
||
attrs: __assign({
|
||
path: [['M', width - TOGGLE_MODEL_OFFSET + 3, this.speedAxisY[1] + 6], ['L', width - TOGGLE_MODEL_OFFSET + 7, this.speedAxisY[1] + 10], ['L', width - TOGGLE_MODEL_OFFSET + 12, this.speedAxisY[1] + 4]]
|
||
}, check),
|
||
capture: false,
|
||
name: 'check-icon'
|
||
});
|
||
if (!isChecked) this.checkedIcon.hide();
|
||
this.checkedText = this.toggleGroup.addShape('text', {
|
||
attrs: __assign({
|
||
text: isChecked ? ((_a = this.controllerCfg) === null || _a === void 0 ? void 0 : _a.timeRangeControllerText) || '时间范围' : ((_b = this.controllerCfg) === null || _b === void 0 ? void 0 : _b.timePointControllerText) || '单一时间',
|
||
x: width - TOGGLE_MODEL_OFFSET + 15,
|
||
y: this.speedAxisY[0] + 4,
|
||
fontFamily: typeof window !== 'undefined' ? window.getComputedStyle(document.body, null).getPropertyValue('font-family') || 'Arial, sans-serif' : 'Arial, sans-serif'
|
||
}, text),
|
||
name: 'checked-text'
|
||
});
|
||
// 根据配置在 timeTypeControllerStyle 中的 scale offsetX offsetY 缩放和移动速度控制器
|
||
var currentBBox = this.toggleGroup.getCanvasBBox();
|
||
var centerX = (currentBBox.maxX + currentBBox.minX) / 2;
|
||
var centerY = (currentBBox.maxY + currentBBox.minY) / 2;
|
||
var matrix = this.toggleGroup.getMatrix() || [1, 0, 0, 0, 1, 0, 0, 0, 1];
|
||
matrix = transform(matrix, [['t', -centerX, -centerY], ['s', scale, scale], ['t', centerX + offsetX * scale, centerY + offsetY * scale]]);
|
||
this.toggleGroup.setMatrix(matrix);
|
||
};
|
||
ControllerBtn.prototype.bindEvent = function () {
|
||
var _this = this;
|
||
this.speedGroup.on('speed-rect:click', function (evt) {
|
||
var currentPointerY = evt.target.attr('y1');
|
||
var pointerMatrix = _this.speedPoint.attr('matrix');
|
||
var currentYIdx = _this.speedAxisY.indexOf(pointerMatrix[7] || 0);
|
||
var targetYIdx = _this.speedAxisY.indexOf(currentPointerY);
|
||
var yDiff = _this.speedAxisY[targetYIdx] - _this.speedAxisY[currentYIdx];
|
||
pointerMatrix = transform(pointerMatrix, [['t', 0, yDiff]]);
|
||
_this.speedPoint.setMatrix(pointerMatrix);
|
||
_this.currentSpeed = _this.speedAxisY.length - targetYIdx;
|
||
_this.speedText.attr('text', "".concat(_this.currentSpeed, ".0X"));
|
||
_this.group.emit(TIMEBAR_CONFIG_CHANGE, {
|
||
speed: _this.currentSpeed,
|
||
type: _this.currentType
|
||
});
|
||
});
|
||
this.speedGroup.on('mousewheel', function (evt) {
|
||
evt.preventDefault();
|
||
var pointerMatrix = _this.speedPoint.attr('matrix') || [1, 0, 0, 0, 1, 0, 0, 0, 1];
|
||
var currentPointerY = pointerMatrix[7];
|
||
var currentYIdx = _this.speedAxisY.indexOf(currentPointerY);
|
||
if (currentYIdx === -1) {
|
||
// 找到最近的一个 y
|
||
var minDist_1 = Infinity;
|
||
_this.speedAxisY.forEach(function (y, idx) {
|
||
var dist = Math.abs(y - currentPointerY);
|
||
if (minDist_1 > dist) {
|
||
minDist_1 = dist;
|
||
currentYIdx = idx;
|
||
}
|
||
});
|
||
}
|
||
if (evt.originalEvent.deltaY > 0) currentYIdx = Math.max(0, currentYIdx - 1);else currentYIdx = Math.min(_this.speedAxisY.length - 1, currentYIdx + 1);
|
||
var yDiff = _this.speedAxisY[currentYIdx] - currentPointerY;
|
||
pointerMatrix = transform(pointerMatrix, [['t', 0, yDiff]]);
|
||
_this.speedPoint.setMatrix(pointerMatrix);
|
||
_this.currentSpeed = _this.speedAxisY.length - currentYIdx;
|
||
_this.speedText.attr('text', "".concat(_this.currentSpeed, ".0X"));
|
||
_this.group.emit(TIMEBAR_CONFIG_CHANGE, {
|
||
speed: _this.currentSpeed,
|
||
type: _this.currentType
|
||
});
|
||
});
|
||
if (this.toggleGroup) {
|
||
this.toggleGroup.on('toggle-model:click', function (evt) {
|
||
var _a, _b;
|
||
var isChecked = evt.target.get('isChecked');
|
||
if (!isChecked) {
|
||
_this.checkedIcon.show();
|
||
_this.checkedText.attr('text', ((_a = _this.controllerCfg) === null || _a === void 0 ? void 0 : _a.timeRangeControllerText) || '时间范围');
|
||
_this.currentType = TIME_TYPE.SINGLE;
|
||
} else {
|
||
_this.checkedIcon.hide();
|
||
_this.checkedText.attr('text', ((_b = _this.controllerCfg) === null || _b === void 0 ? void 0 : _b.timePointControllerText) || '单一时间');
|
||
_this.currentType = TIME_TYPE.RANGE;
|
||
}
|
||
evt.target.set('isChecked', !isChecked);
|
||
_this.group.emit(TIMEBAR_CONFIG_CHANGE, {
|
||
type: _this.currentType,
|
||
speed: _this.currentSpeed
|
||
});
|
||
});
|
||
}
|
||
};
|
||
ControllerBtn.prototype.destroy = function () {
|
||
this.speedGroup.off('speed-rect:click');
|
||
if (this.toggleGroup) {
|
||
this.toggleGroup.off('toggle-model:click');
|
||
this.toggleGroup.destroy();
|
||
}
|
||
this.speedGroup.destroy();
|
||
};
|
||
return ControllerBtn;
|
||
}();
|
||
export default ControllerBtn; |