document.addEventListener('DOMContentLoaded', function () { const textInput = document.getElementById('textInput'); const fontFamily = document.getElementById('fontFamily'); const invertColors = document.getElementById('invertColors'); const showGrid = document.getElementById('showGrid'); const generateBtn = document.getElementById('generateBtn'); const upload_rili_text = document.getElementById('upload_rili_text'); const previewCanvas = document.getElementById('previewCanvas'); const codeOutput = document.getElementById('codeOutput'); const copyBtn = document.getElementById('copyBtn'); const gridInfoText = document.getElementById('gridInfoText'); const fontSizeSlider = document.getElementById('fontSizeSlider'); const fontSizeValue = document.getElementById('fontSizeValue'); const gridSizeSelect = document.getElementById('gridSizeSelect'); const currentGridSize = document.getElementById('currentGridSize'); const sizeHint = document.getElementById('sizeHint'); const ctx = previewCanvas.getContext('2d'); document.getElementById('fullAutoActivateBtn').addEventListener('click', fullAutoActivate); const previewScale = 8; let fontSizeRatio = 0.85; const grid_Size=16; updateGridSize(); drawPreview(); generateBtn.addEventListener('click', function () { drawPreview(); generateCode(); }); upload_rili_text.addEventListener('click', function () { drawPreview(); upload_rili(); }); copyBtn.addEventListener('click', function () { sendcode(); }); fontSizeSlider.addEventListener('input', function () { const value = this.value; fontSizeValue.textContent = `${value}%`; fontSizeRatio = value / 100; drawPreview(); }); gridSizeSelect.addEventListener('change', function () { updateGridSize(); drawPreview(); }); function getCurrentGridSize() { return parseInt(gridSizeSelect.value); } function updateGridSize() { const gridSize = getCurrentGridSize(); currentGridSize.textContent = ``; } function formatDate(date) { const year = date.getFullYear(); const month = date.getMonth() + 1; const day = date.getDate(); return `${year}年${month}月${day}日`; } function drawPreview() { const text = textInput.value || 'ABCDEFGH'; const charCount = text.length; const font = fontFamily.value; const invert = invertColors.checked; const grid = showGrid.checked; const gridSize = getCurrentGridSize(); const gridSize_all=gridSize==16?128:96; // 计算实际显示宽度 function getCharWidth(char) { if (/[\u4e00-\u9fff\u3000-\u303f\uff00-\uffef]/.test(char)) { return gridSize; // 汉字/中文标点 } return gridSize/2; // 英文/数字/英文标点 } function getTotalWidth(str) { let width = 0; for (let char of str) { width += getCharWidth(char); } return width; } const totalDisplayWidth = getTotalWidth(text); const actualCharWidth = gridSize * getCharWidth(text[0] || 'A'); if (totalDisplayWidth > gridSize_all) { alert(`超出总字符(当前:${totalDisplayWidth},时钟倒计时最大支持16个英文或8个汉字,日历倒计时最大支持8个英文或4个汉字)`); return; } previewCanvas.width = totalDisplayWidth * previewScale; previewCanvas.height = gridSize * previewScale; ctx.clearRect(0, 0, previewCanvas.width, previewCanvas.height); ctx.fillStyle = invert ? '#000000' : '#ffffff'; ctx.fillRect(0, 0, previewCanvas.width, previewCanvas.height); let currentX = 0; ctx.font = `bold ${gridSize * fontSizeRatio * previewScale}px ${font}`; ctx.textBaseline = 'middle'; ctx.fillStyle = invert ? '#ffffff' : '#000000'; for (let i = 0; i < charCount; i++) { const currentChar = text[i]; const charDisplayWidth = getCharWidth(currentChar); const charPixelWidth = charDisplayWidth * previewScale; const charX = currentX + charPixelWidth / 2; ctx.textAlign = 'center'; ctx.fillText(currentChar, charX, previewCanvas.height / 2); currentX += charPixelWidth; } if (grid) { ctx.strokeStyle = invert ? '#333333' : '#dddddd'; for (let x = 0; x <= charCount * gridSize; x++) { const lineX = x * previewScale; ctx.beginPath(); ctx.moveTo(lineX, 0); ctx.lineTo(lineX, previewCanvas.height); ctx.lineWidth = x % gridSize === 0 ? 2 : 1; ctx.stroke(); } for (let y = 0; y <= gridSize; y++) { const lineY = y * previewScale; ctx.beginPath(); ctx.moveTo(0, lineY); ctx.lineTo(previewCanvas.width, lineY); ctx.lineWidth = 1; ctx.stroke(); } } } async function sendcode() { triggerRxTxCmd('FA'); await delay(1000); triggerRxTxCmd('E2'); } function calculateTextWidth(text) { let totalWidth = 0; for (let i = 0; i < text.length; i++) { const char = text[i]; if (/[\u4e00-\u9fff\u3400-\u4dbf\uf900-\ufaff\u2e80-\u2eff\u3000-\u303f\u31c0-\u31ef\u2f00-\u2fdf\u2e80-\u2eff\u1100-\u11ff\u3130-\u318f\uac00-\ud7af]/.test(char)) { totalWidth += 2; // 中文字符宽度 } else { totalWidth += 1; // 英文字符及数字、标点等宽度 } } return Math.ceil(totalWidth / 2); } async function generateCode() { const text = textInput.value || 'ABCDEFGH'; const gridSize = getCurrentGridSize(); const charCount =calculateTextWidth(text) ; const font = fontFamily.value; const invert = invertColors.checked; const totalGridWidth = charCount * gridSize; const totalGridHeight = gridSize; const tempCanvas = document.createElement('canvas'); tempCanvas.width = totalGridWidth; tempCanvas.height = totalGridHeight; const tempCtx = tempCanvas.getContext('2d'); tempCtx.fillStyle = invert ? '#000000' : '#ffffff'; tempCtx.fillRect(0, 0, totalGridWidth, totalGridHeight); tempCtx.font = `bold ${totalGridHeight * fontSizeRatio}px ${font}`; tempCtx.textAlign = 'center'; tempCtx.textBaseline = 'middle'; tempCtx.fillStyle = invert ? '#ffffff' : '#000000'; tempCtx.fillText(text, totalGridWidth / 2, totalGridHeight / 2); const imageData = tempCtx.getImageData(0, 0, totalGridWidth, totalGridHeight); const data = imageData.data; const allBytes = []; for (let y = 0; y < totalGridHeight; y++) { const bytesPerLine = totalGridWidth / 8; const lineBytes = new Array(bytesPerLine).fill(0); for (let x = 0; x < totalGridWidth; x++) { const pixelIndex = (y * totalGridWidth + x) * 4; const brightness = (data[pixelIndex] + data[pixelIndex + 1] + data[pixelIndex + 2]) / 3; const bitValue = invert ? (brightness > 128 ? 0 : 1) : (brightness > 128 ? 1 : 0); const byteIndex = Math.floor(x / 8); const bitPosition = 7 - (x % 8); lineBytes[byteIndex] |= (bitValue << bitPosition); } allBytes.push(...lineBytes); } if (gridSize == 16) { if (charCount > 8) {addLog(`设置字符超过了16个(纯中文字符最多4个,纯英文字符最多8个)`); return;} if (charCount > 4) { let code = '0' + 4; for (let i = 0; i < allBytes.length - 1 - (charCount - 4) * 32; i++) { code += `${allBytes[i].toString(16).padStart(2, '0')}`; } triggerRxTxCmd(code); await delay(1000); let code1 = '0' + charCount; for (let i = 128; i < allBytes.length - 1; i++) { code1 += `${allBytes[i].toString(16).padStart(2, '0')}`; } triggerRxTxCmd(code1); } else { let code = '0' + (charCount); for (let i = 0; i < allBytes.length - 1; i++) { code += `${allBytes[i].toString(16).padStart(2, '0')}`; } triggerRxTxCmd(code); } } else if (gridSize == 24) { if (charCount > 4) {addLog(`设置字符超过了8个(纯中文字符最多4个,纯英文字符最多8个)`); return;} for (let j = 0; j < charCount; j++) { let code = '990' + j; for (let i = 0; i < 72; i++) { code += `${allBytes[i + j * 72].toString(16).padStart(2, '0')}`; } triggerRxTxCmd(code); await delay(1000); } } const selectedDate = new Date(datePicker.value); let year = selectedDate.getFullYear(); let month = selectedDate.getMonth() + 1; let day = selectedDate.getDate(); await delay(1000); if (month < 10) month = '0' + month; if (day < 10) day = '0' + day; if (gridSize == 24) { let code2 = 'ffff' + year + month + day; if (year > 2000) { triggerRxTxCmd(code2); }; } else { let code2 = 'ff00' + year + month + day; if (year > 2000) { triggerRxTxCmd(code2); }; } await delay(1000); triggerRxTxCmd('E2'); } async function upload_rili() { const text = textInput.value || 'ABCDEFGH'; const gridSize = getCurrentGridSize(); const charCount = calculateTextWidth(text); const font = fontFamily.value; const invert = invertColors.checked; const totalGridWidth = charCount * gridSize; const totalGridHeight = gridSize; const tempCanvas = document.createElement('canvas'); tempCanvas.width = totalGridWidth; tempCanvas.height = totalGridHeight; const tempCtx = tempCanvas.getContext('2d'); tempCtx.fillStyle = invert ? '#000000' : '#ffffff'; tempCtx.fillRect(0, 0, totalGridWidth, totalGridHeight); tempCtx.font = `bold ${totalGridHeight * fontSizeRatio}px ${font}`; tempCtx.textAlign = 'center'; tempCtx.textBaseline = 'middle'; tempCtx.fillStyle = invert ? '#ffffff' : '#000000'; tempCtx.fillText(text, totalGridWidth / 2, totalGridHeight / 2); const imageData = tempCtx.getImageData(0, 0, totalGridWidth, totalGridHeight); const data = imageData.data; const allBytes = []; for (let y = 0; y < totalGridHeight; y++) { const bytesPerLine = totalGridWidth / 8; const lineBytes = new Array(bytesPerLine).fill(0); for (let x = 0; x < totalGridWidth; x++) { const pixelIndex = (y * totalGridWidth + x) * 4; const brightness = (data[pixelIndex] + data[pixelIndex + 1] + data[pixelIndex + 2]) / 3; const bitValue = invert ? (brightness > 128 ? 0 : 1) : (brightness > 128 ? 1 : 0); const byteIndex = Math.floor(x / 8); const bitPosition = 7 - (x % 8); lineBytes[byteIndex] |= (bitValue << bitPosition); } allBytes.push(...lineBytes); } if (gridSize == 24) { if (charCount > 4) {addLog(`设置字符超过了8个(纯中文字符最多4个,纯英文字符最多8个)`); return;} for (let j = 0; j < charCount; j++) { let code = '990' + j; for (let i = 0; i < 72; i++) { code += `${allBytes[i + j * 72].toString(16).padStart(2, '0')}`; } triggerRxTxCmd(code); await delay(1000); } } triggerRxTxCmd('FA'); await delay(1000); triggerRxTxCmd('e10103'); await delay(1000); triggerRxTxCmd('E2'); } textInput.addEventListener('input', drawPreview); fontFamily.addEventListener('change', drawPreview); invertColors.addEventListener('change', drawPreview); showGrid.addEventListener('change', drawPreview); window.drawPreview = drawPreview; });