Jump to content
Search Community

Saving animation state between page loads

EddieGreen test
Moderator Tag

Go to solution Solved by EddieGreen,

Recommended Posts

I'm using GSAP to manipulate an SVG map. See pen, based on @OSUblakes fine work with

See the Pen oGoyYb by osublake (@osublake) on CodePen

 

I'd like to be able to maintain the map's position following a page refresh or ajax call for updated content. The whole SVG content will change although the bounds will not - the change would be in the icons.

 

I've already attempted to save what I think might be useful in sessionStorage but get errors storing the object data. It doesn't help that I'm not a JavaScript man, as might be obvious with the following code that spits out it's dummy at the point of storing object with TypeError: cyclic object value Is what I'm trying to do possible, and if so, how?

 

See the Pen dyjLbPm by EddieGreen (@EddieGreen) on CodePen

Link to comment
Share on other sites

Hi @EddieGreen and welcome to the GreenSock forums!

 

Thanks for being a Club GreenSock member and supporting GreenSock!

 

It's a bit hard to follow the code you pasted in your post but based on the error you're getting, you are creating a circular reference which means that you are trying to Stringify an object that has a reference to itself inside:

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Cyclic_object_value

 

I would recommend you to start really simple, with a button and a method to store something simple in the session storage and then start adding complexity to it until it breaks. Then you'll find what is causing the issue and how.

 

Let us know if you have more questions.

Happy Tweening!

Link to comment
Share on other sites

Super stuff and thanks for the response. Let's get to it...

On 2/1/2023 at 3:27 PM, Rodrigo said:

based on the error you're getting, you are creating a circular reference which means that you are trying to Stringify an object that has a reference to itself inside:

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Cyclic_object_value

Yah well I figured that out real quick and got the solution too..

 

Before I got into fixing recursive references, I reached out to ask the fundamental questions

 

Question 1: Is it possible to save animation state between page loads?

 

Question 2: If it is possible, how would you implement this?

 

I realise now that I made a mistake in offering any code. Forget my code. How would you achieve the result?

 

Link to comment
Share on other sites

23 hours ago, EddieGreen said:

Question 1: Is it possible to save animation state between page loads?

 

Question 2: If it is possible, how would you implement this?

  1. Absolutely, just use either session or local storage, whichever makes more sense to you. I believe both have the same API so implementation should be the same.
  2. I would create a method to store in a single object all the possible animation variables for zoom, pan and rotation passing the specific object for each event. For example if you pan, then pass an object with the x and y coordinates. If you zoom the viewbox values for that specific zoom level. Finally if you rotate the rotation angle. When you refresh the page read if there's any value stored, if there is just apply it using a to or set instance (depending if you want to implement them immediately or animate the implementation).

In my limited experience with this API, when working with session/loca storage simplicity is the key, in order to prevent complex write/read operations when you're using it.

 

Hopefully this helps.

Happy Tweening!

Link to comment
Share on other sites

  • Solution

To answer my own question...

 

The position, scale and orientation is modified on the SVG object - this is where to look to save and restore the state of the SVG.

 

The scale and position are in the viewBox attribute, orientation in data-svg-origin and transform, for example in the demo shown:

 

<svg id="map" class="svg" xmlns="http://www.w3.org/2000/svg" viewBox="173.169 19.9044 1000 1000" style="">
  <title>Demo Square</title>
  <g id="viewport" data-svg-origin="488.94370908783253 572.0179250471222" transform="matrix(-0.80649,0.59125,-0.59125,-0.80649,1243.48156,500.66229)" style="translate: none; rotate: none; scale: none; transform-origin: 0px 0px 0px;">
...
</svg>

Add a function to store these values in session, or elsewhere, for example:

 

//
// Update saved map state in session
// ===========================================================================
function updateCurrentTransformation() {
  var savedMapState = new Object();

  savedMapState.svgViewBox = svg.getAttribute("viewBox");
  savedMapState.viewportOrigin = viewport.getAttribute("data-svg-origin");
  savedMapState.viewportTransform = viewport.getAttribute("transform");

  sessionStorage.setItem("savedMapState", JSON.stringify(savedMapState));

  //console.log("VBX: " + savedMapState.svgViewBox + "  VPO: " + savedMapState.viewportOrigin + "  VPT: " + savedMapState.viewportTransform);
}

Call this function whenever the map changes - for example at the end of the drag:

 

var draggedSvg = Draggable.create(proxy, {
	...
  onDragEnd: function () {
    updateCurrentTransformation();
  },
});

At page initialisation, read these values and modify the SVG attributes with saved values if any:

 

// Get saved map state - will exist if map moved
var savedMapState = JSON.parse(sessionStorage.getItem("savedMapState"));

if (savedMapState != null) {
  //console.log("Session exists")

  if (savedMapState.svgViewBox != null) {
    svg.setAttribute("viewBox", savedMapState.svgViewBox);
  };
  if (savedMapState.viewportOrigin != null) {
    viewport.setAttribute("data-svg-origin", savedMapState.viewportOrigin);
  };
  if (savedMapState.viewportTransform != null) {
    viewport.setAttribute("transform", savedMapState.viewportTransform);
  };
}

Finally, remove the stored session when required, fore example when the SVG is set to original size etc:

 

//
// RESET VIEWPORT
// ===========================================================================
function resetViewport() {

  ...

  // remove saved map sate session values
  sessionStorage.removeItem("savedMapState");
}

 

A working demo and the code referred to is here

  • Like 2
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...