// 二维码功能 - 优化版编辑器工具栏 (function() { 'use strict'; // ========== 配置 ========== const CONFIG = { MIN_SIZE: 0, MAX_SIZE: 200, DEFAULT_SIZE: 100, PREVIEW_SIZE: 128, DEBOUNCE_DELAY: 300 }; // ========== DOM 元素缓存 ========== const elements = { btn: document.getElementById('qr-btn'), modal: document.getElementById('qr-modal'), input: document.getElementById('qr-input'), preview: document.getElementById('qr-preview'), closeBtn: document.querySelector('.qr-close'), cancelBtn: document.querySelector('.qr-cancel'), okBtn: document.querySelector('.qr-ok'), // 工具栏 editorToolbar: document.getElementById('editorToolbar'), textTools: document.getElementById('textTools'), imageTools: document.getElementById('imageTools'), bgTools: document.getElementById('bgTools'), qrTools: document.getElementById('qrTools'), qrOpacitySlider: document.getElementById('qrOpacitySlider'), qrOpacityValue: document.getElementById('qrOpacityValue'), qrScaleSlider: document.getElementById('qrScaleSlider'), qrScaleValue: document.getElementById('qrScaleValue') }; // 验证必需元素 if (!elements.btn || !elements.modal) return; // ========== 状态管理 ========== const state = { currentQR: null, selectedQR: null, previewTimer: null, isDragging: false }; // ========== 核心功能 ========== /** * 检查背景图并显示/隐藏二维码按钮 */ function checkBackground() { const container = document.getElementById('imageContainer'); if (!container) return; const bgImg = container.querySelector('img:not([data-type="qrcode"])'); const hasBackground = bgImg && bgImg.src && !bgImg.src.endsWith(window.location.href); elements.btn.classList.toggle('show', hasBackground); } /** * 打开二维码生成弹窗 */ function openModal() { elements.modal.classList.add('active'); elements.input.value = ''; elements.preview.innerHTML = ''; state.currentQR = null; elements.input.focus(); } /** * 关闭二维码生成弹窗 */ function closeModal() { elements.modal.classList.remove('active'); } /** * 生成二维码预览 */ function generatePreview() { const text = elements.input.value.trim(); if (!text) { elements.preview.innerHTML = ''; state.currentQR = null; return; } elements.preview.innerHTML = ''; try { state.currentQR = new QRCode(elements.preview, { text: text, width: CONFIG.PREVIEW_SIZE, height: CONFIG.PREVIEW_SIZE, colorDark: '#000000', colorLight: '#ffffff', correctLevel: QRCode.CorrectLevel.M }); } catch (error) { console.error('二维码生成失败:', error); } } /** * 将二维码添加到画布 */ function addToCanvas() { if (!state.currentQR) { alert('请输入内容'); return; } const canvas = elements.preview.querySelector('canvas'); if (!canvas) return; const container = document.getElementById('imageContainer'); const rect = container.getBoundingClientRect(); const img = document.createElement('img'); img.src = canvas.toDataURL('image/png'); img.className = 'qr-item'; img.dataset.type = 'qrcode'; img.style.cssText = ` width: ${CONFIG.DEFAULT_SIZE}px; height: ${CONFIG.DEFAULT_SIZE}px; opacity: 1; left: ${(rect.width / 2 - CONFIG.DEFAULT_SIZE / 2)}px; top: ${(rect.height / 2 - CONFIG.DEFAULT_SIZE / 2)}px; `; container.appendChild(img); makeDraggable(img); selectQR(img); closeModal(); saveState(); } /** * 选中二维码 */ function selectQR(img) { // 取消其他选中状态 document.querySelectorAll('.qr-item').forEach(el => { el.classList.remove('qr-selected'); }); // 选中当前二维码 img.classList.add('qr-selected'); state.selectedQR = img; // 显示二维码工具栏 showQRTools(); } /** * 显示二维码工具栏 */ function showQRTools() { if (!state.selectedQR) return; // 激活编辑器工具栏 if (elements.editorToolbar) { elements.editorToolbar.classList.add('active'); } // 隐藏其他工具栏 ['textTools', 'imageTools', 'bgTools'].forEach(key => { if (elements[key]) elements[key].classList.remove('active'); }); // 显示二维码工具栏 if (elements.qrTools) { elements.qrTools.classList.add('active'); } // 同步滑块值 syncToolbarValues(); } /** * 同步工具栏滑块值 */ function syncToolbarValues() { if (!state.selectedQR) return; const opacity = parseFloat(state.selectedQR.style.opacity) || 1; const size = parseInt(state.selectedQR.style.width) || CONFIG.DEFAULT_SIZE; if (elements.qrOpacitySlider) { elements.qrOpacitySlider.value = Math.round(opacity * 100); elements.qrOpacityValue.textContent = Math.round(opacity * 100) + '%'; } if (elements.qrScaleSlider) { elements.qrScaleSlider.value = size; elements.qrScaleValue.textContent = size + '%'; } } /** * 隐藏二维码工具栏 */ function hideQRTools() { if (elements.qrTools) { elements.qrTools.classList.remove('active'); } document.querySelectorAll('.qr-item').forEach(el => { el.classList.remove('qr-selected'); }); state.selectedQR = null; } /** * 更新二维码透明度 */ function updateOpacity(value) { if (!state.selectedQR) return; state.selectedQR.style.opacity = value / 100; elements.qrOpacityValue.textContent = value + '%'; } /** * 更新二维码大小 */ function updateScale(value) { if (!state.selectedQR) return; state.selectedQR.style.width = value + 'px'; state.selectedQR.style.height = value + 'px'; elements.qrScaleValue.textContent = value + '%'; } /** * 保存状态 */ function saveState() { if (typeof window.saveState === 'function') { window.saveState(); } } // ========== 拖拽功能 ========== /** * 使元素可拖拽 */ function makeDraggable(el) { let isDragging = false; let startX, startY, startLeft, startTop; function startDrag(clientX, clientY) { isDragging = true; startX = clientX; startY = clientY; startLeft = parseInt(el.style.left) || 0; startTop = parseInt(el.style.top) || 0; el.style.cursor = 'grabbing'; } function moveDrag(clientX, clientY) { if (!isDragging) return; el.style.left = (startLeft + clientX - startX) + 'px'; el.style.top = (startTop + clientY - startY) + 'px'; } function endDrag() { if (isDragging) { isDragging = false; el.style.cursor = 'move'; saveState(); } } // 鼠标事件 el.addEventListener('mousedown', (e) => { e.preventDefault(); e.stopPropagation(); selectQR(el); startDrag(e.clientX, e.clientY); }); // 触摸事件 el.addEventListener('touchstart', (e) => { e.preventDefault(); e.stopPropagation(); selectQR(el); if (e.touches.length === 1) { startDrag(e.touches[0].clientX, e.touches[0].clientY); } }, { passive: false }); // 全局移动事件 document.addEventListener('mousemove', (e) => moveDrag(e.clientX, e.clientY)); document.addEventListener('touchmove', (e) => { if (isDragging && e.touches.length === 1) { e.preventDefault(); moveDrag(e.touches[0].clientX, e.touches[0].clientY); } }, { passive: false }); // 全局结束事件 document.addEventListener('mouseup', endDrag); document.addEventListener('touchend', endDrag); } // ========== 事件绑定 ========== function bindEvents() { // 弹窗事件 elements.btn.addEventListener('click', openModal); elements.closeBtn.addEventListener('click', closeModal); elements.cancelBtn.addEventListener('click', closeModal); elements.okBtn.addEventListener('click', addToCanvas); elements.modal.addEventListener('click', (e) => { if (e.target === elements.modal) closeModal(); }); // 输入防抖 elements.input.addEventListener('input', () => { clearTimeout(state.previewTimer); state.previewTimer = setTimeout(generatePreview, CONFIG.DEBOUNCE_DELAY); }); // 透明度滑块 if (elements.qrOpacitySlider) { elements.qrOpacitySlider.addEventListener('input', (e) => { updateOpacity(e.target.value); }); elements.qrOpacitySlider.addEventListener('change', saveState); } // 缩放滑块 if (elements.qrScaleSlider) { elements.qrScaleSlider.addEventListener('input', (e) => { updateScale(e.target.value); }); elements.qrScaleSlider.addEventListener('change', saveState); } } // ========== 初始化 ========== function init() { // 监听背景图变化 const container = document.getElementById('imageContainer'); if (container) { const observer = new MutationObserver(checkBackground); observer.observe(container, { childList: true, subtree: true }); } // 定期检查背景图状态 setInterval(checkBackground, 500); // 绑定事件 bindEvents(); // 初始检查 checkBackground(); // 暴露全局 API window.QRCodeAPI = { hideTools: hideQRTools, getSelected: () => state.selectedQR }; } // 启动 init(); })();