feat(damage-flow): rotate zoomed detail view to natural orientation (90/-90/180 per zone)
This commit is contained in:
@@ -3,342 +3,399 @@
|
|||||||
"x": 278.11,
|
"x": 278.11,
|
||||||
"y": 88.77,
|
"y": 88.77,
|
||||||
"w": 262.74,
|
"w": 262.74,
|
||||||
"h": 45.43
|
"h": 45.43,
|
||||||
|
"rotation": 0
|
||||||
},
|
},
|
||||||
"52": {
|
"52": {
|
||||||
"x": 699.8,
|
"x": 699.8,
|
||||||
"y": 296.93,
|
"y": 296.93,
|
||||||
"w": 41.31,
|
"w": 41.31,
|
||||||
"h": 70.61
|
"h": 70.61,
|
||||||
|
"rotation": -90
|
||||||
},
|
},
|
||||||
"51": {
|
"51": {
|
||||||
"x": 81.04,
|
"x": 81.04,
|
||||||
"y": 295.79,
|
"y": 295.79,
|
||||||
"w": 41.4,
|
"w": 41.4,
|
||||||
"h": 71.68
|
"h": 71.68,
|
||||||
|
"rotation": 90
|
||||||
},
|
},
|
||||||
"1": {
|
"1": {
|
||||||
"x": 488.5,
|
"x": 488.5,
|
||||||
"y": 132.88,
|
"y": 132.88,
|
||||||
"w": 50.92,
|
"w": 50.92,
|
||||||
"h": 20.77
|
"h": 20.77,
|
||||||
|
"rotation": 0
|
||||||
},
|
},
|
||||||
"2": {
|
"2": {
|
||||||
"x": 279.61,
|
"x": 279.61,
|
||||||
"y": 132.82,
|
"y": 132.82,
|
||||||
"w": 50.93,
|
"w": 50.93,
|
||||||
"h": 21.24
|
"h": 21.24,
|
||||||
|
"rotation": 0
|
||||||
},
|
},
|
||||||
"3": {
|
"3": {
|
||||||
"x": 350.0,
|
"x": 350.0,
|
||||||
"y": 130.0,
|
"y": 130.0,
|
||||||
"w": 120.0,
|
"w": 120.0,
|
||||||
"h": 22.0
|
"h": 22.0,
|
||||||
|
"rotation": 0
|
||||||
},
|
},
|
||||||
"30": {
|
"30": {
|
||||||
"x": 509.22,
|
"x": 509.22,
|
||||||
"y": 734.61,
|
"y": 734.61,
|
||||||
"w": 130.89,
|
"w": 130.89,
|
||||||
"h": 41.63
|
"h": 41.63,
|
||||||
|
"rotation": 0
|
||||||
},
|
},
|
||||||
"31": {
|
"31": {
|
||||||
"x": 182.12,
|
"x": 182.12,
|
||||||
"y": 734.5,
|
"y": 734.5,
|
||||||
"w": 129.26,
|
"w": 129.26,
|
||||||
"h": 41.56
|
"h": 41.56,
|
||||||
|
"rotation": 0
|
||||||
},
|
},
|
||||||
"28": {
|
"28": {
|
||||||
"x": 170.41,
|
"x": 170.41,
|
||||||
"y": 496.19,
|
"y": 496.19,
|
||||||
"w": 6.35,
|
"w": 6.35,
|
||||||
"h": 8.34
|
"h": 8.34,
|
||||||
|
"rotation": 90
|
||||||
},
|
},
|
||||||
"29": {
|
"29": {
|
||||||
"x": 645.28,
|
"x": 645.28,
|
||||||
"y": 496.19,
|
"y": 496.19,
|
||||||
"w": 6.53,
|
"w": 6.53,
|
||||||
"h": 8.58
|
"h": 8.58,
|
||||||
|
"rotation": -90
|
||||||
},
|
},
|
||||||
"11": {
|
"11": {
|
||||||
"x": 278.5,
|
"x": 278.5,
|
||||||
"y": 477.86,
|
"y": 477.86,
|
||||||
"w": 465.53,
|
"w": 465.53,
|
||||||
"h": 152.09
|
"h": 152.09,
|
||||||
|
"rotation": 0
|
||||||
},
|
},
|
||||||
"10": {
|
"10": {
|
||||||
"x": 78.52,
|
"x": 78.52,
|
||||||
"y": 478.98,
|
"y": 478.98,
|
||||||
"w": 91.6,
|
"w": 91.6,
|
||||||
"h": 150.99
|
"h": 150.99,
|
||||||
|
"rotation": 90
|
||||||
},
|
},
|
||||||
"4": {
|
"4": {
|
||||||
"x": 300.72,
|
"x": 300.72,
|
||||||
"y": 311.52,
|
"y": 311.52,
|
||||||
"w": 219.3,
|
"w": 219.3,
|
||||||
"h": 146.72
|
"h": 146.72,
|
||||||
|
"rotation": 0
|
||||||
},
|
},
|
||||||
"5": {
|
"5": {
|
||||||
"x": 305.05,
|
"x": 305.05,
|
||||||
"y": 442.76,
|
"y": 442.76,
|
||||||
"w": 210.67,
|
"w": 210.67,
|
||||||
"h": 127.13
|
"h": 127.13,
|
||||||
|
"rotation": 0
|
||||||
},
|
},
|
||||||
"22": {
|
"22": {
|
||||||
"x": 281.48,
|
"x": 281.48,
|
||||||
"y": 1063.81,
|
"y": 1063.81,
|
||||||
"w": 260.16,
|
"w": 260.16,
|
||||||
"h": 59.34
|
"h": 59.34,
|
||||||
|
"rotation": 0
|
||||||
},
|
},
|
||||||
"49": {
|
"49": {
|
||||||
"x": 87.78,
|
"x": 87.78,
|
||||||
"y": 826.98,
|
"y": 826.98,
|
||||||
"w": 50.54,
|
"w": 50.54,
|
||||||
"h": 99.5
|
"h": 99.5,
|
||||||
|
"rotation": 90
|
||||||
},
|
},
|
||||||
"50": {
|
"50": {
|
||||||
"x": 684.83,
|
"x": 684.83,
|
||||||
"y": 827.25,
|
"y": 827.25,
|
||||||
"w": 49.78,
|
"w": 49.78,
|
||||||
"h": 99.71
|
"h": 99.71,
|
||||||
|
"rotation": -90
|
||||||
},
|
},
|
||||||
"33": {
|
"33": {
|
||||||
"x": 284.24,
|
"x": 284.24,
|
||||||
"y": 1038.88,
|
"y": 1038.88,
|
||||||
"w": 29.65,
|
"w": 29.65,
|
||||||
"h": 22.7
|
"h": 22.7,
|
||||||
|
"rotation": 0
|
||||||
},
|
},
|
||||||
"32": {
|
"32": {
|
||||||
"x": 507.74,
|
"x": 507.74,
|
||||||
"y": 1038.78,
|
"y": 1038.78,
|
||||||
"w": 29.66,
|
"w": 29.66,
|
||||||
"h": 22.69
|
"h": 22.69,
|
||||||
|
"rotation": 0
|
||||||
},
|
},
|
||||||
"21": {
|
"21": {
|
||||||
"x": 303.29,
|
"x": 303.29,
|
||||||
"y": 841.39,
|
"y": 841.39,
|
||||||
"w": 215.88,
|
"w": 215.88,
|
||||||
"h": 236.13
|
"h": 236.13,
|
||||||
|
"rotation": 0
|
||||||
},
|
},
|
||||||
"38": {
|
"38": {
|
||||||
"x": 510.42,
|
"x": 510.42,
|
||||||
"y": 195.83,
|
"y": 195.83,
|
||||||
"w": 26.67,
|
"w": 26.67,
|
||||||
"h": 821.6
|
"h": 821.6,
|
||||||
|
"rotation": -90
|
||||||
},
|
},
|
||||||
"39": {
|
"39": {
|
||||||
"x": 281.9,
|
"x": 281.9,
|
||||||
"y": 195.94,
|
"y": 195.94,
|
||||||
"w": 26.67,
|
"w": 26.67,
|
||||||
"h": 14.24
|
"h": 14.24,
|
||||||
|
"rotation": 0
|
||||||
},
|
},
|
||||||
"23": {
|
"23": {
|
||||||
"x": 316.23,
|
"x": 316.23,
|
||||||
"y": 766.98,
|
"y": 766.98,
|
||||||
"w": 187.94,
|
"w": 187.94,
|
||||||
"h": 89.25
|
"h": 89.25,
|
||||||
|
"rotation": 0
|
||||||
},
|
},
|
||||||
"6": {
|
"6": {
|
||||||
"x": 78.13,
|
"x": 78.13,
|
||||||
"y": 314.95,
|
"y": 314.95,
|
||||||
"w": 91.98,
|
"w": 91.98,
|
||||||
"h": 168.83
|
"h": 168.83,
|
||||||
|
"rotation": 90
|
||||||
},
|
},
|
||||||
"7": {
|
"7": {
|
||||||
"x": 651.97,
|
"x": 651.97,
|
||||||
"y": 314.84,
|
"y": 314.84,
|
||||||
"w": 92.1,
|
"w": 92.1,
|
||||||
"h": 168.93
|
"h": 168.93,
|
||||||
|
"rotation": -90
|
||||||
},
|
},
|
||||||
"8": {
|
"8": {
|
||||||
"x": 81.05,
|
"x": 81.05,
|
||||||
"y": 734.43,
|
"y": 734.43,
|
||||||
"w": 104.0,
|
"w": 104.0,
|
||||||
"h": 176.79
|
"h": 176.79,
|
||||||
|
"rotation": 90
|
||||||
},
|
},
|
||||||
"9": {
|
"9": {
|
||||||
"x": 590.75,
|
"x": 590.75,
|
||||||
"y": 666.97,
|
"y": 666.97,
|
||||||
"w": 150.45,
|
"w": 150.45,
|
||||||
"h": 244.25
|
"h": 244.25,
|
||||||
|
"rotation": -90
|
||||||
},
|
},
|
||||||
"12": {
|
"12": {
|
||||||
"x": 81.53,
|
"x": 81.53,
|
||||||
"y": 628.12,
|
"y": 628.12,
|
||||||
"w": 99.38,
|
"w": 99.38,
|
||||||
"h": 147.01
|
"h": 147.01,
|
||||||
|
"rotation": 90
|
||||||
},
|
},
|
||||||
"13": {
|
"13": {
|
||||||
"x": 641.53,
|
"x": 641.53,
|
||||||
"y": 627.6,
|
"y": 627.6,
|
||||||
"w": 99.42,
|
"w": 99.42,
|
||||||
"h": 147.14
|
"h": 147.14,
|
||||||
|
"rotation": -90
|
||||||
},
|
},
|
||||||
"16": {
|
"16": {
|
||||||
"x": 325.94,
|
"x": 325.94,
|
||||||
"y": 563.11,
|
"y": 563.11,
|
||||||
"w": 168.93,
|
"w": 168.93,
|
||||||
"h": 208.89
|
"h": 208.89,
|
||||||
|
"rotation": 90
|
||||||
},
|
},
|
||||||
"14": {
|
"14": {
|
||||||
"x": 72.11,
|
"x": 72.11,
|
||||||
"y": 471.33,
|
"y": 471.33,
|
||||||
"w": 5.0,
|
"w": 5.0,
|
||||||
"h": 161.47
|
"h": 161.47,
|
||||||
|
"rotation": 90
|
||||||
},
|
},
|
||||||
"47": {
|
"47": {
|
||||||
"x": 72.83,
|
"x": 72.83,
|
||||||
"y": 615.64,
|
"y": 615.64,
|
||||||
"w": 5.6,
|
"w": 5.6,
|
||||||
"h": 124.59
|
"h": 124.59,
|
||||||
|
"rotation": 90
|
||||||
},
|
},
|
||||||
"15": {
|
"15": {
|
||||||
"x": 744.0,
|
"x": 744.0,
|
||||||
"y": 461.0,
|
"y": 461.0,
|
||||||
"w": 6.0,
|
"w": 6.0,
|
||||||
"h": 171.5
|
"h": 171.5,
|
||||||
|
"rotation": -90
|
||||||
},
|
},
|
||||||
"48": {
|
"48": {
|
||||||
"x": 744.0,
|
"x": 744.0,
|
||||||
"y": 632.5,
|
"y": 632.5,
|
||||||
"w": 6.0,
|
"w": 6.0,
|
||||||
"h": 107.5
|
"h": 107.5,
|
||||||
|
"rotation": -90
|
||||||
},
|
},
|
||||||
"27": {
|
"27": {
|
||||||
"x": 596.56,
|
"x": 596.56,
|
||||||
"y": 643.76,
|
"y": 643.76,
|
||||||
"w": 50.37,
|
"w": 50.37,
|
||||||
"h": 84.35
|
"h": 84.35,
|
||||||
|
"rotation": -90
|
||||||
},
|
},
|
||||||
"26": {
|
"26": {
|
||||||
"x": 175.44,
|
"x": 175.44,
|
||||||
"y": 643.75,
|
"y": 643.75,
|
||||||
"w": 50.57,
|
"w": 50.57,
|
||||||
"h": 84.4
|
"h": 84.4,
|
||||||
|
"rotation": 90
|
||||||
},
|
},
|
||||||
"24": {
|
"24": {
|
||||||
"x": 171.07,
|
"x": 171.07,
|
||||||
"y": 526.12,
|
"y": 526.12,
|
||||||
"w": 53.81,
|
"w": 53.81,
|
||||||
"h": 105.33
|
"h": 105.33,
|
||||||
|
"rotation": 90
|
||||||
},
|
},
|
||||||
"25": {
|
"25": {
|
||||||
"x": 597.45,
|
"x": 597.45,
|
||||||
"y": 526.06,
|
"y": 526.06,
|
||||||
"w": 53.57,
|
"w": 53.57,
|
||||||
"h": 105.33
|
"h": 105.33,
|
||||||
|
"rotation": -90
|
||||||
},
|
},
|
||||||
"18": {
|
"18": {
|
||||||
"x": 42.7,
|
"x": 42.7,
|
||||||
"y": 369.77,
|
"y": 369.77,
|
||||||
"w": 89.47,
|
"w": 89.47,
|
||||||
"h": 88.82
|
"h": 88.82,
|
||||||
|
"rotation": 0
|
||||||
},
|
},
|
||||||
"43": {
|
"43": {
|
||||||
"x": 56.05,
|
"x": 56.05,
|
||||||
"y": 382.97,
|
"y": 382.97,
|
||||||
"w": 63.97,
|
"w": 63.97,
|
||||||
"h": 63.6
|
"h": 63.6,
|
||||||
|
"rotation": 0
|
||||||
},
|
},
|
||||||
"17": {
|
"17": {
|
||||||
"x": 688.66,
|
"x": 688.66,
|
||||||
"y": 369.75,
|
"y": 369.75,
|
||||||
"w": 89.51,
|
"w": 89.51,
|
||||||
"h": 88.83
|
"h": 88.83,
|
||||||
|
"rotation": 0
|
||||||
},
|
},
|
||||||
"42": {
|
"42": {
|
||||||
"x": 702.04,
|
"x": 702.04,
|
||||||
"y": 382.95,
|
"y": 382.95,
|
||||||
"w": 63.97,
|
"w": 63.97,
|
||||||
"h": 63.61
|
"h": 63.61,
|
||||||
|
"rotation": 0
|
||||||
},
|
},
|
||||||
"20": {
|
"20": {
|
||||||
"x": 42.55,
|
"x": 42.55,
|
||||||
"y": 751.33,
|
"y": 751.33,
|
||||||
"w": 90.63,
|
"w": 90.63,
|
||||||
"h": 88.87
|
"h": 88.87,
|
||||||
|
"rotation": 0
|
||||||
},
|
},
|
||||||
"40": {
|
"40": {
|
||||||
"x": 56.71,
|
"x": 56.71,
|
||||||
"y": 764.4,
|
"y": 764.4,
|
||||||
"w": 61.8,
|
"w": 61.8,
|
||||||
"h": 62.63
|
"h": 62.63,
|
||||||
|
"rotation": 0
|
||||||
},
|
},
|
||||||
"19": {
|
"19": {
|
||||||
"x": 688.96,
|
"x": 688.96,
|
||||||
"y": 751.25,
|
"y": 751.25,
|
||||||
"w": 89.2,
|
"w": 89.2,
|
||||||
"h": 88.92
|
"h": 88.92,
|
||||||
|
"rotation": 0
|
||||||
},
|
},
|
||||||
"41": {
|
"41": {
|
||||||
"x": 701.6,
|
"x": 701.6,
|
||||||
"y": 763.49,
|
"y": 763.49,
|
||||||
"w": 64.65,
|
"w": 64.65,
|
||||||
"h": 64.46
|
"h": 64.46,
|
||||||
|
"rotation": 0
|
||||||
},
|
},
|
||||||
"44": {
|
"44": {
|
||||||
"x": 42.66,
|
"x": 42.66,
|
||||||
"y": 0.0,
|
"y": 0.0,
|
||||||
"w": 426.67,
|
"w": 426.67,
|
||||||
"h": 512.0
|
"h": 512.0,
|
||||||
|
"rotation": 90
|
||||||
},
|
},
|
||||||
"45": {
|
"45": {
|
||||||
"x": 42.66,
|
"x": 42.66,
|
||||||
"y": 0.0,
|
"y": 0.0,
|
||||||
"w": 426.67,
|
"w": 426.67,
|
||||||
"h": 512.0
|
"h": 512.0,
|
||||||
|
"rotation": 90
|
||||||
},
|
},
|
||||||
"46": {
|
"46": {
|
||||||
"x": 42.66,
|
"x": 42.66,
|
||||||
"y": 0.0,
|
"y": 0.0,
|
||||||
"w": 426.67,
|
"w": 426.67,
|
||||||
"h": 512.0
|
"h": 512.0,
|
||||||
|
"rotation": 90
|
||||||
},
|
},
|
||||||
"34": {
|
"34": {
|
||||||
"x": 0.0,
|
"x": 0.0,
|
||||||
"y": 76.0,
|
"y": 76.0,
|
||||||
"w": 512.0,
|
"w": 512.0,
|
||||||
"h": 360.0
|
"h": 360.0,
|
||||||
|
"rotation": 0
|
||||||
},
|
},
|
||||||
"35": {
|
"35": {
|
||||||
"x": 0.0,
|
"x": 0.0,
|
||||||
"y": 76.0,
|
"y": 76.0,
|
||||||
"w": 512.0,
|
"w": 512.0,
|
||||||
"h": 360.0
|
"h": 360.0,
|
||||||
|
"rotation": 0
|
||||||
},
|
},
|
||||||
"36": {
|
"36": {
|
||||||
"x": 0.0,
|
"x": 0.0,
|
||||||
"y": 76.0,
|
"y": 76.0,
|
||||||
"w": 512.0,
|
"w": 512.0,
|
||||||
"h": 360.0
|
"h": 360.0,
|
||||||
|
"rotation": 0
|
||||||
},
|
},
|
||||||
"37": {
|
"37": {
|
||||||
"x": 0.0,
|
"x": 0.0,
|
||||||
"y": 76.0,
|
"y": 76.0,
|
||||||
"w": 512.0,
|
"w": 512.0,
|
||||||
"h": 360.0
|
"h": 360.0,
|
||||||
|
"rotation": 0
|
||||||
},
|
},
|
||||||
"53": {
|
"53": {
|
||||||
"x": 185.83,
|
"x": 185.83,
|
||||||
"y": 719.15,
|
"y": 719.15,
|
||||||
"w": 42.97,
|
"w": 42.97,
|
||||||
"h": 94.96
|
"h": 94.96,
|
||||||
|
"rotation": 90
|
||||||
},
|
},
|
||||||
"54": {
|
"54": {
|
||||||
"x": 594.89,
|
"x": 594.89,
|
||||||
"y": 723.2,
|
"y": 723.2,
|
||||||
"w": 46.0,
|
"w": 46.0,
|
||||||
"h": 101.37
|
"h": 101.37,
|
||||||
|
"rotation": -90
|
||||||
},
|
},
|
||||||
"55": {
|
"55": {
|
||||||
"x": 170.0,
|
"x": 170.0,
|
||||||
"y": 450.0,
|
"y": 450.0,
|
||||||
"w": 60.0,
|
"w": 60.0,
|
||||||
"h": 130.0
|
"h": 130.0,
|
||||||
|
"rotation": 90
|
||||||
},
|
},
|
||||||
"56": {
|
"56": {
|
||||||
"x": 595.0,
|
"x": 595.0,
|
||||||
"y": 450.0,
|
"y": 450.0,
|
||||||
"w": 55.0,
|
"w": 55.0,
|
||||||
"h": 130.0
|
"h": 130.0,
|
||||||
|
"rotation": -90
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -11,6 +11,7 @@ interface ZoneBBox {
|
|||||||
y: number;
|
y: number;
|
||||||
w: number;
|
w: number;
|
||||||
h: number;
|
h: number;
|
||||||
|
rotation?: number; // degrees, 0 / 90 / -90 / 180
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
@@ -36,13 +37,30 @@ async function loadBBoxes(): Promise<Record<string, ZoneBBox>> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function paddedViewBox(b: ZoneBBox): string {
|
function paddedViewBox(b: ZoneBBox): string {
|
||||||
const padX = b.w * PADDING;
|
const rotation = b.rotation ?? 0;
|
||||||
const padY = b.h * PADDING;
|
// For 90°/-90° rotation, after wrapping content in <g transform="rotate(angle cx cy)">,
|
||||||
const x = b.x - padX;
|
// the rotated bbox dims swap (w↔h). Center stays at (cx, cy).
|
||||||
const y = b.y - padY;
|
const cx = b.x + b.w / 2;
|
||||||
const w = b.w + 2 * padX;
|
const cy = b.y + b.h / 2;
|
||||||
const h = b.h + 2 * padY;
|
let w = b.w;
|
||||||
return `${x} ${y} ${w} ${h}`;
|
let h = b.h;
|
||||||
|
if (rotation === 90 || rotation === -90) {
|
||||||
|
w = b.h;
|
||||||
|
h = b.w;
|
||||||
|
}
|
||||||
|
const padX = w * PADDING;
|
||||||
|
const padY = h * PADDING;
|
||||||
|
const minX = cx - w / 2 - padX;
|
||||||
|
const minY = cy - h / 2 - padY;
|
||||||
|
return `${minX} ${minY} ${w + 2 * padX} ${h + 2 * padY}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function rotationTransform(b: ZoneBBox): string | null {
|
||||||
|
const rotation = b.rotation ?? 0;
|
||||||
|
if (rotation === 0) return null;
|
||||||
|
const cx = b.x + b.w / 2;
|
||||||
|
const cy = b.y + b.h / 2;
|
||||||
|
return `rotate(${rotation} ${cx} ${cy})`;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function ZoneDetailView({ open, zoneId, zoneLabel, onConfirm, onCancel }: Props) {
|
export function ZoneDetailView({ open, zoneId, zoneLabel, onConfirm, onCancel }: Props) {
|
||||||
@@ -65,27 +83,40 @@ export function ZoneDetailView({ open, zoneId, zoneLabel, onConfirm, onCancel }:
|
|||||||
]).then(([text, bboxes]) => {
|
]).then(([text, bboxes]) => {
|
||||||
if (cancelled) return;
|
if (cancelled) return;
|
||||||
const b = bboxes[String(zoneId)];
|
const b = bboxes[String(zoneId)];
|
||||||
if (b) setViewBox(paddedViewBox(b));
|
const finalVB = b ? paddedViewBox(b) : `0 0 ${COMPOSITE_W} ${COMPOSITE_H}`;
|
||||||
else setViewBox(`0 0 ${COMPOSITE_W} ${COMPOSITE_H}`); // fallback to full view
|
const rotXform = b ? rotationTransform(b) : null;
|
||||||
|
setViewBox(finalVB);
|
||||||
|
|
||||||
// Rewrite the SVG root viewBox + strip script and set fills BEFORE mounting,
|
// Rewrite SVG BEFORE mounting so first paint is already zoomed + rotated correctly.
|
||||||
// so the SVG is correct from the very first paint (no flash of full unfolded view).
|
|
||||||
const finalVB = bboxes[String(zoneId)] ? paddedViewBox(bboxes[String(zoneId)]) : `0 0 ${COMPOSITE_W} ${COMPOSITE_H}`;
|
|
||||||
let mutated = text;
|
let mutated = text;
|
||||||
// strip <script>...</script>
|
// strip <script>...</script>
|
||||||
mutated = mutated.replace(/<script[\s\S]*?<\/script>/gi, "");
|
mutated = mutated.replace(/<script[\s\S]*?<\/script>/gi, "");
|
||||||
// replace viewBox attribute on the root <svg ...> opening tag
|
// replace viewBox on root <svg>
|
||||||
mutated = mutated.replace(/(<svg\b[^>]*?)\sviewBox\s*=\s*"[^"]*"/i, `$1 viewBox="${finalVB}"`);
|
mutated = mutated.replace(/(<svg\b[^>]*?)\sviewBox\s*=\s*"[^"]*"/i, `$1 viewBox="${finalVB}"`);
|
||||||
// ensure preserveAspectRatio is present
|
// strip existing width/height
|
||||||
if (!/preserveAspectRatio/i.test(mutated.slice(0, 400))) {
|
|
||||||
mutated = mutated.replace(/<svg\b/i, `<svg preserveAspectRatio="xMidYMid meet"`);
|
|
||||||
}
|
|
||||||
// ensure width/height attributes are 100%
|
|
||||||
mutated = mutated.replace(
|
mutated = mutated.replace(
|
||||||
/(<svg\b[^>]*?)\s(?:width|height)\s*=\s*"[^"]*"/gi,
|
/(<svg\b[^>]*?)\s(?:width|height)\s*=\s*"[^"]*"/gi,
|
||||||
"$1"
|
"$1"
|
||||||
);
|
);
|
||||||
mutated = mutated.replace(/<svg\b/i, `<svg width="100%" height="100%"`);
|
// inject width/height + preserveAspectRatio on the root tag
|
||||||
|
mutated = mutated.replace(
|
||||||
|
/<svg\b/i,
|
||||||
|
`<svg width="100%" height="100%" preserveAspectRatio="xMidYMid meet"`
|
||||||
|
);
|
||||||
|
// Wrap all root children of <svg> in a <g transform="rotate(...)"> if rotation needed.
|
||||||
|
// This makes rotation visible AND keeps getScreenCTM correct for tap conversion.
|
||||||
|
if (rotXform) {
|
||||||
|
// Find the end of the root opening tag and the closing </svg>; wrap everything between.
|
||||||
|
const openMatch = mutated.match(/<svg\b[^>]*?>/i);
|
||||||
|
const closeIdx = mutated.lastIndexOf("</svg>");
|
||||||
|
if (openMatch && closeIdx > -1) {
|
||||||
|
const openEnd = (openMatch.index ?? 0) + openMatch[0].length;
|
||||||
|
const before = mutated.slice(0, openEnd);
|
||||||
|
const inner = mutated.slice(openEnd, closeIdx);
|
||||||
|
const after = mutated.slice(closeIdx);
|
||||||
|
mutated = `${before}<g transform="${rotXform}">${inner}</g>${after}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
setSvgText(mutated);
|
setSvgText(mutated);
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user