fix(web): design1/2 缩略图与 design2 设为背景交互修复
- design1:预览/最近文件缩略图按 background 边界截取,去掉多余白盘 - design2:设为背景贴齐 1012x648 卡框,保存/打开保留用户背景 src - design2:列表可选中锁定对象并加载完整属性,缩略图叠加 front_bg 模板 - design2:固定卡框锚点,避免选中背景时标尺/蒙版随属性面板漂移 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+371
-61
@@ -165,7 +165,13 @@ function initRulers() {
|
||||
// background_image在画布坐标系中的left值,需要转换到标尺坐标系
|
||||
// 画布从标尺的marginOffset位置开始,所以:标尺0点 = marginOffset + background_image.left (如果存在)
|
||||
let originX = marginOffset;
|
||||
if (typeof background_image !== 'undefined' && background_image) {
|
||||
var rulerSide = ($('#back_side').hasClass('ui-button-active')) ? canvas2 : canvas1;
|
||||
var anchorX = typeof soonDesign2GetFrameAnchor === 'function'
|
||||
? soonDesign2GetFrameAnchor(rulerSide)
|
||||
: null;
|
||||
if (anchorX) {
|
||||
originX = marginOffset + anchorX.left;
|
||||
} else if (typeof background_image !== 'undefined' && background_image) {
|
||||
originX = marginOffset + background_image.left;
|
||||
}
|
||||
const startX = 0;
|
||||
@@ -257,7 +263,13 @@ function initRulers() {
|
||||
// background_image在画布坐标系中的top值,需要转换到标尺坐标系
|
||||
// 画布从标尺的marginOffset + rulerHeightOffset位置开始,所以:标尺0点 = marginOffset + rulerHeightOffset + background_image.top (如果存在)
|
||||
let originY = marginOffset + rulerHeightOffset;
|
||||
if (typeof background_image !== 'undefined' && background_image) {
|
||||
var rulerSideY = ($('#back_side').hasClass('ui-button-active')) ? canvas2 : canvas1;
|
||||
var anchorY = typeof soonDesign2GetFrameAnchor === 'function'
|
||||
? soonDesign2GetFrameAnchor(rulerSideY)
|
||||
: null;
|
||||
if (anchorY) {
|
||||
originY = marginOffset + rulerHeightOffset + anchorY.top;
|
||||
} else if (typeof background_image !== 'undefined' && background_image) {
|
||||
originY = marginOffset + rulerHeightOffset + background_image.top;
|
||||
}
|
||||
const startY = 0;
|
||||
@@ -355,15 +367,19 @@ function initRulers() {
|
||||
}, 100);
|
||||
});
|
||||
|
||||
// 监听画布缩放/渲染变化,仅用于重绘标尺
|
||||
// 辅助线交给 Fabric 自己渲染,否则会出现“重影 / 变两三根”的现象
|
||||
canvas1.off('after:render');
|
||||
canvas2.off('after:render');
|
||||
canvas1.on('after:render', function () {
|
||||
drawHorizontalRuler();
|
||||
drawVerticalRuler();
|
||||
soonDesign2DrawCardMask(canvas1, ctx1, document.getElementById('source_front'));
|
||||
soonDesign2DrawTemplateOverlay(canvas1, ctx1, document.getElementById('source_front'));
|
||||
});
|
||||
canvas2.on('after:render', function () {
|
||||
drawHorizontalRuler();
|
||||
drawVerticalRuler();
|
||||
soonDesign2DrawCardMask(canvas2, ctx2, document.getElementById('source_back'));
|
||||
soonDesign2DrawTemplateOverlay(canvas2, ctx2, document.getElementById('source_back'));
|
||||
});
|
||||
|
||||
// --- 辅助线功能 (参考 design1) ---
|
||||
@@ -568,6 +584,221 @@ function soonDesign2ScaleBgSources() {
|
||||
}
|
||||
}
|
||||
|
||||
function soonDesign2BgOverlayMetrics(imgEl) {
|
||||
if (!imgEl || !imgEl.complete || imgEl.naturalWidth <= 0) return null;
|
||||
var z = zoom || window.zoom || 0.5;
|
||||
var w = parseFloat(imgEl.style.width);
|
||||
if (!w || w <= 0) w = imgEl.naturalWidth * z;
|
||||
var h = parseFloat(imgEl.style.height);
|
||||
if (!h || h <= 0) h = imgEl.naturalHeight * z;
|
||||
return { w: w, h: h };
|
||||
}
|
||||
|
||||
/** 卡面区域:与 background_image 对齐(1012×648),fallback 模板线框 */
|
||||
function soonDesign2ResolveCardFrame(fabricCanvas, imgEl) {
|
||||
if (!fabricCanvas) return null;
|
||||
var metaList = (fabricCanvas === canvas2) ? (window.objs2 || objs2) : (window.objs1 || objs1);
|
||||
if (soonDesign2IsUserBgMeta(metaList)) {
|
||||
var anchor = soonDesign2GetFrameAnchor(fabricCanvas);
|
||||
var card = soonDesign2CardSize();
|
||||
if (anchor) {
|
||||
return { left: anchor.left, top: anchor.top, width: card.w, height: card.h };
|
||||
}
|
||||
}
|
||||
var bg = (fabricCanvas === canvas1) ? background_image1 : background_image2;
|
||||
if (bg && bg.width) {
|
||||
var sx = bg.scaleX == null ? 1 : bg.scaleX;
|
||||
var sy = bg.scaleY == null ? 1 : bg.scaleY;
|
||||
return {
|
||||
left: bg.left,
|
||||
top: bg.top,
|
||||
width: bg.width * sx,
|
||||
height: bg.height * sy
|
||||
};
|
||||
}
|
||||
var cw = fabricCanvas.width || 1012;
|
||||
var ch = fabricCanvas.height || 648;
|
||||
if (imgEl) {
|
||||
var metrics = soonDesign2BgOverlayMetrics(imgEl);
|
||||
if (metrics) {
|
||||
return {
|
||||
left: (cw - metrics.w) / 2,
|
||||
top: (ch - metrics.h) / 2,
|
||||
width: metrics.w,
|
||||
height: metrics.h
|
||||
};
|
||||
}
|
||||
}
|
||||
return { left: 0, top: 0, width: cw, height: ch };
|
||||
}
|
||||
|
||||
function soonDesign2CardSize() {
|
||||
return { w: 1012, h: 648 };
|
||||
}
|
||||
|
||||
function soonDesign2IsUserBgMeta(metaList) {
|
||||
return !!(metaList && metaList.length > 0 && metaList[0] && metaList[0].type === 1);
|
||||
}
|
||||
|
||||
function soonDesign2SyncFrameAnchor(fabricCanvas, frame) {
|
||||
if (!frame) return;
|
||||
var pt = { left: frame.left, top: frame.top };
|
||||
if (fabricCanvas === canvas2) {
|
||||
window.soonDesign2FrameAnchor2 = pt;
|
||||
} else {
|
||||
window.soonDesign2FrameAnchor1 = pt;
|
||||
}
|
||||
var active = window.canvas || canvas;
|
||||
if (!active || fabricCanvas === active) {
|
||||
window.soonDesign2FrameAnchor = pt;
|
||||
}
|
||||
}
|
||||
|
||||
function soonDesign2GetFrameAnchor(fabricCanvas) {
|
||||
if (fabricCanvas === canvas2 && window.soonDesign2FrameAnchor2) {
|
||||
return window.soonDesign2FrameAnchor2;
|
||||
}
|
||||
if (window.soonDesign2FrameAnchor1) {
|
||||
return window.soonDesign2FrameAnchor1;
|
||||
}
|
||||
return window.soonDesign2FrameAnchor || null;
|
||||
}
|
||||
|
||||
/** 用户设为背景的对象:坐标系锚点,属性面板不应再移动它 */
|
||||
function soonDesign2ActiveIsAnchorBg() {
|
||||
var c = window.canvas || canvas;
|
||||
if (!c) return false;
|
||||
var ao = c.getActiveObject();
|
||||
if (!ao) return false;
|
||||
var meta = (c === canvas2) ? (window.objs2 || objs2) : (window.objs1 || objs1);
|
||||
if (c === (window.canvas || canvas)) {
|
||||
meta = window.objs || objs || meta;
|
||||
}
|
||||
if (!soonDesign2IsUserBgMeta(meta)) return false;
|
||||
var bg = (c === canvas2) ? (window.background_image2 || background_image2) : (window.background_image1 || background_image1);
|
||||
return ao === bg;
|
||||
}
|
||||
|
||||
function soonDesign2FrameOrigin(fabricCanvas) {
|
||||
var frame = soonDesign2ResolveCardFrame(fabricCanvas, null);
|
||||
if (frame) return frame;
|
||||
var card = soonDesign2CardSize();
|
||||
var cw = (fabricCanvas && fabricCanvas.width) || card.w;
|
||||
var ch = (fabricCanvas && fabricCanvas.height) || card.h;
|
||||
return { left: (cw - card.w) / 2, top: (ch - card.h) / 2, width: card.w, height: card.h };
|
||||
}
|
||||
|
||||
/** 用户图铺满卡面框(1012×648),与蒙版/线框同源坐标 */
|
||||
function soonDesign2SnapImageToCardFrame(img, fabricCanvas, frame) {
|
||||
if (!img || !img.width) return frame || soonDesign2FrameOrigin(fabricCanvas);
|
||||
frame = frame || soonDesign2FrameOrigin(fabricCanvas);
|
||||
var card = soonDesign2CardSize();
|
||||
img.set({
|
||||
originX: 'left',
|
||||
originY: 'top',
|
||||
scaleX: card.w / img.width,
|
||||
scaleY: card.h / img.height,
|
||||
left: frame.left,
|
||||
top: frame.top
|
||||
});
|
||||
img.setCoords();
|
||||
soonDesign2SyncFrameAnchor(fabricCanvas, frame);
|
||||
return frame;
|
||||
}
|
||||
|
||||
function soonDesign2ApplyUserBgAsCanvas0(userImg, fabricCanvas, oldBg) {
|
||||
if (!userImg || !fabricCanvas) return;
|
||||
if (oldBg && oldBg !== userImg) {
|
||||
fabricCanvas.remove(oldBg);
|
||||
}
|
||||
fabricCanvas.sendToBack(userImg);
|
||||
if (fabricCanvas === canvas2) {
|
||||
background_image2 = userImg;
|
||||
window.background_image2 = userImg;
|
||||
} else {
|
||||
background_image1 = userImg;
|
||||
window.background_image1 = userImg;
|
||||
}
|
||||
var activeCanvas = window.canvas || canvas;
|
||||
if (fabricCanvas === activeCanvas) {
|
||||
background_image = userImg;
|
||||
window.background_image = userImg;
|
||||
}
|
||||
}
|
||||
|
||||
function soonDesign2LockBgObject(bgObj) {
|
||||
if (!bgObj) return;
|
||||
bgObj.set({
|
||||
lockMovementX: true,
|
||||
lockMovementY: true,
|
||||
lockRotation: true,
|
||||
lockScalingX: true,
|
||||
lockScalingY: true,
|
||||
lockSkewingX: true,
|
||||
lockSkewingY: true,
|
||||
selectable: false,
|
||||
evented: false,
|
||||
hoverCursor: 'default'
|
||||
});
|
||||
}
|
||||
|
||||
/** 打开旧文件:去掉残留模板层,用户背景独占 canvas[0] 并贴齐卡框 */
|
||||
function soonDesign2NormalizeUserBg(fabricCanvas, metaList) {
|
||||
if (!soonDesign2IsUserBgMeta(metaList) || !fabricCanvas) return null;
|
||||
var all = fabricCanvas.getObjects().filter(function (o) { return !o.isGuideLine; });
|
||||
if (!all.length) return null;
|
||||
var frame = soonDesign2FrameOrigin(fabricCanvas);
|
||||
var userBg = all[0];
|
||||
if (all.length > 1) {
|
||||
fabricCanvas.remove(all[0]);
|
||||
userBg = fabricCanvas.getObjects().filter(function (o) { return !o.isGuideLine; })[0];
|
||||
}
|
||||
if (!userBg) return null;
|
||||
soonDesign2SnapImageToCardFrame(userBg, fabricCanvas, frame);
|
||||
soonDesign2ApplyUserBgAsCanvas0(userBg, fabricCanvas, null);
|
||||
soonDesign2LockBgObject(userBg);
|
||||
return userBg;
|
||||
}
|
||||
|
||||
window.soonDesign2CardSize = soonDesign2CardSize;
|
||||
window.soonDesign2IsUserBgMeta = soonDesign2IsUserBgMeta;
|
||||
window.soonDesign2SyncFrameAnchor = soonDesign2SyncFrameAnchor;
|
||||
window.soonDesign2GetFrameAnchor = soonDesign2GetFrameAnchor;
|
||||
window.soonDesign2ActiveIsAnchorBg = soonDesign2ActiveIsAnchorBg;
|
||||
window.soonDesign2FrameOrigin = soonDesign2FrameOrigin;
|
||||
window.soonDesign2SnapImageToCardFrame = soonDesign2SnapImageToCardFrame;
|
||||
window.soonDesign2ApplyUserBgAsCanvas0 = soonDesign2ApplyUserBgAsCanvas0;
|
||||
window.soonDesign2LockBgObject = soonDesign2LockBgObject;
|
||||
window.soonDesign2NormalizeUserBg = soonDesign2NormalizeUserBg;
|
||||
|
||||
function soonDesign2DrawCardMask(fabricCanvas, ctx, imgEl) {
|
||||
if (window._soonSkipDesign2CardMask || !fabricCanvas || !ctx) return;
|
||||
var frame = soonDesign2ResolveCardFrame(fabricCanvas, imgEl);
|
||||
if (!frame) return;
|
||||
var left = frame.left;
|
||||
var top = frame.top;
|
||||
var cardW = frame.width;
|
||||
var cardH = frame.height;
|
||||
ctx.save();
|
||||
ctx.beginPath();
|
||||
ctx.rect(0, 0, fabricCanvas.width, fabricCanvas.height);
|
||||
ctx.moveTo(left + cardW, top);
|
||||
ctx.lineTo(left, top);
|
||||
ctx.lineTo(left, top + cardH);
|
||||
ctx.lineTo(left + cardW, top + cardH);
|
||||
ctx.closePath();
|
||||
ctx.fillStyle = 'rgba(0, 0, 0, 0.9)';
|
||||
ctx.fill('evenodd');
|
||||
ctx.restore();
|
||||
}
|
||||
|
||||
function soonDesign2DrawTemplateOverlay(fabricCanvas, ctx, imgEl) {
|
||||
if (!window.is_bgi_add || !fabricCanvas || !ctx || !imgEl) return;
|
||||
var frame = soonDesign2ResolveCardFrame(fabricCanvas, imgEl);
|
||||
if (!frame) return;
|
||||
ctx.drawImage(imgEl, frame.left, frame.top, frame.width, frame.height);
|
||||
}
|
||||
|
||||
function soonDesign2PrepareBgSources(done) {
|
||||
var sf = document.getElementById('source_front');
|
||||
var sb = document.getElementById('source_back');
|
||||
@@ -647,21 +878,47 @@ canvas2.preserveObjectStacking = true
|
||||
// 对象选择和属性更新函数
|
||||
// ==========================================
|
||||
// 将 updateControls 附加到 window 对象,确保在 eval() 加载 .jsc 文件时也能访问
|
||||
window.updateControls = function updateControls() {
|
||||
// 使用 window.canvas 和 window.background_image 作为后备,确保在 eval() 执行时也能访问
|
||||
window._soonSyncingFontControls = false;
|
||||
|
||||
function soonFontSizeUiVal(fontSizePx) {
|
||||
var d = window.dpi || 300;
|
||||
var uiVal = parseFloat(fontSizePx) * 72 / d;
|
||||
if (uiVal % 0.5 !== 0) uiVal = Math.round(uiVal * 2) / 2;
|
||||
return uiVal;
|
||||
}
|
||||
|
||||
function soonSyncActiveFontSizeInput(activeObj, currentCanvas) {
|
||||
if (!activeObj || !currentCanvas) return;
|
||||
var idx = getIndex(activeObj, currentCanvas);
|
||||
if (idx <= 0) return;
|
||||
var objData = (currentCanvas === canvas1 ? objs1 : objs2)[idx - 1];
|
||||
if (!objData) return;
|
||||
var uiVal = soonFontSizeUiVal(activeObj.get('fontSize'));
|
||||
if (objData.type === 3) $("#text_size").val(uiVal);
|
||||
else if (objData.type === 4) $("#out_text_size").val(uiVal);
|
||||
else if (objData.type === 10) $("#count_size").val(uiVal);
|
||||
}
|
||||
|
||||
window.updateControls = function () {
|
||||
const currentCanvas = window.canvas || canvas;
|
||||
const currentBackgroundImage = window.background_image || background_image;
|
||||
if (!currentCanvas || !currentCanvas.getActiveObject()) return;
|
||||
$("#text_r").val(currentCanvas.getActiveObject().get("angle").toFixed(0));
|
||||
$("#text_x").val((currentCanvas.getActiveObject().get("left") - currentBackgroundImage.left).toFixed(0));
|
||||
$("#text_y").val((currentCanvas.getActiveObject().get("top") - currentBackgroundImage.top).toFixed(0));
|
||||
$("#text_h").val((currentCanvas.getActiveObject().get("scaleY") * currentCanvas.getActiveObject().get("height")).toFixed(0));
|
||||
$("#text_w").val((currentCanvas.getActiveObject().get("scaleX") * currentCanvas.getActiveObject().get("width")).toFixed(0));
|
||||
// 根据锁定状态显示图标(使用lockMovementX判断,因为锁定时会设置所有lock属性)
|
||||
if (currentCanvas.getActiveObject().get("lockMovementX")) {
|
||||
$("#lock_img").attr("src", soonAsset("lock20.png"))//已锁定
|
||||
} else {
|
||||
$("#lock_img").attr("src", soonAsset("unlock20.png"))//未锁定
|
||||
const activeObj = currentCanvas.getActiveObject();
|
||||
window._soonSyncingFontControls = true;
|
||||
try {
|
||||
$("#text_r").val(activeObj.get("angle").toFixed(0));
|
||||
$("#text_x").val((activeObj.get("left") - currentBackgroundImage.left).toFixed(0));
|
||||
$("#text_y").val((activeObj.get("top") - currentBackgroundImage.top).toFixed(0));
|
||||
$("#text_h").val((activeObj.get("scaleY") * activeObj.get("height")).toFixed(0));
|
||||
$("#text_w").val((activeObj.get("scaleX") * activeObj.get("width")).toFixed(0));
|
||||
soonSyncActiveFontSizeInput(activeObj, currentCanvas);
|
||||
if (activeObj.get("lockMovementX")) {
|
||||
$("#lock_img").attr("src", soonAsset("lock20.png"));
|
||||
} else {
|
||||
$("#lock_img").attr("src", soonAsset("unlock20.png"));
|
||||
}
|
||||
} finally {
|
||||
window._soonSyncingFontControls = false;
|
||||
}
|
||||
};
|
||||
// 向后兼容
|
||||
@@ -1052,8 +1309,10 @@ function handleObjectSelected(e) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 3. 获取索引
|
||||
let i = getIndex(select_obj, canvas);
|
||||
// 3. 解析 objs 下标(用户设为背景时在 canvas[0],不能仅用 getIndex)
|
||||
let metaIdx = typeof soonDesign2ResolveObjMetaIndex === 'function'
|
||||
? soonDesign2ResolveObjMetaIndex(select_obj, canvas)
|
||||
: (getIndex(select_obj, canvas) > 0 ? getIndex(select_obj, canvas) - 1 : -1);
|
||||
|
||||
// 如果不是通过对象列表选中的,且对象被锁定,则取消选中
|
||||
if (!window._selectingFromList && isObjectLocked(select_obj)) {
|
||||
@@ -1065,58 +1324,52 @@ function handleObjectSelected(e) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (i != 0) {
|
||||
// --- 选中了普通对象 ---
|
||||
--i; // 转换为 objs 数组下标
|
||||
|
||||
// 安全检查:确保 objs[i] 存在且有 type 属性
|
||||
if (objs[i] && typeof objs[i].type !== 'undefined') {
|
||||
switch (objs[i].type) {
|
||||
if (metaIdx >= 0) {
|
||||
if (objs[metaIdx] && typeof objs[metaIdx].type !== 'undefined') {
|
||||
switch (objs[metaIdx].type) {
|
||||
case 1: // 图片
|
||||
$("#component_type").text(language_str("img"));
|
||||
selectObject(select_obj, i); selectPic(select_obj, i); break;
|
||||
selectObject(select_obj, metaIdx); selectPic(select_obj, metaIdx); break;
|
||||
case 2: // 合成图片
|
||||
$("#component_type").text(language_str("simg"));
|
||||
selectObject(select_obj, i); selectOutPic(select_obj, i); break;
|
||||
selectObject(select_obj, metaIdx); selectOutPic(select_obj, metaIdx); break;
|
||||
case 3: // 文本
|
||||
$("#component_type").text(language_str("text"));
|
||||
selectObject(select_obj, i); selectText(select_obj, i); break;
|
||||
selectObject(select_obj, metaIdx); selectText(select_obj, metaIdx); break;
|
||||
case 4: // 合成文本
|
||||
$("#component_type").text(language_str("stext"));
|
||||
selectObject(select_obj, i); selectOutText(select_obj, i); break;
|
||||
selectObject(select_obj, metaIdx); selectOutText(select_obj, metaIdx); break;
|
||||
case 5: // 矩形
|
||||
$("#component_type").text(language_str("rect"));
|
||||
selectObject(select_obj, i); selectRect(select_obj, i); break;
|
||||
selectObject(select_obj, metaIdx); selectRect(select_obj, metaIdx); break;
|
||||
case 6: // 圆形
|
||||
$("#component_type").text(language_str("circ"));
|
||||
selectObject(select_obj, i); selectCircle(select_obj, i); break;
|
||||
selectObject(select_obj, metaIdx); selectCircle(select_obj, metaIdx); break;
|
||||
case 7: // 直线
|
||||
$("#component_type").text(language_str("line"));
|
||||
selectObject(select_obj, i); selectLine(select_obj, i); break;
|
||||
selectObject(select_obj, metaIdx); selectLine(select_obj, metaIdx); break;
|
||||
case 8: // 二维码
|
||||
$("#component_type").text(language_str("qrc"));
|
||||
selectObject(select_obj, i); selectQrCode(select_obj, i); break;
|
||||
selectObject(select_obj, metaIdx); selectQrCode(select_obj, metaIdx); break;
|
||||
case 9: // 条形码
|
||||
$("#component_type").text(language_str("barc"));
|
||||
selectObject(select_obj, i); selectBarCode(select_obj, i); break;
|
||||
selectObject(select_obj, metaIdx); selectBarCode(select_obj, metaIdx); break;
|
||||
case 10: // 计数器
|
||||
$("#component_type").text(language_str("counter"));
|
||||
selectObject(select_obj, i); selectCounter(select_obj, i); break;
|
||||
selectObject(select_obj, metaIdx); selectCounter(select_obj, metaIdx); break;
|
||||
case 11: // 圆形文本
|
||||
$("#component_type").text(language_str("ctext"));
|
||||
selectObject(select_obj, i); selectCircleText(select_obj, i); break;
|
||||
selectObject(select_obj, metaIdx); selectCircleText(select_obj, metaIdx); break;
|
||||
}
|
||||
}
|
||||
|
||||
// 【关键】这里传入 true!
|
||||
// 意思是:因为我已经是在画布上选中它了,selectObj 函数只负责把左边的条目变灰,不要再回头去 setActiveObject 了
|
||||
selectObj(i, true);
|
||||
selectObj(metaIdx, true);
|
||||
|
||||
} else {
|
||||
// --- 选中了背景 ---
|
||||
// --- 模板背景(canvas[0] 且不在 objs 中)---
|
||||
$("#base_control, #line_control, #pic_control, #out_pic_control, #text_control, #circle_text_control, #out_text_control, #rect_control, #circle_control, #counter_control, #qrcode_Controll, #barcode_controll").hide();
|
||||
selectObj(-1, true);
|
||||
$("#component_type").text(language_str("bg"));
|
||||
selectObj(-1, true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1363,22 +1616,24 @@ function initCanvasEvents() {
|
||||
return;
|
||||
}
|
||||
let target = event.target;
|
||||
var modAction = event.action || (event.transform && event.transform.action);
|
||||
|
||||
if ([3, 4, 10].includes(objData.type)) {
|
||||
target.fontSize = (target.fontSize * target.scaleX).toFixed(0);
|
||||
target.scaleX = 1; target.scaleY = 1;
|
||||
if ([3, 4, 10].includes(objData.type) && modAction === 'scale') {
|
||||
target.set({
|
||||
fontSize: Math.round(target.fontSize * (target.scaleX || 1)),
|
||||
scaleX: 1,
|
||||
scaleY: 1,
|
||||
});
|
||||
target._clearCache();
|
||||
if (objData.type == 3) $("#text_size").val(target.fontSize);
|
||||
if (objData.type == 4) $("#out_text_size").val(target.fontSize);
|
||||
if (objData.type == 10) $("#count_size").val(target.fontSize);
|
||||
currentCanvas.renderAll();
|
||||
updateControls();
|
||||
} else if (objData.type == 5) {
|
||||
target.width *= target.scaleX; target.height *= target.scaleY;
|
||||
target.scaleX = 1; target.scaleY = 1;
|
||||
updateControls();
|
||||
} else if (objData.type == 5 && modAction === 'scale') {
|
||||
target.width *= target.scaleX || 1;
|
||||
target.height *= target.scaleY || 1;
|
||||
target.scaleX = 1;
|
||||
target.scaleY = 1;
|
||||
}
|
||||
recordState();
|
||||
updateControls();
|
||||
// 更新对象列表以同步锁状态
|
||||
if (typeof window.updateList === 'function') {
|
||||
window.updateList();
|
||||
@@ -1430,8 +1685,10 @@ window.updateList = function updateList() {
|
||||
// 检查锁定状态(通过lockMovementX判断,因为锁定时会设置所有lock属性)
|
||||
// 注意:索引0是背景图,objs数组是从下标0开始存第1个对象的,所以是 i+1
|
||||
let isLocked = false;
|
||||
if (currentCanvas.getObjects()[i + 1]) {
|
||||
let canvasObj = currentCanvas.getObjects()[i + 1];
|
||||
var canvasObj = typeof window.soonCanvasObjForListIndex === 'function'
|
||||
? window.soonCanvasObjForListIndex(i)
|
||||
: currentCanvas.getObjects()[i + 1];
|
||||
if (canvasObj) {
|
||||
isLocked = canvasObj.get('lockMovementX') === true;
|
||||
}
|
||||
|
||||
@@ -1454,9 +1711,9 @@ window.updateList = function updateList() {
|
||||
|
||||
// 重新绑定点击事件(防止 updateList 后点击失效)
|
||||
$(".obj_list > div").on("click", function () {
|
||||
let imgId = $(this).find("img").attr("id");
|
||||
let imgId = $(this).find("img[id^='obj']").attr("id");
|
||||
if (imgId) {
|
||||
let idx = parseInt(imgId.replace("obj", ""));
|
||||
let idx = parseInt(imgId.replace("obj", ""), 10);
|
||||
selectObj(idx);
|
||||
}
|
||||
});
|
||||
@@ -1465,6 +1722,40 @@ window.updateList = function updateList() {
|
||||
// 标记是否通过对象列表选中(用于区分鼠标点击和列表点击)
|
||||
window._selectingFromList = false;
|
||||
|
||||
// 对象列表下标 → 画布对象(设为背景后 objs 与 canvas 一一对应)
|
||||
function soonCanvasObjForListIndex(listIdx) {
|
||||
var c = window.canvas || canvas;
|
||||
var metaList = window.objs || objs;
|
||||
if (!c || listIdx < 0 || listIdx >= metaList.length) return null;
|
||||
var all = c.getObjects().filter(function (o) { return !o.isGuideLine; });
|
||||
var bgListedInObjs = metaList.length >= all.length;
|
||||
if (bgListedInObjs) {
|
||||
return all[listIdx] || null;
|
||||
}
|
||||
for (var j = 0; j < all.length; j++) {
|
||||
var o = all[j];
|
||||
var ci = getIndex(o, c);
|
||||
if (ci > 0 && ci - 1 === listIdx) return o;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
window.soonCanvasObjForListIndex = soonCanvasObjForListIndex;
|
||||
|
||||
/** 画布选中对象 → objs 下标;-1 表示模板背景(不在 objs 中) */
|
||||
function soonDesign2ResolveObjMetaIndex(select_obj, fabricCanvas) {
|
||||
if (!select_obj || !fabricCanvas) return -1;
|
||||
var metaList = fabricCanvas === canvas2 ? (window.objs2 || objs2) : (window.objs1 || objs1);
|
||||
if (fabricCanvas === (window.canvas || canvas)) {
|
||||
metaList = window.objs || objs || metaList;
|
||||
}
|
||||
if (!metaList || !metaList.length) return -1;
|
||||
for (var li = 0; li < metaList.length; li++) {
|
||||
if (soonCanvasObjForListIndex(li) === select_obj) return li;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
window.soonDesign2ResolveObjMetaIndex = soonDesign2ResolveObjMetaIndex;
|
||||
|
||||
// 将 selectObj 附加到 window 对象,确保全局可访问
|
||||
window.selectObj = function selectObj(objIndices, isFromCanvas = false) {
|
||||
let indicesArray = (Array.isArray(objIndices)) ? objIndices : ((typeof objIndices === 'number' && objIndices >= 0) ? [objIndices] : []);
|
||||
@@ -1474,10 +1765,10 @@ window.selectObj = function selectObj(objIndices, isFromCanvas = false) {
|
||||
|
||||
// 遍历列表查找并高亮
|
||||
$('.obj_list > div').each(function () {
|
||||
let $img = $(this).find("img");
|
||||
let $img = $(this).find("img[id^='obj']");
|
||||
if ($img.length === 0) return;
|
||||
|
||||
let idIndex = parseInt($img.attr("id").replace("obj", ""));
|
||||
let idIndex = parseInt($img.attr("id").replace("obj", ""), 10);
|
||||
|
||||
if (indicesArray.includes(idIndex)) {
|
||||
$(this).css("background-color", "#6F7A84");
|
||||
@@ -1491,7 +1782,7 @@ window.selectObj = function selectObj(objIndices, isFromCanvas = false) {
|
||||
|
||||
// 如果是点击列表,触发画布选中
|
||||
if (!isFromCanvas && indicesArray.length === 1) {
|
||||
let target = canvas.getObjects()[indicesArray[0] + 1];
|
||||
let target = soonCanvasObjForListIndex(indicesArray[0]);
|
||||
if (target) {
|
||||
// 检查对象是否被锁定
|
||||
let isLocked = isObjectLocked(target);
|
||||
@@ -1733,6 +2024,15 @@ function soonPlaceBgOnCanvas(image, canvasSelector) {
|
||||
image.selectable = false
|
||||
image.hoverable = false
|
||||
image.hoverCursor = 'default'
|
||||
var fc = (canvasSelector === '#canvas2') ? canvas2 : canvas1;
|
||||
if (fc && typeof soonDesign2SyncFrameAnchor === 'function') {
|
||||
soonDesign2SyncFrameAnchor(fc, {
|
||||
left: image.left,
|
||||
top: image.top,
|
||||
width: image.width * (image.get('scaleX') || 1),
|
||||
height: image.height * (image.get('scaleY') || 1)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function soonOpenPendingDesignFile() {
|
||||
@@ -2264,7 +2564,12 @@ var out_pic_op = slider.render({
|
||||
if (canvas.getActiveObject()) {
|
||||
canvas.getActiveObject().set('opacity', 1 - value / 100);
|
||||
canvas.renderAll();
|
||||
updateControls();
|
||||
window._soonSyncingFontControls = true;
|
||||
try {
|
||||
updateControls();
|
||||
} finally {
|
||||
window._soonSyncingFontControls = false;
|
||||
}
|
||||
recordState();
|
||||
}
|
||||
}
|
||||
@@ -2279,7 +2584,12 @@ var pic_op = slider.render({
|
||||
if (canvas.getActiveObject()) {
|
||||
canvas.getActiveObject().set('opacity', 1 - value / 100);
|
||||
canvas.renderAll();
|
||||
updateControls();
|
||||
window._soonSyncingFontControls = true;
|
||||
try {
|
||||
updateControls();
|
||||
} finally {
|
||||
window._soonSyncingFontControls = false;
|
||||
}
|
||||
recordState();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user