@@ -132,6 +132,10 @@ export async function captureDOM(element, options) {
132132 const TOTAL = matrixFromComputed ( measure ) ;
133133 document . documentElement . removeChild ( measure ) ;
134134
135+ // -- NUEVO: extraigo la traslación total (px) para cancelarla en el container
136+ const e = TOTAL . e ?? TOTAL . m41 ?? 0 ; // translateX total
137+ const f = TOTAL . f ?? TOTAL . m42 ?? 0 ; // translateY total
138+
135139 // 4) bbox proyectado (sin traslación) sobre el tamaño w,h
136140 const M2D = TOTAL . is2D ? matrix2DNoTranslate ( TOTAL ) : matrix2DNoTranslate ( new DOMMatrix ( TOTAL . toString ( ) ) ) ;
137141 const bb = bboxFromMatrix ( w , h , M2D ) ;
@@ -158,22 +162,26 @@ export async function captureDOM(element, options) {
158162 classCSS ;
159163 fo . appendChild ( styleTag ) ;
160164
161- // 6) contenedor para el re-escalado por width/height (si aplica)
165+ // 6) contenedor para el re-escalado y la cancelación de translate
162166 const container = document . createElement ( "div" ) ;
163167 container . setAttribute ( "xmlns" , "http://www.w3.org/1999/xhtml" ) ;
164168 container . style . width = `${ w } px` ;
165169 container . style . height = `${ h } px` ;
166170 container . style . overflow = "visible" ;
167171 container . style . transformOrigin = "0 0" ;
168172
173+ // armamos la transform del container empezando por CANCELAR la traslación total
174+ const cancels = [ `translate(${ - e } px, ${ - f } px)` ] ;
175+
176+ // luego tu lógica de escalado de salida
169177 if ( ! hasScale && ( hasW || hasH ) ) {
170- // escalo solo por petición de output w/h
171178 const sxWH = rect . width ? ( w / rect . width ) : 1 ;
172179 const syWH = rect . height ? ( h / rect . height ) : 1 ;
173- container . style . transform = `scale(${ sxWH } , ${ syWH } )` ;
180+ cancels . push ( `scale(${ sxWH } , ${ syWH } )` ) ;
174181 } else if ( hasScale ) {
175- container . style . transform = `scale(${ scaleOpt } )` ;
182+ cancels . push ( `scale(${ scaleOpt } )` ) ;
176183 }
184+ container . style . transform = cancels . join ( " " ) ;
177185
178186 // 7) aplicar al clone EXACTAMENTE lo que tenía el elemento
179187 clone . setAttribute ( "xmlns" , "http://www.w3.org/1999/xhtml" ) ;
@@ -210,83 +218,83 @@ export async function captureDOM(element, options) {
210218 return dataURL ;
211219}
212220
213- // helpers -----------------------------------------------------------------------
214- function getNaturalBorderBoxSize ( el ) {
215- const cs = getComputedStyle ( el ) ;
216- const px = ( v ) => parseFloat ( v ) || 0 ;
217- let w = px ( cs . width ) ;
218- let h = px ( cs . height ) ;
219- if ( cs . boxSizing === "content-box" ) {
220- w += px ( cs . paddingLeft ) + px ( cs . paddingRight ) + px ( cs . borderLeftWidth ) + px ( cs . borderRightWidth ) ;
221- h += px ( cs . paddingTop ) + px ( cs . paddingBottom ) + px ( cs . borderTopWidth ) + px ( cs . borderBottomWidth ) ;
222- }
223- return { width : w , height : h } ;
224- }
221+ // helpers -----------------------------------------------------------------------
222+ function getNaturalBorderBoxSize ( el ) {
223+ const cs = getComputedStyle ( el ) ;
224+ const px = ( v ) => parseFloat ( v ) || 0 ;
225+ let w = px ( cs . width ) ;
226+ let h = px ( cs . height ) ;
227+ if ( cs . boxSizing === "content-box" ) {
228+ w += px ( cs . paddingLeft ) + px ( cs . paddingRight ) + px ( cs . borderLeftWidth ) + px ( cs . borderRightWidth ) ;
229+ h += px ( cs . paddingTop ) + px ( cs . paddingBottom ) + px ( cs . borderTopWidth ) + px ( cs . borderBottomWidth ) ;
230+ }
231+ return { width : w , height : h } ;
232+ }
225233
226- function matrixFromComputed ( el ) {
227- const tr = getComputedStyle ( el ) . transform ;
228- if ( ! tr || tr === "none" ) return new DOMMatrix ( ) ; // identidad
229- try { return new DOMMatrix ( tr ) ; }
230- catch { return new WebKitCSSMatrix ( tr ) ; } // fallback WebKit
231- }
234+ function matrixFromComputed ( el ) {
235+ const tr = getComputedStyle ( el ) . transform ;
236+ if ( ! tr || tr === "none" ) return new DOMMatrix ( ) ; // identidad
237+ try { return new DOMMatrix ( tr ) ; }
238+ catch { return new WebKitCSSMatrix ( tr ) ; } // fallback WebKit
239+ }
232240
233- function matrix2DNoTranslate ( M ) {
234- // devuelvo solo a,b,c,d y cero e,f para bbox
235- return new DOMMatrix ( [ M . a , M . b , M . c , M . d , 0 , 0 ] ) ;
236- }
241+ function matrix2DNoTranslate ( M ) {
242+ // devuelvo solo a,b,c,d y cero e,f para bbox
243+ return new DOMMatrix ( [ M . a , M . b , M . c , M . d , 0 , 0 ] ) ;
244+ }
237245
238- function bboxFromMatrix ( w , h , M2D ) {
239- const pts = [
240- { x : 0 , y : 0 } ,
241- { x : w , y : 0 } ,
242- { x : 0 , y : h } ,
243- { x : w , y : h } ,
244- ] ;
245- const t = pts . map ( p => ( {
246- x : M2D . a * p . x + M2D . c * p . y ,
247- y : M2D . b * p . x + M2D . d * p . y ,
248- } ) ) ;
249- const minX = Math . min ( ...t . map ( p => p . x ) ) ;
250- const maxX = Math . max ( ...t . map ( p => p . x ) ) ;
251- const minY = Math . min ( ...t . map ( p => p . y ) ) ;
252- const maxY = Math . max ( ...t . map ( p => p . y ) ) ;
253- return { minX, minY, width : maxX - minX , height : maxY - minY } ;
254- }
246+ function bboxFromMatrix ( w , h , M2D ) {
247+ const pts = [
248+ { x : 0 , y : 0 } ,
249+ { x : w , y : 0 } ,
250+ { x : 0 , y : h } ,
251+ { x : w , y : h } ,
252+ ] ;
253+ const t = pts . map ( p => ( {
254+ x : M2D . a * p . x + M2D . c * p . y ,
255+ y : M2D . b * p . x + M2D . d * p . y ,
256+ } ) ) ;
257+ const minX = Math . min ( ...t . map ( p => p . x ) ) ;
258+ const maxX = Math . max ( ...t . map ( p => p . x ) ) ;
259+ const minY = Math . min ( ...t . map ( p => p . y ) ) ;
260+ const maxY = Math . max ( ...t . map ( p => p . y ) ) ;
261+ return { minX, minY, width : maxX - minX , height : maxY - minY } ;
262+ }
255263
256- // lectura de typed OM (cuando existe)
257- function readIndividualTransforms ( el ) {
258- const out = { rotate : "0deg" , scale : null , translate : null } ;
259- const map = el . computedStyleMap ?. ( ) ;
260- if ( map ) {
261- const rot = map . get ( "rotate" ) ;
262- if ( rot ) {
263- const ang = rot . angle ?? rot ;
264- if ( ang && "unit" in ang ) {
265- out . rotate = ang . unit === "rad" ? ( ang . value * 180 / Math . PI ) + "deg" : ang . value + ang . unit ;
266- } else {
267- out . rotate = String ( rot ) ;
268- }
269- }
270- const sc = map . get ( "scale" ) ;
271- if ( sc && sc . length ) {
272- const sx = sc [ 0 ] ?. value ?? 1 ;
273- const sy = sc [ 1 ] ?. value ?? sx ;
274- out . scale = `${ sx } ${ sy } ` ;
275- }
276- const tr = map . get ( "translate" ) ;
277- if ( tr && tr . length ) {
278- const tx = tr [ 0 ] ?. value ?? 0 ;
279- const ty = tr [ 1 ] ?. value ?? 0 ;
280- const ux = tr [ 0 ] ?. unit ?? "px" ;
281- const uy = tr [ 1 ] ?. unit ?? "px" ;
282- out . translate = `${ tx } ${ ux } ${ ty } ${ uy } ` ;
283- }
284- return out ;
285- }
286- // fallbacks por si no hay Typed OM
287- const cs = getComputedStyle ( el ) ;
288- out . rotate = cs . rotate && cs . rotate !== "none" ? cs . rotate : "0deg" ;
289- out . scale = cs . scale && cs . scale !== "none" ? cs . scale : null ;
290- out . translate = cs . translate && cs . translate !== "none" ? cs . translate : null ;
291- return out ;
292- }
264+ // lectura de typed OM (cuando existe)
265+ function readIndividualTransforms ( el ) {
266+ const out = { rotate : "0deg" , scale : null , translate : null } ;
267+ const map = el . computedStyleMap ?. ( ) ;
268+ if ( map ) {
269+ const rot = map . get ( "rotate" ) ;
270+ if ( rot ) {
271+ const ang = rot . angle ?? rot ;
272+ if ( ang && "unit" in ang ) {
273+ out . rotate = ang . unit === "rad" ? ( ang . value * 180 / Math . PI ) + "deg" : ang . value + ang . unit ;
274+ } else {
275+ out . rotate = String ( rot ) ;
276+ }
277+ }
278+ const sc = map . get ( "scale" ) ;
279+ if ( sc && sc . length ) {
280+ const sx = sc [ 0 ] ?. value ?? 1 ;
281+ const sy = sc [ 1 ] ?. value ?? sx ;
282+ out . scale = `${ sx } ${ sy } ` ;
283+ }
284+ const tr = map . get ( "translate" ) ;
285+ if ( tr && tr . length ) {
286+ const tx = tr [ 0 ] ?. value ?? 0 ;
287+ const ty = tr [ 1 ] ?. value ?? 0 ;
288+ const ux = tr [ 0 ] ?. unit ?? "px" ;
289+ const uy = tr [ 1 ] ?. unit ?? "px" ;
290+ out . translate = `${ tx } ${ ux } ${ ty } ${ uy } ` ;
291+ }
292+ return out ;
293+ }
294+ // fallbacks por si no hay Typed OM
295+ const cs = getComputedStyle ( el ) ;
296+ out . rotate = cs . rotate && cs . rotate !== "none" ? cs . rotate : "0deg" ;
297+ out . scale = cs . scale && cs . scale !== "none" ? cs . scale : null ;
298+ out . translate = cs . translate && cs . translate !== "none" ? cs . translate : null ;
299+ return out ;
300+ }
0 commit comments