优化调整辅助线等
This commit is contained in:
+78
-20
@@ -2305,6 +2305,11 @@ function initCanvasEvents() {
|
||||
let idx = getIndex(event.target);
|
||||
if (idx <= 0) return;
|
||||
let objData = objs[idx - 1];
|
||||
// 安全检查:确保 objData 存在且有 type 属性
|
||||
if (!objData || typeof objData.type === 'undefined') {
|
||||
console.warn('objData is undefined or missing type at index', idx - 1);
|
||||
return;
|
||||
}
|
||||
let target = event.target;
|
||||
|
||||
if ([3, 4, 10].includes(objData.type)) {
|
||||
@@ -2327,10 +2332,10 @@ function initCanvasEvents() {
|
||||
// 8. 【完美修复版】渲染后绘制:外部蒙版 + 中心圆孔 (修复三角形Bug)
|
||||
// ==================================================
|
||||
currentCanvas.on('after:render', function () {
|
||||
const ctx = currentCanvas.getContext();
|
||||
let bgObj = (currentCanvas === canvas1) ? background_image1 : background_image2;
|
||||
|
||||
if (bgObj) {
|
||||
const ctx = currentCanvas.getContext();
|
||||
const width = currentCanvas.width;
|
||||
const height = currentCanvas.height;
|
||||
|
||||
@@ -2378,6 +2383,32 @@ function initCanvasEvents() {
|
||||
ctx.fill();
|
||||
ctx.restore();
|
||||
}
|
||||
|
||||
// 在遮罩之后重新绘制辅助线,确保辅助线在最上层
|
||||
const objects = currentCanvas.getObjects();
|
||||
objects.forEach(obj => {
|
||||
if (obj.isGuideLine) {
|
||||
ctx.save();
|
||||
// 应用对象的变换矩阵
|
||||
const m = obj.calcTransformMatrix();
|
||||
ctx.transform(m[0], m[1], m[2], m[3], m[4], m[5]);
|
||||
|
||||
// 设置透明度
|
||||
ctx.globalAlpha = obj.opacity || 1;
|
||||
|
||||
// 应用阴影
|
||||
if (obj.shadow) {
|
||||
ctx.shadowColor = obj.shadow.color;
|
||||
ctx.shadowBlur = obj.shadow.blur;
|
||||
ctx.shadowOffsetX = obj.shadow.offsetX;
|
||||
ctx.shadowOffsetY = obj.shadow.offsetY;
|
||||
}
|
||||
|
||||
// 使用 Fabric 对象的内置渲染方法
|
||||
obj._render(ctx);
|
||||
ctx.restore();
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -2469,30 +2500,54 @@ function initRulers() {
|
||||
|
||||
// --- 2. 在画布中创建辅助线 ---
|
||||
function createFabricGuide(type, domX, domY) {
|
||||
// 计算画布内的逻辑坐标 (减去 margin 偏移,除以缩放)
|
||||
let boxOffset = canvasBox.offset();
|
||||
let wrapperOffset = canvasWrapper.offset();
|
||||
|
||||
// 计算相对于 canvasBox 的像素位置
|
||||
let relX = domX - (boxOffset.left - wrapperOffset.left);
|
||||
let relY = domY - (boxOffset.top - wrapperOffset.top);
|
||||
|
||||
// domX 和 domY 是相对于 canvas-wrapper 的坐标
|
||||
// 需要转换为相对于 canvas_box 的坐标,然后再转换为 Fabric 画布坐标
|
||||
|
||||
// 获取 canvas_box 相对于 canvas-wrapper 的位置
|
||||
let boxPosition = canvasBox.position();
|
||||
let boxMarginLeft = parseFloat(canvasBox.css('margin-left')) || 0;
|
||||
let boxMarginTop = parseFloat(canvasBox.css('margin-top')) || 0;
|
||||
|
||||
// 计算相对于 canvas_box 的坐标(减去 box 在 wrapper 中的位置和 margin)
|
||||
let relX = domX - boxPosition.left - boxMarginLeft;
|
||||
let relY = domY - boxPosition.top - boxMarginTop;
|
||||
|
||||
// 转为 Fabric 坐标 (除以 zoom)
|
||||
let canvasX = relX / zoom;
|
||||
let canvasY = relY / zoom;
|
||||
|
||||
// 构造线对象
|
||||
// 获取画布的实际尺寸和可见区域尺寸
|
||||
let canvasWidth = canvas.width || 10000;
|
||||
let canvasHeight = canvas.height || 10000;
|
||||
// 获取可见区域的尺寸(考虑缩放)
|
||||
let visibleWidth = canvasWrapper.width() || canvasWidth;
|
||||
let visibleHeight = canvasWrapper.height() || canvasHeight;
|
||||
// 使用足够大的固定值,确保辅助线能够覆盖整个画布和可见区域
|
||||
// 使用 100000 确保无论画布多大、如何缩放,都能覆盖整个可见区域
|
||||
let lineExtent = 100000;
|
||||
|
||||
// 构造线对象,使用足够大的范围确保覆盖整个画布
|
||||
// 线的起点和终点要足够远,确保覆盖整个可见区域
|
||||
let linePoints = [];
|
||||
if (type === 'horizontal') {
|
||||
linePoints = [-5000, canvasY, 5000, canvasY];
|
||||
// 水平线:从很远的左边到很远的右边
|
||||
linePoints = [-lineExtent, canvasY, lineExtent, canvasY];
|
||||
} else {
|
||||
linePoints = [canvasX, -5000, canvasX, 5000];
|
||||
// 垂直线:从很远的上面到很远的下面
|
||||
linePoints = [canvasX, -lineExtent, canvasX, lineExtent];
|
||||
}
|
||||
|
||||
let guideLine = new fabric.Line(linePoints, {
|
||||
stroke: '#00FFFF',
|
||||
stroke: '#0066FF',
|
||||
strokeWidth: 1 / zoom,
|
||||
strokeDashArray: [5, 5],
|
||||
opacity: 0.9,
|
||||
shadow: {
|
||||
color: '#0066FF',
|
||||
blur: 6,
|
||||
offsetX: 0,
|
||||
offsetY: 0,
|
||||
affectStroke: true
|
||||
},
|
||||
selectable: true,
|
||||
evented: true,
|
||||
hasControls: false,
|
||||
@@ -2501,6 +2556,9 @@ function initRulers() {
|
||||
lockScalingX: true,
|
||||
lockScalingY: true,
|
||||
hoverCursor: type === 'horizontal' ? 'ns-resize' : 'ew-resize',
|
||||
perPixelTargetFind: false, // 使用边界框检测而不是像素检测
|
||||
targetFindTolerance: 10, // 增加点击容差,扩大可点击区域(像素)
|
||||
padding: 10, // 增加选择边界的内边距
|
||||
isGuideLine: true,
|
||||
ignoreSave: true
|
||||
});
|
||||
@@ -2508,9 +2566,9 @@ function initRulers() {
|
||||
// 限制移动方向
|
||||
guideLine.on('moving', function (e) {
|
||||
if (type === 'horizontal') {
|
||||
this.left = -5000;
|
||||
this.left = -lineExtent;
|
||||
} else {
|
||||
this.top = -5000;
|
||||
this.top = -lineExtent;
|
||||
}
|
||||
});
|
||||
|
||||
@@ -2558,14 +2616,14 @@ function initRulers() {
|
||||
function drawHorizontal() {
|
||||
ctxH.clearRect(0, 0, currentCanvasWidth, rulerHeight);
|
||||
|
||||
ctxH.strokeStyle = '#999';
|
||||
ctxH.strokeStyle = '#666';
|
||||
ctxH.lineWidth = 1;
|
||||
ctxH.beginPath();
|
||||
ctxH.moveTo(0, 19);
|
||||
ctxH.lineTo(currentCanvasWidth, 19);
|
||||
ctxH.stroke();
|
||||
|
||||
ctxH.fillStyle = '#CCC';
|
||||
ctxH.fillStyle = '#888';
|
||||
ctxH.font = '9px Arial';
|
||||
ctxH.textAlign = 'left';
|
||||
ctxH.textBaseline = 'top';
|
||||
@@ -2626,14 +2684,14 @@ function initRulers() {
|
||||
function drawVertical() {
|
||||
ctxV.clearRect(0, 0, rulerWidth, currentCanvasHeight);
|
||||
|
||||
ctxV.strokeStyle = '#999';
|
||||
ctxV.strokeStyle = '#666';
|
||||
ctxV.lineWidth = 1;
|
||||
ctxV.beginPath();
|
||||
ctxV.moveTo(19, 0);
|
||||
ctxV.lineTo(19, currentCanvasHeight);
|
||||
ctxV.stroke();
|
||||
|
||||
ctxV.fillStyle = '#CCC';
|
||||
ctxV.fillStyle = '#888';
|
||||
ctxV.font = '9px Arial';
|
||||
ctxV.textAlign = 'center';
|
||||
ctxV.textBaseline = 'middle';
|
||||
|
||||
Reference in New Issue
Block a user