diff --git a/design1.html b/design1.html index 0fb5b87..1e98ce2 100644 --- a/design1.html +++ b/design1.html @@ -15,6 +15,45 @@ height: 2787px; border-radius: 50%; } + /* 标尺样式 */ + .ruler-container { + position: relative; + background-color: #2C2C2C; + border: 1px solid #1E1E1E; + overflow: hidden; + } + .ruler-horizontal { + position: absolute; + top: 0; + left: 0; + height: 20px; + background-color: #2C2C2C; + border-bottom: 1px solid #1E1E1E; + z-index: 1000; + } + .ruler-vertical { + position: absolute; + top: 0; + left: 0; + width: 20px; + background-color: #2C2C2C; + border-right: 1px solid #1E1E1E; + z-index: 1000; + } + .ruler-corner { + position: absolute; + top: 0; + left: 0; + width: 20px; + height: 20px; + background-color: #2C2C2C; + border-right: 1px solid #1E1E1E; + border-bottom: 1px solid #1E1E1E; + z-index: 1001; + } + .canvas-wrapper { + position: relative; + } @@ -195,7 +234,7 @@
- +
@@ -575,9 +614,14 @@
-
- - +
+
+ + +
+ + +
@@ -912,6 +956,10 @@ let is_bgi_add = false; canvas1.zoomToPoint(new fabric.Point(0, 0), 1); canvas2.zoomToPoint(new fabric.Point(0, 0), 1); + + // 初始化标尺 + initRulers(); + $("#source_front").width(zoom * $("#source_front").width()); $("#source_back").width(zoom * $("#source_back").width()); $(".canvas-container:eq(0)").css('transform', 'scale(' + zoom + ')') @@ -3164,7 +3212,8 @@ _inputEdit = false }) $("body").keyup(function (event) { - if (event.keyCode == 17) { + // 兼容三端的 modifier key 检测(Windows/Linux: Ctrl, Mac: Cmd/Meta) + if (event.keyCode == 17 || event.keyCode == 91 || event.keyCode == 93) { // Ctrl 键或 Meta 键(Mac Cmd)释放 _keyctrl = false; }; if (event.keyCode == 67) { @@ -3172,7 +3221,74 @@ }; }) $("body").keydown(function (event) { - if (event.keyCode == 17) { + // 统一的快捷键处理(兼容 Windows/Linux: Ctrl, Mac: Cmd/Meta) + const isModifierKey = event.ctrlKey || event.metaKey; // 兼容三端 + + // 快捷键处理(在输入框或文本区域中时不触发,除了删除相关的) + if (!_inputEdit && !_textEdit) { + // CTRL/CMD+N - 新建 + if (isModifierKey && event.keyCode == 78) { + event.preventDefault(); + $("#new").click(); + return; + } + // CTRL/CMD+O - 打开 + if (isModifierKey && event.keyCode == 79) { + event.preventDefault(); + $("#open").click(); + return; + } + // CTRL/CMD+S - 保存 + if (isModifierKey && !event.shiftKey && event.keyCode == 83) { + event.preventDefault(); + $("#save").click(); + return; + } + // CTRL/CMD+SHIFT+S - 保存副本 + if (isModifierKey && event.shiftKey && event.keyCode == 83) { + event.preventDefault(); + output(null, saveAs); + return; + } + // CTRL/CMD+Z - 还原 + if (isModifierKey && !event.shiftKey && event.keyCode == 90) { + event.preventDefault(); + $("#previous").click(); + return; + } + // CTRL/CMD+Y - 重做 + if (isModifierKey && !event.shiftKey && event.keyCode == 89) { + event.preventDefault(); + $("#next").click(); + return; + } + // CTRL/CMD+C - 复制 + if (isModifierKey && event.keyCode == 67 && event.target.nodeName == 'BODY') { + event.preventDefault(); + copySelection(); + return; + } + // CTRL/CMD+V - 粘贴 + if (isModifierKey && event.keyCode == 86 && event.target.nodeName == 'BODY') { + event.preventDefault(); + pasteFromClipboard(); + return; + } + // CTRL/CMD+SHIFT+DEL - 清空 + if (isModifierKey && event.shiftKey && event.keyCode == 46) { + event.preventDefault(); + $("#clean").click(); + return; + } + // CTRL/CMD+DEL - 删除 + if (isModifierKey && !event.shiftKey && event.keyCode == 46) { + event.preventDefault(); + $("#delete").click(); + return; + } + } + // 兼容三端的 modifier key 检测(Windows/Linux: Ctrl, Mac: Cmd/Meta) + if (event.keyCode == 17 || event.metaKey) { // Ctrl 键或 Meta 键(Mac Cmd) _keyctrl = true; if (_keyc && _textEdit) { //同时按下且在编辑状态 @@ -3191,7 +3307,7 @@ if (event.keyCode == 37) { //left let v = -1; - if (_keyctrl) { + if (_keyctrl || event.ctrlKey || event.metaKey) { v = -5; } let x = canvas.getActiveObject().get("left"); @@ -3204,7 +3320,7 @@ if (event.keyCode == 38) { //up let v = -1; - if (_keyctrl) { + if (_keyctrl || event.ctrlKey || event.metaKey) { v = -5; } let y = canvas.getActiveObject().get("top"); @@ -3217,7 +3333,7 @@ if (event.keyCode == 39) { //right let v = 1; - if (_keyctrl) { + if (_keyctrl || event.ctrlKey || event.metaKey) { v = 5; } let x = canvas.getActiveObject().get("left"); @@ -3230,7 +3346,7 @@ if (event.keyCode == 40) { //down let v = +1; - if (_keyctrl) { + if (_keyctrl || event.ctrlKey || event.metaKey) { v = 5; } let y = canvas.getActiveObject().get("top"); @@ -3240,25 +3356,27 @@ recordState(); updateControls(); } - if (event.keyCode != 46 || _inputEdit || _textEdit) return; - let actObjs = canvas.getActiveObjects(); - let allObjs = canvas.getObjects(); - let flag = 0; - for (let item of actObjs) { - if (item != allObjs[0]) { - let i = getIndex(item);//0是背景,所以从1开始,但objs不包含背景图片,故要-1 - objs.splice(i - 1, 1); - canvas.remove(item); - flag = 1; + // 普通删除键(DEL键,没有按CTRL/CMD) + if (event.keyCode == 46 && !isModifierKey && !_inputEdit && !_textEdit) { + let actObjs = canvas.getActiveObjects(); + let allObjs = canvas.getObjects(); + let flag = 0; + for (let item of actObjs) { + if (item != allObjs[0]) { + let i = getIndex(item);//0是背景,所以从1开始,但objs不包含背景图片,故要-1 + objs.splice(i - 1, 1); + canvas.remove(item); + flag = 1; + } + } + updateList(); + canvas.discardActiveObject(); + if (flag == 1) { + recordState(); + canvas.renderAll(); + handleObjectSelected() } - } - updateList(); - canvas.discardActiveObject(); - if (flag == 1) { - recordState(); - canvas.renderAll(); - handleObjectSelected() } }); let pre_add_image; @@ -4211,7 +4329,9 @@ openAs.name = result.filePath; layer.msg(language_str("saveSucc") + openAs.name);//'保存成功至' saveHistory(); - callback(); + if (callback && typeof callback === 'function') { + callback(); + } }).catch(err => { console.log() }) @@ -4262,7 +4382,9 @@ fs.writeFileSync(openAs.name, JSON.stringify(con_o)) layer.msg(language_str("saveSucc") + openAs.name);//'保存成功至' saveHistory(); - callback(); + if (callback && typeof callback === 'function') { + callback(); + } return; } dialog.showSaveDialog({ @@ -4281,7 +4403,9 @@ openAs.name = result.filePath; layer.msg(language_str("saveSucc") + openAs.name);//'保存成功至' saveHistory(); - callback(); + if (callback && typeof callback === 'function') { + callback(); + } }).catch(err => { console.log() }) @@ -6331,27 +6455,6 @@ } updateControls(); }); - // 监听键盘事件 - window.addEventListener('keydown', handleKeyDown); - function handleKeyDown(e) { - // 检测 Ctrl+C - if ((e.ctrlKey || e.metaKey) && e.keyCode === 67 && e.target.nodeName == 'BODY') { - copySelection(); - e.preventDefault(); // 阻止默认复制行为 - } - - // 检测 Ctrl+V - if ((e.ctrlKey || e.metaKey) && e.keyCode === 86 && e.target.nodeName == 'BODY') { - pasteFromClipboard(); - e.preventDefault(); // 阻止默认粘贴行为 - } - - // 检测 Ctrl+S - if ((e.ctrlKey || e.metaKey) && e.keyCode === 83) { - output(); - e.preventDefault(); // 阻止默认粘贴行为 - } - } // 复制选中对象 function copySelection() { @@ -6997,6 +7100,198 @@ canvas.renderAll(); } }); + + // 标尺绘制函数 + function initRulers() { + const dpi = 600; + const mmToPx = dpi / 25.4; // 1mm = 23.622px (600 DPI) + const rulerHeight = 20; + const rulerWidth = 20; + + // 获取实际画布的像素尺寸(px) + const actualCanvasWidth = canvas1.width || 2787; // 实际画布宽度(px) + const actualCanvasHeight = canvas1.height || 2787; // 实际画布高度(px) + + // 获取显示区域的尺寸(包括 margin) + const canvasBox = $('.canvas_box'); + const canvasWrapper = $('.canvas-wrapper'); + // 使用 canvas-wrapper 的宽度,如果没有则使用 canvas_box + margin + let canvasWidth = canvasWrapper.width(); + let canvasHeight = canvasWrapper.height(); + if (!canvasWidth || canvasWidth === 0) { + canvasWidth = canvasBox.width() + 20; // 加上 margin-left: 20px + } + if (!canvasHeight || canvasHeight === 0) { + canvasHeight = canvasBox.height() + 20; // 加上 margin-top: 20px + } + + // 设置标尺尺寸(使用显示区域的尺寸) + $('#ruler-h').attr('width', canvasWidth).attr('height', rulerHeight); + $('#ruler-v').attr('width', rulerWidth).attr('height', canvasHeight); + $('.ruler-horizontal').css('width', canvasWidth + 'px'); + $('.ruler-vertical').css('height', canvasHeight + 'px'); + + // 绘制水平标尺 + function drawHorizontalRuler() { + const ctx = document.getElementById('ruler-h').getContext('2d'); + ctx.clearRect(0, 0, canvasWidth, rulerHeight); + + // 背景 + ctx.fillStyle = '#2C2C2C'; + ctx.fillRect(0, 0, canvasWidth, rulerHeight); + + // 边框 + ctx.strokeStyle = '#1E1E1E'; + ctx.lineWidth = 1; + ctx.strokeRect(0, 0, canvasWidth, rulerHeight); + ctx.beginPath(); + ctx.moveTo(0, rulerHeight - 1); + ctx.lineTo(canvasWidth, rulerHeight - 1); + ctx.stroke(); + + // 刻度线 + ctx.strokeStyle = '#888888'; + ctx.fillStyle = '#CCCCCC'; + ctx.font = '10px Arial'; + ctx.textAlign = 'left'; + ctx.textBaseline = 'top'; + + // 计算:实际画布尺寸(px)对应的物理尺寸(mm),然后根据显示区域的缩放比例计算 + // 实际画布物理宽度 = actualCanvasWidth / dpi * 25.4 (mm) + // 显示区域宽度 = actualCanvasWidth * zoom (px) + // 所以:1mm 在显示区域中 = (actualCanvasWidth * zoom) / (actualCanvasWidth / dpi * 25.4) = zoom * dpi / 25.4 + const pxPerMm = zoom * mmToPx; // 在显示区域中,1mm对应的像素数 + const startX = 0; + const endX = canvasWidth; + + // 绘制主要刻度(每10mm) + for (let mm = 0; mm * pxPerMm <= endX; mm += 10) { + const x = startX + mm * pxPerMm; + if (x > endX) break; + + ctx.beginPath(); + ctx.moveTo(x, 0); + ctx.lineTo(x, rulerHeight); + ctx.stroke(); + + // 数字 + ctx.fillText(mm + 'mm', x + 2, 2); + } + + // 绘制次要刻度(每1mm) + for (let mm = 0; mm * pxPerMm <= endX; mm += 1) { + const x = startX + mm * pxPerMm; + if (x > endX) break; + if (mm % 10 === 0) continue; // 跳过主要刻度 + + ctx.beginPath(); + ctx.moveTo(x, rulerHeight - 8); + ctx.lineTo(x, rulerHeight); + ctx.stroke(); + } + } + + // 绘制垂直标尺 + function drawVerticalRuler() { + const ctx = document.getElementById('ruler-v').getContext('2d'); + ctx.clearRect(0, 0, rulerWidth, canvasHeight); + + // 背景 + ctx.fillStyle = '#2C2C2C'; + ctx.fillRect(0, 0, rulerWidth, canvasHeight); + + // 边框 + ctx.strokeStyle = '#1E1E1E'; + ctx.lineWidth = 1; + ctx.strokeRect(0, 0, rulerWidth, canvasHeight); + ctx.beginPath(); + ctx.moveTo(rulerWidth - 1, 0); + ctx.lineTo(rulerWidth - 1, canvasHeight); + ctx.stroke(); + + // 刻度线 + ctx.strokeStyle = '#888888'; + ctx.fillStyle = '#CCCCCC'; + ctx.font = '10px Arial'; + ctx.textAlign = 'left'; + ctx.textBaseline = 'top'; + + // 计算:实际画布尺寸(px)对应的物理尺寸(mm),然后根据显示区域的缩放比例计算 + const pxPerMm = zoom * mmToPx; // 在显示区域中,1mm对应的像素数 + const startY = 0; + const endY = canvasHeight; + + // 绘制主要刻度(每10mm) + for (let mm = 0; mm * pxPerMm <= endY; mm += 10) { + const y = startY + mm * pxPerMm; + if (y > endY) break; + + ctx.beginPath(); + ctx.moveTo(0, y); + ctx.lineTo(rulerWidth, y); + ctx.stroke(); + + // 数字(旋转90度) + ctx.save(); + ctx.translate(2, y + 8); + ctx.rotate(-Math.PI / 2); + ctx.fillText(mm + 'mm', 0, 0); + ctx.restore(); + } + + // 绘制次要刻度(每1mm) + for (let mm = 0; mm * pxPerMm <= endY; mm += 1) { + const y = startY + mm * pxPerMm; + if (y > endY) break; + if (mm % 10 === 0) continue; // 跳过主要刻度 + + ctx.beginPath(); + ctx.moveTo(rulerWidth - 8, y); + ctx.lineTo(rulerWidth, y); + ctx.stroke(); + } + } + + // 初始绘制 + drawHorizontalRuler(); + drawVerticalRuler(); + + // 监听窗口大小变化 + $(window).on('resize', function() { + setTimeout(function() { + const canvasBox = $('.canvas_box'); + const canvasWrapper = $('.canvas-wrapper'); + let newWidth = canvasWrapper.width(); + let newHeight = canvasWrapper.height(); + if (!newWidth || newWidth === 0) { + newWidth = canvasBox.width() + 20; // 加上 margin-left: 20px + } + if (!newHeight || newHeight === 0) { + newHeight = canvasBox.height() + 20; // 加上 margin-top: 20px + } + if (newWidth !== canvasWidth || newHeight !== canvasHeight) { + canvasWidth = newWidth; + canvasHeight = newHeight; + $('#ruler-h').attr('width', newWidth); + $('#ruler-v').attr('height', newHeight); + $('.ruler-horizontal').css('width', newWidth + 'px'); + $('.ruler-vertical').css('height', newHeight + 'px'); + drawHorizontalRuler(); + drawVerticalRuler(); + } + }, 100); + }); + + // 监听画布缩放变化 + canvas1.on('after:render', function() { + drawHorizontalRuler(); + drawVerticalRuler(); + }); + canvas2.on('after:render', function() { + drawHorizontalRuler(); + drawVerticalRuler(); + }); + } }) }); diff --git a/design2.html b/design2.html index 1014524..b73d956 100644 --- a/design2.html +++ b/design2.html @@ -7,6 +7,47 @@ Soon Design + @@ -193,6 +234,10 @@ style="display: inline-block;width: 150px;position: relative;top:-3px;left:5px;">
+
+ + +
@@ -554,9 +599,15 @@
- - - +
+
+ + +
+ + +
+