How to get HTMLElement properties before destroy in svelte?

97 Views Asked by At

There is a simple demo:

https://stackblitz.com/edit/sveltejs-kit-template-default-qns8y9?file=src%2Fcomponents%2FCard.svelte

In the Card.svelte, line 29 - 37, before routing(destroy), the Writable crossPageState should remember the location of this Card, but it only remember {left: 0, top: 0, width: 0, height: 0}.

I have tried using action and remember the location in the returned destroy function, but it still remember the {left: 0, top: 0, width: 0, height: 0}

1

There are 1 best solutions below

2
Stephane Vanraes On

I believe onDestroy runs after the component has been destroyed and thus the element is no longer on the screen. You can fix this by storing the position of your div during onMount instead.

export let key: string;
let wrapDiv: HTMLDivElement;
let currentPos: ElementState;

onMount(() => { 
  currentPos = getRect(wrapDiv);
  
  const v = $crossPageState;
  if (key in v) {
    const prevPos = v[key];
    const invert = {
      left: prevPos.left - currentPos.left,
      top: prevPos.top - currentPos.top
    };
    const keyframes = [
      { transform: `translate(${invert.left}px, ${invert.top}px)` },
      { transform: `translate(0)` }
    ];
    const options = { duration: 300, easing: "cubic-bezier(0,0,0.32,1)" };
      
    wrapDiv.animate(keyframes, options);
          
  }
});

onDestroy(() => {
  $crossPageState[key] = currentPos
});

The important changes:

  • store the elements position directly during onMount (before animating it)
  • use the stored value in onDestroy

Less import changes:

  • using get is discouraged, use the store subscription instead

Different approach:

You are animating an element between it's position on one page versus it's position on a different page. Consider using the View Transition API for this instead (it is made for it), while as of today it is not fully supported in Safari or Firefox and the cards will simply "jump" in those two browsers, consider how important the animation itself is (does it break functionality or is it just cosmetic?) and that this will likely be supported "soon" in both those browsers.