feat(design1): 光盘导出环形裁剪与画布/缩略图样式统一

导出与预览 PNG 按光盘外圆与中心孔透明裁剪;画布蒙版改为与背景同色 #31373D;缩略图改 PNG 环形铺底;Web/Electron 同步。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
24kycj
2026-06-28 22:16:15 +08:00
parent c24004d6c7
commit efeb3bcc41
4 changed files with 185 additions and 27 deletions
+103 -11
View File
@@ -51,6 +51,91 @@ async function saveImageAsPNG(buffer) {
}
}
function soonDesign1GetHoleDiameterMm(canvas) {
var hole = 24;
if (canvas === window.canvas1 && typeof window.bg_version !== 'undefined' && window.bg_version === 2) {
hole = 42;
}
return hole;
}
function soonDesign1ApplyDiscAlpha(tctx, w, h, holeDiameterMm) {
var cx = w / 2;
var cy = h / 2;
var rOuter = w / 2;
var rInner = rOuter * (holeDiameterMm / 120);
tctx.save();
tctx.globalCompositeOperation = 'destination-in';
tctx.fillStyle = '#fff';
tctx.beginPath();
tctx.arc(cx, cy, rOuter, 0, Math.PI * 2);
tctx.moveTo(cx + rInner, cy);
tctx.arc(cx, cy, rInner, 0, Math.PI * 2, true);
tctx.fill('evenodd');
tctx.restore();
}
function soonDesign1ApplyDiscMatte(tctx, w, h, holeDiameterMm, color) {
var snap = document.createElement('canvas');
snap.width = w;
snap.height = h;
snap.getContext('2d').drawImage(tctx.canvas, 0, 0);
tctx.fillStyle = color;
tctx.fillRect(0, 0, w, h);
tctx.save();
var cx = w / 2;
var cy = h / 2;
var rOuter = w / 2;
var rInner = rOuter * (holeDiameterMm / 120);
tctx.beginPath();
tctx.arc(cx, cy, rOuter, 0, Math.PI * 2);
tctx.moveTo(cx + rInner, cy);
tctx.arc(cx, cy, rInner, 0, Math.PI * 2, true);
tctx.clip('evenodd');
tctx.drawImage(snap, 0, 0);
tctx.restore();
}
function soonDesign1CaptureCanvasRect(canvas, outW, outH, format, quality, clipDisc, discMatte) {
var bg = window.background_image1 || window.background_image;
if (!canvas || !bg) return '';
var srcEl = canvas.lowerCanvasEl;
if (!srcEl || !srcEl.getContext) return '';
var sx = bg.scaleX == null ? 1 : bg.scaleX;
var sy = bg.scaleY == null ? 1 : bg.scaleY;
var sw = bg.width * sx;
var sh = bg.height * sy;
var retina = (typeof canvas.getRetinaScaling === 'function') ? canvas.getRetinaScaling() : 1;
outW = outW || Math.round(sw);
outH = outH || Math.round(sh);
var tmp = document.createElement('canvas');
tmp.width = outW;
tmp.height = outH;
var tctx = tmp.getContext('2d');
tctx.drawImage(
srcEl,
bg.left * retina, bg.top * retina, sw * retina, sh * retina,
0, 0, outW, outH
);
if (discMatte) {
soonDesign1ApplyDiscMatte(tctx, outW, outH, soonDesign1GetHoleDiameterMm(canvas), discMatte);
} else if (clipDisc && format !== 'jpeg') {
soonDesign1ApplyDiscAlpha(tctx, outW, outH, soonDesign1GetHoleDiameterMm(canvas));
}
if (format === 'jpeg') return tmp.toDataURL('image/jpeg', quality == null ? 0.75 : quality);
return tmp.toDataURL('image/png');
}
function soonDesign1CaptureDiscPng(canvas, outW, outH) {
window._soonSkipDesign1CdMask = true;
if (canvas.discardActiveObject) canvas.discardActiveObject();
canvas.renderAll();
var url = soonDesign1CaptureCanvasRect(canvas, outW, outH, 'png', null, true);
window._soonSkipDesign1CdMask = false;
canvas.renderAll();
return url;
}
// 将 display_func 附加到 window 对象,确保全局可访问
window.display_func = function display_func(img1, img2, img3) {
$("#base_control").hide();
@@ -217,13 +302,16 @@ window.display_func = function display_func(img1, img2, img3) {
left: all_left
});
g3.push(img1);
let url3 = new fabric.Group(g3).toDataURL({
height: 2787,
width: 2787,
top: all_top,
left: all_left
var hiddenForPreview = [];
canvas1.getObjects().forEach(function (o) {
if (o.isGuideLine) {
hiddenForPreview.push(o);
o.visible = false;
}
});
let url3 = soonDesign1CaptureDiscPng(canvas1, 2787, 2787);
hiddenForPreview.forEach(function (o) { o.visible = true; });
canvas1.renderAll();
let url5 = new fabric.Group(g5).toDataURL({
height: 2787,
width: 2787,
@@ -596,12 +684,16 @@ window.output = function output(callback = null, _save = save) {
left: all_left
});
g3.push(img1);
let url3 = new fabric.Group(g3).toDataURL({
height: 2787,
width: 2787,
top: all_top,
left: all_left
var hiddenForSave = [];
canvas1.getObjects().forEach(function (o) {
if (o.isGuideLine) {
hiddenForSave.push(o);
o.visible = false;
}
});
let url3 = soonDesign1CaptureDiscPng(canvas1, 2787, 2787);
hiddenForSave.forEach(function (o) { o.visible = true; });
canvas1.renderAll();
let url5 = new fabric.Group(g5).toDataURL({
height: 2787,
width: 2787,