feat(qr): 添加二维码工具栏并优化交互体验
添加二维码编辑工具栏,支持透明度和缩放调整 优化选中状态和拖拽交互,增强用户体验 重构代码结构,提高可维护性
This commit is contained in:
29
css/qr.css
29
css/qr.css
@@ -1,6 +1,6 @@
|
|||||||
/* 二维码功能样式 */
|
/* 二维码功能样式 */
|
||||||
|
|
||||||
/* 悬浮按钮 */
|
/* ========== 悬浮按钮 ========== */
|
||||||
#qr-btn {
|
#qr-btn {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
bottom: 100px;
|
bottom: 100px;
|
||||||
@@ -29,7 +29,7 @@
|
|||||||
background: #3a7bc8;
|
background: #3a7bc8;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 弹窗 */
|
/* ========== 弹窗 ========== */
|
||||||
#qr-modal {
|
#qr-modal {
|
||||||
display: none;
|
display: none;
|
||||||
position: fixed;
|
position: fixed;
|
||||||
@@ -128,9 +128,32 @@
|
|||||||
color: #fff;
|
color: #fff;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 画布上的二维码 */
|
/* ========== 画布上的二维码 ========== */
|
||||||
.qr-item {
|
.qr-item {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
cursor: move;
|
cursor: move;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
|
touch-action: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 选中状态 */
|
||||||
|
.qr-item.qr-selected {
|
||||||
|
outline: 2px solid #4a90e2;
|
||||||
|
outline-offset: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ========== 二维码工具栏 - 与背景图工具栏保持一致 ========== */
|
||||||
|
.qr-tools {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.qr-tools.active {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 数值显示固定宽度,单独占位 */
|
||||||
|
#qrOpacityValue, #qrScaleValue {
|
||||||
|
display: inline-block;
|
||||||
|
min-width: 40px;
|
||||||
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|||||||
14
index.html
14
index.html
@@ -74,6 +74,20 @@
|
|||||||
<div class="toolbar-divider"></div>
|
<div class="toolbar-divider"></div>
|
||||||
<button class="toolbar-btn mirror-btn" id="mirrorHBtn" title="水平镜像">↔</button>
|
<button class="toolbar-btn mirror-btn" id="mirrorHBtn" title="水平镜像">↔</button>
|
||||||
</div>
|
</div>
|
||||||
|
<!-- 二维码编辑工具 -->
|
||||||
|
<div class="toolbar-group qr-tools" id="qrTools">
|
||||||
|
<label class="toolbar-label">
|
||||||
|
<span>透明度</span>
|
||||||
|
<input type="range" id="qrOpacitySlider" min="0" max="100" value="100" class="opacity-slider">
|
||||||
|
<span id="qrOpacityValue">100%</span>
|
||||||
|
</label>
|
||||||
|
<div class="toolbar-divider"></div>
|
||||||
|
<label class="toolbar-label">
|
||||||
|
<span>缩放</span>
|
||||||
|
<input type="range" id="qrScaleSlider" min="0" max="200" value="100" class="scale-slider">
|
||||||
|
<span id="qrScaleValue">100%</span>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
<!-- 背景图编辑工具 -->
|
<!-- 背景图编辑工具 -->
|
||||||
<div class="toolbar-group bg-tools" id="bgTools">
|
<div class="toolbar-group bg-tools" id="bgTools">
|
||||||
<label class="toolbar-label">
|
<label class="toolbar-label">
|
||||||
|
|||||||
381
js/qr.js
381
js/qr.js
@@ -1,153 +1,305 @@
|
|||||||
// 二维码功能 - 简洁可靠
|
// 二维码功能 - 优化版编辑器工具栏
|
||||||
(function() {
|
(function() {
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
// 获取元素
|
// ========== 配置 ==========
|
||||||
const btn = document.getElementById('qr-btn');
|
const CONFIG = {
|
||||||
const modal = document.getElementById('qr-modal');
|
MIN_SIZE: 0,
|
||||||
const input = document.getElementById('qr-input');
|
MAX_SIZE: 200,
|
||||||
const preview = document.getElementById('qr-preview');
|
DEFAULT_SIZE: 100,
|
||||||
const closeBtn = document.querySelector('.qr-close');
|
PREVIEW_SIZE: 128,
|
||||||
const cancelBtn = document.querySelector('.qr-cancel');
|
DEBOUNCE_DELAY: 300
|
||||||
const okBtn = document.querySelector('.qr-ok');
|
};
|
||||||
|
|
||||||
if (!btn || !modal) return;
|
// ========== 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')
|
||||||
|
};
|
||||||
|
|
||||||
let currentQR = null;
|
// 验证必需元素
|
||||||
let qrCount = 0;
|
if (!elements.btn || !elements.modal) return;
|
||||||
|
|
||||||
// 检查背景图并显示按钮
|
// ========== 状态管理 ==========
|
||||||
function checkBg() {
|
const state = {
|
||||||
|
currentQR: null,
|
||||||
|
selectedQR: null,
|
||||||
|
previewTimer: null,
|
||||||
|
isDragging: false
|
||||||
|
};
|
||||||
|
|
||||||
|
// ========== 核心功能 ==========
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查背景图并显示/隐藏二维码按钮
|
||||||
|
*/
|
||||||
|
function checkBackground() {
|
||||||
const container = document.getElementById('imageContainer');
|
const container = document.getElementById('imageContainer');
|
||||||
if (!container) return;
|
if (!container) return;
|
||||||
// 排除二维码图片,只检查背景图
|
|
||||||
const img = container.querySelector('img:not([data-type="qrcode"])');
|
const bgImg = container.querySelector('img:not([data-type="qrcode"])');
|
||||||
if (img && img.src && !img.src.endsWith(window.location.href)) {
|
const hasBackground = bgImg && bgImg.src && !bgImg.src.endsWith(window.location.href);
|
||||||
btn.classList.add('show');
|
|
||||||
} else {
|
elements.btn.classList.toggle('show', hasBackground);
|
||||||
btn.classList.remove('show');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 监听背景图变化
|
/**
|
||||||
const observer = new MutationObserver(checkBg);
|
* 打开二维码生成弹窗
|
||||||
const container = document.getElementById('imageContainer');
|
*/
|
||||||
if (container) {
|
|
||||||
observer.observe(container, { childList: true, subtree: true });
|
|
||||||
}
|
|
||||||
setInterval(checkBg, 500);
|
|
||||||
|
|
||||||
// 打开弹窗
|
|
||||||
function openModal() {
|
function openModal() {
|
||||||
modal.classList.add('active');
|
elements.modal.classList.add('active');
|
||||||
input.value = '';
|
elements.input.value = '';
|
||||||
preview.innerHTML = '';
|
elements.preview.innerHTML = '';
|
||||||
currentQR = null;
|
state.currentQR = null;
|
||||||
input.focus();
|
elements.input.focus();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 关闭弹窗
|
/**
|
||||||
|
* 关闭二维码生成弹窗
|
||||||
|
*/
|
||||||
function closeModal() {
|
function closeModal() {
|
||||||
modal.classList.remove('active');
|
elements.modal.classList.remove('active');
|
||||||
}
|
}
|
||||||
|
|
||||||
// 生成预览
|
/**
|
||||||
function genPreview() {
|
* 生成二维码预览
|
||||||
const text = input.value.trim();
|
*/
|
||||||
|
function generatePreview() {
|
||||||
|
const text = elements.input.value.trim();
|
||||||
|
|
||||||
if (!text) {
|
if (!text) {
|
||||||
preview.innerHTML = '';
|
elements.preview.innerHTML = '';
|
||||||
currentQR = null;
|
state.currentQR = null;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
preview.innerHTML = '';
|
|
||||||
|
elements.preview.innerHTML = '';
|
||||||
|
|
||||||
try {
|
try {
|
||||||
currentQR = new QRCode(preview, {
|
state.currentQR = new QRCode(elements.preview, {
|
||||||
text: text,
|
text: text,
|
||||||
width: 128,
|
width: CONFIG.PREVIEW_SIZE,
|
||||||
height: 128
|
height: CONFIG.PREVIEW_SIZE,
|
||||||
|
colorDark: '#000000',
|
||||||
|
colorLight: '#ffffff',
|
||||||
|
correctLevel: QRCode.CorrectLevel.M
|
||||||
});
|
});
|
||||||
} catch (e) {
|
} catch (error) {
|
||||||
console.error('生成失败', e);
|
console.error('二维码生成失败:', error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 添加到画布
|
/**
|
||||||
|
* 将二维码添加到画布
|
||||||
|
*/
|
||||||
function addToCanvas() {
|
function addToCanvas() {
|
||||||
if (!currentQR) {
|
if (!state.currentQR) {
|
||||||
alert('请输入内容');
|
alert('请输入内容');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const canvas = preview.querySelector('canvas');
|
|
||||||
if (!canvas) return;
|
|
||||||
|
|
||||||
const img = document.createElement('img');
|
const canvas = elements.preview.querySelector('canvas');
|
||||||
img.src = canvas.toDataURL();
|
if (!canvas) return;
|
||||||
img.className = 'qr-item';
|
|
||||||
img.dataset.type = 'qrcode';
|
|
||||||
img.style.width = '100px';
|
|
||||||
img.style.height = '100px';
|
|
||||||
|
|
||||||
const container = document.getElementById('imageContainer');
|
const container = document.getElementById('imageContainer');
|
||||||
const rect = container.getBoundingClientRect();
|
const rect = container.getBoundingClientRect();
|
||||||
img.style.left = (rect.width / 2 - 50) + 'px';
|
|
||||||
img.style.top = (rect.height / 2 - 50) + 'px';
|
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);
|
container.appendChild(img);
|
||||||
makeDraggable(img);
|
makeDraggable(img);
|
||||||
|
selectQR(img);
|
||||||
closeModal();
|
closeModal();
|
||||||
|
|
||||||
if (typeof saveState === 'function') saveState();
|
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) {
|
function makeDraggable(el) {
|
||||||
let dragging = false;
|
let isDragging = false;
|
||||||
let startX, startY, startLeft, startTop;
|
let startX, startY, startLeft, startTop;
|
||||||
|
|
||||||
function startDrag(clientX, clientY) {
|
function startDrag(clientX, clientY) {
|
||||||
dragging = true;
|
isDragging = true;
|
||||||
startX = clientX;
|
startX = clientX;
|
||||||
startY = clientY;
|
startY = clientY;
|
||||||
startLeft = parseInt(el.style.left) || 0;
|
startLeft = parseInt(el.style.left) || 0;
|
||||||
startTop = parseInt(el.style.top) || 0;
|
startTop = parseInt(el.style.top) || 0;
|
||||||
|
el.style.cursor = 'grabbing';
|
||||||
}
|
}
|
||||||
|
|
||||||
function moveDrag(clientX, clientY) {
|
function moveDrag(clientX, clientY) {
|
||||||
if (!dragging) return;
|
if (!isDragging) return;
|
||||||
el.style.left = (startLeft + clientX - startX) + 'px';
|
el.style.left = (startLeft + clientX - startX) + 'px';
|
||||||
el.style.top = (startTop + clientY - startY) + 'px';
|
el.style.top = (startTop + clientY - startY) + 'px';
|
||||||
}
|
}
|
||||||
|
|
||||||
function endDrag() {
|
function endDrag() {
|
||||||
if (dragging) {
|
if (isDragging) {
|
||||||
dragging = false;
|
isDragging = false;
|
||||||
if (typeof saveState === 'function') saveState();
|
el.style.cursor = 'move';
|
||||||
|
saveState();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 鼠标事件
|
// 鼠标事件
|
||||||
el.addEventListener('mousedown', function(e) {
|
el.addEventListener('mousedown', (e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
|
selectQR(el);
|
||||||
startDrag(e.clientX, e.clientY);
|
startDrag(e.clientX, e.clientY);
|
||||||
});
|
});
|
||||||
|
|
||||||
// 触摸事件
|
// 触摸事件
|
||||||
el.addEventListener('touchstart', function(e) {
|
el.addEventListener('touchstart', (e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
|
selectQR(el);
|
||||||
if (e.touches.length === 1) {
|
if (e.touches.length === 1) {
|
||||||
startDrag(e.touches[0].clientX, e.touches[0].clientY);
|
startDrag(e.touches[0].clientX, e.touches[0].clientY);
|
||||||
}
|
}
|
||||||
}, { passive: false });
|
}, { passive: false });
|
||||||
|
|
||||||
// 全局移动事件
|
// 全局移动事件
|
||||||
document.addEventListener('mousemove', function(e) {
|
document.addEventListener('mousemove', (e) => moveDrag(e.clientX, e.clientY));
|
||||||
moveDrag(e.clientX, e.clientY);
|
document.addEventListener('touchmove', (e) => {
|
||||||
});
|
if (isDragging && e.touches.length === 1) {
|
||||||
|
|
||||||
document.addEventListener('touchmove', function(e) {
|
|
||||||
if (dragging && e.touches.length === 1) {
|
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
moveDrag(e.touches[0].clientX, e.touches[0].clientY);
|
moveDrag(e.touches[0].clientX, e.touches[0].clientY);
|
||||||
}
|
}
|
||||||
@@ -158,22 +310,67 @@
|
|||||||
document.addEventListener('touchend', endDrag);
|
document.addEventListener('touchend', endDrag);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 事件绑定
|
// ========== 事件绑定 ==========
|
||||||
btn.addEventListener('click', openModal);
|
|
||||||
closeBtn.addEventListener('click', closeModal);
|
|
||||||
cancelBtn.addEventListener('click', closeModal);
|
|
||||||
okBtn.addEventListener('click', addToCanvas);
|
|
||||||
modal.addEventListener('click', function(e) {
|
|
||||||
if (e.target === modal) closeModal();
|
|
||||||
});
|
|
||||||
|
|
||||||
// 输入防抖
|
function bindEvents() {
|
||||||
let timer;
|
// 弹窗事件
|
||||||
input.addEventListener('input', function() {
|
elements.btn.addEventListener('click', openModal);
|
||||||
clearTimeout(timer);
|
elements.closeBtn.addEventListener('click', closeModal);
|
||||||
timer = setTimeout(genPreview, 300);
|
elements.cancelBtn.addEventListener('click', closeModal);
|
||||||
});
|
elements.okBtn.addEventListener('click', addToCanvas);
|
||||||
|
elements.modal.addEventListener('click', (e) => {
|
||||||
|
if (e.target === elements.modal) closeModal();
|
||||||
|
});
|
||||||
|
|
||||||
// 初始检查
|
// 输入防抖
|
||||||
checkBg();
|
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();
|
||||||
})();
|
})();
|
||||||
|
|||||||
38
js/script.js
38
js/script.js
@@ -381,9 +381,10 @@
|
|||||||
e.target === document.getElementById('emptyTip');
|
e.target === document.getElementById('emptyTip');
|
||||||
const isOverlayImage = e.target.closest('.overlay-image');
|
const isOverlayImage = e.target.closest('.overlay-image');
|
||||||
const isTextInput = e.target.closest('.text-input');
|
const isTextInput = e.target.closest('.text-input');
|
||||||
|
const isQRCode = e.target.closest('.qr-item');
|
||||||
|
|
||||||
// 点击背景/空白区域
|
// 点击背景/空白区域(排除二维码)
|
||||||
if (isBackground && !isOverlayImage) {
|
if (isBackground && !isOverlayImage && !isQRCode) {
|
||||||
// 如果正在编辑,先结束编辑
|
// 如果正在编辑,先结束编辑
|
||||||
if (editingInput) {
|
if (editingInput) {
|
||||||
endEdit(editingInput);
|
endEdit(editingInput);
|
||||||
@@ -398,18 +399,26 @@
|
|||||||
selectedOverlay.classList.remove('selected');
|
selectedOverlay.classList.remove('selected');
|
||||||
selectedOverlay = null;
|
selectedOverlay = null;
|
||||||
}
|
}
|
||||||
|
// 隐藏二维码工具栏
|
||||||
|
if (window.QRCodeAPI) {
|
||||||
|
window.QRCodeAPI.hideTools();
|
||||||
|
}
|
||||||
// 隐藏辅助线
|
// 隐藏辅助线
|
||||||
hideGuides();
|
hideGuides();
|
||||||
// 隐藏编辑器工具栏
|
// 隐藏编辑器工具栏
|
||||||
editorToolbar.classList.remove('active');
|
editorToolbar.classList.remove('active');
|
||||||
}
|
}
|
||||||
|
|
||||||
// 点击空白区域(不是层叠图和输入框)
|
// 点击空白区域(不是层叠图、输入框和二维码)
|
||||||
if (!isOverlayImage && !isTextInput && !isBackground) {
|
if (!isOverlayImage && !isTextInput && !isBackground && !isQRCode) {
|
||||||
if (selectedOverlay) {
|
if (selectedOverlay) {
|
||||||
selectedOverlay.classList.remove('selected');
|
selectedOverlay.classList.remove('selected');
|
||||||
selectedOverlay = null;
|
selectedOverlay = null;
|
||||||
}
|
}
|
||||||
|
// 隐藏二维码工具栏
|
||||||
|
if (window.QRCodeAPI) {
|
||||||
|
window.QRCodeAPI.hideTools();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1198,6 +1207,9 @@
|
|||||||
textTools.classList.remove('active');
|
textTools.classList.remove('active');
|
||||||
imageTools.classList.add('active');
|
imageTools.classList.add('active');
|
||||||
bgTools.classList.remove('active');
|
bgTools.classList.remove('active');
|
||||||
|
// 隐藏二维码工具栏
|
||||||
|
const qrTools = document.getElementById('qrTools');
|
||||||
|
if (qrTools) qrTools.classList.remove('active');
|
||||||
|
|
||||||
// 更新透明度滑块为当前层叠图的透明度
|
// 更新透明度滑块为当前层叠图的透明度
|
||||||
const currentOpacity = overlayEl.style.opacity || '1';
|
const currentOpacity = overlayEl.style.opacity || '1';
|
||||||
@@ -1371,6 +1383,9 @@
|
|||||||
textTools.classList.remove('active');
|
textTools.classList.remove('active');
|
||||||
imageTools.classList.remove('active');
|
imageTools.classList.remove('active');
|
||||||
bgTools.classList.add('active');
|
bgTools.classList.add('active');
|
||||||
|
// 隐藏二维码工具栏
|
||||||
|
const qrTools = document.getElementById('qrTools');
|
||||||
|
if (qrTools) qrTools.classList.remove('active');
|
||||||
|
|
||||||
// 同步滑块值
|
// 同步滑块值
|
||||||
bgScaleSlider.value = bgImageScale * 100;
|
bgScaleSlider.value = bgImageScale * 100;
|
||||||
@@ -1394,6 +1409,9 @@
|
|||||||
textTools.classList.remove('active');
|
textTools.classList.remove('active');
|
||||||
imageTools.classList.remove('active');
|
imageTools.classList.remove('active');
|
||||||
bgTools.classList.add('active');
|
bgTools.classList.add('active');
|
||||||
|
// 隐藏二维码工具栏
|
||||||
|
const qrTools = document.getElementById('qrTools');
|
||||||
|
if (qrTools) qrTools.classList.remove('active');
|
||||||
|
|
||||||
// 同步滑块值
|
// 同步滑块值
|
||||||
bgScaleSlider.value = bgImageScale * 100;
|
bgScaleSlider.value = bgImageScale * 100;
|
||||||
@@ -1444,6 +1462,9 @@
|
|||||||
textTools.classList.remove('active');
|
textTools.classList.remove('active');
|
||||||
imageTools.classList.remove('active');
|
imageTools.classList.remove('active');
|
||||||
bgTools.classList.add('active');
|
bgTools.classList.add('active');
|
||||||
|
// 隐藏二维码工具栏
|
||||||
|
const qrTools = document.getElementById('qrTools');
|
||||||
|
if (qrTools) qrTools.classList.remove('active');
|
||||||
|
|
||||||
// 同步滑块值
|
// 同步滑块值
|
||||||
bgScaleSlider.value = bgImageScale * 100;
|
bgScaleSlider.value = bgImageScale * 100;
|
||||||
@@ -1701,6 +1722,9 @@
|
|||||||
textTools.classList.add('active');
|
textTools.classList.add('active');
|
||||||
imageTools.classList.remove('active');
|
imageTools.classList.remove('active');
|
||||||
bgTools.classList.remove('active');
|
bgTools.classList.remove('active');
|
||||||
|
// 隐藏二维码工具栏
|
||||||
|
const qrTools = document.getElementById('qrTools');
|
||||||
|
if (qrTools) qrTools.classList.remove('active');
|
||||||
|
|
||||||
// 更新工具栏状态
|
// 更新工具栏状态
|
||||||
updateToolbarState(element);
|
updateToolbarState(element);
|
||||||
@@ -1724,6 +1748,9 @@
|
|||||||
textTools.classList.add('active');
|
textTools.classList.add('active');
|
||||||
imageTools.classList.remove('active');
|
imageTools.classList.remove('active');
|
||||||
bgTools.classList.remove('active');
|
bgTools.classList.remove('active');
|
||||||
|
// 隐藏二维码工具栏
|
||||||
|
const qrTools = document.getElementById('qrTools');
|
||||||
|
if (qrTools) qrTools.classList.remove('active');
|
||||||
|
|
||||||
// 移动端/编辑模式:固定在顶部始终可见
|
// 移动端/编辑模式:固定在顶部始终可见
|
||||||
if (window.innerWidth <= 768 || 'ontouchstart' in window) {
|
if (window.innerWidth <= 768 || 'ontouchstart' in window) {
|
||||||
@@ -2666,6 +2693,9 @@
|
|||||||
textTools.classList.remove('active');
|
textTools.classList.remove('active');
|
||||||
imageTools.classList.remove('active');
|
imageTools.classList.remove('active');
|
||||||
bgTools.classList.add('active');
|
bgTools.classList.add('active');
|
||||||
|
// 隐藏二维码工具栏
|
||||||
|
const qrTools = document.getElementById('qrTools');
|
||||||
|
if (qrTools) qrTools.classList.remove('active');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user