fix: 优化叠加图层级关系与选中失焦逻辑
This commit is contained in:
@@ -53,7 +53,7 @@
|
||||
13. 顶部工具栏下方16px的位置,固定放置文本编辑器工具栏,加粗,斜体,字体颜色,字体,字号,可编辑文字样式
|
||||
14. 字号逻辑调整,输入框字号只在自身原本字号上增减
|
||||
15. 文本输入框添加辅助线,完善辅助线的吸附逻辑更加精准,辅助线颜色为红色
|
||||
16.
|
||||
16. 顶部工具栏新增层叠图,可添加多张层叠图,单击选中状态可缩放删除自由移动位置,置于背景图之上,输入框与层叠图点击只能同时选中一个
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -222,14 +222,15 @@ html, body {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* 层叠图层 - 位于背景图之上、文字之下 */
|
||||
/* 层叠图层 - 位于背景图之上、文字之下、提示文字之上 */
|
||||
.overlay-layer {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
pointer-events: none;
|
||||
pointer-events: auto;
|
||||
z-index: 6;
|
||||
}
|
||||
|
||||
.overlay-layer .overlay-image {
|
||||
@@ -282,11 +283,13 @@ html, body {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
pointer-events: none;
|
||||
z-index: 7;
|
||||
}
|
||||
|
||||
/* 输入框可交互 */
|
||||
.preview-input-layer .text-input {
|
||||
pointer-events: auto;
|
||||
z-index: 8;
|
||||
}
|
||||
|
||||
/* 背景图 - 保持比例,可滑动调整位置 */
|
||||
|
||||
@@ -48,8 +48,6 @@
|
||||
<!-- 图片展示区 -->
|
||||
<div class="canvas-area" id="canvasArea">
|
||||
<div class="preview image-container empty" id="imageContainer">
|
||||
<!-- 提示文字移到预览白板中 -->
|
||||
<div class="empty-tip" id="emptyTip">请点击上方「添加图片」按钮上传背景图</div>
|
||||
<!-- 背景图层 -->
|
||||
<div class="preview-bg-layer" id="bgLayer">
|
||||
<img id="bgImage" src="" alt="背景图">
|
||||
@@ -66,6 +64,8 @@
|
||||
<!-- 文字输入框2 - 右下角 -->
|
||||
<div class="text-input" id="input2" contenteditable="false" style="left: 5%; top: 90%;">编号:</div>
|
||||
</div>
|
||||
<!-- 提示文字(最上层,层叠图之下) -->
|
||||
<div class="empty-tip" id="emptyTip">请点击上方「添加图片」按钮上传背景图</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
70
js/script.js
70
js/script.js
@@ -405,23 +405,29 @@
|
||||
});
|
||||
}
|
||||
|
||||
// 选中层叠图
|
||||
// 选中层叠图(同时取消输入框选中)
|
||||
let selectedOverlay = null;
|
||||
function selectOverlay(overlayEl) {
|
||||
if (selectedOverlay) {
|
||||
if (selectedInput) {
|
||||
selectedInput.classList.remove('selected');
|
||||
selectedInput = null;
|
||||
}
|
||||
if (editingInput) {
|
||||
endEdit(editingInput);
|
||||
}
|
||||
if (selectedOverlay && selectedOverlay !== overlayEl) {
|
||||
selectedOverlay.classList.remove('selected');
|
||||
}
|
||||
selectedOverlay = overlayEl;
|
||||
overlayEl.classList.add('selected');
|
||||
}
|
||||
|
||||
// 点击背景取消选中层叠图
|
||||
// 点击背景/空白处取消选中层叠图
|
||||
imageContainer.addEventListener('click', (e) => {
|
||||
if (e.target === imageContainer ||
|
||||
e.target === bgLayer ||
|
||||
e.target === bgImage ||
|
||||
e.target === emptyTip ||
|
||||
e.target.closest('.preview-bg-layer')) {
|
||||
const isOverlayImage = e.target.closest('.overlay-image');
|
||||
const isTextInput = e.target.closest('.text-input');
|
||||
|
||||
if (!isOverlayImage && !isTextInput) {
|
||||
if (selectedOverlay) {
|
||||
selectedOverlay.classList.remove('selected');
|
||||
selectedOverlay = null;
|
||||
@@ -732,6 +738,10 @@
|
||||
|
||||
// 选中输入框
|
||||
function selectInput(element) {
|
||||
if (selectedOverlay) {
|
||||
selectedOverlay.classList.remove('selected');
|
||||
selectedOverlay = null;
|
||||
}
|
||||
if (editingInput && editingInput !== element) {
|
||||
endEdit(editingInput);
|
||||
}
|
||||
@@ -1404,6 +1414,9 @@
|
||||
drawImageWithOffset(ctx, currentImage, containerWidth, containerHeight);
|
||||
}
|
||||
|
||||
// 绘制层叠图(等待图片加载完成)
|
||||
await drawOverlayImages(ctx);
|
||||
|
||||
// 绘制文字
|
||||
drawTextOnCanvas(ctx, input1);
|
||||
drawTextOnCanvas(ctx, input2);
|
||||
@@ -1411,6 +1424,47 @@
|
||||
return canvas;
|
||||
}
|
||||
|
||||
// 绘制层叠图
|
||||
function drawOverlayImages(ctx) {
|
||||
return new Promise((resolve) => {
|
||||
const overlayImages = overlayLayer.querySelectorAll('.overlay-image');
|
||||
if (overlayImages.length === 0) {
|
||||
resolve();
|
||||
return;
|
||||
}
|
||||
|
||||
let loadedCount = 0;
|
||||
overlayImages.forEach(overlayEl => {
|
||||
const imgEl = overlayEl.querySelector('img');
|
||||
if (!imgEl) {
|
||||
loadedCount++;
|
||||
return;
|
||||
}
|
||||
|
||||
const left = overlayEl.offsetLeft;
|
||||
const top = overlayEl.offsetTop;
|
||||
const width = overlayEl.offsetWidth;
|
||||
const height = overlayEl.offsetHeight;
|
||||
|
||||
const img = new Image();
|
||||
img.onload = () => {
|
||||
ctx.drawImage(img, left, top, width, height);
|
||||
loadedCount++;
|
||||
if (loadedCount >= overlayImages.length) {
|
||||
resolve();
|
||||
}
|
||||
};
|
||||
img.onerror = () => {
|
||||
loadedCount++;
|
||||
if (loadedCount >= overlayImages.length) {
|
||||
resolve();
|
||||
}
|
||||
};
|
||||
img.src = imgEl.src;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// 绘制图片(考虑滑动偏移)
|
||||
function drawImageWithOffset(ctx, img, containerWidth, containerHeight) {
|
||||
const imgRatio = img.naturalWidth / img.naturalHeight;
|
||||
|
||||
Reference in New Issue
Block a user