diff --git a/js/qr.js b/js/qr.js index 0846e72..e29de7b 100644 --- a/js/qr.js +++ b/js/qr.js @@ -40,7 +40,8 @@ currentQR: null, selectedQR: null, previewTimer: null, - isDragging: false + isDragging: false, + qrCounter: 0 }; // ========== 核心功能 ========== @@ -119,10 +120,15 @@ const container = document.getElementById('imageContainer'); const rect = container.getBoundingClientRect(); + // 生成图层 ID + state.qrCounter++; + const layerId = `qr_${state.qrCounter}`; + // 创建二维码容器 const wrapper = document.createElement('div'); wrapper.className = 'qr-item'; wrapper.dataset.type = 'qrcode'; + wrapper.dataset.layerId = layerId; wrapper.style.cssText = ` position: absolute; width: ${CONFIG.DEFAULT_SIZE}px; @@ -168,6 +174,9 @@ // 保存状态 saveState(); + // 更新图层列表 + updateLayersList(); + return false; }; @@ -179,6 +188,9 @@ closeModal(); saveState(); + + // 更新图层列表 + updateLayersList(); } /** @@ -292,6 +304,15 @@ } } + /** + * 更新图层列表 + */ + function updateLayersList() { + // 触发图层更新事件 + const event = new CustomEvent('updateLayers'); + document.dispatchEvent(event); + } + // ========== 拖拽功能 ========== /** diff --git a/js/script.js b/js/script.js index 098cef9..b81d03e 100644 --- a/js/script.js +++ b/js/script.js @@ -2436,6 +2436,11 @@ if (!layersBtn || !layersPanel) return; + // 监听二维码图层更新事件 + document.addEventListener('updateLayers', () => { + updateLayersList(); + }); + // 打开/关闭图层面板(同时支持桌面和移动端) const toggleLayersPanel = () => { layersPanel.classList.toggle('active'); @@ -2590,7 +2595,20 @@ } }); - // 4. 层叠图(最上层) + // 4. 二维码 + const qrItems = document.querySelectorAll('.qr-item'); + qrItems.forEach((qr, index) => { + layers.push({ + id: qr.dataset.layerId || `qr_${index}`, + element: qr, + name: `二维码 ${index + 1}`, + type: 'qrcode', + icon: '🔲', + visible: !qr.classList.contains('layer-hidden') + }); + }); + + // 5. 层叠图(最上层) const overlayImages = overlayLayer.querySelectorAll('.overlay-image'); overlayImages.forEach((overlay, index) => { layers.push({ @@ -2660,7 +2678,8 @@ const names = { 'text': '文本', 'overlay': '层叠图', - 'background': '背景图' + 'background': '背景图', + 'qrcode': '二维码' }; return names[type] || type; } @@ -2687,6 +2706,40 @@ selectInput(element); } else if (element.classList.contains('overlay-image')) { selectOverlay(element); + } else if (element.classList.contains('qr-item')) { + // 选中二维码 + if (window.QRCodeAPI) { + window.QRCodeAPI.hideTools(); + } + // 取消其他选中 + document.querySelectorAll('.qr-item').forEach(el => { + el.classList.remove('qr-selected'); + }); + // 选中当前二维码 + element.classList.add('qr-selected'); + // 显示二维码工具栏 + editorToolbar.classList.add('active'); + textTools.classList.remove('active'); + imageTools.classList.remove('active'); + bgTools.classList.remove('active'); + const qrTools = document.getElementById('qrTools'); + if (qrTools) qrTools.classList.add('active'); + // 同步工具栏值 + const qrImg = element.querySelector('img'); + const qrOpacitySlider = document.getElementById('qrOpacitySlider'); + const qrOpacityValue = document.getElementById('qrOpacityValue'); + const qrScaleSlider = document.getElementById('qrScaleSlider'); + const qrScaleValue = document.getElementById('qrScaleValue'); + if (qrImg && qrOpacitySlider) { + const opacity = parseFloat(qrImg.style.opacity) || 1; + qrOpacitySlider.value = Math.round(opacity * 100); + qrOpacityValue.textContent = Math.round(opacity * 100) + '%'; + } + if (qrScaleSlider) { + const size = parseInt(element.style.width) || 100; + qrScaleSlider.value = size; + qrScaleValue.textContent = size + '%'; + } } else if (element.id === 'bgImage') { // 选中背景图 editorToolbar.classList.add('active'); @@ -3206,16 +3259,24 @@ }); // 绘制二维码 - const qrImages = container.querySelectorAll('img[data-type="qrcode"]'); - for (const qrImg of qrImages) { - if (!qrImg.classList.contains('layer-hidden')) { - const rect = qrImg.getBoundingClientRect(); + const qrWrappers = container.querySelectorAll('.qr-item'); + for (const qrWrapper of qrWrappers) { + if (!qrWrapper.classList.contains('layer-hidden')) { + const qrImg = qrWrapper.querySelector('img'); + if (!qrImg) continue; + + const rect = qrWrapper.getBoundingClientRect(); const containerRect = container.getBoundingClientRect(); const x = (rect.left - containerRect.left) * scale; const y = (rect.top - containerRect.top) * scale; const w = rect.width * scale; const h = rect.height * scale; + // 应用透明度 + const opacity = parseFloat(qrImg.style.opacity) || 1; + ctx.save(); + ctx.globalAlpha = opacity; + // 确保图片已加载 if (qrImg.complete && qrImg.naturalWidth > 0) { ctx.drawImage(qrImg, x, y, w, h); @@ -3231,6 +3292,8 @@ setTimeout(resolve, 100); }); } + + ctx.restore(); } }