显卡分页逻辑以及移动逻辑修复

This commit is contained in:
1 2025-07-25 16:25:33 +08:00
parent 830f16a9f5
commit 2355147ed5

View File

@ -752,7 +752,7 @@ export default {
imageSize: 1, // 32x32 imageSize: 1, // 32x32
imageColor: 0, // imageColor: 0, //
effect: 0, effect: 0,
speed: 4, speed: 0,
stayTime: 5, stayTime: 5,
hAlign: 1, hAlign: 1,
vAlign: 1, vAlign: 1,
@ -1053,7 +1053,7 @@ export default {
imageSize: 1, imageSize: 1,
imageColor: 0, // imageColor: 0, //
effect: 0, effect: 0,
speed: 4, speed: 0,
stayTime: 5, stayTime: 5,
hAlign: 1, hAlign: 1,
vAlign: 1, vAlign: 1,
@ -1093,7 +1093,7 @@ export default {
// //
if (item.anim) { if (item.anim) {
zone.effect = item.anim.typ ? item.anim.typ - 1 : 0; // 1 zone.effect = item.anim.typ ? item.anim.typ - 1 : 0; // 1
zone.speed = item.anim.spd || 4; // zone.speed = item.anim.spd || 0; //
zone.stayTime = item.anim.pauseT ? this.getStayTimeIndex(item.anim.pauseT) : 5; // zone.stayTime = item.anim.pauseT ? this.getStayTimeIndex(item.anim.pauseT) : 5; //
} }
} }
@ -1117,7 +1117,7 @@ export default {
imageSize: 1, imageSize: 1,
imageColor: 0, // imageColor: 0, //
effect: 0, effect: 0,
speed: 4, speed: 0,
stayTime: 5, stayTime: 5,
hAlign: 1, hAlign: 1,
vAlign: 1, vAlign: 1,
@ -2231,7 +2231,7 @@ export default {
imageSize: 1, imageSize: 1,
imageColor: 0, // imageColor: 0, //
effect: 0, effect: 0,
speed: 4, speed: 0,
stayTime: 5, stayTime: 5,
hAlign: 1, hAlign: 1,
vAlign: 1, vAlign: 1,
@ -2275,7 +2275,7 @@ export default {
imageSize: 1, imageSize: 1,
imageColor: 0, // imageColor: 0, //
effect: 0, effect: 0,
speed: 4, speed: 0,
stayTime: 5, stayTime: 5,
hAlign: 1, hAlign: 1,
vAlign: 1, vAlign: 1,
@ -2413,7 +2413,7 @@ export default {
// //
const programData = { const programData = {
del_prog: 0, // // del_prog: 0, //
prog_list: [programObj] prog_list: [programObj]
}; };
@ -2517,7 +2517,7 @@ export default {
if (zone.playType === 0 && asset.isText) { if (zone.playType === 0 && asset.isText) {
// //
const page = this.addProgramPreviewPage[zIdx] || 0; const page = state && typeof state.currentPage === 'number' ? state.currentPage : 0;
const pageLines = asset.pages[page] || []; const pageLines = asset.pages[page] || [];
// //
@ -2580,7 +2580,17 @@ export default {
if (effect === 3 || effect === 4) animOffsetY = state.currentY; if (effect === 3 || effect === 4) animOffsetY = state.currentY;
} }
ctx.fillText(line, startX + animOffsetX, startY + lineIdx * lineHeight + animOffsetY); //
if (zone.effect === 5 && state) {
let x1 = zoneX + state.currentX;
let x2 = x1 + textWidth;
//
let y = zoneY + (zoneHeight - lineHeight) / 2;
ctx.fillText(line, x1, y);
ctx.fillText(line, x2, y);
} else {
ctx.fillText(line, startX + (state ? state.currentX : 0), startY + lineIdx * lineHeight + (state ? state.currentY : 0));
}
}); });
} else if (zone.playType === 1 && asset.isImage) { } else if (zone.playType === 1 && asset.isImage) {
// //
@ -2668,124 +2678,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;
// 90270 // 90270
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 renderWidth = 640; //
const scale = Math.min(renderWidth / screenW, 240 / screenH); const scale = Math.min(renderWidth / screenW, 240 / screenH);
this.addProgramPreviewAssets = this.addProgramForm.zones.map(zone => { this.addProgramPreviewAssets = this.addProgramForm.zones.map(zone => {
if (zone.playType === 1 && zone.image) { if (zone.playType === 1 && zone.image) {
console.log('加载图片', zone.image); //
// const img = new window.Image();
const img = new window.Image(); const asset = { img, isImage: true, loaded: false };
// img.crossOrigin = 'Anonymous'; img.onload = () => {
const asset = { img, isImage: true, loaded: false }; asset.loaded = true;
img.onload = () => { this.drawAddProgramPreview();
asset.loaded = true; };
this.drawAddProgramPreview(); img.onerror = (e) => {
}; console.error("Preview image failed to load:", e);
img.onerror = (e) => { };
console.error("Preview image failed to load:", e); img.src = zone.image;
}; return asset;
img.src = zone.image; }
return asset; if (zone.playType !== 0 || !zone.displayText) {
} return { pages: [[]], isText: false };
if (zone.playType !== 0 || !zone.displayText) { }
return { pages: [[]], isText: false };
}
// //
const fontSize = parseInt(this.addProgramFontSizes[zone.fontSize] || '16px'); const fontSize = parseInt(this.addProgramFontSizes[zone.fontSize] || '16px');
// //
const scaledFontSize = Math.max(10, Math.round(fontSize * scale * 0.8)); // 0.8 const scaledFontSize = Math.max(10, Math.round(fontSize * scale * 0.8)); // 0.8
const fontFamily = [ const fontFamily = [
'SimSun, 宋体, Songti SC, serif', 'SimSun, 宋体, Songti SC, serif',
'SimHei, 黑体, Heiti SC, sans-serif', 'SimHei, 黑体, Heiti SC, sans-serif',
'KaiTi, 楷体, Kaiti SC, serif' 'KaiTi, 楷体, Kaiti SC, serif'
]; ];
const fontWeight = zone.fontBold ? 'bold' : 'normal'; const fontWeight = zone.fontBold ? 'bold' : 'normal';
// canvas // canvas
const measureCanvas = document.createElement('canvas'); const measureCanvas = document.createElement('canvas');
const measureCtx = measureCanvas.getContext('2d'); const measureCtx = measureCanvas.getContext('2d');
const fontFamilies2 = [ const enFontMap = [
'SimSun, 宋体, Songti SC, serif', 'Courier New', 'Arial Black', 'Arial Italic', 'Lucida Console', 'Impact', 'Gothic', 'Arial Narrow', 'Comic Sans MS', 'Brush Script MT', 'Century Gothic', 'Times New Roman'
'SimHei, 黑体, Heiti SC, sans-serif', ];
'KaiTi, 楷体, Kaiti SC, serif' let fontFamilyUsed;
]; if (/^[A-Za-z0-9\s]+$/.test(zone.displayText)) {
const enFontMap2 = [ fontFamilyUsed = enFontMap[zone.fontEn] || fontFamily[0];
'Courier New', 'Arial Black', 'Arial Italic', 'Lucida Console', 'Impact', 'Gothic', 'Arial Narrow', 'Comic Sans MS', 'Brush Script MT', 'Century Gothic', 'Times New Roman' } else {
]; fontFamilyUsed = fontFamily[zone.font] || fontFamily[0];
let fontFamily2; }
if (/^[A-Za-z0-9\s]+$/.test(zone.displayText)) { measureCtx.font = `${fontWeight} ${scaledFontSize}px ${fontFamilyUsed}`;
fontFamily2 = enFontMap2[zone.fontEn] || fontFamilies2[0];
// -
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 { } else {
fontFamily2 = fontFamilies2[zone.font] || fontFamilies2[0]; currentLine = testLine;
} }
measureCtx.font = `${fontWeight} ${scaledFontSize}px ${fontFamily2}`; }
// if (currentLine) lines.push(currentLine);
const zoneRenderWidth = swapWH ? zone.height : zone.width; }
const maxWidth = zoneRenderWidth * scale - 4; // 4px
let currentLine = '';
const lines = [];
for (const char of zone.displayText) { //
const testLine = currentLine + char; const zoneRenderHeight = swapWH ? zone.width : zone.height;
const metrics = measureCtx.measureText(testLine); const lineHeight = scaledFontSize * 1.2;
const maxLines = Math.max(1, Math.floor((zoneRenderHeight * scale - 4) / lineHeight));
if (metrics.width > maxWidth) { //
if (currentLine) lines.push(currentLine); const pages = [];
currentLine = char; for (let i = 0; i < lines.length; i += maxLines) {
} else { pages.push(lines.slice(i, i + maxLines));
currentLine = testLine; }
}
}
if (currentLine) lines.push(currentLine); if (pages.length === 0) pages.push([]);
// //
const zoneRenderHeight = swapWH ? zone.width : zone.height; const totalWidth = Math.max(...pages.flat().map(line => measureCtx.measureText(line).width), 0);
const lineHeight = scaledFontSize * 1.2; const totalHeight = Math.min(lines.length, maxLines) * lineHeight;
const maxLines = Math.max(1, Math.floor((zoneRenderHeight * scale - 4) / lineHeight));
// return {
const pages = []; pages,
for (let i = 0; i < lines.length; i += maxLines) { isText: true,
pages.push(lines.slice(i, i + maxLines)); scaledFontSize,
} fontFamily: fontFamilyUsed,
fontWeight,
if (pages.length === 0) pages.push([]); lineHeight,
totalWidth,
// totalHeight,
const totalWidth = Math.max(...lines.map(line => measureCtx.measureText(line).width), 0); zoneRenderWidth: (swapWH ? zone.height : zone.width) * scale,
const totalHeight = lines.length * lineHeight; zoneRenderHeight: (swapWH ? zone.width : zone.height) * scale
return { };
pages, });
isText: true, },
scaledFontSize,
fontFamily: fontFamily2,
fontWeight,
lineHeight,
totalWidth,
totalHeight,
zoneRenderWidth: zoneRenderWidth * scale,
zoneRenderHeight: zoneRenderHeight * scale
};
});
},
resetAddProgramPreviewPage() { resetAddProgramPreviewPage() {
this.addProgramPreviewPage = this.addProgramForm.zones.map(() => 0); this.addProgramPreviewPage = this.addProgramForm.zones.map(() => 0);
}, },
@ -2881,292 +2891,118 @@ export default {
this.addProgramPreviewAnimFrame = requestAnimationFrame(loop); this.addProgramPreviewAnimFrame = requestAnimationFrame(loop);
}, },
updateAddProgramPreviewAnimState() { updateAddProgramPreviewAnimState() {
// //
const renderWidth = 640; const renderWidth = 640;
const renderHeight = 240; const renderHeight = 240;
// const scale = Math.min(renderWidth / 32, renderHeight / 64); let screenW = this.screenParams.width || 32;
// 使 prepareAddProgramPreviewAssets scale let screenH = this.screenParams.height || 64;
let screenW = this.screenParams.width || 32; const angle = this.screenParams.angle;
let screenH = this.screenParams.height || 64; const swapWH = angle === 90 || angle === 270;
const angle = this.screenParams.angle; if (swapWH) {
const swapWH = angle === 90 || angle === 270; [screenW, screenH] = [screenH, screenW];
if (swapWH) { }
[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) => {
const asset = this.addProgramPreviewAssets[idx];
const state = this.addProgramPreviewAnimState[idx];
this.addProgramForm.zones.forEach((zone, idx) => { if (!asset || !state || !asset.isText) return;
const asset = this.addProgramPreviewAssets[idx];
const state = this.addProgramPreviewAnimState[idx];
if (!asset || !state || !asset.isText) return; const effect = zone.effect;
const page = this.addProgramPreviewPage[idx] || 0;
const pageLines = asset.pages[page] || [];
const lineHeight = asset.lineHeight;
const totalHeight = asset.totalHeight;
const totalWidth = asset.totalWidth;
const effect = zone.effect; //
const page = this.addProgramPreviewPage[idx] || 0; const speedMap = [1, 2, 3, 4, 5];
const pageLines = asset.pages[page] || []; const animSpeed = (speedMap[zone.speed] || 3) * scale * 0.5; // /
const lineHeight = asset.lineHeight;
// const totalHeight = pageLines.length * lineHeight; //
// const totalWidth = Math.max(...pageLines.map(line => measureCtx.measureText(line).width), 0); //
// 使 prepareAddProgramPreviewAssets
const totalHeight = asset.totalHeight;
const totalWidth = asset.totalWidth;
// (使)
const zoneWidth = asset.zoneRenderWidth;
const zoneHeight = asset.zoneRenderHeight;
// // ()
const speedMap = [1, 2, 3, 4, 5]; const pauseMs = this.getPauseTime(zone.stayTime);
const animSpeed = (speedMap[zone.speed] || 3) * scale * 0.5; // /
// (使) //
const zoneWidth = asset.zoneRenderWidth; if (typeof state.isPausing !== 'boolean') state.isPausing = false;
const zoneHeight = asset.zoneRenderHeight; if (typeof state.pauseStart !== 'number') state.pauseStart = 0;
if (typeof state.pausePhase !== 'string') state.pausePhase = 'start'; // 'start' | 'move'
// () switch (effect) {
const pauseMs = this.getPauseTime(zone.stayTime); case 1: //
if (typeof state.currentX !== 'number') state.currentX = zoneWidth;
// state.currentX -= animSpeed;
if (typeof state.isPausing !== 'boolean') state.isPausing = false; if (state.currentX < -totalWidth) {
if (typeof state.pauseStart !== 'number') state.pauseStart = 0; if (asset.pages.length > 1) {
if (typeof state.pausePhase !== 'string') state.pausePhase = 'start'; // 'start' | 'move' state.currentPage = (state.currentPage + 1) % asset.pages.length;
}
state.currentX = zoneWidth;
switch (effect) {
case 1: //
// state.currentX
if (typeof state.currentX !== 'number') state.currentX = 0;
// pausePhase
if (!state.pausePhase) state.pausePhase = 'start'; // 'start' | 'move'
//
if (!state.isPausing && state.pausePhase === 'start') {
state.isPausing = true;
state.pauseStart = Date.now();
}
//
if (state.isPausing && state.pausePhase === 'start') {
if (Date.now() - state.pauseStart >= pauseMs) {
state.isPausing = false;
state.pausePhase = 'move';
}
//
} else if (!state.isPausing && state.pausePhase === 'move') {
// --- ---
// !!! !!!
// : if (state.currentX + totalWidth > 0)
// : (0) (-state.currentX)
// ""
const pixelsMoved = -state.currentX; // X=0
const distanceToTriggerReset = zoneWidth + 100; // <--- +
// 32 + 100 = 132
// 100
if (pixelsMoved < distanceToTriggerReset) {
//
state.currentX -= animSpeed;
} else {
//
// console.log(`Zone ${idx} - Left Move: Forcefully reset after moving ${pixelsMoved.toFixed(2)} pixels.`); //
state.currentX = 0; //
state.pausePhase = 'start'; //
}
// --- ---
}
// Y
state.currentY = 0;
break;
case 2: //
// state.currentX
if (typeof state.currentX !== 'number') state.currentX = 0; //
// pausePhase
if (!state.pausePhase) state.pausePhase = 'start'; // 'start' | 'move'
//
if (!state.isPausing && state.pausePhase === 'start') {
state.isPausing = true;
state.pauseStart = Date.now();
}
//
if (state.isPausing && state.pausePhase === 'start') {
if (Date.now() - state.pauseStart >= pauseMs) {
state.isPausing = false;
state.pausePhase = 'move';
}
//
} else if (!state.isPausing && state.pausePhase === 'move') {
// --- ---
//
// (currentX < zoneWidth)
if (state.currentX < zoneWidth) {
state.currentX += animSpeed;
//
// if (state.currentX > zoneWidth) {
// state.currentX = zoneWidth; //
// }
} else {
//
// 'end'
state.currentX = 0; //
state.pausePhase = 'start'; //
}
// --- ---
}
// Y
state.currentY = 0;
break;
case 3: //
// state.currentY
if (typeof state.currentY !== 'number') state.currentY = 0;
// pausePhase
if (!state.pausePhase) state.pausePhase = 'start'; // 'start' | 'move'
//
if (!state.isPausing && state.pausePhase === 'start') {
state.isPausing = true;
state.pauseStart = Date.now();
}
//
if (state.isPausing && state.pausePhase === 'start') {
if (Date.now() - state.pauseStart >= pauseMs) {
state.isPausing = false;
state.pausePhase = 'move';
}
//
} else if (!state.isPausing && state.pausePhase === 'move') {
// --- ---
//
// (currentY + totalHeight > 0)
if (state.currentY + totalHeight > 0) {
state.currentY -= animSpeed;
//
// if (state.currentY + totalHeight < 0) {
// state.currentY = -totalHeight;
// }
} else {
//
// 'end'
state.currentY = 0; //
state.pausePhase = 'start'; //
}
// --- ---
}
// X
state.currentX = 0;
break;
case 4: //
// state.currentY
if (typeof state.currentY !== 'number') state.currentY = 0; //
// pausePhase
if (!state.pausePhase) state.pausePhase = 'start'; // 'start' | 'move'
//
if (!state.isPausing && state.pausePhase === 'start') {
state.isPausing = true;
state.pauseStart = Date.now();
}
//
if (state.isPausing && state.pausePhase === 'start') {
if (Date.now() - state.pauseStart >= pauseMs) {
state.isPausing = false;
state.pausePhase = 'move';
}
//
} else if (!state.isPausing && state.pausePhase === 'move') {
// --- ---
//
// (currentY < zoneHeight)
if (state.currentY < zoneHeight) {
state.currentY += animSpeed;
//
// if (state.currentY > zoneHeight) {
// state.currentY = zoneHeight;
// }
} else {
//
// 'end'
state.currentY = 0; //
state.pausePhase = 'start'; //
}
// --- ---
}
// X
state.currentX = 0;
break;
case 5: // ( -> -> -> ...)
// state.currentX
if (typeof state.currentX !== 'number') state.currentX = 0;
// pausePhase
if (!state.pausePhase) state.pausePhase = 'start'; // 'start' | 'move'
// ()
if (!state.isPausing && state.pausePhase === 'start') {
// pauseMs
state.isPausing = true;
state.pauseStart = Date.now();
}
//
if (state.isPausing && state.pausePhase === 'start') {
if (Date.now() - state.pauseStart >= pauseMs) {
state.isPausing = false;
state.pausePhase = 'move'; //
}
// ()
} else if (!state.isPausing && state.pausePhase === 'move') {
// --- () ---
//
if (state.currentX > -totalWidth) {
state.currentX -= animSpeed;
//
// if (state.currentX < -totalWidth) {
// state.currentX = -totalWidth;
// }
} else {
//
// pauseMs
state.isPausing = true;
state.pauseStart = Date.now();
state.currentX = 0; //
state.pausePhase = 'start'; // 'start'
}
// --- ---
}
state.currentY = 0; // Y
break;
case 6: //
//
state.currentX = 0;
state.currentY = 0;
break;
default: // (effect === 0)
state.currentX = 0;
state.currentY = 0;
//
// if (!state.isPausing && state.pausePhase === 'start') {
// state.isPausing = true;
// state.pauseStart = Date.now();
// }
// if (state.isPausing && state.pausePhase === 'start') {
// if (Date.now() - state.pauseStart >= pauseMs) {
// state.isPausing = false;
// state.pausePhase = 'end'; // 'start'
// }
// }
// state.pausePhase = 'start'; // 便
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');