324 lines
14 KiB
JavaScript
324 lines
14 KiB
JavaScript
|
|
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;
|
|
|
|
});
|