更新
This commit is contained in:
+325
-30
@@ -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;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
@@ -195,7 +234,7 @@
|
||||
</select>
|
||||
</div>
|
||||
<div class="component-line">
|
||||
<span class="name" language="m" zh="自动圆心:" ozh="自動圆心:" en="Automatic center:"></span>
|
||||
<span class="name" language="m" zh="中心辅助调整圆弧:" ozh="中心輔助調整圓弧:" en="Adjust the arc using the center:"></span>
|
||||
<input type="checkbox" name="circle_text_center" id="circle_text_center" class="radio">
|
||||
</div>
|
||||
<div class="component-line">
|
||||
@@ -575,10 +614,15 @@
|
||||
</div>
|
||||
<div class="right" style="background-color: #1E252D">
|
||||
<div style="background-color: #1E252D;" id="canvas-div">
|
||||
<div class="canvas_box">
|
||||
<div class="canvas-wrapper">
|
||||
<div class="ruler-corner"></div>
|
||||
<canvas class="ruler-horizontal" id="ruler-h"></canvas>
|
||||
<canvas class="ruler-vertical" id="ruler-v"></canvas>
|
||||
<div class="canvas_box" style="margin-left: 20px; margin-top: 20px;">
|
||||
<canvas id="canvas1"></canvas>
|
||||
<canvas id="canvas2"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
<div class="canvas_bg">
|
||||
<!-- 类型改变 -->
|
||||
<img id="canvas_bg_img" class="canvas_bg_img" src="./public/images/bg_1.png" />
|
||||
@@ -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,7 +3356,8 @@
|
||||
recordState();
|
||||
updateControls();
|
||||
}
|
||||
if (event.keyCode != 46 || _inputEdit || _textEdit) return;
|
||||
// 普通删除键(DEL键,没有按CTRL/CMD)
|
||||
if (event.keyCode == 46 && !isModifierKey && !_inputEdit && !_textEdit) {
|
||||
let actObjs = canvas.getActiveObjects();
|
||||
let allObjs = canvas.getObjects();
|
||||
let flag = 0;
|
||||
@@ -3260,6 +3377,7 @@
|
||||
canvas.renderAll();
|
||||
handleObjectSelected()
|
||||
}
|
||||
}
|
||||
});
|
||||
let pre_add_image;
|
||||
$("#addPic").click(function () {
|
||||
@@ -4211,7 +4329,9 @@
|
||||
openAs.name = result.filePath;
|
||||
layer.msg(language_str("saveSucc") + openAs.name);//'保存成功至'
|
||||
saveHistory();
|
||||
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();
|
||||
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();
|
||||
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();
|
||||
});
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
|
||||
+469
-60
@@ -7,6 +7,47 @@
|
||||
<title>Soon Design</title>
|
||||
<link rel="stylesheet" href="./layui/css/layui.css">
|
||||
<link rel="stylesheet" href="./public/css/design.css">
|
||||
<style>
|
||||
/* 标尺样式 */
|
||||
.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;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
@@ -193,6 +234,10 @@
|
||||
style="display: inline-block;width: 150px;position: relative;top:-3px;left:5px;">
|
||||
</div>
|
||||
</div>
|
||||
<div class="component-line">
|
||||
<span class="name" language="m" zh="中心辅助调整圆弧:" ozh="中心輔助調整圓弧:" en="Adjust the arc using the center:"></span>
|
||||
<input type="checkbox" name="circle_text_center" id="circle_text_center" class="radio">
|
||||
</div>
|
||||
<div class="component-line">
|
||||
<span class="name" language="m" zh="颜色:" ozh="顏色:" en="Color:"></span>
|
||||
<input type="color" id="circle_text_color" class="input_color">
|
||||
@@ -554,9 +599,15 @@
|
||||
</div>
|
||||
<div class="right" style="background-color: #1E252D">
|
||||
<div style="background-color: #1E252D;" id="canvas-div">
|
||||
<div class="canvas-wrapper">
|
||||
<div class="ruler-corner"></div>
|
||||
<canvas class="ruler-horizontal" id="ruler-h"></canvas>
|
||||
<canvas class="ruler-vertical" id="ruler-v"></canvas>
|
||||
<div style="margin-left: 20px; margin-top: 20px;">
|
||||
<canvas id="canvas1"></canvas>
|
||||
<canvas id="canvas2"></canvas>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="footer" style="background-color: #31373D">
|
||||
<div id="posText" style="display: inline-block">X : Y : </div>
|
||||
@@ -898,6 +949,9 @@
|
||||
//console.log($("#canvas-div").width() / 1200 > 1 ? 1 : $("#canvas-div").width() / 1200);
|
||||
canvas2.zoomToPoint(new fabric.Point(canvas2.width / 2, canvas2.height / 2), $('#canvas-div').width() / 1200 > 1 ? 1 : $('#canvas-div').width() / 1200)
|
||||
zoom = $('#canvas-div').width() / 1200 > 1 ? 1 : $('#canvas-div').width() / 1200
|
||||
|
||||
// 初始化标尺
|
||||
initRulers();
|
||||
$('#source_front').width(zoom * $('#source_front').width())
|
||||
$('#source_back').width(zoom * $('#source_back').width())
|
||||
$('.canvas-container:eq(1)').hide()
|
||||
@@ -1795,6 +1849,26 @@
|
||||
});
|
||||
}
|
||||
*/
|
||||
} else if (type == 11) {
|
||||
//circle_text
|
||||
op.frontData.push({
|
||||
"type" : 2,
|
||||
"Text" : item.get("text"),
|
||||
"FontFamily" : item.get("fontFamily"),
|
||||
"FontSize" : parseInt(item.get("fontSize")),
|
||||
"FontColor" : "#000000",
|
||||
"FontBackgroudColor" : item.get("textBackgroundColor"),
|
||||
"Bold" : item.get("fontWeight") == "bold",
|
||||
"Underline" : item.get("underline"),
|
||||
"Italic" : item.get("fontStyle") == "italic",
|
||||
"Strikeout" : item.get("linethrough"),
|
||||
"x" : parseInt((item.get("left") - background_image1.left).toFixed(0)),
|
||||
"y" : parseInt((item.get("top") - background_image1.top).toFixed(0)),
|
||||
"h" : parseInt((item.get("scaleY") * item.get("height")).toFixed(0)),
|
||||
"w" : parseInt((item.get("scaleX") * item.get("width")).toFixed(0)),
|
||||
"rotate" : parseInt(item.get("angle").toFixed(0)),
|
||||
"circleCenter" : objs1[idx - 1].circleCenter || 0
|
||||
});
|
||||
} else if (type == 4) {
|
||||
//out_text
|
||||
let xy = getAbsoluteXY(item)
|
||||
@@ -1912,6 +1986,26 @@
|
||||
});
|
||||
}
|
||||
*/
|
||||
} else if (type == 11) {
|
||||
//circle_text
|
||||
op.backData.push({
|
||||
"type" : 2,
|
||||
"Text" : item.get("text"),
|
||||
"FontFamily" : item.get("fontFamily"),
|
||||
"FontSize" : parseInt(item.get("fontSize")),
|
||||
"FontColor" : "#000000",
|
||||
"FontBackgroudColor" : item.get("textBackgroundColor"),
|
||||
"Bold" : item.get("fontWeight") == "bold",
|
||||
"Underline" : item.get("underline"),
|
||||
"Italic" : item.get("fontStyle") == "italic",
|
||||
"Strikeout" : item.get("linethrough"),
|
||||
"x" : parseInt((item.get("left") - background_image2.left).toFixed(0)),
|
||||
"y" : parseInt((item.get("top") - background_image2.top).toFixed(0)),
|
||||
"h" : parseInt((item.get("scaleY") * item.get("height")).toFixed(0)),
|
||||
"w" : parseInt((item.get("scaleX") * item.get("width")).toFixed(0)),
|
||||
"rotate" : parseInt(item.get("angle").toFixed(0)),
|
||||
"circleCenter" : objs2[idx - 1].circleCenter || 0
|
||||
});
|
||||
} else if (type == 4) {
|
||||
let xy = getAbsoluteXY(item)
|
||||
op.backData.push({
|
||||
@@ -2289,6 +2383,26 @@
|
||||
});
|
||||
}
|
||||
*/
|
||||
} else if (type == 11) {
|
||||
//circle_text
|
||||
op.frontData.push({
|
||||
"type" : 2,
|
||||
"Text" : item.get("text"),
|
||||
"FontFamily" : item.get("fontFamily"),
|
||||
"FontSize" : parseInt(item.get("fontSize")),
|
||||
"FontColor" : "#000000",
|
||||
"FontBackgroudColor" : item.get("textBackgroundColor"),
|
||||
"Bold" : item.get("fontWeight") == "bold",
|
||||
"Underline" : item.get("underline"),
|
||||
"Italic" : item.get("fontStyle") == "italic",
|
||||
"Strikeout" : item.get("linethrough"),
|
||||
"x" : parseInt((item.get("left") - background_image1.left).toFixed(0)),
|
||||
"y" : parseInt((item.get("top") - background_image1.top).toFixed(0)),
|
||||
"h" : parseInt((item.get("scaleY") * item.get("height")).toFixed(0)),
|
||||
"w" : parseInt((item.get("scaleX") * item.get("width")).toFixed(0)),
|
||||
"rotate" : parseInt(item.get("angle").toFixed(0)),
|
||||
"circleCenter" : objs1[idx - 1].circleCenter || 0
|
||||
});
|
||||
} else if (type == 4) {
|
||||
//out_text
|
||||
let xy = getAbsoluteXY(item)
|
||||
@@ -2406,6 +2520,26 @@
|
||||
});
|
||||
}
|
||||
*/
|
||||
} else if (type == 11) {
|
||||
//circle_text
|
||||
op.backData.push({
|
||||
"type" : 2,
|
||||
"Text" : item.get("text"),
|
||||
"FontFamily" : item.get("fontFamily"),
|
||||
"FontSize" : parseInt(item.get("fontSize")),
|
||||
"FontColor" : "#000000",
|
||||
"FontBackgroudColor" : item.get("textBackgroundColor"),
|
||||
"Bold" : item.get("fontWeight") == "bold",
|
||||
"Underline" : item.get("underline"),
|
||||
"Italic" : item.get("fontStyle") == "italic",
|
||||
"Strikeout" : item.get("linethrough"),
|
||||
"x" : parseInt((item.get("left") - background_image2.left).toFixed(0)),
|
||||
"y" : parseInt((item.get("top") - background_image2.top).toFixed(0)),
|
||||
"h" : parseInt((item.get("scaleY") * item.get("height")).toFixed(0)),
|
||||
"w" : parseInt((item.get("scaleX") * item.get("width")).toFixed(0)),
|
||||
"rotate" : parseInt(item.get("angle").toFixed(0)),
|
||||
"circleCenter" : objs2[idx - 1].circleCenter || 0
|
||||
});
|
||||
} else if (type == 4) {
|
||||
let xy = getAbsoluteXY(item)
|
||||
op.backData.push({
|
||||
@@ -2518,7 +2652,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) {
|
||||
@@ -2526,9 +2661,74 @@
|
||||
}
|
||||
})
|
||||
$('body').keydown(function (event) {
|
||||
console.log(event)
|
||||
// 统一的快捷键处理(兼容 Windows/Linux: Ctrl, Mac: Cmd/Meta)
|
||||
const isModifierKey = event.ctrlKey || event.metaKey; // 兼容三端
|
||||
|
||||
if (event.keyCode == 17) {
|
||||
// 快捷键处理(在输入框或文本区域中时不触发,除了删除相关的)
|
||||
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) {
|
||||
//同时按下且在编辑状态
|
||||
@@ -2547,7 +2747,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')
|
||||
@@ -2560,7 +2760,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')
|
||||
@@ -2573,7 +2773,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')
|
||||
@@ -2586,7 +2786,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')
|
||||
@@ -2596,7 +2796,8 @@
|
||||
recordState()
|
||||
updateControls()
|
||||
}
|
||||
if (event.keyCode != 46 || _inputEdit || _textEdit) return
|
||||
// 普通删除键(DEL键,没有按CTRL/CMD)
|
||||
if (event.keyCode == 46 && !isModifierKey && !_inputEdit && !_textEdit) {
|
||||
let actObjs = canvas.getActiveObjects()
|
||||
let allObjs = canvas.getObjects()
|
||||
let flag = 0
|
||||
@@ -2615,6 +2816,7 @@
|
||||
canvas.renderAll()
|
||||
handleObjectSelected()
|
||||
}
|
||||
}
|
||||
})
|
||||
let pre_add_image
|
||||
$('#addPic').click(function () {
|
||||
@@ -3549,7 +3751,9 @@
|
||||
openAs.name = result.filePath
|
||||
layer.msg(language_str('saveSucc') + openAs.name) //'保存成功至'
|
||||
saveHistory()
|
||||
if (callback && typeof callback === 'function') {
|
||||
callback()
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log()
|
||||
@@ -3604,7 +3808,9 @@
|
||||
fs.writeFileSync(openAs.name, JSON.stringify(con_o))
|
||||
layer.msg(language_str('saveSucc') + openAs.name) //'保存成功至'
|
||||
saveHistory()
|
||||
if (callback && typeof callback === 'function') {
|
||||
callback()
|
||||
}
|
||||
return
|
||||
}
|
||||
dialog
|
||||
@@ -3625,7 +3831,9 @@
|
||||
openAs.name = result.filePath
|
||||
layer.msg(language_str('saveSucc') + openAs.name) //'保存成功至'
|
||||
saveHistory()
|
||||
if (callback && typeof callback === 'function') {
|
||||
callback()
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log()
|
||||
@@ -4459,18 +4667,20 @@
|
||||
text.setControlVisible("mr", false);
|
||||
text.setControlVisible("mb", false);
|
||||
canvas.add(text);
|
||||
objs.push({ type: 11, black: false });
|
||||
objs.push({ type: 11, black: false, circleCenter: 0 });
|
||||
canvas.renderAll();
|
||||
updateList();
|
||||
recordState();
|
||||
}
|
||||
function selectCircleText() {
|
||||
console.log(canvas.getActiveObject().get("text"))
|
||||
let idx = getIndex(canvas.getActiveObject());
|
||||
$("#circle_text_control").show();
|
||||
$("#circle_text_color").val(canvas.getActiveObject().get("fill"));
|
||||
$("#circle_text_back_color").val(canvas.getActiveObject().get("textBackgroundColor") == "" ? '#ffffff' : canvas.getActiveObject().get("textBackgroundColor"));
|
||||
circle_text_size.setValue(canvas.getActiveObject().get("fontSize") - 10);
|
||||
circle_text_diameter.setValue(canvas.getActiveObject().get("diameter")-50);
|
||||
$("#circle_text_center").prop("checked", objs[idx - 1].circleCenter ? 'checked' : '');
|
||||
$("#circle_text_text").val(canvas.getActiveObject().get("text"));
|
||||
$("#circle_text_font_family").val(canvas.getActiveObject().get("fontFamily"));
|
||||
|
||||
@@ -5187,6 +5397,15 @@
|
||||
updateList();
|
||||
recordState();
|
||||
})
|
||||
$("#circle_text_center").click(function () {
|
||||
let idx = getIndex(canvas.getActiveObject());
|
||||
if ($(this).prop("checked")) {
|
||||
objs[idx - 1].circleCenter = 1;
|
||||
} else {
|
||||
objs[idx - 1].circleCenter = 0;
|
||||
}
|
||||
recordState();
|
||||
});
|
||||
$('#out_text_color').bind('input propertychange', function () {
|
||||
canvas.getActiveObject().set('fill', $('#out_text_color').val())
|
||||
canvas.renderAll()
|
||||
@@ -5643,44 +5862,25 @@
|
||||
)
|
||||
})
|
||||
canvas1.on("object:moving", function (e) {
|
||||
let obj = canvas.getActiveObject()
|
||||
// if (objs[getIndex(e.target) - 1].type ===11) {
|
||||
// let pointer = {
|
||||
// x: obj.left,
|
||||
// y: obj.top > canvas.height/2 ? obj.top + obj.height/2 : obj.top - obj.height/2
|
||||
// }
|
||||
// console.log(obj)
|
||||
// let distance = getDisdance(pointer.x, pointer.y, canvas.width/2,canvas.height/2)
|
||||
// let angleDeg = getDeg(pointer)
|
||||
// let flipped = pointer.y > canvas.height/2 ? true : false
|
||||
// obj.set("diameter", distance*2);
|
||||
// obj.set("angle", angleDeg);
|
||||
// obj.set("flipped", flipped);
|
||||
// // canvas.renderAll();
|
||||
// }
|
||||
let obj = canvas1.getActiveObject()
|
||||
let idx = getIndex(e.target, canvas1);
|
||||
// 添加边界检查,避免访问 undefined
|
||||
if (idx > 0 && idx <= objs1.length && objs1[idx - 1] && objs1[idx - 1].type && objs1[idx - 1].type === 11 && $("#circle_text_center").prop("checked")) {
|
||||
let pointer = {
|
||||
x: obj.left,
|
||||
y: obj.top
|
||||
}
|
||||
let distance = getDisdance(pointer.x, pointer.y, canvas1.width/2, canvas1.height/2)
|
||||
let angleDeg = getDeg(pointer)
|
||||
let flipped = pointer.y > canvas1.height/2 ? true : false
|
||||
circle_text_diameter.setValue(distance*2-50);
|
||||
obj.set("diameter", distance*2);
|
||||
obj.set("angle", angleDeg);
|
||||
obj.set("flipped", flipped);
|
||||
}
|
||||
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() {
|
||||
@@ -6036,21 +6236,34 @@
|
||||
$('#posText').text('X: ' + (e.pointer.x - background_image.left).toFixed(0) + ' Y: ' + (e.pointer.y - background_image.top).toFixed(0))
|
||||
})
|
||||
canvas2.on("object:moving", function (e) {
|
||||
let obj = canvas.getActiveObject()
|
||||
// if (objs[getIndex(e.target) - 1].type ===11) {
|
||||
// let pointer = {
|
||||
// x: obj.left,
|
||||
// y: obj.top > canvas.height/2 ? obj.top + obj.height/2 : obj.top - obj.height/2
|
||||
// }
|
||||
// console.log(obj)
|
||||
// let distance = getDisdance(pointer.x, pointer.y, canvas.width/2,canvas.height/2)
|
||||
// let angleDeg = getDeg(pointer)
|
||||
// let flipped = pointer.y > canvas.height/2 ? true : false
|
||||
// obj.set("diameter", distance*2);
|
||||
// // obj.set("angle", angleDeg);
|
||||
// obj.set("flipped", flipped);
|
||||
// // canvas.renderAll();
|
||||
// }
|
||||
let obj = canvas2.getActiveObject()
|
||||
let idx = getIndex(e.target, canvas2);
|
||||
// 添加边界检查,避免访问 undefined
|
||||
if (idx > 0 && idx <= objs2.length && objs2[idx - 1] && objs2[idx - 1].type && objs2[idx - 1].type === 11 && $("#circle_text_center").prop("checked")) {
|
||||
let pointer = {
|
||||
x: obj.left,
|
||||
y: obj.top
|
||||
}
|
||||
let distance = getDisdance(pointer.x, pointer.y, canvas2.width/2, canvas2.height/2)
|
||||
// 计算角度时需要使用 canvas2
|
||||
let centerX = canvas2.width / 2;
|
||||
let centerY = canvas2.height / 2;
|
||||
let mouseX = pointer.x;
|
||||
let mouseY = pointer.y;
|
||||
let dx = mouseX - centerX;
|
||||
let dy = mouseY - centerY;
|
||||
let angleRad = Math.atan2(dy, dx);
|
||||
let angleDeg = angleRad * (180/Math.PI);
|
||||
if (angleDeg < 0) {
|
||||
angleDeg += 360;
|
||||
}
|
||||
angleDeg += 90;
|
||||
let flipped = pointer.y > canvas2.height/2 ? true : false
|
||||
circle_text_diameter.setValue(distance*2-50);
|
||||
obj.set("diameter", distance*2);
|
||||
obj.set("angle", angleDeg);
|
||||
obj.set("flipped", flipped);
|
||||
}
|
||||
updateControls();
|
||||
});
|
||||
canvas2.on('object:scaling', function (e) {
|
||||
@@ -6346,6 +6559,202 @@
|
||||
canvas.renderAll()
|
||||
}
|
||||
})
|
||||
|
||||
// 标尺绘制函数
|
||||
function initRulers() {
|
||||
const dpi = 300;
|
||||
const mmToPx = dpi / 25.4; // 1mm = 11.811px (300 DPI)
|
||||
const rulerHeight = 20;
|
||||
const rulerWidth = 20;
|
||||
|
||||
// 获取实际画布的像素尺寸(px)
|
||||
// design2.html 的实际画布尺寸是 1012px x 648px
|
||||
const actualCanvasWidth = canvas1.width || 1012; // 实际画布宽度(px)
|
||||
const actualCanvasHeight = canvas1.height || 648; // 实际画布高度(px)
|
||||
|
||||
// 获取显示区域的尺寸(包括 margin)
|
||||
const canvasDiv = $('#canvas-div');
|
||||
const canvasWrapper = $('.canvas-wrapper');
|
||||
// 使用 canvas-wrapper 的宽度,如果没有则使用 canvas_div 的宽度
|
||||
let canvasWidth = canvasWrapper.width();
|
||||
let canvasHeight = canvasWrapper.height();
|
||||
if (!canvasWidth || canvasWidth === 0) {
|
||||
const canvas1Width = $('#canvas1').width() || canvasDiv.width() - 20;
|
||||
canvasWidth = canvas1Width + 20; // 加上 margin-left: 20px
|
||||
}
|
||||
if (!canvasHeight || canvasHeight === 0) {
|
||||
const canvas1Height = $('#canvas1').height() || canvasDiv.height() - 20;
|
||||
canvasHeight = canvas1Height + 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 canvasWrapper = $('.canvas-wrapper');
|
||||
let newWidth = canvasWrapper.width();
|
||||
let newHeight = canvasWrapper.height();
|
||||
if (!newWidth || newWidth === 0) {
|
||||
const canvas1Width = $('#canvas1').width() || $('#canvas-div').width() - 20;
|
||||
newWidth = canvas1Width + 20; // 加上 margin-left: 20px
|
||||
}
|
||||
if (!newHeight || newHeight === 0) {
|
||||
const canvas1Height = $('#canvas1').height() || $('#canvas-div').height() - 20;
|
||||
newHeight = canvas1Height + 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();
|
||||
});
|
||||
}
|
||||
})
|
||||
|
||||
</script>
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 424 B |
Binary file not shown.
|
After Width: | Height: | Size: 367 B |
Reference in New Issue
Block a user