显卡完善
This commit is contained in:
parent
2355147ed5
commit
7236a95236
@ -333,17 +333,17 @@
|
|||||||
$t('device.running-status.866086-12') }}</el-link>
|
$t('device.running-status.866086-12') }}</el-link>
|
||||||
</template>
|
</template>
|
||||||
<el-descriptions-item :label="$t('device.running-status.866086-13')">{{ firmware.firmwareName
|
<el-descriptions-item :label="$t('device.running-status.866086-13')">{{ firmware.firmwareName
|
||||||
}}</el-descriptions-item>
|
}}</el-descriptions-item>
|
||||||
<el-descriptions-item :label="$t('device.device-edit.148398-4')">{{ firmware.productName
|
<el-descriptions-item :label="$t('device.device-edit.148398-4')">{{ firmware.productName
|
||||||
}}</el-descriptions-item>
|
}}</el-descriptions-item>
|
||||||
<el-descriptions-item :label="$t('device.device-edit.148398-12')">Version {{ firmware.version
|
<el-descriptions-item :label="$t('device.device-edit.148398-12')">Version {{ firmware.version
|
||||||
}}</el-descriptions-item>
|
}}</el-descriptions-item>
|
||||||
<el-descriptions-item :label="$t('device.running-status.866086-16')">
|
<el-descriptions-item :label="$t('device.running-status.866086-16')">
|
||||||
<el-link :href="getDownloadUrl(firmware.filePath)" :underline="false" type="primary">{{
|
<el-link :href="getDownloadUrl(firmware.filePath)" :underline="false" type="primary">{{
|
||||||
getDownloadUrl(firmware.filePath) }}</el-link>
|
getDownloadUrl(firmware.filePath) }}</el-link>
|
||||||
</el-descriptions-item>
|
</el-descriptions-item>
|
||||||
<el-descriptions-item :label="$t('device.running-status.866086-17')">{{ firmware.remark
|
<el-descriptions-item :label="$t('device.running-status.866086-17')">{{ firmware.remark
|
||||||
}}</el-descriptions-item>
|
}}</el-descriptions-item>
|
||||||
</el-descriptions>
|
</el-descriptions>
|
||||||
<div slot="footer" class="dialog-footer">
|
<div slot="footer" class="dialog-footer">
|
||||||
<el-button type="success" @click="otaUpgrade"
|
<el-button type="success" @click="otaUpgrade"
|
||||||
@ -561,7 +561,7 @@
|
|||||||
<div style="text-align: right;margin-top:8px;">
|
<div style="text-align: right;margin-top:8px;">
|
||||||
<el-button @click="addProgramDialogVisible = false" size="mini">取 消</el-button>
|
<el-button @click="addProgramDialogVisible = false" size="mini">取 消</el-button>
|
||||||
<el-button type="primary" @click="submitAddProgram" size="mini">{{ isEditProgram ? '更新' : '确定'
|
<el-button type="primary" @click="submitAddProgram" size="mini">{{ isEditProgram ? '更新' : '确定'
|
||||||
}}</el-button>
|
}}</el-button>
|
||||||
</div>
|
</div>
|
||||||
</el-form>
|
</el-form>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
@ -2483,6 +2483,7 @@ export default {
|
|||||||
this.addProgramForm.zones.forEach((zone, zIdx) => {
|
this.addProgramForm.zones.forEach((zone, zIdx) => {
|
||||||
const asset = this.addProgramPreviewAssets[zIdx];
|
const asset = this.addProgramPreviewAssets[zIdx];
|
||||||
if (!asset) return;
|
if (!asset) return;
|
||||||
|
const state = this.addProgramPreviewAnimState[zIdx] || {};
|
||||||
|
|
||||||
// 计算分区在画布中的位置(角度为90或270时,x/y/width/height互换)
|
// 计算分区在画布中的位置(角度为90或270时,x/y/width/height互换)
|
||||||
let zoneX, zoneY, zoneWidth, zoneHeight;
|
let zoneX, zoneY, zoneWidth, zoneHeight;
|
||||||
@ -2512,12 +2513,9 @@ export default {
|
|||||||
ctx.rect(zoneX, zoneY, zoneWidth, zoneHeight);
|
ctx.rect(zoneX, zoneY, zoneWidth, zoneHeight);
|
||||||
ctx.clip();
|
ctx.clip();
|
||||||
|
|
||||||
// 获取动画状态
|
|
||||||
const state = this.addProgramPreviewAnimState[zIdx];
|
|
||||||
|
|
||||||
if (zone.playType === 0 && asset.isText) {
|
if (zone.playType === 0 && asset.isText) {
|
||||||
// 文本类型分区
|
// 获取当前页(使用状态中的当前页)
|
||||||
const page = state && typeof state.currentPage === 'number' ? state.currentPage : 0;
|
const page = state.currentPage || 0;
|
||||||
const pageLines = asset.pages[page] || [];
|
const pageLines = asset.pages[page] || [];
|
||||||
|
|
||||||
// 设置字体样式
|
// 设置字体样式
|
||||||
@ -2589,7 +2587,7 @@ export default {
|
|||||||
ctx.fillText(line, x1, y);
|
ctx.fillText(line, x1, y);
|
||||||
ctx.fillText(line, x2, y);
|
ctx.fillText(line, x2, y);
|
||||||
} else {
|
} else {
|
||||||
ctx.fillText(line, startX + (state ? state.currentX : 0), startY + lineIdx * lineHeight + (state ? state.currentY : 0));
|
ctx.fillText(line, startX + animOffsetX, startY + lineIdx * lineHeight + animOffsetY);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else if (zone.playType === 1 && asset.isImage) {
|
} else if (zone.playType === 1 && asset.isImage) {
|
||||||
@ -2678,124 +2676,124 @@ export default {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
prepareAddProgramPreviewAssets() {
|
prepareAddProgramPreviewAssets() {
|
||||||
const canvas = this.$refs.addProgramPreviewCanvas;
|
const canvas = this.$refs.addProgramPreviewCanvas;
|
||||||
if (!canvas) return;
|
if (!canvas) return;
|
||||||
|
|
||||||
// 动态获取屏幕参数
|
// 动态获取屏幕参数
|
||||||
let screenW = this.screenParams.width || 32;
|
let screenW = this.screenParams.width || 32;
|
||||||
let screenH = this.screenParams.height || 64;
|
let screenH = this.screenParams.height || 64;
|
||||||
// 如果角度为90或270,渲染时宽高互换
|
// 如果角度为90或270,渲染时宽高互换
|
||||||
const angle = this.screenParams.angle;
|
const angle = this.screenParams.angle;
|
||||||
const swapWH = angle === 90 || angle === 270;
|
const swapWH = angle === 90 || angle === 270;
|
||||||
if (swapWH) {
|
if (swapWH) {
|
||||||
[screenW, screenH] = [screenH, screenW];
|
[screenW, screenH] = [screenH, screenW];
|
||||||
}
|
|
||||||
const renderWidth = 640; // 与实际渲染宽度匹配
|
|
||||||
const scale = Math.min(renderWidth / screenW, 240 / screenH);
|
|
||||||
|
|
||||||
this.addProgramPreviewAssets = this.addProgramForm.zones.map(zone => {
|
|
||||||
if (zone.playType === 1 && zone.image) {
|
|
||||||
// 图片类型,异步加载图片
|
|
||||||
const img = new window.Image();
|
|
||||||
const asset = { img, isImage: true, loaded: false };
|
|
||||||
img.onload = () => {
|
|
||||||
asset.loaded = true;
|
|
||||||
this.drawAddProgramPreview();
|
|
||||||
};
|
|
||||||
img.onerror = (e) => {
|
|
||||||
console.error("Preview image failed to load:", e);
|
|
||||||
};
|
|
||||||
img.src = zone.image;
|
|
||||||
return asset;
|
|
||||||
}
|
|
||||||
if (zone.playType !== 0 || !zone.displayText) {
|
|
||||||
return { pages: [[]], isText: false };
|
|
||||||
}
|
|
||||||
|
|
||||||
// 获取原始字体大小(像素值)
|
|
||||||
const fontSize = parseInt(this.addProgramFontSizes[zone.fontSize] || '16px');
|
|
||||||
|
|
||||||
// 计算缩放后的字体大小
|
|
||||||
const scaledFontSize = Math.max(10, Math.round(fontSize * scale * 0.8)); // 添加0.8缩放系数
|
|
||||||
|
|
||||||
const fontFamily = [
|
|
||||||
'SimSun, 宋体, Songti SC, serif',
|
|
||||||
'SimHei, 黑体, Heiti SC, sans-serif',
|
|
||||||
'KaiTi, 楷体, Kaiti SC, serif'
|
|
||||||
];
|
|
||||||
const fontWeight = zone.fontBold ? 'bold' : 'normal';
|
|
||||||
|
|
||||||
// 创建临时canvas测量文本
|
|
||||||
const measureCanvas = document.createElement('canvas');
|
|
||||||
const measureCtx = measureCanvas.getContext('2d');
|
|
||||||
const enFontMap = [
|
|
||||||
'Courier New', 'Arial Black', 'Arial Italic', 'Lucida Console', 'Impact', 'Gothic', 'Arial Narrow', 'Comic Sans MS', 'Brush Script MT', 'Century Gothic', 'Times New Roman'
|
|
||||||
];
|
|
||||||
let fontFamilyUsed;
|
|
||||||
if (/^[A-Za-z0-9\s]+$/.test(zone.displayText)) {
|
|
||||||
fontFamilyUsed = enFontMap[zone.fontEn] || fontFamily[0];
|
|
||||||
} else {
|
|
||||||
fontFamilyUsed = fontFamily[zone.font] || fontFamily[0];
|
|
||||||
}
|
|
||||||
measureCtx.font = `${fontWeight} ${scaledFontSize}px ${fontFamilyUsed}`;
|
|
||||||
|
|
||||||
// 分行逻辑 - 特殊处理连续左移效果
|
|
||||||
let lines = [];
|
|
||||||
if (zone.effect === 5) { // 连续左移效果
|
|
||||||
// 强制不分行,整个文本作为一行
|
|
||||||
lines = [zone.displayText];
|
|
||||||
} else {
|
|
||||||
// 正常的分行逻辑
|
|
||||||
const zoneRenderWidth = swapWH ? zone.height : zone.width;
|
|
||||||
const maxWidth = zoneRenderWidth * scale - 4; // 预留4px边距
|
|
||||||
let currentLine = '';
|
|
||||||
|
|
||||||
for (const char of zone.displayText) {
|
|
||||||
const testLine = currentLine + char;
|
|
||||||
const metrics = measureCtx.measureText(testLine);
|
|
||||||
|
|
||||||
if (metrics.width > maxWidth) {
|
|
||||||
if (currentLine) lines.push(currentLine);
|
|
||||||
currentLine = char;
|
|
||||||
} else {
|
|
||||||
currentLine = testLine;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
const renderWidth = 640; // 与实际渲染宽度匹配
|
||||||
|
const scale = Math.min(renderWidth / screenW, 240 / screenH);
|
||||||
|
|
||||||
if (currentLine) lines.push(currentLine);
|
this.addProgramPreviewAssets = this.addProgramForm.zones.map(zone => {
|
||||||
}
|
if (zone.playType === 1 && zone.image) {
|
||||||
|
// 图片类型,异步加载图片
|
||||||
|
const img = new window.Image();
|
||||||
|
const asset = { img, isImage: true, loaded: false };
|
||||||
|
img.onload = () => {
|
||||||
|
asset.loaded = true;
|
||||||
|
this.drawAddProgramPreview();
|
||||||
|
};
|
||||||
|
img.onerror = (e) => {
|
||||||
|
console.error("Preview image failed to load:", e);
|
||||||
|
};
|
||||||
|
img.src = zone.image;
|
||||||
|
return asset;
|
||||||
|
}
|
||||||
|
if (zone.playType !== 0 || !zone.displayText) {
|
||||||
|
return { pages: [[]], isText: false };
|
||||||
|
}
|
||||||
|
|
||||||
// 计算每页最大行数
|
// 获取原始字体大小(像素值)
|
||||||
const zoneRenderHeight = swapWH ? zone.width : zone.height;
|
const fontSize = parseInt(this.addProgramFontSizes[zone.fontSize] || '16px');
|
||||||
const lineHeight = scaledFontSize * 1.2;
|
|
||||||
const maxLines = Math.max(1, Math.floor((zoneRenderHeight * scale - 4) / lineHeight));
|
|
||||||
|
|
||||||
// 分页
|
// 计算缩放后的字体大小
|
||||||
const pages = [];
|
const scaledFontSize = Math.max(10, Math.round(fontSize * scale * 0.8)); // 添加0.8缩放系数
|
||||||
for (let i = 0; i < lines.length; i += maxLines) {
|
|
||||||
pages.push(lines.slice(i, i + maxLines));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pages.length === 0) pages.push([]);
|
const fontFamily = [
|
||||||
|
'SimSun, 宋体, Songti SC, serif',
|
||||||
|
'SimHei, 黑体, Heiti SC, sans-serif',
|
||||||
|
'KaiTi, 楷体, Kaiti SC, serif'
|
||||||
|
];
|
||||||
|
const fontWeight = zone.fontBold ? 'bold' : 'normal';
|
||||||
|
|
||||||
// 计算总宽高和区域宽高,供动画用
|
// 创建临时canvas测量文本
|
||||||
const totalWidth = Math.max(...pages.flat().map(line => measureCtx.measureText(line).width), 0);
|
const measureCanvas = document.createElement('canvas');
|
||||||
const totalHeight = Math.min(lines.length, maxLines) * lineHeight;
|
const measureCtx = measureCanvas.getContext('2d');
|
||||||
|
const enFontMap = [
|
||||||
return {
|
'Courier New', 'Arial Black', 'Arial Italic', 'Lucida Console', 'Impact', 'Gothic', 'Arial Narrow', 'Comic Sans MS', 'Brush Script MT', 'Century Gothic', 'Times New Roman'
|
||||||
pages,
|
];
|
||||||
isText: true,
|
let fontFamilyUsed;
|
||||||
scaledFontSize,
|
if (/^[A-Za-z0-9\s]+$/.test(zone.displayText)) {
|
||||||
fontFamily: fontFamilyUsed,
|
fontFamilyUsed = enFontMap[zone.fontEn] || fontFamily[0];
|
||||||
fontWeight,
|
} else {
|
||||||
lineHeight,
|
fontFamilyUsed = fontFamily[zone.font] || fontFamily[0];
|
||||||
totalWidth,
|
}
|
||||||
totalHeight,
|
measureCtx.font = `${fontWeight} ${scaledFontSize}px ${fontFamilyUsed}`;
|
||||||
zoneRenderWidth: (swapWH ? zone.height : zone.width) * scale,
|
|
||||||
zoneRenderHeight: (swapWH ? zone.width : zone.height) * scale
|
// 分行逻辑 - 特殊处理连续左移效果
|
||||||
};
|
let lines = [];
|
||||||
});
|
if (zone.effect === 5) { // 连续左移效果
|
||||||
},
|
// 强制不分行,整个文本作为一行
|
||||||
|
lines = [zone.displayText];
|
||||||
|
} else {
|
||||||
|
// 正常的分行逻辑
|
||||||
|
const zoneRenderWidth = swapWH ? zone.height : zone.width;
|
||||||
|
const maxWidth = zoneRenderWidth * scale - 4; // 预留4px边距
|
||||||
|
let currentLine = '';
|
||||||
|
|
||||||
|
for (const char of zone.displayText) {
|
||||||
|
const testLine = currentLine + char;
|
||||||
|
const metrics = measureCtx.measureText(testLine);
|
||||||
|
|
||||||
|
if (metrics.width > maxWidth) {
|
||||||
|
if (currentLine) lines.push(currentLine);
|
||||||
|
currentLine = char;
|
||||||
|
} else {
|
||||||
|
currentLine = testLine;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentLine) lines.push(currentLine);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 计算每页最大行数
|
||||||
|
const zoneRenderHeight = swapWH ? zone.width : zone.height;
|
||||||
|
const lineHeight = scaledFontSize * 1.2;
|
||||||
|
const maxLines = Math.max(1, Math.floor((zoneRenderHeight * scale - 4) / lineHeight));
|
||||||
|
|
||||||
|
// 分页
|
||||||
|
const pages = [];
|
||||||
|
for (let i = 0; i < lines.length; i += maxLines) {
|
||||||
|
pages.push(lines.slice(i, i + maxLines));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pages.length === 0) pages.push([]);
|
||||||
|
|
||||||
|
// 计算总宽高和区域宽高,供动画用
|
||||||
|
const totalWidth = Math.max(...pages.flat().map(line => measureCtx.measureText(line).width), 0);
|
||||||
|
const totalHeight = Math.min(lines.length, maxLines) * lineHeight;
|
||||||
|
|
||||||
|
return {
|
||||||
|
pages,
|
||||||
|
isText: true,
|
||||||
|
scaledFontSize,
|
||||||
|
fontFamily: fontFamilyUsed,
|
||||||
|
fontWeight,
|
||||||
|
lineHeight,
|
||||||
|
totalWidth,
|
||||||
|
totalHeight,
|
||||||
|
zoneRenderWidth: (swapWH ? zone.height : zone.width) * scale,
|
||||||
|
zoneRenderHeight: (swapWH ? zone.width : zone.height) * scale
|
||||||
|
};
|
||||||
|
});
|
||||||
|
},
|
||||||
resetAddProgramPreviewPage() {
|
resetAddProgramPreviewPage() {
|
||||||
this.addProgramPreviewPage = this.addProgramForm.zones.map(() => 0);
|
this.addProgramPreviewPage = this.addProgramForm.zones.map(() => 0);
|
||||||
},
|
},
|
||||||
@ -2864,17 +2862,20 @@ export default {
|
|||||||
return { lines, maxLines };
|
return { lines, maxLines };
|
||||||
},
|
},
|
||||||
resetAddProgramPreviewAnimState() {
|
resetAddProgramPreviewAnimState() {
|
||||||
// 初始化每个分区动画状态
|
this.addProgramPreviewAnimState = this.addProgramForm.zones.map((zone, idx) => {
|
||||||
this.addProgramPreviewAnimState = this.addProgramForm.zones.map((zone, idx) => {
|
return {
|
||||||
return {
|
currentX: 0,
|
||||||
currentX: 0,
|
currentY: 0,
|
||||||
currentY: 0,
|
currentPage: 0,
|
||||||
currentPage: this.addProgramPreviewPage[idx] || 0,
|
isMoving: false,
|
||||||
pageTimer: null,
|
isPausing: false,
|
||||||
effect: zone.effect,
|
moveStart: 0,
|
||||||
};
|
pauseStart: 0,
|
||||||
});
|
currentChar: 0, // 当前显示的字符索引
|
||||||
},
|
effect: zone.effect,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
},
|
||||||
stopAddProgramPreviewAnimLoop() {
|
stopAddProgramPreviewAnimLoop() {
|
||||||
if (this.addProgramPreviewAnimFrame) {
|
if (this.addProgramPreviewAnimFrame) {
|
||||||
cancelAnimationFrame(this.addProgramPreviewAnimFrame);
|
cancelAnimationFrame(this.addProgramPreviewAnimFrame);
|
||||||
@ -2891,118 +2892,233 @@ export default {
|
|||||||
this.addProgramPreviewAnimFrame = requestAnimationFrame(loop);
|
this.addProgramPreviewAnimFrame = requestAnimationFrame(loop);
|
||||||
},
|
},
|
||||||
updateAddProgramPreviewAnimState() {
|
updateAddProgramPreviewAnimState() {
|
||||||
// 动画主循环,更新每个分区的动画状态
|
// 动画主循环,更新每个分区的动画状态
|
||||||
const renderWidth = 640;
|
const renderWidth = 640;
|
||||||
const renderHeight = 240;
|
const renderHeight = 240;
|
||||||
let screenW = this.screenParams.width || 32;
|
let screenW = this.screenParams.width || 32;
|
||||||
let screenH = this.screenParams.height || 64;
|
let screenH = this.screenParams.height || 64;
|
||||||
const angle = this.screenParams.angle;
|
const angle = this.screenParams.angle;
|
||||||
const swapWH = angle === 90 || angle === 270;
|
const swapWH = angle === 90 || angle === 270;
|
||||||
if (swapWH) {
|
if (swapWH) {
|
||||||
[screenW, screenH] = [screenH, screenW];
|
[screenW, screenH] = [screenH, screenW];
|
||||||
}
|
}
|
||||||
const scale = Math.min(renderWidth / screenW, renderHeight / screenH);
|
const scale = Math.min(renderWidth / screenW, renderHeight / screenH);
|
||||||
|
|
||||||
this.addProgramForm.zones.forEach((zone, idx) => {
|
this.addProgramForm.zones.forEach((zone, idx) => {
|
||||||
const asset = this.addProgramPreviewAssets[idx];
|
const asset = this.addProgramPreviewAssets[idx];
|
||||||
const state = this.addProgramPreviewAnimState[idx];
|
const state = this.addProgramPreviewAnimState[idx];
|
||||||
|
|
||||||
if (!asset || !state || !asset.isText) return;
|
if (!asset || !state || !asset.isText) return;
|
||||||
|
|
||||||
const effect = zone.effect;
|
const effect = zone.effect;
|
||||||
const page = this.addProgramPreviewPage[idx] || 0;
|
const pageLines = asset.pages[state.currentPage] || [];
|
||||||
const pageLines = asset.pages[page] || [];
|
const lineHeight = asset.lineHeight;
|
||||||
const lineHeight = asset.lineHeight;
|
const totalHeight = asset.totalHeight;
|
||||||
const totalHeight = asset.totalHeight;
|
const totalWidth = asset.totalWidth;
|
||||||
const totalWidth = asset.totalWidth;
|
|
||||||
|
|
||||||
// 动画速度
|
// 动画速度
|
||||||
const speedMap = [1, 2, 3, 4, 5];
|
const speedMap = [1, 2, 3, 4, 5];
|
||||||
const animSpeed = (speedMap[zone.speed] || 3) * scale * 0.5; // 像素/帧
|
const animSpeed = (speedMap[zone.speed] || 3) * scale * 0.5; // 像素/帧
|
||||||
|
|
||||||
// 区域宽高 (使用预先计算并缩放的值)
|
// 区域宽高 (使用预先计算并缩放的值)
|
||||||
const zoneWidth = asset.zoneRenderWidth;
|
const zoneWidth = asset.zoneRenderWidth;
|
||||||
const zoneHeight = asset.zoneRenderHeight;
|
const zoneHeight = asset.zoneRenderHeight;
|
||||||
|
|
||||||
// 暂停时间 (毫秒)
|
// 暂停时间 (毫秒)
|
||||||
const pauseMs = this.getPauseTime(zone.stayTime);
|
const pauseMs = this.getPauseTime(zone.stayTime);
|
||||||
|
|
||||||
// 确保初始状态值存在
|
// 确保初始状态值存在
|
||||||
if (typeof state.isPausing !== 'boolean') state.isPausing = false;
|
if (typeof state.isMoving !== 'boolean') state.isMoving = false;
|
||||||
if (typeof state.pauseStart !== 'number') state.pauseStart = 0;
|
if (typeof state.isPausing !== 'boolean') state.isPausing = false;
|
||||||
if (typeof state.pausePhase !== 'string') state.pausePhase = 'start'; // 'start' | 'move'
|
if (typeof state.pauseStart !== 'number') state.pauseStart = 0;
|
||||||
|
if (typeof state.moveStart !== 'number') state.moveStart = 0;
|
||||||
|
|
||||||
switch (effect) {
|
switch (effect) {
|
||||||
case 1: // 左移
|
case 0: // 立即显示
|
||||||
if (typeof state.currentX !== 'number') state.currentX = zoneWidth;
|
if (!state.isPausing && !state.isMoving) {
|
||||||
state.currentX -= animSpeed;
|
// 初始状态:直接进入停留阶段
|
||||||
if (state.currentX < -totalWidth) {
|
state.isPausing = true;
|
||||||
if (asset.pages.length > 1) {
|
state.pauseStart = Date.now();
|
||||||
state.currentPage = (state.currentPage + 1) % asset.pages.length;
|
} else if (state.isPausing) {
|
||||||
}
|
// 检查停留时间是否结束
|
||||||
state.currentX = zoneWidth;
|
if (Date.now() - state.pauseStart >= pauseMs) {
|
||||||
|
state.isPausing = false;
|
||||||
|
state.isMoving = true; // 准备翻页
|
||||||
|
}
|
||||||
|
} else if (state.isMoving) {
|
||||||
|
// 翻页操作
|
||||||
|
state.currentPage = (state.currentPage + 1) % asset.pages.length;
|
||||||
|
state.isMoving = false;
|
||||||
|
state.isPausing = true;
|
||||||
|
state.pauseStart = Date.now();
|
||||||
|
}
|
||||||
|
// 位置保持不变
|
||||||
|
state.currentX = 0;
|
||||||
|
state.currentY = 0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 1: // 左移
|
||||||
|
if (!state.isMoving && !state.isPausing) {
|
||||||
|
// 初始状态:设置初始位置(右侧外部)
|
||||||
|
state.currentX = zoneWidth;
|
||||||
|
state.isMoving = true;
|
||||||
|
state.moveStart = Date.now();
|
||||||
|
} else if (state.isMoving) {
|
||||||
|
// 移动阶段
|
||||||
|
const elapsed = Date.now() - state.moveStart;
|
||||||
|
const progress = Math.min(1, elapsed / (totalWidth * 1000 / animSpeed));
|
||||||
|
|
||||||
|
// 计算移动位置(从右侧移动到左侧)
|
||||||
|
state.currentX = zoneWidth - progress * (zoneWidth + totalWidth);
|
||||||
|
|
||||||
|
// 检查是否到达目标位置
|
||||||
|
if (progress >= 1) {
|
||||||
|
state.isMoving = false;
|
||||||
|
state.isPausing = true;
|
||||||
|
state.pauseStart = Date.now();
|
||||||
|
}
|
||||||
|
} else if (state.isPausing) {
|
||||||
|
// 停留阶段
|
||||||
|
if (Date.now() - state.pauseStart >= pauseMs) {
|
||||||
|
state.isPausing = false;
|
||||||
|
state.isMoving = true; // 准备翻页
|
||||||
|
}
|
||||||
|
} else if (!state.isPausing && state.isMoving) {
|
||||||
|
// 翻页操作
|
||||||
|
state.currentPage = (state.currentPage + 1) % asset.pages.length;
|
||||||
|
state.currentX = zoneWidth; // 重置位置
|
||||||
|
state.isMoving = true;
|
||||||
|
state.moveStart = Date.now();
|
||||||
|
}
|
||||||
|
state.currentY = 0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 2: // 右移
|
||||||
|
if (!state.isMoving && !state.isPausing) {
|
||||||
|
state.currentX = -totalWidth;
|
||||||
|
state.isMoving = true;
|
||||||
|
state.moveStart = Date.now();
|
||||||
|
} else if (state.isMoving) {
|
||||||
|
const elapsed = Date.now() - state.moveStart;
|
||||||
|
const progress = Math.min(1, elapsed / (totalWidth * 1000 / animSpeed));
|
||||||
|
|
||||||
|
state.currentX = -totalWidth + progress * (zoneWidth + totalWidth);
|
||||||
|
|
||||||
|
if (progress >= 1) {
|
||||||
|
state.isMoving = false;
|
||||||
|
state.isPausing = true;
|
||||||
|
state.pauseStart = Date.now();
|
||||||
|
}
|
||||||
|
} else if (state.isPausing) {
|
||||||
|
if (Date.now() - state.pauseStart >= pauseMs) {
|
||||||
|
state.isPausing = false;
|
||||||
|
state.isMoving = true; // 准备翻页
|
||||||
|
}
|
||||||
|
} else if (!state.isPausing && state.isMoving) {
|
||||||
|
state.currentPage = (state.currentPage + 1) % asset.pages.length;
|
||||||
|
state.currentX = -totalWidth;
|
||||||
|
state.isMoving = true;
|
||||||
|
state.moveStart = Date.now();
|
||||||
|
}
|
||||||
|
state.currentY = 0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 3: // 上移
|
||||||
|
if (!state.isMoving && !state.isPausing) {
|
||||||
|
state.currentY = zoneHeight;
|
||||||
|
state.isMoving = true;
|
||||||
|
state.moveStart = Date.now();
|
||||||
|
} else if (state.isMoving) {
|
||||||
|
const elapsed = Date.now() - state.moveStart;
|
||||||
|
const progress = Math.min(1, elapsed / (totalHeight * 1000 / animSpeed));
|
||||||
|
|
||||||
|
state.currentY = zoneHeight - progress * (zoneHeight + totalHeight);
|
||||||
|
|
||||||
|
if (progress >= 1) {
|
||||||
|
state.isMoving = false;
|
||||||
|
state.isPausing = true;
|
||||||
|
state.pauseStart = Date.now();
|
||||||
|
}
|
||||||
|
} else if (state.isPausing) {
|
||||||
|
if (Date.now() - state.pauseStart >= pauseMs) {
|
||||||
|
state.isPausing = false;
|
||||||
|
state.isMoving = true; // 准备翻页
|
||||||
|
}
|
||||||
|
} else if (!state.isPausing && state.isMoving) {
|
||||||
|
state.currentPage = (state.currentPage + 1) % asset.pages.length;
|
||||||
|
state.currentY = zoneHeight;
|
||||||
|
state.isMoving = true;
|
||||||
|
state.moveStart = Date.now();
|
||||||
|
}
|
||||||
|
state.currentX = 0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 4: // 下移
|
||||||
|
if (!state.isMoving && !state.isPausing) {
|
||||||
|
state.currentY = -totalHeight;
|
||||||
|
state.isMoving = true;
|
||||||
|
state.moveStart = Date.now();
|
||||||
|
} else if (state.isMoving) {
|
||||||
|
const elapsed = Date.now() - state.moveStart;
|
||||||
|
const progress = Math.min(1, elapsed / (totalHeight * 1000 / animSpeed));
|
||||||
|
|
||||||
|
state.currentY = -totalHeight + progress * (zoneHeight + totalHeight);
|
||||||
|
|
||||||
|
if (progress >= 1) {
|
||||||
|
state.isMoving = false;
|
||||||
|
state.isPausing = true;
|
||||||
|
state.pauseStart = Date.now();
|
||||||
|
}
|
||||||
|
} else if (state.isPausing) {
|
||||||
|
if (Date.now() - state.pauseStart >= pauseMs) {
|
||||||
|
state.isPausing = false;
|
||||||
|
state.isMoving = true; // 准备翻页
|
||||||
|
}
|
||||||
|
} else if (!state.isPausing && state.isMoving) {
|
||||||
|
state.currentPage = (state.currentPage + 1) % asset.pages.length;
|
||||||
|
state.currentY = -totalHeight;
|
||||||
|
state.isMoving = true;
|
||||||
|
state.moveStart = Date.now();
|
||||||
|
}
|
||||||
|
state.currentX = 0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 5: // 连续左移 (跑马灯效果)
|
||||||
|
// 特殊处理 - 不分页
|
||||||
|
if (typeof state.currentX !== 'number') state.currentX = zoneWidth;
|
||||||
|
state.currentX -= animSpeed;
|
||||||
|
if (state.currentX < -totalWidth) {
|
||||||
|
state.currentX += totalWidth;
|
||||||
|
}
|
||||||
|
state.currentY = (zoneHeight - totalHeight) / 2;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 6: // 闪烁换页
|
||||||
|
if (!state.isPausing && !state.isMoving) {
|
||||||
|
state.isPausing = true;
|
||||||
|
state.pauseStart = Date.now();
|
||||||
|
} else if (state.isPausing) {
|
||||||
|
if (Date.now() - state.pauseStart >= pauseMs) {
|
||||||
|
state.isPausing = false;
|
||||||
|
state.isMoving = true; // 准备翻页
|
||||||
|
}
|
||||||
|
} else if (state.isMoving) {
|
||||||
|
state.currentPage = (state.currentPage + 1) % asset.pages.length;
|
||||||
|
state.isMoving = false;
|
||||||
|
state.isPausing = true;
|
||||||
|
state.pauseStart = Date.now();
|
||||||
|
}
|
||||||
|
state.currentX = 0;
|
||||||
|
state.currentY = 0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default: // 立即显示 (effect === 0) 或其他未知效果
|
||||||
|
state.currentX = 0;
|
||||||
|
state.currentY = 0;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
state.currentY = 0;
|
});
|
||||||
break;
|
},
|
||||||
case 2: // 右移
|
|
||||||
if (typeof state.currentX !== 'number') state.currentX = -totalWidth;
|
|
||||||
state.currentX += animSpeed;
|
|
||||||
if (state.currentX > zoneWidth) {
|
|
||||||
if (asset.pages.length > 1) {
|
|
||||||
state.currentPage = (state.currentPage + 1) % asset.pages.length;
|
|
||||||
}
|
|
||||||
state.currentX = -totalWidth;
|
|
||||||
}
|
|
||||||
state.currentY = 0;
|
|
||||||
break;
|
|
||||||
case 3: // 上移
|
|
||||||
if (typeof state.currentY !== 'number') state.currentY = zoneHeight;
|
|
||||||
state.currentY -= animSpeed;
|
|
||||||
if (state.currentY < -totalHeight) {
|
|
||||||
if (asset.pages.length > 1) {
|
|
||||||
state.currentPage = (state.currentPage + 1) % asset.pages.length;
|
|
||||||
}
|
|
||||||
state.currentY = zoneHeight;
|
|
||||||
}
|
|
||||||
state.currentX = 0;
|
|
||||||
break;
|
|
||||||
case 4: // 下移
|
|
||||||
if (typeof state.currentY !== 'number') state.currentY = -totalHeight;
|
|
||||||
state.currentY += animSpeed;
|
|
||||||
if (state.currentY > zoneHeight) {
|
|
||||||
if (asset.pages.length > 1) {
|
|
||||||
state.currentPage = (state.currentPage + 1) % asset.pages.length;
|
|
||||||
}
|
|
||||||
state.currentY = -totalHeight;
|
|
||||||
}
|
|
||||||
state.currentX = 0;
|
|
||||||
break;
|
|
||||||
case 5: // 连续左移 (跑马灯效果)
|
|
||||||
// 确保初始位置在分区右侧外部
|
|
||||||
if (typeof state.currentX !== 'number') state.currentX = zoneWidth;
|
|
||||||
// 向左移动文本
|
|
||||||
state.currentX -= animSpeed;
|
|
||||||
// 当文本完全移出左侧边界时,重置到右侧重新开始(无缝循环)
|
|
||||||
if (state.currentX < -totalWidth) {
|
|
||||||
state.currentX += totalWidth;
|
|
||||||
}
|
|
||||||
// Y轴居中显示
|
|
||||||
state.currentY = (zoneHeight - totalHeight) / 2;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 6: // 闪烁换页
|
|
||||||
// 由自动翻页定时器控制,此处不处理动画位移
|
|
||||||
state.currentX = 0;
|
|
||||||
state.currentY = 0;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default: // 立即显示 (effect === 0) 或其他未知效果
|
|
||||||
state.currentX = 0;
|
|
||||||
state.currentY = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
measureTextWidth(text, asset) {
|
measureTextWidth(text, asset) {
|
||||||
// 用于动画宽度测量
|
// 用于动画宽度测量
|
||||||
const canvas = document.createElement('canvas');
|
const canvas = document.createElement('canvas');
|
||||||
|
Loading…
x
Reference in New Issue
Block a user