@pixldocs/canvas-renderer 0.5.101 → 0.5.102
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +390 -50
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +390 -50
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -3663,28 +3663,33 @@ function updateCoverLayout(g) {
|
|
|
3663
3663
|
const hasCustomSvgMask = Boolean(
|
|
3664
3664
|
currentClipPath && (isSvgMaskClipPath(currentClipPath) || isLuminanceMaskClipPath(currentClipPath) || currentClipPath.__svgMask)
|
|
3665
3665
|
);
|
|
3666
|
-
|
|
3666
|
+
const hasEdgeFadeMask = Boolean(currentClipPath && currentClipPath.__edgeFadeMask);
|
|
3667
|
+
if (hasCustomSvgMask || hasEdgeFadeMask) {
|
|
3667
3668
|
if (isSvgMaskClipPath(currentClipPath)) {
|
|
3668
3669
|
syncSvgMaskClipPath(g);
|
|
3669
3670
|
} else if (currentClipPath && typeof currentClipPath.set === "function") {
|
|
3670
|
-
|
|
3671
|
-
|
|
3672
|
-
|
|
3673
|
-
|
|
3674
|
-
|
|
3675
|
-
|
|
3676
|
-
|
|
3677
|
-
|
|
3678
|
-
|
|
3679
|
-
|
|
3680
|
-
|
|
3681
|
-
|
|
3682
|
-
|
|
3683
|
-
|
|
3684
|
-
|
|
3685
|
-
|
|
3686
|
-
|
|
3687
|
-
|
|
3671
|
+
if (hasEdgeFadeMask) {
|
|
3672
|
+
currentClipPath.dirty = true;
|
|
3673
|
+
} else {
|
|
3674
|
+
const baseW = Math.max(1, Number(currentClipPath.width) || frameW);
|
|
3675
|
+
const baseH = Math.max(1, Number(currentClipPath.height) || frameH);
|
|
3676
|
+
currentClipPath.set({
|
|
3677
|
+
left: 0,
|
|
3678
|
+
top: 0,
|
|
3679
|
+
originX: "center",
|
|
3680
|
+
originY: "center",
|
|
3681
|
+
scaleX: frameW / baseW,
|
|
3682
|
+
scaleY: frameH / baseH,
|
|
3683
|
+
selectable: false,
|
|
3684
|
+
evented: false,
|
|
3685
|
+
hasControls: false,
|
|
3686
|
+
hasBorders: false
|
|
3687
|
+
});
|
|
3688
|
+
currentClipPath.absolutePositioned = false;
|
|
3689
|
+
currentClipPath.excludeFromExport = true;
|
|
3690
|
+
currentClipPath.dirty = true;
|
|
3691
|
+
currentClipPath.setCoords();
|
|
3692
|
+
}
|
|
3688
3693
|
}
|
|
3689
3694
|
} else {
|
|
3690
3695
|
const needsNewClipPath = !g.clipPath || shape === "circle" && !(g.clipPath instanceof fabric.Ellipse) || shape !== "circle" && !(g.clipPath instanceof fabric.Rect);
|
|
@@ -4641,10 +4646,12 @@ function exitCropMode(g, commit = true) {
|
|
|
4641
4646
|
g.hasControls = true;
|
|
4642
4647
|
g.borderDashArray = void 0;
|
|
4643
4648
|
installCanvaMaskControls(g);
|
|
4644
|
-
g.borderColor =
|
|
4645
|
-
g.
|
|
4646
|
-
g.
|
|
4649
|
+
g.borderColor = "#4f46e5";
|
|
4650
|
+
g.borderDashArray = void 0;
|
|
4651
|
+
g.cornerColor = "#ffffff";
|
|
4652
|
+
g.cornerStrokeColor = "#4f46e5";
|
|
4647
4653
|
g.cornerStyle = "rect";
|
|
4654
|
+
g.transparentCorners = false;
|
|
4648
4655
|
g[CROP_MODE_FLAG] = false;
|
|
4649
4656
|
g.__cropZoomLastPointer = void 0;
|
|
4650
4657
|
g.__lastPointerForCrop = void 0;
|
|
@@ -6174,6 +6181,127 @@ function renderSmartElementToDataUri(type, props, width, height) {
|
|
|
6174
6181
|
if (!svg) return null;
|
|
6175
6182
|
return `data:image/svg+xml;charset=utf-8,${encodeURIComponent(svg)}`;
|
|
6176
6183
|
}
|
|
6184
|
+
function hasEdgeFade(p) {
|
|
6185
|
+
if (!p) return false;
|
|
6186
|
+
const sides = [
|
|
6187
|
+
[p.fadeTopSize, p.fadeTopAmount],
|
|
6188
|
+
[p.fadeRightSize, p.fadeRightAmount],
|
|
6189
|
+
[p.fadeBottomSize, p.fadeBottomAmount],
|
|
6190
|
+
[p.fadeLeftSize, p.fadeLeftAmount]
|
|
6191
|
+
];
|
|
6192
|
+
for (const [size, amount] of sides) {
|
|
6193
|
+
const s = Number(size) || 0;
|
|
6194
|
+
const a = amount == null ? 1 : Number(amount);
|
|
6195
|
+
if (s > 0 && a < 1) return true;
|
|
6196
|
+
}
|
|
6197
|
+
return false;
|
|
6198
|
+
}
|
|
6199
|
+
function edgeFadeKey(p) {
|
|
6200
|
+
if (!hasEdgeFade(p)) return "";
|
|
6201
|
+
return [
|
|
6202
|
+
(p == null ? void 0 : p.fadeTopSize) ?? 0,
|
|
6203
|
+
(p == null ? void 0 : p.fadeTopAmount) ?? 1,
|
|
6204
|
+
(p == null ? void 0 : p.fadeRightSize) ?? 0,
|
|
6205
|
+
(p == null ? void 0 : p.fadeRightAmount) ?? 1,
|
|
6206
|
+
(p == null ? void 0 : p.fadeBottomSize) ?? 0,
|
|
6207
|
+
(p == null ? void 0 : p.fadeBottomAmount) ?? 1,
|
|
6208
|
+
(p == null ? void 0 : p.fadeLeftSize) ?? 0,
|
|
6209
|
+
(p == null ? void 0 : p.fadeLeftAmount) ?? 1,
|
|
6210
|
+
(p == null ? void 0 : p.fadeTopHardness) ?? 1,
|
|
6211
|
+
(p == null ? void 0 : p.fadeRightHardness) ?? 1,
|
|
6212
|
+
(p == null ? void 0 : p.fadeBottomHardness) ?? 1,
|
|
6213
|
+
(p == null ? void 0 : p.fadeLeftHardness) ?? 1
|
|
6214
|
+
].join("|");
|
|
6215
|
+
}
|
|
6216
|
+
function clamp01(n) {
|
|
6217
|
+
if (!Number.isFinite(n)) return 0;
|
|
6218
|
+
return Math.max(0, Math.min(1, n));
|
|
6219
|
+
}
|
|
6220
|
+
function bakeEdgeFade(source, fade) {
|
|
6221
|
+
const w = source.naturalWidth || source.width || 0;
|
|
6222
|
+
const h = source.naturalHeight || source.height || 0;
|
|
6223
|
+
const canvas = document.createElement("canvas");
|
|
6224
|
+
canvas.width = Math.max(1, w);
|
|
6225
|
+
canvas.height = Math.max(1, h);
|
|
6226
|
+
const ctx = canvas.getContext("2d");
|
|
6227
|
+
if (!ctx) return canvas;
|
|
6228
|
+
ctx.drawImage(source, 0, 0, canvas.width, canvas.height);
|
|
6229
|
+
const clampHardness = (n) => {
|
|
6230
|
+
const v = Number(n);
|
|
6231
|
+
if (!Number.isFinite(v) || v <= 0) return 1;
|
|
6232
|
+
return Math.max(0.1, Math.min(5, v));
|
|
6233
|
+
};
|
|
6234
|
+
const sides = [
|
|
6235
|
+
{ side: "top", size: clamp01(fade.fadeTopSize ?? 0), amount: clamp01(fade.fadeTopAmount ?? 1), hardness: clampHardness(fade.fadeTopHardness) },
|
|
6236
|
+
{ side: "right", size: clamp01(fade.fadeRightSize ?? 0), amount: clamp01(fade.fadeRightAmount ?? 1), hardness: clampHardness(fade.fadeRightHardness) },
|
|
6237
|
+
{ side: "bottom", size: clamp01(fade.fadeBottomSize ?? 0), amount: clamp01(fade.fadeBottomAmount ?? 1), hardness: clampHardness(fade.fadeBottomHardness) },
|
|
6238
|
+
{ side: "left", size: clamp01(fade.fadeLeftSize ?? 0), amount: clamp01(fade.fadeLeftAmount ?? 1), hardness: clampHardness(fade.fadeLeftHardness) }
|
|
6239
|
+
];
|
|
6240
|
+
for (const { side, size, amount, hardness } of sides) {
|
|
6241
|
+
if (size <= 0 || amount >= 1) continue;
|
|
6242
|
+
const mask = document.createElement("canvas");
|
|
6243
|
+
mask.width = canvas.width;
|
|
6244
|
+
mask.height = canvas.height;
|
|
6245
|
+
const mctx = mask.getContext("2d");
|
|
6246
|
+
if (!mctx) continue;
|
|
6247
|
+
mctx.fillStyle = "#000";
|
|
6248
|
+
mctx.fillRect(0, 0, mask.width, mask.height);
|
|
6249
|
+
let g;
|
|
6250
|
+
let x = 0, y = 0, rectW = mask.width, rectH = mask.height;
|
|
6251
|
+
const STOPS = 24;
|
|
6252
|
+
const innerAlpha = (t) => {
|
|
6253
|
+
const keepProgress = Math.pow(t, hardness);
|
|
6254
|
+
const erase = (1 - amount) * (1 - keepProgress);
|
|
6255
|
+
return 1 - erase;
|
|
6256
|
+
};
|
|
6257
|
+
const fillStops = (grad, reverse) => {
|
|
6258
|
+
for (let i = 0; i <= STOPS; i++) {
|
|
6259
|
+
const t = i / STOPS;
|
|
6260
|
+
const a = innerAlpha(t);
|
|
6261
|
+
grad.addColorStop(t, `rgba(0,0,0,${a})`);
|
|
6262
|
+
}
|
|
6263
|
+
};
|
|
6264
|
+
if (side === "top") {
|
|
6265
|
+
const band = Math.max(1, Math.round(mask.height * size));
|
|
6266
|
+
g = mctx.createLinearGradient(0, 0, 0, band);
|
|
6267
|
+
fillStops(g);
|
|
6268
|
+
rectH = band;
|
|
6269
|
+
} else if (side === "bottom") {
|
|
6270
|
+
const band = Math.max(1, Math.round(mask.height * size));
|
|
6271
|
+
y = mask.height - band;
|
|
6272
|
+
g = mctx.createLinearGradient(0, mask.height, 0, y);
|
|
6273
|
+
fillStops(g);
|
|
6274
|
+
rectH = band;
|
|
6275
|
+
} else if (side === "left") {
|
|
6276
|
+
const band = Math.max(1, Math.round(mask.width * size));
|
|
6277
|
+
g = mctx.createLinearGradient(0, 0, band, 0);
|
|
6278
|
+
fillStops(g);
|
|
6279
|
+
rectW = band;
|
|
6280
|
+
} else {
|
|
6281
|
+
const band = Math.max(1, Math.round(mask.width * size));
|
|
6282
|
+
x = mask.width - band;
|
|
6283
|
+
g = mctx.createLinearGradient(mask.width, 0, x, 0);
|
|
6284
|
+
fillStops(g);
|
|
6285
|
+
rectW = band;
|
|
6286
|
+
}
|
|
6287
|
+
mctx.fillStyle = g;
|
|
6288
|
+
mctx.fillRect(x, y, rectW, rectH);
|
|
6289
|
+
if (amount <= 1e-3) {
|
|
6290
|
+
const edgePx = Math.min(2, side === "top" || side === "bottom" ? rectH : rectW);
|
|
6291
|
+
mctx.fillStyle = "rgba(0,0,0,0)";
|
|
6292
|
+
mctx.globalCompositeOperation = "copy";
|
|
6293
|
+
if (side === "top") mctx.fillRect(0, 0, mask.width, edgePx);
|
|
6294
|
+
if (side === "bottom") mctx.fillRect(0, mask.height - edgePx, mask.width, edgePx);
|
|
6295
|
+
if (side === "left") mctx.fillRect(0, 0, edgePx, mask.height);
|
|
6296
|
+
if (side === "right") mctx.fillRect(mask.width - edgePx, 0, edgePx, mask.height);
|
|
6297
|
+
mctx.globalCompositeOperation = "source-over";
|
|
6298
|
+
}
|
|
6299
|
+
ctx.globalCompositeOperation = "destination-in";
|
|
6300
|
+
ctx.drawImage(mask, 0, 0);
|
|
6301
|
+
ctx.globalCompositeOperation = "source-over";
|
|
6302
|
+
}
|
|
6303
|
+
return canvas;
|
|
6304
|
+
}
|
|
6177
6305
|
function angleToCoords(angleDeg) {
|
|
6178
6306
|
const rad = angleDeg * Math.PI / 180;
|
|
6179
6307
|
const x1 = 0.5 - Math.sin(rad) * 0.5;
|
|
@@ -7683,6 +7811,10 @@ const PageCanvas = forwardRef(
|
|
|
7683
7811
|
fabricCanvas.on("mouse:dblclick", (e) => {
|
|
7684
7812
|
if (!isActiveRef.current || !allowEditing) return;
|
|
7685
7813
|
let target = e.target;
|
|
7814
|
+
if (!target) {
|
|
7815
|
+
const active = fabricCanvas.getActiveObject();
|
|
7816
|
+
if (active) target = active;
|
|
7817
|
+
}
|
|
7686
7818
|
if (target && target instanceof fabric.Group && target.__cropGroup) {
|
|
7687
7819
|
const ct = target.__cropData;
|
|
7688
7820
|
if ((ct == null ? void 0 : ct._img) && !isCropGroupInCropMode(target)) {
|
|
@@ -7838,7 +7970,7 @@ const PageCanvas = forwardRef(
|
|
|
7838
7970
|
visibilityUpdateInProgressRef.current = false;
|
|
7839
7971
|
}
|
|
7840
7972
|
doSyncRef.current = () => {
|
|
7841
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _i;
|
|
7973
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
|
|
7842
7974
|
const shouldSkipUpdates2 = syncLockedRef.current || editLockRef.current;
|
|
7843
7975
|
const state = useEditorStore.getState();
|
|
7844
7976
|
const elementsToSync = elements;
|
|
@@ -7999,15 +8131,22 @@ const PageCanvas = forwardRef(
|
|
|
7999
8131
|
const storedImageUrl = existingObj.__imageSrc;
|
|
8000
8132
|
const currentUrlNormalized = currentImageUrl.trim();
|
|
8001
8133
|
const storedUrlNormalized = storedImageUrl ? String(storedImageUrl).trim() : "";
|
|
8002
|
-
const svgColorMapStr = element.svgColorMap ? JSON.stringify(element.svgColorMap) : "";
|
|
8003
|
-
const storedColorMapStr = existingObj.__svgColorMap || "";
|
|
8004
|
-
const colorMapChanged = svgColorMapStr !== storedColorMapStr;
|
|
8005
|
-
const sourceUrlChanged = currentUrlNormalized !== storedUrlNormalized;
|
|
8006
|
-
const needsReload = sourceUrlChanged || colorMapChanged;
|
|
8007
8134
|
const hasUrl = currentUrlNormalized !== "";
|
|
8008
8135
|
const isCropGroup2 = existingObj instanceof fabric.Group && existingObj.__cropGroup;
|
|
8009
8136
|
const isPlaceholderGroup = isEmptyImagePlaceholderGroup(existingObj);
|
|
8010
8137
|
const isPlaceholder = isPlaceholderGroup || !(existingObj instanceof fabric.FabricImage) || existingObj instanceof fabric.Group && !isCropGroup2;
|
|
8138
|
+
const svgColorMapStr = element.svgColorMap ? JSON.stringify(element.svgColorMap) : "";
|
|
8139
|
+
const storedColorMapStr = existingObj.__svgColorMap || "";
|
|
8140
|
+
const colorMapChanged = svgColorMapStr !== storedColorMapStr;
|
|
8141
|
+
const sourceUrlChanged = currentUrlNormalized !== storedUrlNormalized;
|
|
8142
|
+
const newFadeKey = edgeFadeKey(element);
|
|
8143
|
+
const oldFadeKey = isCropGroup2 ? existingObj.__edgeFadeInputKey || "" : existingObj.__edgeFadeKey || "";
|
|
8144
|
+
const innerImg = (_e = existingObj == null ? void 0 : existingObj.__cropData) == null ? void 0 : _e._img;
|
|
8145
|
+
const innerOldKey = isCropGroup2 ? oldFadeKey : innerImg ? innerImg.__edgeFadeKey || "" : oldFadeKey;
|
|
8146
|
+
const cropFadeRendererMissing = isCropGroup2 && Boolean(newFadeKey) && !existingObj.__edgeFadeRenderConfig;
|
|
8147
|
+
const fadeKeyChanged = newFadeKey !== oldFadeKey || newFadeKey !== innerOldKey || cropFadeRendererMissing;
|
|
8148
|
+
const needsReload = sourceUrlChanged || colorMapChanged || fadeKeyChanged && !isCropGroup2;
|
|
8149
|
+
const needsCropGroupFadeUpdate = isCropGroup2 && fadeKeyChanged;
|
|
8011
8150
|
const hadUrlBefore = storedImageUrl && String(storedImageUrl).trim() !== "";
|
|
8012
8151
|
if (!hasUrl && hadUrlBefore) {
|
|
8013
8152
|
const placeholder = isCropGroup2 ? createImagePlaceholderForGroup(element) : createImagePlaceholder(element);
|
|
@@ -8023,16 +8162,16 @@ const PageCanvas = forwardRef(
|
|
|
8023
8162
|
fc.requestRenderAll();
|
|
8024
8163
|
continue;
|
|
8025
8164
|
}
|
|
8026
|
-
const imageFitForReplace = element.imageFit || ((
|
|
8027
|
-
const clipShapeForReplace = element.clipShape ?? ((
|
|
8165
|
+
const imageFitForReplace = element.imageFit || ((_f = element.style) == null ? void 0 : _f.imageFit) || "cover";
|
|
8166
|
+
const clipShapeForReplace = element.clipShape ?? ((_g = element.style) == null ? void 0 : _g.imageFrameShape) ?? (isPreviewMode ? "rectangle" : "none");
|
|
8028
8167
|
const needCropGroupForElement = imageFitForReplace !== "fill" || clipShapeForReplace && clipShapeForReplace !== "none";
|
|
8029
8168
|
const plainImageNeedsCropGroup = hasUrl && !isCropGroup2 && existingObj instanceof fabric.FabricImage && needCropGroupForElement;
|
|
8030
|
-
if (hasUrl && (needsReload || isPlaceholder || plainImageNeedsCropGroup)) {
|
|
8169
|
+
if (hasUrl && (needsReload || isPlaceholder || plainImageNeedsCropGroup || needsCropGroupFadeUpdate)) {
|
|
8031
8170
|
if (needsReload && !isBeingTransformed && (!wasJustModified || sourceUrlChanged)) {
|
|
8032
8171
|
loadImageAsync(element, existingObj, fc);
|
|
8033
8172
|
} else if (plainImageNeedsCropGroup) {
|
|
8034
8173
|
loadImageAsync(element, existingObj, fc);
|
|
8035
|
-
} else if (!needsReload && isCropGroup2) {
|
|
8174
|
+
} else if ((!needsReload || needsCropGroupFadeUpdate) && isCropGroup2) {
|
|
8036
8175
|
const ct = existingObj.__cropData;
|
|
8037
8176
|
if (ct) {
|
|
8038
8177
|
const resolvedCrop = pageTree.length > 0 ? getNodeBounds(element, pageTree) : { width: typeof element.width === "number" ? element.width : 200, height: typeof element.height === "number" ? element.height : 50 };
|
|
@@ -8129,6 +8268,7 @@ const PageCanvas = forwardRef(
|
|
|
8129
8268
|
}
|
|
8130
8269
|
}
|
|
8131
8270
|
updateCoverLayout(existingObj);
|
|
8271
|
+
applyEdgeFadeFrameClipPath(existingObj, element, ct.frameW, ct.frameH, ct.shape || "rect", ct.rx || 0);
|
|
8132
8272
|
if (allowEditing) {
|
|
8133
8273
|
installCanvaMaskControls(existingObj);
|
|
8134
8274
|
} else {
|
|
@@ -8438,7 +8578,7 @@ const PageCanvas = forwardRef(
|
|
|
8438
8578
|
fc.add(placeholder);
|
|
8439
8579
|
fc.bringObjectToFront(placeholder);
|
|
8440
8580
|
const activeObj = fc.getActiveObject();
|
|
8441
|
-
if (activeObj && (((
|
|
8581
|
+
if (activeObj && (((_h = activeObj._ct) == null ? void 0 : _h.isCropGroup) || activeObj.__cropGroup)) {
|
|
8442
8582
|
fc.setActiveObject(activeObj);
|
|
8443
8583
|
}
|
|
8444
8584
|
placeholder.dirty = true;
|
|
@@ -8478,7 +8618,7 @@ const PageCanvas = forwardRef(
|
|
|
8478
8618
|
fc.add(obj);
|
|
8479
8619
|
fc.bringObjectToFront(obj);
|
|
8480
8620
|
const activeObj = fc.getActiveObject();
|
|
8481
|
-
if (activeObj && (((
|
|
8621
|
+
if (activeObj && (((_i = activeObj._ct) == null ? void 0 : _i.isCropGroup) || activeObj.__cropGroup)) {
|
|
8482
8622
|
fc.setActiveObject(activeObj);
|
|
8483
8623
|
}
|
|
8484
8624
|
obj.dirty = true;
|
|
@@ -8512,7 +8652,7 @@ const PageCanvas = forwardRef(
|
|
|
8512
8652
|
isRebuildingRef.current = false;
|
|
8513
8653
|
fc.requestRenderAll();
|
|
8514
8654
|
if (activeBeforeSync && fc.getObjects().includes(activeBeforeSync)) {
|
|
8515
|
-
const isCropGroup2 = ((
|
|
8655
|
+
const isCropGroup2 = ((_j = activeBeforeSync._ct) == null ? void 0 : _j.isCropGroup) || activeBeforeSync.__cropGroup;
|
|
8516
8656
|
if (isCropGroup2) {
|
|
8517
8657
|
fc.setActiveObject(activeBeforeSync);
|
|
8518
8658
|
fc.requestRenderAll();
|
|
@@ -8934,6 +9074,7 @@ const PageCanvas = forwardRef(
|
|
|
8934
9074
|
}
|
|
8935
9075
|
}
|
|
8936
9076
|
updateCoverLayout(obj);
|
|
9077
|
+
applyEdgeFadeFrameClipPath(obj, element, elementWidth, elementHeight, ct.shape || "rect", ct.rx || 0);
|
|
8937
9078
|
obj.setCoords();
|
|
8938
9079
|
obj.dirty = true;
|
|
8939
9080
|
if (obj.clipPath) {
|
|
@@ -9517,8 +9658,131 @@ const PageCanvas = forwardRef(
|
|
|
9517
9658
|
obj.__lastStrokeGradientJson = "null";
|
|
9518
9659
|
}
|
|
9519
9660
|
};
|
|
9661
|
+
const clamp2 = (v, min, max) => {
|
|
9662
|
+
return Math.max(min, Math.min(max, v));
|
|
9663
|
+
};
|
|
9664
|
+
const applyEdgeFadeFrameClipPath = (group, element, frameW, frameH, shape, rxRatio) => {
|
|
9665
|
+
var _a, _b, _c;
|
|
9666
|
+
const fadeElement = element;
|
|
9667
|
+
const fadeGroup = group;
|
|
9668
|
+
const inputKey = edgeFadeKey(fadeElement);
|
|
9669
|
+
const hasFade = hasEdgeFade(fadeElement);
|
|
9670
|
+
if (!fadeGroup.__edgeFadeOriginalDrawObject) {
|
|
9671
|
+
fadeGroup.__edgeFadeOriginalDrawObject = group.drawObject;
|
|
9672
|
+
}
|
|
9673
|
+
if (hasFade) {
|
|
9674
|
+
if ((_a = group.clipPath) == null ? void 0 : _a.__edgeFadeMask) {
|
|
9675
|
+
group.clipPath = void 0;
|
|
9676
|
+
updateCoverLayout(group);
|
|
9677
|
+
}
|
|
9678
|
+
fadeGroup.__edgeFadeRenderConfig = {
|
|
9679
|
+
key: `${inputKey}|${Math.round(frameW)}|${Math.round(frameH)}|${shape}|${rxRatio}`,
|
|
9680
|
+
frameW: Math.max(1, Number(frameW) || 1),
|
|
9681
|
+
frameH: Math.max(1, Number(frameH) || 1),
|
|
9682
|
+
topSize: clamp2(Number(fadeElement.fadeTopSize) || 0, 0, 1),
|
|
9683
|
+
topAmount: clamp2(fadeElement.fadeTopAmount == null ? 1 : Number(fadeElement.fadeTopAmount), 0, 1),
|
|
9684
|
+
rightSize: clamp2(Number(fadeElement.fadeRightSize) || 0, 0, 1),
|
|
9685
|
+
rightAmount: clamp2(fadeElement.fadeRightAmount == null ? 1 : Number(fadeElement.fadeRightAmount), 0, 1),
|
|
9686
|
+
bottomSize: clamp2(Number(fadeElement.fadeBottomSize) || 0, 0, 1),
|
|
9687
|
+
bottomAmount: clamp2(fadeElement.fadeBottomAmount == null ? 1 : Number(fadeElement.fadeBottomAmount), 0, 1),
|
|
9688
|
+
leftSize: clamp2(Number(fadeElement.fadeLeftSize) || 0, 0, 1),
|
|
9689
|
+
leftAmount: clamp2(fadeElement.fadeLeftAmount == null ? 1 : Number(fadeElement.fadeLeftAmount), 0, 1),
|
|
9690
|
+
topHardness: clamp2(Number(fadeElement.fadeTopHardness) || 1, 0.1, 5),
|
|
9691
|
+
rightHardness: clamp2(Number(fadeElement.fadeRightHardness) || 1, 0.1, 5),
|
|
9692
|
+
bottomHardness: clamp2(Number(fadeElement.fadeBottomHardness) || 1, 0.1, 5),
|
|
9693
|
+
leftHardness: clamp2(Number(fadeElement.fadeLeftHardness) || 1, 0.1, 5)
|
|
9694
|
+
};
|
|
9695
|
+
const originalDrawObject = fadeGroup.__edgeFadeOriginalDrawObject ?? group.drawObject;
|
|
9696
|
+
group.drawObject = function edgeFadeDrawObject(ctx, forClipping, context) {
|
|
9697
|
+
originalDrawObject.call(this, ctx, forClipping, context);
|
|
9698
|
+
if (forClipping) return;
|
|
9699
|
+
const cfg = this.__edgeFadeRenderConfig;
|
|
9700
|
+
if (!cfg) return;
|
|
9701
|
+
const liveW = Number(this.width) || 0;
|
|
9702
|
+
const liveH = Number(this.height) || 0;
|
|
9703
|
+
const w = liveW > 0 ? liveW : cfg.frameW;
|
|
9704
|
+
const h = liveH > 0 ? liveH : cfg.frameH;
|
|
9705
|
+
const x = -w / 2;
|
|
9706
|
+
const y = -h / 2;
|
|
9707
|
+
const paintBand = (side, size, amount, hardness) => {
|
|
9708
|
+
if (size <= 0 || amount >= 1) return;
|
|
9709
|
+
ctx.save();
|
|
9710
|
+
ctx.globalCompositeOperation = "destination-out";
|
|
9711
|
+
let gradient;
|
|
9712
|
+
const eraseAtEdge = 1 - amount;
|
|
9713
|
+
const STOPS = 24;
|
|
9714
|
+
const addStops = (g) => {
|
|
9715
|
+
for (let i = 0; i <= STOPS; i++) {
|
|
9716
|
+
const t = i / STOPS;
|
|
9717
|
+
const keepProgress = Math.pow(t, hardness);
|
|
9718
|
+
const a = eraseAtEdge * (1 - keepProgress);
|
|
9719
|
+
g.addColorStop(t, `rgba(0,0,0,${a})`);
|
|
9720
|
+
}
|
|
9721
|
+
};
|
|
9722
|
+
if (side === "top") {
|
|
9723
|
+
const band = Math.max(1, h * size);
|
|
9724
|
+
gradient = ctx.createLinearGradient(0, y, 0, y + band);
|
|
9725
|
+
addStops(gradient);
|
|
9726
|
+
ctx.fillStyle = gradient;
|
|
9727
|
+
ctx.fillRect(x, y, w, band);
|
|
9728
|
+
if (amount <= 1e-3) ctx.fillRect(x, y, w, Math.min(2, band));
|
|
9729
|
+
} else if (side === "bottom") {
|
|
9730
|
+
const band = Math.max(1, h * size);
|
|
9731
|
+
gradient = ctx.createLinearGradient(0, y + h, 0, y + h - band);
|
|
9732
|
+
addStops(gradient);
|
|
9733
|
+
ctx.fillStyle = gradient;
|
|
9734
|
+
ctx.fillRect(x, y + h - band, w, band);
|
|
9735
|
+
if (amount <= 1e-3) ctx.fillRect(x, y + h - Math.min(2, band), w, Math.min(2, band));
|
|
9736
|
+
} else if (side === "left") {
|
|
9737
|
+
const band = Math.max(1, w * size);
|
|
9738
|
+
gradient = ctx.createLinearGradient(x, 0, x + band, 0);
|
|
9739
|
+
addStops(gradient);
|
|
9740
|
+
ctx.fillStyle = gradient;
|
|
9741
|
+
ctx.fillRect(x, y, band, h);
|
|
9742
|
+
if (amount <= 1e-3) ctx.fillRect(x, y, Math.min(2, band), h);
|
|
9743
|
+
} else {
|
|
9744
|
+
const band = Math.max(1, w * size);
|
|
9745
|
+
gradient = ctx.createLinearGradient(x + w, 0, x + w - band, 0);
|
|
9746
|
+
addStops(gradient);
|
|
9747
|
+
ctx.fillStyle = gradient;
|
|
9748
|
+
ctx.fillRect(x + w - band, y, band, h);
|
|
9749
|
+
if (amount <= 1e-3) ctx.fillRect(x + w - Math.min(2, band), y, Math.min(2, band), h);
|
|
9750
|
+
}
|
|
9751
|
+
ctx.restore();
|
|
9752
|
+
};
|
|
9753
|
+
paintBand("top", cfg.topSize, cfg.topAmount, cfg.topHardness);
|
|
9754
|
+
paintBand("right", cfg.rightSize, cfg.rightAmount, cfg.rightHardness);
|
|
9755
|
+
paintBand("bottom", cfg.bottomSize, cfg.bottomAmount, cfg.bottomHardness);
|
|
9756
|
+
paintBand("left", cfg.leftSize, cfg.leftAmount, cfg.leftHardness);
|
|
9757
|
+
};
|
|
9758
|
+
group.set({ objectCaching: true, noScaleCache: false });
|
|
9759
|
+
fadeGroup.__edgeFadeKey = fadeGroup.__edgeFadeRenderConfig.key;
|
|
9760
|
+
fadeGroup.__edgeFadeInputKey = inputKey;
|
|
9761
|
+
} else {
|
|
9762
|
+
if (fadeGroup.__edgeFadeOriginalDrawObject) {
|
|
9763
|
+
group.drawObject = fadeGroup.__edgeFadeOriginalDrawObject;
|
|
9764
|
+
}
|
|
9765
|
+
delete fadeGroup.__edgeFadeRenderConfig;
|
|
9766
|
+
delete fadeGroup.__edgeFadeKey;
|
|
9767
|
+
delete fadeGroup.__edgeFadeInputKey;
|
|
9768
|
+
if ((_b = group.clipPath) == null ? void 0 : _b.__edgeFadeMask) {
|
|
9769
|
+
group.clipPath = void 0;
|
|
9770
|
+
updateCoverLayout(group);
|
|
9771
|
+
}
|
|
9772
|
+
}
|
|
9773
|
+
if (group.clipPath) {
|
|
9774
|
+
group.clipPath.dirty = true;
|
|
9775
|
+
group.clipPath.setCoords();
|
|
9776
|
+
}
|
|
9777
|
+
fadeGroup.dirty = true;
|
|
9778
|
+
const children = group.getObjects();
|
|
9779
|
+
children.forEach((child) => {
|
|
9780
|
+
child.dirty = true;
|
|
9781
|
+
});
|
|
9782
|
+
(_c = group.canvas) == null ? void 0 : _c.requestRenderAll();
|
|
9783
|
+
};
|
|
9520
9784
|
const loadImageAsync = async (element, placeholder, fc) => {
|
|
9521
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m;
|
|
9785
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p;
|
|
9522
9786
|
const imageUrl = element.src || element.imageUrl;
|
|
9523
9787
|
if (!imageUrl) return;
|
|
9524
9788
|
const elementId = element.id;
|
|
@@ -9531,7 +9795,9 @@ const PageCanvas = forwardRef(
|
|
|
9531
9795
|
const existingImg = ct == null ? void 0 : ct._img;
|
|
9532
9796
|
const existingSrc = placeholder.__imageSrc;
|
|
9533
9797
|
const existingSvgColorMap = placeholder.__svgColorMap || "";
|
|
9534
|
-
|
|
9798
|
+
const existingFadeKey = existingImg && existingImg.__edgeFadeKey || placeholder.__edgeFadeKey || "";
|
|
9799
|
+
const nextFadeKey = edgeFadeKey(element);
|
|
9800
|
+
if (existingImg && existingSrc === imageUrl && existingSvgColorMap === nextSvgColorMap && existingFadeKey === nextFadeKey) {
|
|
9535
9801
|
return placeholder;
|
|
9536
9802
|
}
|
|
9537
9803
|
}
|
|
@@ -9548,6 +9814,22 @@ const PageCanvas = forwardRef(
|
|
|
9548
9814
|
if (!fabricRef.current || !isLatestRequest()) return;
|
|
9549
9815
|
await normalizeSvgImageDimensions(img, imageUrl, element.sourceFormat);
|
|
9550
9816
|
if (!isLatestRequest()) return;
|
|
9817
|
+
const imageFitForFade = element.imageFit || ((_a = element.style) == null ? void 0 : _a.imageFit) || "cover";
|
|
9818
|
+
const clipShapeForFade = element.clipShape ?? ((_b = element.style) == null ? void 0 : _b.imageFrameShape) ?? (isPreviewMode ? "rectangle" : "none");
|
|
9819
|
+
const willUseCropGroupForFade = imageFitForFade !== "fill" || clipShapeForFade && clipShapeForFade !== "none";
|
|
9820
|
+
try {
|
|
9821
|
+
if (hasEdgeFade(element) && !willUseCropGroupForFade) {
|
|
9822
|
+
const srcEl = (_c = img.getElement) == null ? void 0 : _c.call(img);
|
|
9823
|
+
if (srcEl) {
|
|
9824
|
+
const baked = bakeEdgeFade(srcEl, element);
|
|
9825
|
+
img.setElement(baked);
|
|
9826
|
+
img.__edgeFadeKey = edgeFadeKey(element);
|
|
9827
|
+
img.dirty = true;
|
|
9828
|
+
}
|
|
9829
|
+
}
|
|
9830
|
+
} catch (e) {
|
|
9831
|
+
console.warn("[edgeFade] bake failed:", e);
|
|
9832
|
+
}
|
|
9551
9833
|
const isHidden = !element.visible;
|
|
9552
9834
|
img.set({
|
|
9553
9835
|
originX: "left",
|
|
@@ -9580,8 +9862,8 @@ const PageCanvas = forwardRef(
|
|
|
9580
9862
|
});
|
|
9581
9863
|
img.setCoords();
|
|
9582
9864
|
} else {
|
|
9583
|
-
const imageFit = element.imageFit || ((
|
|
9584
|
-
const clipShape = element.clipShape ?? ((
|
|
9865
|
+
const imageFit = element.imageFit || ((_d = element.style) == null ? void 0 : _d.imageFit) || "cover";
|
|
9866
|
+
const clipShape = element.clipShape ?? ((_e = element.style) == null ? void 0 : _e.imageFrameShape) ?? (isPreviewMode ? "rectangle" : "none");
|
|
9585
9867
|
const needCropGroup2 = imageFit !== "fill" || clipShape && clipShape !== "none";
|
|
9586
9868
|
const imgNaturalWidth = img.width || 1;
|
|
9587
9869
|
const imgNaturalHeight = img.height || 1;
|
|
@@ -9608,7 +9890,7 @@ const PageCanvas = forwardRef(
|
|
|
9608
9890
|
if (imageFit === "fill" && !needCropGroup2) {
|
|
9609
9891
|
const finalScaleX = baseScaleX * (element.scaleX ?? 1);
|
|
9610
9892
|
const finalScaleY = baseScaleY * (element.scaleY ?? 1);
|
|
9611
|
-
const pageTreeForCreate = ((pageChildren == null ? void 0 : pageChildren.length) ? pageChildren : (
|
|
9893
|
+
const pageTreeForCreate = ((pageChildren == null ? void 0 : pageChildren.length) ? pageChildren : (_f = useEditorStore.getState().canvas.pages.find((p) => p.id === pageId)) == null ? void 0 : _f.children) ?? [];
|
|
9612
9894
|
const createPos = pageTreeForCreate.length > 0 ? (() => {
|
|
9613
9895
|
const node = findNodeById(pageTreeForCreate, element.id);
|
|
9614
9896
|
return node ? getAbsoluteBounds(node, pageTreeForCreate) : { left: element.left ?? 0, top: element.top ?? 0 };
|
|
@@ -9653,12 +9935,12 @@ const PageCanvas = forwardRef(
|
|
|
9653
9935
|
}
|
|
9654
9936
|
img.__imageSrc = imageUrl;
|
|
9655
9937
|
img.__svgColorMap = element.svgColorMap ? JSON.stringify(element.svgColorMap) : "";
|
|
9656
|
-
const imageFitFinal = element.imageFit || ((
|
|
9657
|
-
const clipShapeFinal = element.clipShape ?? ((
|
|
9938
|
+
const imageFitFinal = element.imageFit || ((_g = element.style) == null ? void 0 : _g.imageFit) || "cover";
|
|
9939
|
+
const clipShapeFinal = element.clipShape ?? ((_h = element.style) == null ? void 0 : _h.imageFrameShape) ?? (isPreviewMode ? "rectangle" : "none");
|
|
9658
9940
|
const needCropGroup = imageFitFinal !== "fill" || clipShapeFinal && clipShapeFinal !== "none";
|
|
9659
9941
|
let finalObject = img;
|
|
9660
9942
|
if (needCropGroup) {
|
|
9661
|
-
const pageTreeForCropResolve = ((pageChildren == null ? void 0 : pageChildren.length) ? pageChildren : (
|
|
9943
|
+
const pageTreeForCropResolve = ((pageChildren == null ? void 0 : pageChildren.length) ? pageChildren : (_i = useEditorStore.getState().canvas.pages.find((p) => p.id === pageId)) == null ? void 0 : _i.children) ?? [];
|
|
9662
9944
|
const nodeForSize = pageTreeForCropResolve.length ? findNodeById(pageTreeForCropResolve, element.id) : null;
|
|
9663
9945
|
const w = nodeForSize && isElement(nodeForSize) ? nodeForSize.width : element.width;
|
|
9664
9946
|
const h = nodeForSize && isElement(nodeForSize) ? nodeForSize.height : element.height;
|
|
@@ -9690,16 +9972,16 @@ const PageCanvas = forwardRef(
|
|
|
9690
9972
|
let panY = element.cropPanY ?? 0.5;
|
|
9691
9973
|
let zoom2 = element.cropZoom ?? 1;
|
|
9692
9974
|
if (existingCropGroup) {
|
|
9693
|
-
const existingImg = (
|
|
9975
|
+
const existingImg = (_j = existingCropGroup.__cropData) == null ? void 0 : _j._img;
|
|
9694
9976
|
if (existingImg) {
|
|
9695
|
-
panX = ((
|
|
9696
|
-
panY = ((
|
|
9697
|
-
zoom2 = ((
|
|
9977
|
+
panX = ((_k = existingImg._ct) == null ? void 0 : _k.panX) ?? existingImg.__panX ?? panX;
|
|
9978
|
+
panY = ((_l = existingImg._ct) == null ? void 0 : _l.panY) ?? existingImg.__panY ?? panY;
|
|
9979
|
+
zoom2 = ((_m = existingImg._ct) == null ? void 0 : _m.zoom) ?? zoom2;
|
|
9698
9980
|
}
|
|
9699
9981
|
}
|
|
9700
9982
|
const isDynamicField = dynamicFieldIds.includes(element.id);
|
|
9701
9983
|
const canBeEvented = isEditorMode || isPreviewMode && isDynamicField;
|
|
9702
|
-
const pageTreeForCrop = ((pageChildren == null ? void 0 : pageChildren.length) ? pageChildren : (
|
|
9984
|
+
const pageTreeForCrop = ((pageChildren == null ? void 0 : pageChildren.length) ? pageChildren : (_n = useEditorStore.getState().canvas.pages.find((p) => p.id === pageId)) == null ? void 0 : _n.children) ?? [];
|
|
9703
9985
|
const createPosForCrop = pageTreeForCrop.length > 0 ? (() => {
|
|
9704
9986
|
const node = findNodeById(pageTreeForCrop, element.id);
|
|
9705
9987
|
return node ? getAbsoluteBounds(node, pageTreeForCrop) : { left: element.left ?? 0, top: element.top ?? 0 };
|
|
@@ -9750,17 +10032,18 @@ const PageCanvas = forwardRef(
|
|
|
9750
10032
|
} else {
|
|
9751
10033
|
installCanvaMaskControls(cropGroup);
|
|
9752
10034
|
}
|
|
9753
|
-
const cropImg = (
|
|
10035
|
+
const cropImg = (_o = cropGroup.__cropData) == null ? void 0 : _o._img;
|
|
9754
10036
|
if (cropImg) {
|
|
9755
10037
|
cropImg._ct = { panX, panY, zoom: zoom2 };
|
|
9756
10038
|
updateCoverLayout(cropGroup);
|
|
9757
10039
|
}
|
|
10040
|
+
applyEdgeFadeFrameClipPath(cropGroup, element, frameW, frameH, shape, rxRatio);
|
|
9758
10041
|
setObjectData(cropGroup, element.id);
|
|
9759
10042
|
cropGroup.__imageElement = cropImg;
|
|
9760
10043
|
cropGroup.__imageSrc = imageUrl;
|
|
9761
10044
|
cropGroup.__svgColorMap = nextSvgColorMap;
|
|
9762
10045
|
if (cropImg && element.imageNaturalWidth == null) {
|
|
9763
|
-
const el = ((
|
|
10046
|
+
const el = ((_p = cropImg.getElement) == null ? void 0 : _p.call(cropImg)) ?? cropImg._element;
|
|
9764
10047
|
const orig = typeof cropImg.getOriginalSize === "function" ? cropImg.getOriginalSize() : null;
|
|
9765
10048
|
const nw = (orig == null ? void 0 : orig.width) ?? (el == null ? void 0 : el.naturalWidth) ?? cropImg.width;
|
|
9766
10049
|
const nh = (orig == null ? void 0 : orig.height) ?? (el == null ? void 0 : el.naturalHeight) ?? cropImg.height;
|
|
@@ -13921,12 +14204,69 @@ class PixldocsRenderer {
|
|
|
13921
14204
|
{ width: canvasWidth, height: canvasHeight },
|
|
13922
14205
|
{ cssOnly: false, backstoreOnly: false }
|
|
13923
14206
|
);
|
|
14207
|
+
const fadeBakeRecords = [];
|
|
14208
|
+
try {
|
|
14209
|
+
const objs = fabricInstance.getObjects().slice();
|
|
14210
|
+
for (const obj of objs) {
|
|
14211
|
+
const isFadedCropGroup = obj instanceof fabric.Group && (Boolean(obj.__edgeFadeRenderConfig) || Boolean(obj.__edgeFadeKey) || Boolean(obj.__edgeFadeInputKey));
|
|
14212
|
+
if (!isFadedCropGroup) continue;
|
|
14213
|
+
try {
|
|
14214
|
+
const baked = obj.toCanvasElement({
|
|
14215
|
+
multiplier: 2,
|
|
14216
|
+
enableRetinaScaling: false
|
|
14217
|
+
});
|
|
14218
|
+
const rect = obj.getBoundingRect();
|
|
14219
|
+
const replacement = new fabric.FabricImage(baked, {
|
|
14220
|
+
left: rect.left,
|
|
14221
|
+
top: rect.top,
|
|
14222
|
+
originX: "left",
|
|
14223
|
+
originY: "top",
|
|
14224
|
+
scaleX: rect.width / baked.width,
|
|
14225
|
+
scaleY: rect.height / baked.height,
|
|
14226
|
+
selectable: false,
|
|
14227
|
+
evented: false,
|
|
14228
|
+
objectCaching: false
|
|
14229
|
+
});
|
|
14230
|
+
const insertIndex = fabricInstance._objects.indexOf(obj);
|
|
14231
|
+
const prevExclude = obj.excludeFromExport;
|
|
14232
|
+
obj.excludeFromExport = true;
|
|
14233
|
+
if (insertIndex >= 0) {
|
|
14234
|
+
fabricInstance.insertAt(insertIndex + 1, replacement);
|
|
14235
|
+
} else {
|
|
14236
|
+
fabricInstance.add(replacement);
|
|
14237
|
+
}
|
|
14238
|
+
fadeBakeRecords.push({
|
|
14239
|
+
original: obj,
|
|
14240
|
+
replacement,
|
|
14241
|
+
prevExclude,
|
|
14242
|
+
insertIndex
|
|
14243
|
+
});
|
|
14244
|
+
} catch (bakeErr) {
|
|
14245
|
+
console.warn("[canvas-renderer][edgeFade] bake-for-svg failed:", bakeErr);
|
|
14246
|
+
}
|
|
14247
|
+
}
|
|
14248
|
+
if (fadeBakeRecords.length) {
|
|
14249
|
+
fabricInstance.renderAll();
|
|
14250
|
+
console.log(
|
|
14251
|
+
`[canvas-renderer][edgeFade] baked ${fadeBakeRecords.length} faded object(s) for SVG capture`
|
|
14252
|
+
);
|
|
14253
|
+
}
|
|
14254
|
+
} catch (e) {
|
|
14255
|
+
console.warn("[canvas-renderer][edgeFade] bake pass failed:", e);
|
|
14256
|
+
}
|
|
13924
14257
|
const rawSvgString = fabricInstance.toSVG();
|
|
13925
14258
|
const svgString = this.normalizeSvgDimensions(
|
|
13926
14259
|
rawSvgString,
|
|
13927
14260
|
canvasWidth,
|
|
13928
14261
|
canvasHeight
|
|
13929
14262
|
);
|
|
14263
|
+
for (const rec of fadeBakeRecords) {
|
|
14264
|
+
try {
|
|
14265
|
+
fabricInstance.remove(rec.replacement);
|
|
14266
|
+
rec.original.excludeFromExport = rec.prevExclude;
|
|
14267
|
+
} catch {
|
|
14268
|
+
}
|
|
14269
|
+
}
|
|
13930
14270
|
fabricInstance.enableRetinaScaling = prevRetina;
|
|
13931
14271
|
fabricInstance.setDimensions(
|
|
13932
14272
|
{ width: prevWidth, height: prevHeight },
|