refactor(elevator): 重构电梯点状态渲染为极简设计,移除动画效果和图标依赖,统一使用静态边框和颜色编码
This commit is contained in:
parent
5f7a9b6dce
commit
624c68d0eb
@ -530,8 +530,8 @@ onMounted(async () => {
|
||||
id: '1998661793706377218',
|
||||
type: 102,
|
||||
elevatorFloor: 5,
|
||||
elevatorDirection: 1, // 停止
|
||||
elevatorFrontDoorStatus: 2, // 正在开关
|
||||
elevatorDirection: 3, // 停止
|
||||
elevatorFrontDoorStatus: 3, // 正在开关
|
||||
isConnected: true
|
||||
});
|
||||
|
||||
|
||||
@ -54,13 +54,31 @@ function drawDisconnectedIcon(ctx: CanvasRenderingContext2D, cx: number, cy: num
|
||||
}
|
||||
|
||||
/**
|
||||
* 绘制电梯点的动态效果 - 矩形框架动画系统
|
||||
* 绘制电梯点的极简状态指示 - 设计理念:
|
||||
* 1. 简约至上:仅使用矩形边框和颜色传达状态,无文字说明
|
||||
* 2. 图片优先:确保48*60电梯图片完全可见,边框不覆盖主体
|
||||
* 3. 响应式设计:所有尺寸基于pen元素宽高动态计算,完美适配画布缩放
|
||||
* 4. 直观色彩:
|
||||
* - 红色虚线:离线状态
|
||||
* - 绿色静态:开关门状态或门已开
|
||||
* - 蓝色静态边框+右侧箭头:上行/下行
|
||||
* - 金色:停止
|
||||
* - 灰色:未知状态
|
||||
* 5. 静态箭头:上下行时在边框右侧显示静态箭头,简洁清晰
|
||||
*
|
||||
* 尺寸计算规则:
|
||||
* - 边框距离:最小4px,否则按pen较小边的15%计算
|
||||
* - 边框宽度:最小1.5px,否则按pen较小边的3%计算
|
||||
* - 圆角半径:最小2px,否则按pen较小边的5%计算
|
||||
* - 方向指示器:最小3px,否则按pen较小边的10%计算
|
||||
* - 右侧箭头:最小4px,否则按pen较小边的12%计算
|
||||
* - 虚线样式:根据pen尺寸动态调整间距比例
|
||||
* @param ctx Canvas上下文
|
||||
* @param pen 画笔对象
|
||||
* @param elevatorData 电梯数据(包含后端字段)
|
||||
* @param time 当前时间戳(毫秒)
|
||||
* @param time 当前时间戳(毫秒)(保留参数以兼容接口,但不再使用)
|
||||
*/
|
||||
function drawElevatorAnimation(
|
||||
function drawElevatorMinimal(
|
||||
ctx: CanvasRenderingContext2D,
|
||||
pen: MapPen,
|
||||
elevatorData: any,
|
||||
@ -71,133 +89,76 @@ function drawElevatorAnimation(
|
||||
elevatorDirection,
|
||||
elevatorFrontDoorStatus,
|
||||
isConnected,
|
||||
|
||||
} = elevatorData;
|
||||
|
||||
const { x = 0, y = 0, width: w = 0, height: h = 0 } = pen.calculative?.worldRect ?? {};
|
||||
|
||||
// 为48*60图片设计矩形动画框架
|
||||
// 外边框距离图片边缘6像素,确保不覆盖图片
|
||||
const framePadding = 6;
|
||||
const frameWidth = 3; // 边框宽度
|
||||
const cornerLength = 12; // 角装饰长度
|
||||
const cornerWidth = 4; // 角装饰宽度
|
||||
// 基于pen元素尺寸的动态边框参数
|
||||
const baseSize = Math.min(w, h); // 取较小的尺寸作为基准
|
||||
const padding = Math.max(4, baseSize * 0.15); // 距离图片边缘:最小4px,否则按15%比例
|
||||
const strokeWidth = Math.max(1.5, baseSize * 0.03); // 边框宽度:最小1.5px,否则按3%比例
|
||||
const borderRadius = Math.max(2, baseSize * 0.05); // 圆角半径:最小2px,否则按5%比例
|
||||
|
||||
// 动画框架的四个角坐标
|
||||
const frameCorners = {
|
||||
topLeft: { x: x - framePadding, y: y - framePadding },
|
||||
topRight: { x: x + w + framePadding, y: y - framePadding },
|
||||
bottomLeft: { x: x - framePadding, y: y + h + framePadding },
|
||||
bottomRight: { x: x + w + framePadding, y: y + h + framePadding }
|
||||
};
|
||||
// 矩形边框坐标(基于动态参数)
|
||||
const rectX = x - padding;
|
||||
const rectY = y - padding;
|
||||
const rectW = w + padding * 2;
|
||||
const rectH = h + padding * 2;
|
||||
|
||||
// 检查是否启用LOD
|
||||
const lodEnabled = (pen.calculative as any)?.lodEnabled || false;
|
||||
|
||||
// 辅助函数:绘制矩形框架的角装饰
|
||||
const drawFrameCorners = (color: string, alpha: number, animated: boolean = true) => {
|
||||
// 辅助函数:绘制极简矩形边框
|
||||
const drawMinimalFrame = (color: string, alpha: number = 1, useDashedLine: boolean = false) => {
|
||||
ctx.save();
|
||||
|
||||
// 设置边框样式
|
||||
ctx.strokeStyle = color;
|
||||
ctx.fillStyle = color;
|
||||
ctx.lineWidth = cornerWidth;
|
||||
ctx.lineCap = 'square';
|
||||
ctx.lineWidth = strokeWidth;
|
||||
ctx.globalAlpha = alpha;
|
||||
|
||||
// 动画效果:角装饰闪烁
|
||||
const animPhase = animated ? Math.sin(time * 0.002) * 0.5 + 0.5 : 1;
|
||||
|
||||
// 左上角
|
||||
ctx.globalAlpha = alpha * animPhase;
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(frameCorners.topLeft.x, frameCorners.topLeft.y + cornerLength);
|
||||
ctx.lineTo(frameCorners.topLeft.x, frameCorners.topLeft.y);
|
||||
ctx.lineTo(frameCorners.topLeft.x + cornerLength, frameCorners.topLeft.y);
|
||||
ctx.stroke();
|
||||
|
||||
// 右上角
|
||||
ctx.globalAlpha = alpha * (animPhase + 0.25) % 1;
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(frameCorners.topRight.x - cornerLength, frameCorners.topRight.y);
|
||||
ctx.lineTo(frameCorners.topRight.x, frameCorners.topRight.y);
|
||||
ctx.lineTo(frameCorners.topRight.x, frameCorners.topRight.y + cornerLength);
|
||||
ctx.stroke();
|
||||
|
||||
// 右下角
|
||||
ctx.globalAlpha = alpha * (animPhase + 0.5) % 1;
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(frameCorners.bottomRight.x, frameCorners.bottomRight.y - cornerLength);
|
||||
ctx.lineTo(frameCorners.bottomRight.x, frameCorners.bottomRight.y);
|
||||
ctx.lineTo(frameCorners.bottomRight.x - cornerLength, frameCorners.bottomRight.y);
|
||||
ctx.stroke();
|
||||
|
||||
// 左下角
|
||||
ctx.globalAlpha = alpha * (animPhase + 0.75) % 1;
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(frameCorners.bottomLeft.x + cornerLength, frameCorners.bottomLeft.y);
|
||||
ctx.lineTo(frameCorners.bottomLeft.x, frameCorners.bottomLeft.y);
|
||||
ctx.lineTo(frameCorners.bottomLeft.x, frameCorners.bottomLeft.y - cornerLength);
|
||||
ctx.stroke();
|
||||
|
||||
ctx.restore();
|
||||
};
|
||||
|
||||
// 辅助函数:绘制完整矩形边框
|
||||
const drawFullFrame = (color: string, alpha: number, dashPattern: number[] = []) => {
|
||||
ctx.save();
|
||||
ctx.strokeStyle = color;
|
||||
ctx.lineWidth = frameWidth;
|
||||
ctx.globalAlpha = alpha;
|
||||
|
||||
if (dashPattern.length > 0) {
|
||||
ctx.setLineDash(dashPattern);
|
||||
// 虚线样式(动态调整间距)
|
||||
if (useDashedLine) {
|
||||
const dashLength = Math.max(3, baseSize * 0.08); // 虚线长度:最小3px,否则按8%比例
|
||||
const gapLength = Math.max(3, baseSize * 0.05); // 间隙长度:最小3px,否则按5%比例
|
||||
ctx.setLineDash([dashLength, gapLength]);
|
||||
}
|
||||
|
||||
ctx.strokeRect(
|
||||
frameCorners.topLeft.x,
|
||||
frameCorners.topLeft.y,
|
||||
frameCorners.bottomRight.x - frameCorners.topLeft.x,
|
||||
frameCorners.bottomRight.y - frameCorners.topLeft.y
|
||||
);
|
||||
// 绘制圆角矩形
|
||||
ctx.beginPath();
|
||||
ctx.roundRect(rectX, rectY, rectW, rectH, borderRadius);
|
||||
ctx.stroke();
|
||||
|
||||
ctx.restore();
|
||||
};
|
||||
|
||||
|
||||
// 辅助函数:绘制方向箭头(在框架外部)
|
||||
const drawDirectionArrows = (direction: 'up' | 'down', color: string) => {
|
||||
// 辅助函数:绘制方向指示(仅当电梯移动时)
|
||||
const drawDirection = (direction: 'up' | 'down', color: string) => {
|
||||
ctx.save();
|
||||
ctx.strokeStyle = color;
|
||||
ctx.fillStyle = color;
|
||||
ctx.lineWidth = 3;
|
||||
ctx.lineCap = 'round';
|
||||
ctx.lineJoin = 'round';
|
||||
ctx.globalAlpha = 0.8;
|
||||
|
||||
const arrowSize = 8;
|
||||
const arrowOffset = 15; // 箭头距离框架的距离
|
||||
const animProgress = (Math.sin(time * 0.003) + 1) * 0.5;
|
||||
// 方向指示器大小基于pen尺寸动态调整
|
||||
const indicatorSize = Math.max(3, baseSize * 0.1); // 最小3px,否则按10%比例
|
||||
const margin = Math.max(2, baseSize * 0.05); // 距离边框的距离:最小2px,否则按5%比例
|
||||
|
||||
if (direction === 'up') {
|
||||
// 上行箭头:在框架上方
|
||||
const arrowY = frameCorners.topLeft.y - arrowOffset - animProgress * 5;
|
||||
// 向上三角 - 位于矩形顶部中央
|
||||
const centerX = x + w / 2;
|
||||
const centerY = rectY + margin + indicatorSize;
|
||||
|
||||
ctx.globalAlpha = 0.8 + animProgress * 0.2;
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(centerX, arrowY);
|
||||
ctx.lineTo(centerX - arrowSize, arrowY + arrowSize);
|
||||
ctx.lineTo(centerX + arrowSize, arrowY + arrowSize);
|
||||
ctx.moveTo(centerX, centerY - indicatorSize);
|
||||
ctx.lineTo(centerX - indicatorSize, centerY + indicatorSize);
|
||||
ctx.lineTo(centerX + indicatorSize, centerY + indicatorSize);
|
||||
ctx.closePath();
|
||||
ctx.fill();
|
||||
} else {
|
||||
// 下行箭头:在框架下方
|
||||
const arrowY = frameCorners.bottomLeft.y + arrowOffset + animProgress * 5;
|
||||
// 向下三角 - 位于矩形底部中央
|
||||
const centerX = x + w / 2;
|
||||
const centerY = rectY + rectH - margin - indicatorSize;
|
||||
|
||||
ctx.globalAlpha = 0.8 + animProgress * 0.2;
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(centerX, arrowY);
|
||||
ctx.lineTo(centerX - arrowSize, arrowY - arrowSize);
|
||||
ctx.lineTo(centerX + arrowSize, arrowY - arrowSize);
|
||||
ctx.moveTo(centerX, centerY + indicatorSize);
|
||||
ctx.lineTo(centerX - indicatorSize, centerY - indicatorSize);
|
||||
ctx.lineTo(centerX + indicatorSize, centerY - indicatorSize);
|
||||
ctx.closePath();
|
||||
ctx.fill();
|
||||
}
|
||||
@ -205,125 +166,120 @@ function drawElevatorAnimation(
|
||||
ctx.restore();
|
||||
};
|
||||
|
||||
// 辅助函数:绘制门状态指示(在框架两侧)
|
||||
const drawDoorIndicators = (isOpening: boolean, color: string) => {
|
||||
ctx.save();
|
||||
ctx.strokeStyle = color;
|
||||
ctx.lineWidth = 2;
|
||||
ctx.globalAlpha = 0.7;
|
||||
|
||||
const progress = isOpening ?
|
||||
(Math.sin(time * 0.001) + 1) * 0.5 :
|
||||
1 - (Math.sin(time * 0.001) + 1) * 0.5;
|
||||
|
||||
const doorHeight = h * 0.3;
|
||||
const doorWidth = 3;
|
||||
const sideOffset = 12; // 距离框架侧边的距离
|
||||
|
||||
// 左门指示
|
||||
const leftDoorX = frameCorners.topLeft.x - sideOffset - progress * 8;
|
||||
const doorY = y + (h - doorHeight) / 2;
|
||||
ctx.strokeRect(leftDoorX, doorY, doorWidth, doorHeight);
|
||||
|
||||
// 右门指示
|
||||
const rightDoorX = frameCorners.topRight.x + sideOffset + progress * 8;
|
||||
ctx.strokeRect(rightDoorX, doorY, doorWidth, doorHeight);
|
||||
|
||||
ctx.restore();
|
||||
};
|
||||
|
||||
// 辅助函数:绘制状态文本
|
||||
const drawStatusText = (text: string, color: string) => {
|
||||
if (lodEnabled) return; // LOD模式下不显示文本
|
||||
|
||||
// 辅助函数:在边框右侧绘制静态方向箭头
|
||||
const drawDirectionSide = (direction: 'up' | 'down', color: string) => {
|
||||
ctx.save();
|
||||
ctx.fillStyle = color;
|
||||
ctx.font = '10px Arial';
|
||||
ctx.textAlign = 'center';
|
||||
ctx.textBaseline = 'top';
|
||||
ctx.globalAlpha = 0.9;
|
||||
ctx.strokeStyle = color;
|
||||
ctx.globalAlpha = 0.8;
|
||||
|
||||
// 在图片下方显示状态文本
|
||||
ctx.fillText(text, x + w / 2, frameCorners.bottomLeft.y + 5);
|
||||
ctx.restore();
|
||||
};
|
||||
// 箭头大小基于pen尺寸动态调整,使用宽度和高度的平均值来更好地适应不同比例
|
||||
const avgSize = (w + h) / 2; // 使用宽高平均值作为基准
|
||||
const arrowSize = Math.max(4, avgSize * 0.12); // 最小4px,否则按12%比例
|
||||
const sideMargin = Math.max(3, avgSize * 0.08); // 距离右侧边框的距离
|
||||
ctx.lineWidth = Math.max(1.5, avgSize * 0.025); // 箭头线条宽度
|
||||
|
||||
// 辅助函数:绘制连接状态指示器
|
||||
const drawConnectionIndicator = () => {
|
||||
if (!isConnected) {
|
||||
ctx.save();
|
||||
const pulseIntensity = 0.5 + Math.sin(time * 0.003) * 0.5;
|
||||
// 箭头位置:在矩形右侧垂直居中
|
||||
const arrowX = rectX + rectW + sideMargin;
|
||||
const centerY = y + h / 2; // 垂直居中
|
||||
|
||||
// 断连图标在右上角
|
||||
ctx.fillStyle = `rgba(255, 59, 48, ${pulseIntensity})`;
|
||||
if (direction === 'up') {
|
||||
// 向上箭头 - 在右侧绘制
|
||||
ctx.beginPath();
|
||||
ctx.arc(frameCorners.topRight.x, frameCorners.topRight.y, 4, 0, Math.PI * 2);
|
||||
ctx.fill();
|
||||
|
||||
ctx.strokeStyle = `rgba(255, 59, 48, ${pulseIntensity})`;
|
||||
ctx.lineWidth = 2;
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(frameCorners.topRight.x - 6, frameCorners.topRight.y - 6);
|
||||
ctx.lineTo(frameCorners.topRight.x + 6, frameCorners.topRight.y + 6);
|
||||
// 箭头主体(竖线)
|
||||
ctx.moveTo(arrowX, centerY + arrowSize);
|
||||
ctx.lineTo(arrowX, centerY - arrowSize);
|
||||
// 箭头尖端(三角形)
|
||||
ctx.lineTo(arrowX - arrowSize * 0.6, centerY - arrowSize * 0.4);
|
||||
ctx.moveTo(arrowX, centerY - arrowSize);
|
||||
ctx.lineTo(arrowX + arrowSize * 0.6, centerY - arrowSize * 0.4);
|
||||
ctx.stroke();
|
||||
|
||||
ctx.restore();
|
||||
// 填充箭头头部
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(arrowX, centerY - arrowSize);
|
||||
ctx.lineTo(arrowX - arrowSize * 0.5, centerY - arrowSize * 0.7);
|
||||
ctx.lineTo(arrowX + arrowSize * 0.5, centerY - arrowSize * 0.7);
|
||||
ctx.closePath();
|
||||
ctx.fill();
|
||||
} else {
|
||||
// 向下箭头 - 在右侧绘制
|
||||
ctx.beginPath();
|
||||
// 箭头主体(竖线)
|
||||
ctx.moveTo(arrowX, centerY - arrowSize);
|
||||
ctx.lineTo(arrowX, centerY + arrowSize);
|
||||
// 箭头尖端(三角形)
|
||||
ctx.lineTo(arrowX - arrowSize * 0.6, centerY + arrowSize * 0.4);
|
||||
ctx.moveTo(arrowX, centerY + arrowSize);
|
||||
ctx.lineTo(arrowX + arrowSize * 0.6, centerY + arrowSize * 0.4);
|
||||
ctx.stroke();
|
||||
|
||||
// 填充箭头头部
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(arrowX, centerY + arrowSize);
|
||||
ctx.lineTo(arrowX - arrowSize * 0.5, centerY + arrowSize * 0.7);
|
||||
ctx.lineTo(arrowX + arrowSize * 0.5, centerY + arrowSize * 0.7);
|
||||
ctx.closePath();
|
||||
ctx.fill();
|
||||
}
|
||||
|
||||
ctx.restore();
|
||||
};
|
||||
|
||||
// 状态渲染逻辑
|
||||
// 辅助函数:呼吸动画效果
|
||||
const breatheAnimation = (baseAlpha: number = 0.6) => {
|
||||
// 使用缓慢的正弦波创建呼吸效果
|
||||
return baseAlpha + Math.sin(time * 0.001) * 0.2;
|
||||
};
|
||||
|
||||
// 辅助函数:脉冲动画效果(用于断连状态)
|
||||
const pulseAnimation = () => {
|
||||
return 0.4 + Math.sin(time * 0.002) * 0.4;
|
||||
};
|
||||
|
||||
// 状态渲染逻辑 - 静态显示,无动画
|
||||
if (!isConnected) {
|
||||
// 离线状态:红色闪烁角 + 断连图标
|
||||
drawFrameCorners('rgba(255, 59, 48, 0.8)', 0.8, true);
|
||||
drawConnectionIndicator();
|
||||
drawStatusText('离线', '#FF3B30');
|
||||
// 离线状态 - 红色虚线
|
||||
drawMinimalFrame('#FF3B30', 0.8, true);
|
||||
} else {
|
||||
// 在线状态根据具体状态渲染
|
||||
switch (elevatorFrontDoorStatus) {
|
||||
case 2: // 正在开关门
|
||||
// 绿色动态框架 + 门指示器
|
||||
drawFrameCorners('rgba(52, 199, 89, 0.8)', 0.7, true);
|
||||
if (!lodEnabled) {
|
||||
drawDoorIndicators(true, 'rgba(52, 199, 89, 0.8)');
|
||||
case 2: { // 正在开关门
|
||||
// 绿色静态边框
|
||||
drawMinimalFrame('#34C759', 0.8);
|
||||
break;
|
||||
}
|
||||
drawStatusText('开门中', '#34C759');
|
||||
break;
|
||||
|
||||
case 3: // 门已开
|
||||
// 蓝色呼吸框架
|
||||
drawStatusText('门已开', '#007AFF');
|
||||
case 3: { // 门已开
|
||||
// 绿色静态边框
|
||||
drawMinimalFrame('#34C759', 0.8);
|
||||
break;
|
||||
}
|
||||
|
||||
case 1: // 门已关
|
||||
case 1: { // 门已关
|
||||
if (elevatorDirection === 2) { // 向上
|
||||
// 紫色动态框架 + 上行箭头
|
||||
drawFrameCorners('rgba(175, 82, 222, 0.8)', 0.7, true);
|
||||
if (!lodEnabled) {
|
||||
drawDirectionArrows('up', 'rgba(175, 82, 222, 0.8)');
|
||||
}
|
||||
drawStatusText('上行中', '#AF52DE');
|
||||
// 蓝色静态边框 + 右侧向上箭头
|
||||
drawMinimalFrame('#007AFF', 0.8);
|
||||
drawDirectionSide('up', '#007AFF');
|
||||
} else if (elevatorDirection === 3) { // 向下
|
||||
// 青色动态框架 + 下行箭头
|
||||
drawFrameCorners('rgba(90, 200, 250, 0.8)', 0.7, true);
|
||||
if (!lodEnabled) {
|
||||
drawDirectionArrows('down', 'rgba(90, 200, 250, 0.8)');
|
||||
}
|
||||
drawStatusText('下行中', '#5AC8FA');
|
||||
// 蓝色静态边框 + 右侧向下箭头
|
||||
drawMinimalFrame('#007AFF', 0.8);
|
||||
drawDirectionSide('down', '#007AFF');
|
||||
} else { // 停止
|
||||
// 金色静态框架
|
||||
drawFullFrame('rgba(255, 204, 0, 0.6)', 0.6);
|
||||
drawStatusText('停止', '#FFCC00');
|
||||
// 金色静态边框
|
||||
drawMinimalFrame('#FFCC00', 0.7);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default: // 未知状态
|
||||
// 灰色静态框架
|
||||
drawFullFrame('rgba(142, 142, 147, 0.5)', 0.5);
|
||||
drawStatusText('未知', '#8E8E93');
|
||||
default: { // 未知状态
|
||||
// 灰色静态边框
|
||||
drawMinimalFrame('#8E8E93', 0.5);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 绘制自动门点断连状态的脉冲效果
|
||||
@ -556,15 +512,15 @@ export function drawPoint(ctx: CanvasRenderingContext2D, pen: MapPen): void {
|
||||
const largeTypeStrokeColor = colorConfig.getColor(`point.types.${type}.stroke`);
|
||||
const largeGeneralStrokeColor = colorConfig.getColor(active ? 'point.large.strokeActive' : 'point.large.stroke');
|
||||
const largeThemeStrokeColor = get(theme, active ? 'point-l.strokeActive' : 'point-l.stroke');
|
||||
ctx.strokeStyle = statusStyle ?? (largeTypeStrokeColor || largeGeneralStrokeColor || largeThemeStrokeColor || '');
|
||||
ctx.strokeStyle = largeTypeStrokeColor || largeGeneralStrokeColor || largeThemeStrokeColor || '';
|
||||
ctx.stroke();
|
||||
|
||||
// 电梯点:添加动画效果
|
||||
// 电梯点:使用极简状态渲染
|
||||
if (type === MapPointType.电梯点) {
|
||||
// 直接传入包含后端字段的 pen.point 数据
|
||||
if (pen.point) {
|
||||
const currentTime = performance.now();
|
||||
drawElevatorAnimation(ctx, pen, pen.point, currentTime);
|
||||
drawElevatorMinimal(ctx, pen, pen.point, currentTime);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
@ -151,20 +151,15 @@ export const useElevatorStore = defineStore('elevator', () => {
|
||||
};
|
||||
|
||||
/**
|
||||
* 更新画布上电梯点的显示 - 增强版
|
||||
* 更新画布上电梯点的显示
|
||||
*/
|
||||
const updateElevatorPointDisplay = (elevatorData: ElevatorData) => {
|
||||
if (!editorService.value || !elevatorData.penId) return;
|
||||
|
||||
const penId = elevatorData.penId;
|
||||
|
||||
// 获取状态对应的颜色、图标和动画配置
|
||||
const displayConfig = getElevatorDisplay(elevatorData);
|
||||
|
||||
// 基础更新数据
|
||||
const updateData: any = {
|
||||
// 设置图标
|
||||
image: displayConfig.iconPath,
|
||||
// 更新点位信息
|
||||
point: {
|
||||
...((editorService.value.getPenById(penId) as any)?.point || {}),
|
||||
@ -173,15 +168,8 @@ export const useElevatorStore = defineStore('elevator', () => {
|
||||
lastUpdate: elevatorData.lastUpdate,
|
||||
// 保存原始后端数据
|
||||
elevatorDirection: elevatorData.elevatorDirection,
|
||||
elevatorFrontDoorStatus: elevatorData.elevatorFrontDoorStatus,
|
||||
// 使用新的颜色系统
|
||||
color: displayConfig.color,
|
||||
// 动画配置
|
||||
animationClass: displayConfig.animationClass,
|
||||
priority: displayConfig.priority
|
||||
},
|
||||
// 增强的样式配置
|
||||
statusStyle: displayConfig.color
|
||||
elevatorFrontDoorStatus: elevatorData.elevatorFrontDoorStatus
|
||||
}
|
||||
};
|
||||
|
||||
try {
|
||||
@ -194,108 +182,6 @@ export const useElevatorStore = defineStore('elevator', () => {
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 获取电梯显示配置(颜色、图标)
|
||||
* 基于后端字段直接判断,使用现代化设计系统
|
||||
*/
|
||||
const getElevatorDisplay = (elevatorData: ElevatorData) => {
|
||||
// 生成图标路径的辅助函数
|
||||
const getIconPath = (theme: string) => `${import.meta.env.BASE_URL}/point/elevator-${theme}.svg`;
|
||||
|
||||
// 现代化颜色配置系统
|
||||
const colors = {
|
||||
offline: '#FF3B30', // 红色 - 离线
|
||||
opening: '#34C759', // 绿色 - 开门中
|
||||
doorOpen: '#007AFF', // 蓝色 - 门已开
|
||||
moving: '#AF52DE', // 紫色 - 运行中
|
||||
upMoving: '#AF52DE', // 紫色 - 上行
|
||||
downMoving: '#5AC8FA', // 青色 - 下行
|
||||
stopped: '#FFCC00', // 金色 - 停止
|
||||
idle: '#8E8E93', // 灰色 - 静止
|
||||
unknown: '#8E8E93' // 灰色 - 未知
|
||||
};
|
||||
|
||||
// 如果离线,显示红色
|
||||
if (!elevatorData.isConnected) {
|
||||
return {
|
||||
color: colors.offline,
|
||||
iconPath: getIconPath('offline'),
|
||||
text: '离线',
|
||||
priority: 'high',
|
||||
animationClass: 'pulse-error'
|
||||
};
|
||||
}
|
||||
|
||||
// 根据后端字段判断显示状态
|
||||
const { elevatorDirection, elevatorFrontDoorStatus, elevatorFloor } = elevatorData;
|
||||
|
||||
// 优先判断门状态
|
||||
switch (elevatorFrontDoorStatus) {
|
||||
case 2: // 正在开关门
|
||||
return {
|
||||
color: colors.opening,
|
||||
iconPath: getIconPath('opening'),
|
||||
text: `开门中 ${elevatorFloor > 0 ? `(${elevatorFloor}F)` : ''}`,
|
||||
priority: 'high',
|
||||
animationClass: 'pulse-success'
|
||||
};
|
||||
|
||||
case 3: // 门已开
|
||||
return {
|
||||
color: colors.doorOpen,
|
||||
iconPath: getIconPath('door-open'),
|
||||
text: `门已开 ${elevatorFloor > 0 ? `(${elevatorFloor}F)` : ''}`,
|
||||
priority: 'normal',
|
||||
animationClass: 'breathe'
|
||||
};
|
||||
|
||||
case 1: // 门已关
|
||||
switch (elevatorDirection) {
|
||||
case 2: // 向上
|
||||
return {
|
||||
color: colors.upMoving,
|
||||
iconPath: getIconPath('up'),
|
||||
text: `上行中 ${elevatorFloor > 0 ? `(${elevatorFloor}F)` : ''}`,
|
||||
priority: 'high',
|
||||
animationClass: 'flow-up'
|
||||
};
|
||||
|
||||
case 3: // 向下
|
||||
return {
|
||||
color: colors.downMoving,
|
||||
iconPath: getIconPath('down'),
|
||||
text: `下行中 ${elevatorFloor > 0 ? `(${elevatorFloor}F)` : ''}`,
|
||||
priority: 'high',
|
||||
animationClass: 'flow-down'
|
||||
};
|
||||
|
||||
case 1: // 停止
|
||||
return {
|
||||
color: colors.stopped,
|
||||
iconPath: getIconPath('stopped'),
|
||||
text: `停止 ${elevatorFloor > 0 ? `(${elevatorFloor}F)` : ''}`,
|
||||
priority: 'normal',
|
||||
animationClass: 'gentle-pulse'
|
||||
};
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// 未知状态
|
||||
return {
|
||||
color: colors.unknown,
|
||||
iconPath: getIconPath('unknown'),
|
||||
text: '未知状态',
|
||||
priority: 'low',
|
||||
animationClass: 'dim'
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
@ -313,10 +199,6 @@ export const useElevatorStore = defineStore('elevator', () => {
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
return {
|
||||
// 状态
|
||||
elevators,
|
||||
@ -325,7 +207,6 @@ export const useElevatorStore = defineStore('elevator', () => {
|
||||
// 方法
|
||||
setEditorService,
|
||||
handleElevatorWebSocketData,
|
||||
refreshMapping,
|
||||
getElevatorDisplay
|
||||
refreshMapping
|
||||
};
|
||||
});
|
||||
Loading…
x
Reference in New Issue
Block a user