-
-
+
@@ -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;">