@@ -1527,15 +1527,15 @@ class SpineWebComponentOverlay extends HTMLElement implements OverlayAttributes,
15271527 // we cannot use window.resize event since it does not fire when body resizes, but not the window
15281528 // Alternatively, we can store the body size, check the current body size in the loop (like the translateCanvas), and
15291529 // if they differs call the resizeCallback. I already tested it, and it works. ResizeObserver should be more efficient.
1530- this . resizeObserver = new ResizeObserver ( this . resizeCallback ) ;
15311530 if ( this . scrollable ) {
1532- const style = getComputedStyle ( this . parentElement ! ) ;
1533- if ( style . transform === "none" && ! this . scrollableTweakOff ) {
1531+ // if the element is scrollable, the user does not disable translate tweak, and the parent did not have already a transform, add the tweak
1532+ if ( this . scrollable && ! this . scrollableTweakOff && getComputedStyle ( this . parentElement ! ) . transform === "none" ) {
15341533 this . parentElement ! . style . transform = `translateZ(0)` ;
15351534 }
1535+ this . resizeObserver = new ResizeObserver ( this . resizeCallback ) ;
15361536 this . resizeObserver . observe ( this . parentElement ! ) ;
15371537 } else {
1538- this . resizeObserver . observe ( document . body ) ;
1538+ window . addEventListener ( "resize" , this . resizeCallback )
15391539 }
15401540
15411541 this . skeletonList . forEach ( ( widget ) => {
@@ -1546,12 +1546,17 @@ class SpineWebComponentOverlay extends HTMLElement implements OverlayAttributes,
15461546 this . startRenderingLoop ( ) ;
15471547 }
15481548
1549+ private hasCssTweakOff ( ) {
1550+ return this . scrollableTweakOff && getComputedStyle ( this . parentElement ! ) . transform === "none" ;
1551+ }
1552+
15491553 private running = false ;
15501554 disconnectedCallback ( ) : void {
15511555 const id = this . getAttribute ( 'id' ) ;
15521556 if ( id ) SpineWebComponentOverlay . OVERLAY_LIST . delete ( id ) ;
15531557 // window.removeEventListener("scroll", this.scrollHandler);
15541558 window . removeEventListener ( "load" , this . onLoadCallback ) ;
1559+ window . removeEventListener ( "resize" , this . resizeCallback ) ;
15551560 window . screen . orientation . removeEventListener ( 'change' , this . orientationChangeCallback ) ;
15561561 this . intersectionObserver ?. disconnect ( ) ;
15571562 this . resizeObserver ?. disconnect ( ) ;
@@ -1582,7 +1587,6 @@ class SpineWebComponentOverlay extends HTMLElement implements OverlayAttributes,
15821587
15831588 private resizeCallback = ( ) => {
15841589 this . updateCanvasSize ( ) ;
1585- this . zoomHandler ( ) ;
15861590 }
15871591
15881592 private orientationChangeCallback = ( ) => {
@@ -1599,7 +1603,6 @@ class SpineWebComponentOverlay extends HTMLElement implements OverlayAttributes,
15991603
16001604 private onLoadCallback = ( ) => {
16011605 this . updateCanvasSize ( ) ;
1602- this . zoomHandler ( ) ;
16031606 this . scrollHandler ( ) ;
16041607 if ( ! this . loaded ) {
16051608 this . parentElement ! . appendChild ( this ) ;
@@ -1657,13 +1660,13 @@ class SpineWebComponentOverlay extends HTMLElement implements OverlayAttributes,
16571660 // fps top-left span
16581661 if ( SpineWebComponentWidget . SHOW_FPS ) {
16591662 if ( ! this . fpsAppended ) {
1660- this . root . appendChild ( this . fps ) ;
1663+ this . div . appendChild ( this . fps ) ;
16611664 this . fpsAppended = true ;
16621665 }
16631666 this . fps . innerText = this . time . framesPerSecond . toFixed ( 2 ) + " fps" ;
16641667 } else {
16651668 if ( this . fpsAppended ) {
1666- this . root . removeChild ( this . fps ) ;
1669+ this . div . removeChild ( this . fps ) ;
16671670 this . fpsAppended = false ;
16681671 }
16691672 }
@@ -1950,6 +1953,7 @@ class SpineWebComponentOverlay extends HTMLElement implements OverlayAttributes,
19501953 this . cursorWorldY = tempVector . y ;
19511954 }
19521955
1956+ // return true if updated
19531957 private cursorWidgetUpdate ( widget : SpineWebComponentWidget ) : boolean {
19541958 if ( widget . worldX === Infinity ) return false ;
19551959
@@ -1987,8 +1991,11 @@ class SpineWebComponentOverlay extends HTMLElement implements OverlayAttributes,
19871991 } ,
19881992 down : ( x , y , ev ) => {
19891993 const input = getInput ( ev ) ;
1994+
1995+ this . cursorUpdate ( input ) ;
1996+
19901997 this . skeletonList . forEach ( widget => {
1991- if ( ! widget . onScreen && widget . dragX === 0 && widget . dragY === 0 ) return ;
1998+ if ( ! this . cursorWidgetUpdate ( widget ) || ! widget . onScreen && widget . dragX === 0 && widget . dragY === 0 ) return ;
19921999
19932000 widget . cursorEventUpdate ( "down" , ev ) ;
19942001
@@ -2064,9 +2071,18 @@ class SpineWebComponentOverlay extends HTMLElement implements OverlayAttributes,
20642071 this . root . appendChild ( this . div ! ) ;
20652072 } else {
20662073 this . div ?. remove ( ) ;
2067- this . div ! . style . width = this . parentElement ! . scrollWidth + "px" ;
2068- this . div ! . style . height = this . parentElement ! . scrollHeight + "px" ;
2069- // this.canvas.style.transform = `translate(${-this.overflowLeftSize}px,${-this.overflowTopSize}px)`;
2074+
2075+ if ( this . hasCssTweakOff ( ) ) {
2076+ // this case lags if scrolls or position fixed
2077+ // users should never use tweak off, unless the parent container has already a transform
2078+ this . div ! . style . width = this . parentElement ! . clientWidth + "px" ;
2079+ this . div ! . style . height = this . parentElement ! . clientHeight + "px" ;
2080+ this . canvas . style . transform = `translate(${ - this . overflowLeftSize } px,${ - this . overflowTopSize } px)` ;
2081+ } else {
2082+ this . div ! . style . width = this . parentElement ! . scrollWidth + "px" ;
2083+ this . div ! . style . height = this . parentElement ! . scrollHeight + "px" ;
2084+ }
2085+
20702086 this . root . appendChild ( this . div ! ) ;
20712087 }
20722088
@@ -2084,15 +2100,6 @@ class SpineWebComponentOverlay extends HTMLElement implements OverlayAttributes,
20842100 height = this . parentElement ! . clientHeight ;
20852101 }
20862102
2087- // this is needed because screen size is wrong when zoom levels occurs
2088- // zooming out will make the canvas smaller and its known that zoom level
2089- // on browsers is not reliable
2090- // ideally, window.innerWidth/innerHeight would be preferrable. However
2091- // on mobile browsers the dynamic search bar makes the innerHeight smaller
2092- // at the beginning (changing the canvas size at each scroll is not ideal)
2093- // width = Math.max(width, window.innerWidth);
2094- // height = Math.max(height, window.innerHeight);
2095-
20962103 if ( this . currentCanvasBaseWidth !== width || this . currentCanvasBaseHeight !== height ) {
20972104 this . currentCanvasBaseWidth = width ;
20982105 this . currentCanvasBaseHeight = height ;
@@ -2106,6 +2113,24 @@ class SpineWebComponentOverlay extends HTMLElement implements OverlayAttributes,
21062113 this . canvas . style . height = totalHeight + "px" ;
21072114 this . resize ( totalWidth , totalHeight ) ;
21082115 }
2116+
2117+ this . skeletonList . forEach ( ( widget ) => {
2118+ // inside mode scale automatically to fit the skeleton within its parent
2119+ if ( widget . mode !== "origin" && widget . fit !== "none" ) return ;
2120+
2121+ const skeleton = widget . skeleton ;
2122+ if ( ! skeleton ) return ;
2123+
2124+ // I'm not sure about this. With mode origin and fit none:
2125+ // case 1) If I comment this scale code, the skeleton is never scaled and will be always at the same size and won't change size while zooming
2126+ // case 2) Otherwise, the skeleton is loaded always at the same size, but changes size while zooming
2127+ const scale = window . devicePixelRatio ;
2128+ skeleton . scaleX = skeleton . scaleX / widget . currentScaleDpi * scale ;
2129+ skeleton . scaleY = skeleton . scaleY / widget . currentScaleDpi * scale ;
2130+ widget . currentScaleDpi = scale ;
2131+
2132+ } ) ;
2133+
21092134 }
21102135
21112136 private translateCanvas ( ) {
@@ -2116,27 +2141,38 @@ class SpineWebComponentOverlay extends HTMLElement implements OverlayAttributes,
21162141 scrollPositionX += window . scrollX ;
21172142 scrollPositionY += window . scrollY ;
21182143 } else {
2119- scrollPositionX += this . parentElement ! . scrollLeft ;
2120- scrollPositionY += this . parentElement ! . scrollTop ;
2121- }
21222144
2123- this . canvas . style . transform = `translate(${ scrollPositionX } px,${ scrollPositionY } px)` ;
2124- }
2145+ // Ideally this should be the only scrollable case (scrollable-tweak-off not enabled or at least an ancestor has transform)
2146+ // I'd like to get rid of the code below
2147+ if ( ! this . hasCssTweakOff ( ) ) {
2148+ scrollPositionX += this . parentElement ! . scrollLeft ;
2149+ scrollPositionY += this . parentElement ! . scrollTop ;
2150+ } else {
2151+ const { left, top } = this . parentElement ! . getBoundingClientRect ( ) ;
2152+ scrollPositionX += left + window . scrollX ;
2153+ scrollPositionY += top + window . scrollY ;
2154+
2155+ let offsetParent = this . offsetParent ;
2156+ do {
2157+ if ( offsetParent === document . body ) break ;
2158+
2159+ const htmlOffsetParentElement = offsetParent as HTMLElement ;
2160+ if ( htmlOffsetParentElement . style . position === "fixed" || htmlOffsetParentElement . style . position === "sticky" || htmlOffsetParentElement . style . position === "absolute" ) {
2161+ const parentRect = htmlOffsetParentElement . getBoundingClientRect ( ) ;
2162+ this . div . style . transform = `translate(${ left - parentRect . left } px,${ top - parentRect . top } px)` ;
2163+ return ;
2164+ }
21252165
2126- private zoomHandler = ( ) => {
2127- this . skeletonList . forEach ( ( widget ) => {
2128- // inside mode scale automatically to fit the skeleton within its parent
2129- if ( widget . mode !== "origin" && widget . fit !== "none" ) return ;
2166+ offsetParent = htmlOffsetParentElement . offsetParent ;
2167+ } while ( offsetParent ) ;
21302168
2131- const skeleton = widget . skeleton ;
2132- if ( ! skeleton ) return ;
2133- const scale = window . devicePixelRatio ;
2134- skeleton . scaleX = skeleton . scaleX / widget . currentScaleDpi * scale ;
2135- skeleton . scaleY = skeleton . scaleY / widget . currentScaleDpi * scale ;
2136- widget . currentScaleDpi = scale ;
2137- } ) ;
2169+ this . div . style . transform = `translate(${ scrollPositionX + this . overflowLeftSize } px,${ scrollPositionY + this . overflowTopSize } px)` ;
2170+ return ;
2171+ }
2172+
2173+ }
21382174
2139- this . resize ( parseFloat ( this . canvas . style . width ) , parseFloat ( this . canvas . style . height ) ) ;
2175+ this . canvas . style . transform = `translate( ${ scrollPositionX } px, ${ scrollPositionY } px)` ;
21402176 }
21412177
21422178 private resize ( width : number , height : number ) {
@@ -2155,16 +2191,29 @@ class SpineWebComponentOverlay extends HTMLElement implements OverlayAttributes,
21552191 return document . body . getBoundingClientRect ( ) ;
21562192 }
21572193
2158- // screen size remain the same when it is rotated
2159- // we need to swap them based and the orientation angle
2194+ private previousWidth = 0 ;
2195+ private previousHeight = 0 ;
2196+ private previousDPR = 0 ;
2197+ private static readonly WIDTH_INCREMENT = 1.15 ;
2198+ private static readonly HEIGHT_INCREMENT = 1.2 ;
21602199 private getScreenSize ( ) {
2161- const { screen } = window ;
2162- const { width, height } = window . screen ;
2163- const angle = screen . orientation . angle ;
2164- const rotated = angle === 90 || angle === 270 ;
2165- return rotated
2166- ? { width : height , height : width }
2167- : { width, height } ;
2200+ let width = window . innerWidth ;
2201+ let height = window . innerHeight ;
2202+
2203+ const dpr = window . devicePixelRatio ;
2204+ if ( dpr !== this . previousDPR ) {
2205+ this . previousDPR = dpr ;
2206+ this . previousWidth = this . previousWidth === 0 ? width : width * SpineWebComponentOverlay . WIDTH_INCREMENT ;
2207+ this . previousHeight = height * SpineWebComponentOverlay . HEIGHT_INCREMENT ;
2208+ } else {
2209+ if ( width > this . previousWidth ) this . previousWidth = width * SpineWebComponentOverlay . WIDTH_INCREMENT ;
2210+ if ( height > this . previousHeight ) this . previousHeight = height * SpineWebComponentOverlay . HEIGHT_INCREMENT ;
2211+ }
2212+
2213+ return {
2214+ width : this . previousWidth ,
2215+ height : this . previousHeight ,
2216+ }
21682217 }
21692218
21702219 /*
0 commit comments