Jump to content
GreenSock

Search In
  • More options...
Find results that contain...
Find results in...
chenxin

How to use gsap in this case

Recommended Posts

I want to animate the property uPosx and uPosy of this.pageCurlMaterial object, but the value can only be signed with the setProperty function. How can I use gsap in this case? I think maybe  I need to call setProperty on the onUpdate callback, but I don't know how to form it.

 

                this.pageCurlMaterial.setProperty("uPosx", this.pointerStartPosx)
                this.pageCurlMaterial.setProperty("uPosy", this.pointerStartPosy)

 

Share this post


Link to post
Share on other sites

Hey chenxin. Cases like this are where using a proxy object is useful. You can use the callbackScope property to pass in what this refers to if you need to. Alternatively you could save this to a different variable and refer to that inside of the onUpdate.

 

Something like this should work:

let proxy = {x: this.pointerStartPosx, y: this.pointerStartPosy);
gsap.to(proxy, {x: targetXVal, y: targetYVal, callbackScope: this, onUpdate: function() {
  this.pageCurlMaterial.setProperty("uPosx", proxy.x);
  this.pageCurlMaterial.setProperty("uPosy", proxy.y);
}});

 

  • Like 1

Share this post


Link to post
Share on other sites

Here's a helper function I whipped up that'll automatically add multi-purpose getter/setter methods to your object without the "get" and "set" in front:

function wrapSetters(target, names) {
  if (names) {
    names.split(",").forEach(name => {
      let cappedName = name.charAt(0).toUpperCase() + name.substr(1),
          setter = target["set" + cappedName],
          getter = target["get" + cappedName];
      (setter && getter) || console.warn("No getter/setter defined for", name);
      target[name] = function(value) {
        return arguments.length ? setter.call(target, value) : getter.call(target);
      };
    });
  } else {
    Object.keys(target).forEach(name => {
      let getter, setter;
      if (name.substr(0, 3) === "set" && (getter = target["get" + name.substr(3)])) {
        setter = target[name];
        target[name.charAt(3).toLowerCase() + name.substr(4)] = function(value) {
          return arguments.length ? setter.call(target, value) : getter.call(target);
        };
      }
    });
  }
}

Usage: 

var obj = {
  _opacity: 0,
  setOpacity(value) {
    this._opacity = value;
  },
  getOpacity() {
    return this._opacity;
  }
};

wrapSetters(obj); // <- loops through all enumerable properties, finds any that start with "set" and have a matching "get" function, adds a new function without the get/set for convenience...
gsap.to(obj, {opacity: 1, duration: 2, ease: "none", onUpdate: () => console.log(obj.getOpacity())});

// -OR- you can feed in a comma-delimited list of property names (without the get/set in front) and it'll just do those:
wrapSetters(obj, "opacity");

So basically, with that helper function your tweening code could be as concise as this from now on...

gsap.to(wrapSetters(obj), {opacity: 1, duration: 3});
gsap.to(wrapSetters(obj2), {x: 100, duration: 1});
...

And you should only need to run that function once on each object you're animating. 

 

Zach's method is also an excellent solution. I just figured that we've had a few people ask about this now, so a helper method might...um...help ;)

  • Like 1

Share this post


Link to post
Share on other sites

Actually, sorry, I rushed when I was reading the original post and didn't catch that your particular setup doesn't use names like "setOpacity()" and "getOpacity()", etc. - you use a standard "setProperty()" and "getProperty()" method for everything. That actually makes it even easier: 

 

function proxySetters(target, names) {
  names.split(",").forEach(name => {
    target[name] = function(value) {
      return arguments.length ? target.setProperty(name, value) : target.getProperty(name);
    };
  });
}

Example: 

var obj = {
  _opacity: 0,
  _x: 0,
  setProperty(name, value) {
    this["_" + name] = value;
  },
  getProperty(name) {
    return this["_" + name];
  }
};

proxySetters(obj, "opacity,x");
gsap.to(obj, {opacity: 1, x: 100, duration: 2, ease: "none", onUpdate: () => console.log("opacity:", obj.getProperty("opacity"), "x:", obj.getProperty("x"))});

So with the helper function your tweens could be as concise as: 

gsap.to(proxySetters(this.pageCurlMaterial, "uPosx,uPosy"), {
  uPosx: 500, 
  uPosy: 100, 
  duration: 2
});

Better? 

  • Like 5

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...

  • Recently Browsing   0 members

    No registered users viewing this page.

×