goatdee-canvas 0.0.13 → 0.0.15
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 +57 -30
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +58 -31
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -3178,6 +3178,8 @@ async function waitForAllImages(container, timeout = 10000) {
|
|
|
3178
3178
|
});
|
|
3179
3179
|
await Promise.all(promises);
|
|
3180
3180
|
}
|
|
3181
|
+
/** 渲染图片的最大边长(物理像素)。超过此值会导致 GPU 纹理上传失败或内存溢出。 */
|
|
3182
|
+
const MAX_IMAGE_DIMENSION = 4096;
|
|
3181
3183
|
|
|
3182
3184
|
/**
|
|
3183
3185
|
* HTML to EditorJSON Converter - Parsing Functions
|
|
@@ -11514,6 +11516,9 @@ async function renderBackgroundToBase64(element, width, height) {
|
|
|
11514
11516
|
}
|
|
11515
11517
|
try {
|
|
11516
11518
|
const dpr = win.devicePixelRatio || 1;
|
|
11519
|
+
// 限制输出物理像素长边不超过 MAX_IMAGE_DIMENSION
|
|
11520
|
+
const maxDim = Math.max(width, height);
|
|
11521
|
+
const clampedDpr = maxDim > 0 ? Math.min(dpr, MAX_IMAGE_DIMENSION / maxDim) : dpr;
|
|
11517
11522
|
const tempContainer = doc.createElement("div");
|
|
11518
11523
|
tempContainer.style.position = "fixed";
|
|
11519
11524
|
tempContainer.style.left = "-9999px";
|
|
@@ -11532,7 +11537,7 @@ async function renderBackgroundToBase64(element, width, height) {
|
|
|
11532
11537
|
doc.body.appendChild(tempContainer);
|
|
11533
11538
|
const canvas = await html2canvasExports(tempContainer, {
|
|
11534
11539
|
backgroundColor: null,
|
|
11535
|
-
scale:
|
|
11540
|
+
scale: clampedDpr,
|
|
11536
11541
|
logging: false,
|
|
11537
11542
|
useCORS: true,
|
|
11538
11543
|
allowTaint: true,
|
|
@@ -11542,8 +11547,8 @@ async function renderBackgroundToBase64(element, width, height) {
|
|
|
11542
11547
|
doc.body.removeChild(tempContainer);
|
|
11543
11548
|
return {
|
|
11544
11549
|
base64: canvas.toDataURL("image/png"),
|
|
11545
|
-
actualWidth: width *
|
|
11546
|
-
actualHeight: height *
|
|
11550
|
+
actualWidth: width * clampedDpr,
|
|
11551
|
+
actualHeight: height * clampedDpr,
|
|
11547
11552
|
logicalWidth: width,
|
|
11548
11553
|
logicalHeight: height,
|
|
11549
11554
|
};
|
|
@@ -11584,6 +11589,9 @@ async function renderElementWithHtml2Canvas(element, styles, rect) {
|
|
|
11584
11589
|
tempContainer.style.zIndex = "-9999";
|
|
11585
11590
|
const totalWidth = width + padding * 2;
|
|
11586
11591
|
const totalHeight = height + padding * 2;
|
|
11592
|
+
// 限制输出物理像素长边不超过 MAX_IMAGE_DIMENSION
|
|
11593
|
+
const maxDim = Math.max(totalWidth, totalHeight);
|
|
11594
|
+
const clampedDpr = maxDim > 0 ? Math.min(dpr, MAX_IMAGE_DIMENSION / maxDim) : dpr;
|
|
11587
11595
|
tempContainer.style.width = `${totalWidth}px`;
|
|
11588
11596
|
tempContainer.style.height = `${totalHeight}px`;
|
|
11589
11597
|
tempContainer.style.overflow = "visible";
|
|
@@ -11597,7 +11605,7 @@ async function renderElementWithHtml2Canvas(element, styles, rect) {
|
|
|
11597
11605
|
doc.body.appendChild(tempContainer);
|
|
11598
11606
|
const canvas = await html2canvasExports(tempContainer, {
|
|
11599
11607
|
backgroundColor: null,
|
|
11600
|
-
scale:
|
|
11608
|
+
scale: clampedDpr,
|
|
11601
11609
|
logging: false,
|
|
11602
11610
|
useCORS: true,
|
|
11603
11611
|
allowTaint: true,
|
|
@@ -11608,8 +11616,8 @@ async function renderElementWithHtml2Canvas(element, styles, rect) {
|
|
|
11608
11616
|
return {
|
|
11609
11617
|
base64: canvas.toDataURL("image/png"),
|
|
11610
11618
|
padding: padding,
|
|
11611
|
-
actualWidth: totalWidth *
|
|
11612
|
-
actualHeight: totalHeight *
|
|
11619
|
+
actualWidth: totalWidth * clampedDpr,
|
|
11620
|
+
actualHeight: totalHeight * clampedDpr,
|
|
11613
11621
|
logicalWidth: totalWidth,
|
|
11614
11622
|
logicalHeight: totalHeight,
|
|
11615
11623
|
};
|
|
@@ -11697,6 +11705,11 @@ async function renderElementWithFilterToBase64(element, width, height, styles) {
|
|
|
11697
11705
|
const w = Math.ceil(width);
|
|
11698
11706
|
const h = Math.ceil(height);
|
|
11699
11707
|
const dpr = win.devicePixelRatio || 1;
|
|
11708
|
+
// 限制输出物理像素长边不超过 MAX_IMAGE_DIMENSION(含 padding 后的总尺寸)
|
|
11709
|
+
const totalW = w + padding * 2;
|
|
11710
|
+
const totalH = h + padding * 2;
|
|
11711
|
+
const maxDim = Math.max(totalW, totalH);
|
|
11712
|
+
const clampedDpr = maxDim > 0 ? Math.min(dpr, MAX_IMAGE_DIMENSION / maxDim) : dpr;
|
|
11700
11713
|
try {
|
|
11701
11714
|
const tempContainer = doc.createElement('div');
|
|
11702
11715
|
tempContainer.style.cssText =
|
|
@@ -11710,7 +11723,7 @@ async function renderElementWithFilterToBase64(element, width, height, styles) {
|
|
|
11710
11723
|
doc.body.appendChild(tempContainer);
|
|
11711
11724
|
const noFilterCanvas = await html2canvasExports(tempContainer, {
|
|
11712
11725
|
backgroundColor: null,
|
|
11713
|
-
scale:
|
|
11726
|
+
scale: clampedDpr,
|
|
11714
11727
|
logging: false,
|
|
11715
11728
|
useCORS: true,
|
|
11716
11729
|
allowTaint: true,
|
|
@@ -11718,22 +11731,20 @@ async function renderElementWithFilterToBase64(element, width, height, styles) {
|
|
|
11718
11731
|
height: h,
|
|
11719
11732
|
});
|
|
11720
11733
|
doc.body.removeChild(tempContainer);
|
|
11721
|
-
const totalW = w + padding * 2;
|
|
11722
|
-
const totalH = h + padding * 2;
|
|
11723
11734
|
const finalCanvas = doc.createElement('canvas');
|
|
11724
|
-
finalCanvas.width = totalW *
|
|
11725
|
-
finalCanvas.height = totalH *
|
|
11735
|
+
finalCanvas.width = totalW * clampedDpr;
|
|
11736
|
+
finalCanvas.height = totalH * clampedDpr;
|
|
11726
11737
|
const ctx = finalCanvas.getContext('2d');
|
|
11727
11738
|
if (!ctx)
|
|
11728
11739
|
return null;
|
|
11729
|
-
ctx.scale(
|
|
11730
|
-
ctx.filter = scaleFilterPxByDpr(filterStr,
|
|
11740
|
+
ctx.scale(clampedDpr, clampedDpr);
|
|
11741
|
+
ctx.filter = scaleFilterPxByDpr(filterStr, clampedDpr);
|
|
11731
11742
|
ctx.drawImage(noFilterCanvas, padding, padding, w, h);
|
|
11732
11743
|
return {
|
|
11733
11744
|
base64: finalCanvas.toDataURL('image/png'),
|
|
11734
11745
|
padding,
|
|
11735
|
-
actualWidth: totalW *
|
|
11736
|
-
actualHeight: totalH *
|
|
11746
|
+
actualWidth: totalW * clampedDpr,
|
|
11747
|
+
actualHeight: totalH * clampedDpr,
|
|
11737
11748
|
logicalWidth: totalW,
|
|
11738
11749
|
logicalHeight: totalH,
|
|
11739
11750
|
};
|
|
@@ -12626,9 +12637,12 @@ async function renderPseudoElementWithHtml2Canvas(element, pseudoElement, rect,
|
|
|
12626
12637
|
}
|
|
12627
12638
|
}
|
|
12628
12639
|
const dpr = win.devicePixelRatio || 1;
|
|
12640
|
+
// 限制输出物理像素长边不超过 MAX_IMAGE_DIMENSION
|
|
12641
|
+
const maxDim = Math.max(totalWidth, totalHeight);
|
|
12642
|
+
const clampedDpr = maxDim > 0 ? Math.min(dpr, MAX_IMAGE_DIMENSION / maxDim) : dpr;
|
|
12629
12643
|
const canvas = await html2canvasExports(tempContainer, {
|
|
12630
12644
|
backgroundColor: null,
|
|
12631
|
-
scale:
|
|
12645
|
+
scale: clampedDpr,
|
|
12632
12646
|
logging: false,
|
|
12633
12647
|
useCORS: true,
|
|
12634
12648
|
allowTaint: true,
|
|
@@ -12640,8 +12654,8 @@ async function renderPseudoElementWithHtml2Canvas(element, pseudoElement, rect,
|
|
|
12640
12654
|
return {
|
|
12641
12655
|
base64: canvas.toDataURL("image/png"),
|
|
12642
12656
|
padding: padding,
|
|
12643
|
-
actualWidth: totalWidth *
|
|
12644
|
-
actualHeight: totalHeight *
|
|
12657
|
+
actualWidth: totalWidth * clampedDpr,
|
|
12658
|
+
actualHeight: totalHeight * clampedDpr,
|
|
12645
12659
|
logicalWidth: totalWidth,
|
|
12646
12660
|
logicalHeight: totalHeight,
|
|
12647
12661
|
};
|
|
@@ -12699,6 +12713,9 @@ async function renderMarkerWithHtml2Canvas(element, rect, markerStyles, elementS
|
|
|
12699
12713
|
const totalWidth = Math.ceil(rect.width);
|
|
12700
12714
|
const totalHeight = Math.ceil(rect.height);
|
|
12701
12715
|
const dpr = win.devicePixelRatio || 1;
|
|
12716
|
+
// 限制输出物理像素长边不超过 MAX_IMAGE_DIMENSION
|
|
12717
|
+
const maxDim = Math.max(totalWidth, totalHeight);
|
|
12718
|
+
const clampedDpr = maxDim > 0 ? Math.min(dpr, MAX_IMAGE_DIMENSION / maxDim) : dpr;
|
|
12702
12719
|
const tempContainer = doc.createElement('div');
|
|
12703
12720
|
tempContainer.style.position = 'fixed';
|
|
12704
12721
|
tempContainer.style.left = '-9999px';
|
|
@@ -12730,7 +12747,7 @@ async function renderMarkerWithHtml2Canvas(element, rect, markerStyles, elementS
|
|
|
12730
12747
|
}
|
|
12731
12748
|
const canvas = await html2canvasExports(tempContainer, {
|
|
12732
12749
|
backgroundColor: null,
|
|
12733
|
-
scale:
|
|
12750
|
+
scale: clampedDpr,
|
|
12734
12751
|
logging: false,
|
|
12735
12752
|
useCORS: true,
|
|
12736
12753
|
allowTaint: true,
|
|
@@ -12741,8 +12758,8 @@ async function renderMarkerWithHtml2Canvas(element, rect, markerStyles, elementS
|
|
|
12741
12758
|
return {
|
|
12742
12759
|
base64: canvas.toDataURL('image/png'),
|
|
12743
12760
|
padding: 0,
|
|
12744
|
-
actualWidth: totalWidth *
|
|
12745
|
-
actualHeight: totalHeight *
|
|
12761
|
+
actualWidth: totalWidth * clampedDpr,
|
|
12762
|
+
actualHeight: totalHeight * clampedDpr,
|
|
12746
12763
|
logicalWidth: totalWidth,
|
|
12747
12764
|
logicalHeight: totalHeight,
|
|
12748
12765
|
};
|
|
@@ -12854,8 +12871,13 @@ function convertCanvasElement(element, context) {
|
|
|
12854
12871
|
const displayWidth = rect.width;
|
|
12855
12872
|
const displayHeight = rect.height;
|
|
12856
12873
|
// 导出 2 倍图:绘制到离屏 canvas (2*displaySize),再 toDataURL
|
|
12857
|
-
|
|
12858
|
-
const
|
|
12874
|
+
// 同时确保物理像素长边不超过 MAX_IMAGE_DIMENSION
|
|
12875
|
+
const rawExportWidth = Math.round(displayWidth * CANVAS_EXPORT_PIXEL_RATIO);
|
|
12876
|
+
const rawExportHeight = Math.round(displayHeight * CANVAS_EXPORT_PIXEL_RATIO);
|
|
12877
|
+
const maxDim = Math.max(rawExportWidth, rawExportHeight);
|
|
12878
|
+
const clampRatio = maxDim > MAX_IMAGE_DIMENSION ? MAX_IMAGE_DIMENSION / maxDim : 1;
|
|
12879
|
+
const exportWidth = Math.round(rawExportWidth * clampRatio);
|
|
12880
|
+
const exportHeight = Math.round(rawExportHeight * clampRatio);
|
|
12859
12881
|
let src;
|
|
12860
12882
|
try {
|
|
12861
12883
|
const doc = element.ownerDocument;
|
|
@@ -12878,8 +12900,9 @@ function convertCanvasElement(element, context) {
|
|
|
12878
12900
|
? resolveVariable(styles.boxShadow, cssVariables)
|
|
12879
12901
|
: null;
|
|
12880
12902
|
const shadow = parseShadow(shadowStr);
|
|
12881
|
-
//
|
|
12882
|
-
const
|
|
12903
|
+
// 图层尺寸用导出宽高,scaleX/scaleY 保证显示尺寸等于 displayWidth x displayHeight,实现高清
|
|
12904
|
+
const scaleX = displayWidth / exportWidth;
|
|
12905
|
+
const scaleY = displayHeight / exportHeight;
|
|
12883
12906
|
const layer = {
|
|
12884
12907
|
type: "image",
|
|
12885
12908
|
id: uuid(),
|
|
@@ -12887,8 +12910,8 @@ function convertCanvasElement(element, context) {
|
|
|
12887
12910
|
top,
|
|
12888
12911
|
width: exportWidth,
|
|
12889
12912
|
height: exportHeight,
|
|
12890
|
-
scaleX
|
|
12891
|
-
scaleY
|
|
12913
|
+
scaleX,
|
|
12914
|
+
scaleY,
|
|
12892
12915
|
src,
|
|
12893
12916
|
};
|
|
12894
12917
|
if (borderRadius > 0) {
|
|
@@ -13018,8 +13041,12 @@ async function convertSVGToPNG(svgDataUrl, width, height, win, scale = 5) {
|
|
|
13018
13041
|
img.onload = () => {
|
|
13019
13042
|
try {
|
|
13020
13043
|
const canvas = document.createElement("canvas");
|
|
13021
|
-
|
|
13022
|
-
const
|
|
13044
|
+
// 动态限制 scale:确保物理像素长边不超过 MAX_IMAGE_DIMENSION
|
|
13045
|
+
const maxDim = Math.max(width, height);
|
|
13046
|
+
const maxScale = maxDim > 0 ? MAX_IMAGE_DIMENSION / (maxDim * dpr) : scale;
|
|
13047
|
+
const clampedScale = Math.min(scale, maxScale);
|
|
13048
|
+
const actualWidth = Math.round(width * clampedScale * dpr);
|
|
13049
|
+
const actualHeight = Math.round(height * clampedScale * dpr);
|
|
13023
13050
|
canvas.width = actualWidth;
|
|
13024
13051
|
canvas.height = actualHeight;
|
|
13025
13052
|
const ctx = canvas.getContext("2d");
|
|
@@ -13027,7 +13054,7 @@ async function convertSVGToPNG(svgDataUrl, width, height, win, scale = 5) {
|
|
|
13027
13054
|
resolve(null);
|
|
13028
13055
|
return;
|
|
13029
13056
|
}
|
|
13030
|
-
ctx.scale(
|
|
13057
|
+
ctx.scale(clampedScale * dpr, clampedScale * dpr);
|
|
13031
13058
|
ctx.drawImage(img, 0, 0, width, height);
|
|
13032
13059
|
resolve({
|
|
13033
13060
|
base64: canvas.toDataURL("image/png"),
|