优化bug
This commit is contained in:
+50
-25
@@ -41,6 +41,8 @@ fabric.Object.prototype.objectCaching = false;
|
||||
ctx1 = canvas1.getSelectionContext();
|
||||
ctx2 = canvas2.getSelectionContext();
|
||||
is_bgi_add = false;
|
||||
// 撤销/重做过程中使用的标志位,防止并发操作和误记录历史
|
||||
window._isApplyingHistory = false;
|
||||
// 同步到 window 对象
|
||||
window.ctx1 = ctx1;
|
||||
window.ctx2 = ctx2;
|
||||
@@ -1224,6 +1226,10 @@ window.selectObj = function selectObj(objIndices, isFromCanvas = false) {
|
||||
}
|
||||
|
||||
window.recordState = function recordState() {
|
||||
// 撤销/重做过程中不记录历史,避免产生“中间状态”,导致需要点多次才能回到预期
|
||||
if (window._isApplyingHistory) {
|
||||
return;
|
||||
}
|
||||
//pre_objs.push(JSON.stringify(objs));
|
||||
//pre_json.push(canvas.toJSON(["selectable","hoverable","hoverCursor","text","fontStyle","fontWeight","underline"]));
|
||||
//next_json = [];
|
||||
@@ -1492,8 +1498,11 @@ function isObjectLocked(obj) {
|
||||
window.isObjectLocked = isObjectLocked;
|
||||
|
||||
// 统一的 toJSON 属性列表,不包含锁定相关属性(锁定状态不应被保存)
|
||||
// 统一的 toJSON 属性列表,不包含锁定相关属性(锁定状态不应被保存)
|
||||
// 包含所有需要保存的属性,特别是自定义对象的属性(如 CurvedText 的 diameter, flipped)
|
||||
const TO_JSON_PROPERTIES = [
|
||||
"selectable", "hoverable", "hoverCursor", "text", "fontStyle", "fontWeight", "underline", "evented"
|
||||
"selectable", "hoverable", "hoverCursor", "text", "fontStyle", "fontWeight", "underline",
|
||||
"evented", "linethrough", "textBackgroundColor", "diameter", "flipped"
|
||||
];
|
||||
// 暴露到全局作用域
|
||||
window.TO_JSON_PROPERTIES = TO_JSON_PROPERTIES;
|
||||
@@ -1608,13 +1617,14 @@ function initCanvasEvents() {
|
||||
handleObjectSelected(e);
|
||||
});
|
||||
|
||||
// 阻止被锁定的对象被框选选中(只过滤被锁定的对象,保留未锁定的对象)
|
||||
// 阻止被锁定的对象和辅助线被框选选中:
|
||||
// - 锁定对象:不能被框选(只能通过列表选中)
|
||||
// - 辅助线:永远不进入选区,避免选区被拉得很大
|
||||
currentCanvas.on('before:selection:created', (e) => {
|
||||
if (!e.targets || e.targets.length === 0) return;
|
||||
// 过滤掉被锁定的对象,保留辅助线和未锁定的对象
|
||||
e.targets = e.targets.filter(target => {
|
||||
if (target.isGuideLine) return true; // 保留辅助线
|
||||
return !isObjectLocked(target); // 移除被锁定的对象,保留未锁定的对象
|
||||
if (target.isGuideLine) return false; // 完全排除辅助线
|
||||
return !isObjectLocked(target); // 排除被锁定的普通对象
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1850,6 +1860,11 @@ function initRulers() {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
// 防止重复调用:如果正在拖拽,直接返回
|
||||
if ($dragLine && $dragLine.length > 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 创建临时显示的线
|
||||
$dragLine = $('<div class="guide-line-drag"></div>');
|
||||
$('.canvas-wrapper').append($dragLine);
|
||||
@@ -1922,18 +1937,13 @@ function initRulers() {
|
||||
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 canvasWidth = canvas.width || 2000;
|
||||
let canvasHeight = canvas.height || 2000;
|
||||
// 使用与画布尺寸相关的长度,避免“整块区域都像辅助线”,同时保证能横穿整个画布
|
||||
let lineExtent = Math.max(canvasWidth, canvasHeight) * 2;
|
||||
|
||||
// 构造线对象,使用足够大的范围确保覆盖整个画布
|
||||
// 线的起点和终点要足够远,确保覆盖整个可见区域
|
||||
// 构造线对象
|
||||
let linePoints = [];
|
||||
if (type === 'horizontal') {
|
||||
// 水平线:从很远的左边到很远的右边
|
||||
@@ -1962,19 +1972,34 @@ function initRulers() {
|
||||
lockScalingX: true,
|
||||
lockScalingY: true,
|
||||
hoverCursor: type === 'horizontal' ? 'ns-resize' : 'ew-resize',
|
||||
perPixelTargetFind: false, // 使用边界框检测而不是像素检测
|
||||
targetFindTolerance: 10, // 增加点击容差,扩大可点击区域(像素)
|
||||
padding: 10, // 增加选择边界的内边距
|
||||
// design1 中改回边框命中模型,保证更容易点中拖拽
|
||||
perPixelTargetFind: false,
|
||||
targetFindTolerance: 10,
|
||||
padding: 10,
|
||||
isGuideLine: true,
|
||||
ignoreSave: true
|
||||
});
|
||||
|
||||
// 限制移动方向
|
||||
guideLine.on('moving', function (e) {
|
||||
// 限制移动方向(只约束方向,不把整条线拖到极远,避免“整片区域是辅助线”的感觉)
|
||||
guideLine.on('moving', function () {
|
||||
if (type === 'horizontal') {
|
||||
this.left = -lineExtent;
|
||||
// 水平线:根据当前中心点的 Y,重算 x1/x2,使其横穿画布
|
||||
const cy = this.getCenterPoint().y;
|
||||
this.set({
|
||||
x1: -lineExtent,
|
||||
y1: cy,
|
||||
x2: lineExtent,
|
||||
y2: cy
|
||||
});
|
||||
} else {
|
||||
this.top = -lineExtent;
|
||||
// 垂直线:根据当前中心点的 X,重算 y1/y2,使其竖穿画布
|
||||
const cx = this.getCenterPoint().x;
|
||||
this.set({
|
||||
x1: cx,
|
||||
y1: -lineExtent,
|
||||
x2: cx,
|
||||
y2: lineExtent
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
@@ -2200,8 +2225,8 @@ window.copySelection = function copySelection() {
|
||||
let appData = (idx > 0 && objs[idx - 1]) ? objs[idx - 1] : { type: 0 };
|
||||
|
||||
return {
|
||||
// 1. 保存画面样式 (坐标、颜色、字号等)
|
||||
fabricJson: obj.toObject(['id', 'name', 'selectable', 'evented', 'data']),
|
||||
// 1. 保存画面样式 (坐标、颜色、字号等,包含图片的 src)
|
||||
fabricJson: obj.toObject(['id', 'name', 'selectable', 'evented', 'data', 'src']),
|
||||
// 2. 保存业务属性 (深拷贝,防止引用冲突)
|
||||
appData: JSON.parse(JSON.stringify(appData))
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user