feat(elevator): 重构电梯方向指示器为独立箭头,将停止状态条带改为装饰性元素以提升视觉清晰度

This commit is contained in:
xudan 2025-12-11 18:23:49 +08:00
parent 0a1608262d
commit 6c0836dfc4

View File

@ -194,109 +194,113 @@ function drawElevatorIcon(
} }
} }
// 绘制电梯顶部指示器 - 基于电梯宽度自适应,增加距离避免被遮挡 // 绘制电梯方向指示器 - 根据方向显示在上方或下方
const indicatorWidth = width * 0.6; // 指示器宽度为电梯宽度的60% const indicatorWidth = width * 0.3; // 指示器宽度为电梯宽度的30%(缩小为装饰性条带)
const indicatorHeight = Math.max(6, width * 0.12); // 指示器高度为电梯宽度的12%最小6px const indicatorHeight = height * 0.04; // 指示器高度为电梯高度的4%
const indicatorY = y - Math.max(10, width * 0.25); // 增加距离电梯宽度的25%最小10px const indicatorDistance = height * 0.15; // 指示器与电梯的距离为电梯高度的15%
// 顶部指示器背景 - 金属质感 // 根据方向确定指示器位置
const indicatorGradient = ctx.createLinearGradient(x + width/2 - indicatorWidth/2, indicatorY, x + width/2 + indicatorWidth/2, indicatorY + indicatorHeight); let indicatorY: number;
indicatorGradient.addColorStop(0, '#6b7280');
indicatorGradient.addColorStop(0.5, '#4b5563');
indicatorGradient.addColorStop(1, '#374151');
ctx.fillStyle = indicatorGradient;
ctx.fillRect(x + width/2 - indicatorWidth/2, indicatorY, indicatorWidth, indicatorHeight);
// 根据方向在顶部指示器内显示状态,使用更大的箭头
if (direction === 2) { if (direction === 2) {
// 向上状态 - 绿色LED效果 // 向上 - 指示器在电梯上方
indicatorY = y - indicatorDistance - indicatorHeight;
} else if (direction === 3) {
// 向下 - 指示器在电梯下方
indicatorY = y + height + indicatorDistance;
} else {
// 停止或未知 - 默认在下方
indicatorY = y + height + indicatorDistance;
}
// 绘制方向箭头(不受指示器限制)
if (direction === 2) {
// 向上状态 - 绿色箭头,显示在上方
const arrowSize = Math.min(width, height) * 0.35; // 箭头大小为图标较小边的35%
const arrowY = y - indicatorDistance - arrowSize - height * 0.05; // 箭头位置留出5%缓冲
// 绘制发光背景 // 绘制发光背景
const glowGradient = ctx.createRadialGradient(cx, indicatorY + indicatorHeight/2, 0, cx, indicatorY + indicatorHeight/2, indicatorHeight * 1.5); const glowGradient = ctx.createRadialGradient(cx, arrowY + arrowSize/2, 0, cx, arrowY + arrowSize/2, arrowSize);
glowGradient.addColorStop(0, 'rgba(16, 185, 129, 0.4)'); glowGradient.addColorStop(0, 'rgba(16, 185, 129, 0.4)');
glowGradient.addColorStop(1, 'rgba(16, 185, 129, 0)'); glowGradient.addColorStop(1, 'rgba(16, 185, 129, 0)');
ctx.fillStyle = glowGradient; ctx.fillStyle = glowGradient;
ctx.fillRect(x + width/2 - indicatorWidth/2 - 3, indicatorY - 3, indicatorWidth + 6, indicatorHeight + 6); ctx.fillRect(cx - arrowSize - 5, arrowY - 5, arrowSize * 2 + 10, arrowSize + 10);
// 绘制向上箭头 - 更大更明显 // 绘制向上箭头
ctx.fillStyle = '#10b981'; ctx.fillStyle = '#10b981';
ctx.shadowColor = '#10b981'; ctx.shadowColor = '#10b981';
ctx.shadowBlur = 8; ctx.shadowBlur = 6;
// 使用更大的箭头,占据整个指示器高度
const arrowSize = Math.min(indicatorWidth * 0.4, indicatorHeight * 0.9);
const arrowTop = indicatorY + indicatorHeight * 0.1;
const arrowBottom = indicatorY + indicatorHeight * 0.9;
// 主箭头 - 加粗版本
ctx.beginPath(); ctx.beginPath();
ctx.moveTo(cx, arrowTop); ctx.moveTo(cx, arrowY);
ctx.lineTo(cx - arrowSize, arrowBottom); ctx.lineTo(cx - arrowSize, arrowY + arrowSize);
ctx.lineTo(cx - arrowSize * 0.4, arrowBottom - arrowSize * 0.2); ctx.lineTo(cx - arrowSize * 0.4, arrowY + arrowSize - arrowSize * 0.15);
ctx.lineTo(cx, arrowBottom - arrowSize * 0.3); ctx.lineTo(cx, arrowY + arrowSize - arrowSize * 0.25);
ctx.lineTo(cx + arrowSize * 0.4, arrowBottom - arrowSize * 0.2); ctx.lineTo(cx + arrowSize * 0.4, arrowY + arrowSize - arrowSize * 0.15);
ctx.lineTo(cx + arrowSize, arrowBottom); ctx.lineTo(cx + arrowSize, arrowY + arrowSize);
ctx.closePath(); ctx.closePath();
ctx.fill(); ctx.fill();
ctx.shadowBlur = 0; ctx.shadowBlur = 0;
} else if (direction === 3) { } else if (direction === 3) {
// 向下状态 - 红色LED效果 // 向下状态 - 橙色箭头,显示在下方
const arrowSize = Math.min(width, height) * 0.35; // 箭头大小为图标较小边的35%
const arrowY = y + height + indicatorDistance + height * 0.05; // 箭头位置留出5%缓冲
// 绘制发光背景 // 绘制发光背景
const glowGradient = ctx.createRadialGradient(cx, indicatorY + indicatorHeight/2, 0, cx, indicatorY + indicatorHeight/2, indicatorHeight * 1.5); const glowGradient = ctx.createRadialGradient(cx, arrowY + arrowSize/2, 0, cx, arrowY + arrowSize/2, arrowSize);
glowGradient.addColorStop(0, 'rgba(239, 68, 68, 0.4)'); glowGradient.addColorStop(0, 'rgba(251, 146, 60, 0.4)');
glowGradient.addColorStop(1, 'rgba(239, 68, 68, 0)'); glowGradient.addColorStop(1, 'rgba(251, 146, 60, 0)');
ctx.fillStyle = glowGradient; ctx.fillStyle = glowGradient;
ctx.fillRect(x + width/2 - indicatorWidth/2 - 3, indicatorY - 3, indicatorWidth + 6, indicatorHeight + 6); ctx.fillRect(cx - arrowSize - 5, arrowY - 5, arrowSize * 2 + 10, arrowSize + 10);
// 绘制向下箭头 - 更大更明显 // 绘制向下箭头
ctx.fillStyle = '#ef4444'; ctx.fillStyle = '#fb923c';
ctx.shadowColor = '#ef4444'; ctx.shadowColor = '#fb923c';
ctx.shadowBlur = 8; ctx.shadowBlur = 6;
// 使用更大的箭头,占据整个指示器高度
const arrowSize = Math.min(indicatorWidth * 0.4, indicatorHeight * 0.9);
const arrowTop = indicatorY + indicatorHeight * 0.1;
const arrowBottom = indicatorY + indicatorHeight * 0.9;
// 主箭头 - 加粗版本
ctx.beginPath(); ctx.beginPath();
ctx.moveTo(cx, arrowBottom); ctx.moveTo(cx, arrowY + arrowSize);
ctx.lineTo(cx - arrowSize, arrowTop); ctx.lineTo(cx - arrowSize, arrowY);
ctx.lineTo(cx - arrowSize * 0.4, arrowTop + arrowSize * 0.2); ctx.lineTo(cx - arrowSize * 0.4, arrowY + arrowSize * 0.15);
ctx.lineTo(cx, arrowTop + arrowSize * 0.3); ctx.lineTo(cx, arrowY + arrowSize * 0.25);
ctx.lineTo(cx + arrowSize * 0.4, arrowTop + arrowSize * 0.2); ctx.lineTo(cx + arrowSize * 0.4, arrowY + arrowSize * 0.15);
ctx.lineTo(cx + arrowSize, arrowTop); ctx.lineTo(cx + arrowSize, arrowY);
ctx.closePath(); ctx.closePath();
ctx.fill(); ctx.fill();
ctx.shadowBlur = 0; ctx.shadowBlur = 0;
} else if (direction === 1) { } else if (direction === 1) {
// 停止状态 - 黄色LED效果 // 停止状态 - 黄色LED效果,显示在下方
// 绘制发光背景 // 绘制发光背景
const glowGradient = ctx.createRadialGradient(cx, indicatorY + indicatorHeight/2, 0, cx, indicatorY + indicatorHeight/2, indicatorHeight); const glowGradient = ctx.createRadialGradient(cx, indicatorY + indicatorHeight/2, 0, cx, indicatorY + indicatorHeight/2, indicatorHeight * 1.5);
glowGradient.addColorStop(0, 'rgba(245, 158, 11, 0.3)'); glowGradient.addColorStop(0, 'rgba(245, 158, 11, 0.3)');
glowGradient.addColorStop(1, 'rgba(245, 158, 11, 0)'); glowGradient.addColorStop(1, 'rgba(245, 158, 11, 0)');
ctx.fillStyle = glowGradient; ctx.fillStyle = glowGradient;
ctx.fillRect(x + width/2 - indicatorWidth/2 - 2, indicatorY - 2, indicatorWidth + 4, indicatorHeight + 4); ctx.fillRect(x + width/2 - indicatorWidth/2 - 3, indicatorY - 3, indicatorWidth + 6, indicatorHeight + 6);
// 绘制停止标志 // 绘制停止标志
ctx.fillStyle = '#f59e0b'; ctx.fillStyle = '#f59e0b';
ctx.shadowColor = '#f59e0b'; ctx.shadowColor = '#f59e0b';
ctx.shadowBlur = 6; ctx.shadowBlur = 4;
const stopSize = Math.min(indicatorHeight * 0.6, indicatorWidth * 0.18); const stopSize = Math.min(indicatorHeight, indicatorWidth * 0.8);
// 绘制矩形停止标志 // 绘制矩形停止标志
ctx.fillRect(cx - stopSize/2, indicatorY + (indicatorHeight - stopSize)/2, stopSize, stopSize); ctx.fillRect(cx - stopSize/2, indicatorY + (indicatorHeight - stopSize)/2, stopSize, stopSize);
// 添加脉冲效果
const pulsePhase = (time % 2000) / 2000 * Math.PI * 2;
const pulseAlpha = 0.3 + 0.2 * Math.sin(pulsePhase);
ctx.fillStyle = `rgba(245, 158, 11, ${pulseAlpha})`;
ctx.fillRect(cx - stopSize/2 - 2, indicatorY + (indicatorHeight - stopSize)/2 - 2, stopSize + 4, stopSize + 4);
ctx.shadowBlur = 0; ctx.shadowBlur = 0;
} }
// 只有停止状态才显示装饰性指示器条
if (direction === 1) {
// 指示器背景 - 金属质感
const indicatorGradient = ctx.createLinearGradient(x + width/2 - indicatorWidth/2, indicatorY, x + width/2 + indicatorWidth/2, indicatorY + indicatorHeight);
indicatorGradient.addColorStop(0, '#6b7280');
indicatorGradient.addColorStop(0.5, '#4b5563');
indicatorGradient.addColorStop(1, '#374151');
ctx.fillStyle = indicatorGradient;
ctx.fillRect(x + width/2 - indicatorWidth/2, indicatorY, indicatorWidth, indicatorHeight);
}
// 添加电梯边框 - 金属边缘效果 // 添加电梯边框 - 金属边缘效果
ctx.strokeStyle = '#1f2937'; ctx.strokeStyle = '#1f2937';
ctx.lineWidth = 2; ctx.lineWidth = 2;
@ -677,7 +681,7 @@ export function drawPoint(ctx: CanvasRenderingContext2D, pen: MapPen): void {
ctx.strokeStyle = largeTypeStrokeColor || largeGeneralStrokeColor || largeThemeStrokeColor || ''; ctx.strokeStyle = largeTypeStrokeColor || largeGeneralStrokeColor || largeThemeStrokeColor || '';
ctx.stroke(); ctx.stroke();
// 电梯点使用Canvas绘制的电梯图标 // 电梯点使用Canvas绘制的电梯图标
if (type === MapPointType.) { if (type === MapPointType.) {
// 绘制Canvas电梯图标和状态 // 绘制Canvas电梯图标和状态
if (pen.point) { if (pen.point) {