Jump to content
Search Community

How to use gsap in this case

chenxin test
Moderator Tag

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)

 

Link to comment
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
Link to comment
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
Link to comment
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
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...