Files
qianbian/analysis/web/timedjs2.js

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;
});