chenxin Posted March 19, 2020 Share Posted March 19, 2020 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 More sharing options...
ZachSaucier Posted March 19, 2020 Share Posted March 19, 2020 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); }}); 1 Link to comment Share on other sites More sharing options...
GreenSock Posted March 19, 2020 Share Posted March 19, 2020 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 1 Link to comment Share on other sites More sharing options...
GreenSock Posted March 19, 2020 Share Posted March 19, 2020 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? 5 Link to comment Share on other sites More sharing options...
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now