Jump to content


Keyframes at specific position with timestamp

Go to solution Solved by GreenSock,

Recommended Posts


I have a custom timeline UI (similar to the timeline in adobe after effects) where you can set keyframes for different properties like position, opacity, scale etc.


I want to save those keyframes in a format like this

{ time: 1, value: { x: 100, y: 0 }}

 for the position and add them to the timeline animation. `time` is the position in the timeline where the element should have the x and y in `value`.


I just can't figure out how I would set up the code without any additional calculations for the duration.


Currently I have a timeline which should be always 3 seconds long and keyframes should be added to that timeline. This code just doesn't feel correct in my opinion because I would need to set the duration manually for each keyframe by checking if there is a keyframe before the current one and then using that time to calculate the duration.

const timeline = gsap.timeline({
  repeat: -1,
  duration: 3,
  paused: true,
  onUpdate: () => {
    // update UI

const prop = { x: 0, y: 0 }

  gsap.to(prop, {
    keyframes: [
      { x: 100, y: 100, duration: 1 },
      { x: 0, y: 0, duration: 1 }


I hope it's understandable because I don't know how I should explain it well. Sorry for that!

Can you please give me a hint how I would do this with gsap? I appreciate any help and advice! :)


For reference: I want to "translate" a view like this into "gsap code".


Link to comment
Share on other sites

  • Solution

I wonder if maybe you're overcomplicating things a bit. I assume the user could add keyframes anywhere for individual properties, thus you can't safely assume that all the keyframes line up for each property. So just loop through and create a tween for each one. 


Here's some pseudo code: 

let keyframes = {
	x: [{time: 1, value: 100}, {time: 2, value: -100}],
	y: [{time: 1, value: 200}, {time: 3, value: 500}]

let tl = gsap.timeline();

for (let p in keyframes) {
	insert(tl, target, p, keyframes[p]);

function insert(tl, target, property, data) {
	let time = 0;
	data.forEach(d => {
		tl.to(target, {[property]: d.value, duration: d.time - time}, time);
		time = d.time;

You could easily incorporate ease data in there too. Or whatever. 


Does that help? 

  • Like 1
Link to comment
Share on other sites

@GreenSock Yeah, overcomplicating stuff is one of my strengths I'm not proud of. 😆 But wow, this is exactly what I need. Just tried it and it works perfectly! Many thanks for that, really appreciate that superb help!! 😊

  • Like 3
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.