\n'; renderPreview(); }); // 清空 els.btnClear.addEventListener('click', function () { els.htmlInput.value = ''; els.emptyHint.style.display = 'flex'; els.previewFrame.style.display = 'none'; els.resultImage.src = ''; els.btnDownload.disabled = true; resultBlob = null; }); // 转换为图片 els.btnConvert.addEventListener('click', handleConvert); // 下载 els.btnDownload.addEventListener('click', handleDownload); // 宽度滑块 els.outputWidth.addEventListener('input', function () { els.widthVal.textContent = this.value; }); // 缩放滑块 els.outputScale.addEventListener('input', function () { els.scaleVal.textContent = this.value; }); // 格式选择 els.formatOptions.forEach(function (opt) { opt.addEventListener('click', function () { els.formatOptions.forEach(function (o) { o.classList.remove('active'); }); opt.classList.add('active'); }); }); // Tab 切换 els.tabBtns.forEach(function (btn) { btn.addEventListener('click', function () { var tab = btn.dataset.tab; els.tabBtns.forEach(function (b) { b.classList.remove('active'); }); btn.classList.add('active'); els.tabContents.forEach(function (c) { c.classList.remove('active'); }); document.getElementById('tab-' + tab).classList.add('active'); }); }); } /** 渲染 HTML 预览 */ function renderPreview() { var html = els.htmlInput.value.trim(); if (!html) { alert('请输入 HTML 代码'); return; } // 在 iframe 中渲染 HTML els.emptyHint.style.display = 'none'; els.previewFrame.style.display = 'block'; els.previewFrame.srcdoc = html; } /** 转换为图片 */ function handleConvert() { var html = els.htmlInput.value.trim(); if (!html) { alert('请输入 HTML 代码'); return; } // 先渲染预览 renderPreview(); var width = parseInt(els.outputWidth.value, 10) || 800; var scale = parseFloat(els.outputScale.value) || 2; var format = document.querySelector('.format-option.active'); var outputFormat = format ? format.dataset.format : 'png'; var mimeType = outputFormat === 'jpeg' ? 'image/jpeg' : 'image/png'; var ext = outputFormat === 'jpeg' ? 'jpg' : 'png'; els.btnConvert.disabled = true; els.btnConvert.textContent = '生成中...'; els.progressArea.style.display = 'block'; els.progressBarFill.style.width = '10%'; // 等待 iframe 渲染完成 setTimeout(function () { try { els.progressBarFill.style.width = '30%'; // 获取 iframe 内的文档元素 var iframeDoc = els.previewFrame.contentDocument || els.previewFrame.contentWindow.document; var iframeBody = iframeDoc.body; if (!iframeBody || iframeBody.innerHTML.trim() === '') { throw new Error('预览区域为空,请先点击「渲染预览」'); } els.progressBarFill.style.width = '50%'; // 使用 html2canvas 截图 html2canvas(iframeBody, { width: width, scale: scale, useCORS: true, allowTaint: false, backgroundColor: '#ffffff', logging: false }).then(function (canvas) { els.progressBarFill.style.width = '80%'; canvas.toBlob(function (blob) { resultBlob = blob; resultFilename = 'html-to-image.' + ext; var url = URL.createObjectURL(blob); els.resultImage.src = url; els.btnDownload.disabled = false; els.progressBarFill.style.width = '100%'; // 切换到结果 tab els.tabBtns.forEach(function (b) { b.classList.remove('active'); }); els.tabContents.forEach(function (c) { c.classList.remove('active'); }); document.querySelector('.tab-btn[data-tab="result"]').classList.add('active'); document.getElementById('tab-result').classList.add('active'); setTimeout(function () { els.progressArea.style.display = 'none'; els.progressBarFill.style.width = '0%'; }, 500); els.btnConvert.disabled = false; els.btnConvert.textContent = '转换为图片'; }, mimeType, 0.92); }).catch(function (err) { console.error('[html-to-image] 截图失败:', err); alert('截图失败: ' + err.message + '\n\n请检查 HTML 代码是否有语法错误'); els.btnConvert.disabled = false; els.btnConvert.textContent = '转换为图片'; els.progressArea.style.display = 'none'; }); } catch (err) { console.error('[html-to-image] 处理失败:', err); alert('处理失败: ' + err.message); els.btnConvert.disabled = false; els.btnConvert.textContent = '转换为图片'; els.progressArea.style.display = 'none'; } }, 500); } /** 下载图片 */ function handleDownload() { if (resultBlob) { downloadBlob(resultBlob, resultFilename); } } // 启动 if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', function () { cacheElements(); bindEvents(); // 默认渲染示例 setTimeout(renderPreview, 100); }); } else { cacheElements(); bindEvents(); setTimeout(renderPreview, 100); } })();