Jump to content
Search Community

Three.js properties

martis test
Moderator Tag

Warning: Please note

This thread was started before GSAP 3 was released. Some information, especially the syntax, may be out of date for GSAP 3. Please see the GSAP 3 migration guide and release notes for more information about how to update the code to GSAP 3's syntax. 

Recommended Posts

Will this plugin still work in GSAP 3? I was using it quite often, I did not needed it for some time but that may change any time now

 

On 8/19/2017 at 11:05 PM, GreenSock said:

Hm, that's a little tricky in Three.js, but I think this'll do it: 


var _gsScope = (typeof module !== "undefined" && module.exports && typeof global !== "undefined") ? global : this || window;
(_gsScope._gsQueue || (_gsScope._gsQueue = [])).push(function () {
    "use strict";
    var _xyzContexts = "position,scale,rotation".split(","),
        _contexts = {x:"position", y:"position", z:"position"},
        _DEG2RAD = Math.PI / 180,
        _visibleSetter = function(target, start, end) {
            var time = end ? 0 : 0.999999999;
            return function(ratio) {
                var value = (ratio > time) ? end : start;
                if (target.visible !== value) {
                    target.visible = value;
                    target.traverse(function (child) {
                        child.visible = value;
                    });
                }
            };
        },
        _addFuncPropTween = function(tween, func) {
            var proxy = {setRatio: func},
                backward = !!tween.vars.runBackwards,
                pt = {_next:tween._firstPT, t:proxy, p:"setRatio", s:backward ? 1 : 0, f:1, pg:0, n:"setRatio", m:0, pr:0, c:backward ? 0 : 1};
            tween._firstPT = pt;
            if (pt._next) {
                pt._next._prev = pt;
            }
            return pt;
        },
        _degreesToRadians = function(value) {
            return (typeof(value) === "string" && value.charAt(1) === "=") ? value.substr(0, 2) + (parseFloat(value.substr(2)) * _DEG2RAD) : value * _DEG2RAD;
        }, i, p;
    for (i = 0; i < _xyzContexts.length; i++) {
        p = _xyzContexts[i];
        _contexts[p + "X"] = p;
        _contexts[p + "Y"] = p;
        _contexts[p + "Z"] = p;
    }
    var ThreePlugin = _gsScope._gsDefine.plugin({
        propName: "three",
        priority: 0,
        API: 2,
        version: "0.0.2",
        init: function (target, values, tween, index) {
            var context, axis, value, p, i, m;
            for (p in values) {
                context = _contexts[p];
                value = values[p];
                if (typeof(value) === "function") {
                    value = value(index || 0, target);
                }
                if (context) {
                    i = p.charAt(p.length-1).toLowerCase();
                    axis = (i.indexOf("x") !== -1) ? "x" : (i.indexOf("z") !== -1) ? "z" : "y";
                    this._addTween(target[context], axis, target[context][axis], (p.indexOf("rotation") !== -1) ? _degreesToRadians(value) : value, p);
                } else if (p === "scale") {
                    this._addTween(target[p], "x", target[p].x, value, p + "X");
                    this._addTween(target[p], "y", target[p].y, value, p + "Y");
                    this._addTween(target[p], "z", target[p].z, value, p + "Z");
                } else if (p === "opacity") {
                    m = (target.material.length) ? target.material : [target.material];
                    i = m.length;
                    while (--i > -1) {
                        m[i].transparent = true;
                        this._addTween(m[i], p, m[i][p], value, p);
                    }
                } else if (p === "visible") {
                    if (target.visible !== value) {
                        _addFuncPropTween(tween, _visibleSetter(target, target.visible, value));
                    }
                } else {
                    this._addTween(target, p, target[p], value, p);
                }
                this._overwriteProps.push(p);
            }
            return true;
        }
    });

}); if (_gsScope._gsDefine) { _gsScope._gsQueue.pop()(); }

 

Does that work for you? 

 

Link to comment
Share on other sites

No, that old plugin was for v2 and earlier. In GSAP 3, the plugin architecture has changed.

 

I don't have the time right now to thoroughly dig into creating and testing the GSAP 3 equivalent, but here's some minified code that may do the trick for ya in GSAP 3: 

!function(e,i){"object"==typeof exports&&"undefined"!=typeof module?i(exports):"function"==typeof define&&define.amd?define(["exports"],i):i((e=e||self).window=e.window||{})}(this,function(e){"use strict";function g(){return i||"undefined"!=typeof window&&(i=window.gsap)&&i.registerPlugin&&i}function j(e,i,t){t=!!t,e.visible!==t&&(e.visible=t,e.traverse(function(e){return e.visible=t}))}function k(e){return("string"==typeof e&&"="===e.charAt(1)?e.substr(0,2)+parseFloat(e.substr(2)):e)*t}function l(e){(i=e||g())&&(d=i.core.PropTween,f=1)}var i,f,d,u={x:"position",y:"position",z:"position"},t=Math.PI/180;"position,scale,rotation".split(",").forEach(function(e){return u[e+"X"]=u[e+"Y"]=u[e+"Z"]=e});var n={version:"3.0.0",name:"three",register:l,init:function init(e,i){var t,n,o,r,s,a;for(r in f||l(),i){if(t=u[r],o=i[r],t)n=~(s=r.charAt(r.length-1).toLowerCase()).indexOf("x")?"x":~s.indexOf("z")?"z":"y",this.add(e[t],n,e[t][n],~r.indexOf("rotation")?k(o):o);else if("scale"===r)this.add(e[r],"x",e[r].x,o),this.add(e[r],"y",e[r].y,o),this.add(e[r],"z",e[r].z,o);else if("opacity"===r)for(s=(a=e.material.length?e.material:[e.material]).length;-1<--s;)a[s].transparent=!0,this.add(a[s],r,a[s][r],o);else"visible"===r?e.visible!==o&&(this._pt=new d(this._pt,e,r,o?0:1,o?1:-1,0,0,j)):this.add(e,r,e[r],o);this._props.push(r)}}};g()&&i.registerPlugin(n),e.ThreePlugin=n,e.default=n;if (typeof(window)==="undefined"||window!==e){Object.defineProperty(e,"__esModule",{value:!0})} else {delete e.default}});

Maybe in the future if there's enough demand we'll create an official one. Here's an ES6 Module file that is what the minified ES5 code above was based on (in case it helps): 

 

let gsap, _coreInitted, PropTween,
	_getGSAP = () => gsap || (typeof(window) !== "undefined" && (gsap = window.gsap) && gsap.registerPlugin && gsap),
	_contexts = {x:"position", y:"position", z:"position"},
	_DEG2RAD = Math.PI / 180,
	_setterVisible = (target, property, value) => {
		value = !!value;
		if (target.visible !== value) {
			target.visible = value;
			target.traverse(child => child.visible = value);
		}
	},
	_degreesToRadians = value => ((typeof(value) === "string" && value.charAt(1) === "=") ? value.substr(0, 2) + (parseFloat(value.substr(2))) : value) * _DEG2RAD,
	_initCore = core => {
		gsap = core || _getGSAP();
		if (gsap) {
			PropTween = gsap.core.PropTween;
			_coreInitted = 1;
		}
	};

"position,scale,rotation".split(",").forEach(p => _contexts[p + "X"] = _contexts[p + "Y"] = _contexts[p + "Z"] = p);

export const ThreePlugin = {
	version: "3.0.0",
	name: "three",
	register: _initCore,
	init(target, vars) {
		_coreInitted || _initCore();
		let context, axis, value, p, i, m;
		for (p in vars) {
			context = _contexts[p];
			value = vars[p];
			if (context) {
				i = p.charAt(p.length-1).toLowerCase();
				axis = ~i.indexOf("x") ? "x" : ~i.indexOf("z") ? "z" : "y";
				this.add(target[context], axis, target[context][axis], ~p.indexOf("rotation") ? _degreesToRadians(value) : value);
			} else if (p === "scale") {
				this.add(target[p], "x", target[p].x, value);
				this.add(target[p], "y", target[p].y, value);
				this.add(target[p], "z", target[p].z, value);
			} else if (p === "opacity") {
				m = (target.material.length) ? target.material : [target.material];
				i = m.length;
				while (--i > -1) {
					m[i].transparent = m[i].needsUpdate = true;
					this.add(m[i], p, m[i][p], value);
				}
			} else if (p === "visible") {
				if (target.visible !== value) {
					this._pt = new PropTween(this._pt, target, p, value ? 0 : 1, value ? 1 : -1, 0, 0, _setterVisible);
				}
			} else {
				this.add(target, p, target[p], value);
			}
			this._props.push(p);
		}
	}

};

_getGSAP() && gsap.registerPlugin(ThreePlugin);

export { ThreePlugin as default };

But I have some ideas that'd make the final version likely look different though. I just don't have the time at this point to sink into crafting it all right now. So none of the above code should be considered "official" ;)

 

Does that help at all? 

Link to comment
Share on other sites

  • 1 month later...
22 minutes ago, GreenSock said:

@wpsoul you used the minified code from my last post? Got a codepen demo or something so we can see how you're using it? 

ok, I tested again, it was syntax mistake, I forgot that we have another syntax in GSAP3 and duration must be set inside arguments 

 

I can confirm that it's working with GSAP3, tested opacity, position, scale and rotation. 

 

 

 

  • Like 1
Link to comment
Share on other sites

49 minutes ago, wpsoul said:

ok, I tested again, it was syntax mistake, I forgot that we have another syntax in GSAP3 and duration must be set inside arguments 

No problem. But I'm a bit confused because you actually don't need to set the duration in the vars object if you don't want to - the old syntax should work fine (we try really hard to make legacy code work as much as possible). So either of these should work: 

gsap.to(".class", 2, {x: 100});

// - OR - 

gsap.to(".class", {duration: 2, x: 100});

Anyway, I'm glad you got it working! Thanks for letting us know. 🙌

Link to comment
Share on other sites

  • 1 year later...
6 minutes ago, ZachSaucier said:

Positions in Three.js are an object. GSAP animates objects. So you just need something along the lines of the following:


gsap.to(myObj.position, { x: 3, y: 1, z: 0 });

 

I mean some thing like camera look at i type this but it is doesnot work `gsap.to(camera.lookAt, { x: scene.position.x, y: scene.position.y, z: scene.position.z,`

Link to comment
Share on other sites

1 minute ago, leenalfalah said:

I mean some thing like camera look at i type this but it is doesnot work `gsap.to(camera.lookAt, { x: scene.position.x, y: scene.position.y, z: scene.position.z,`

If you need to update where the camera is looking at, you could use GSAP's ticker or an onUpdate callback of a relevant tween/timeline. It'd probably be better to use an onUpdate unless you have a lot of different tweens/timelines that affect where the camera needs to look.

  • Like 1
Link to comment
Share on other sites

  • 1 year later...
On 8/17/2017 at 5:26 PM, GreenSock said:

I haven't done a ton of testing, but it should support:

...

  • opacity

Indeed, it does work quite well, thanks for putting this together, Jack! One exception is there seems to be an issue with tweening opacity. Scaling position, rotation, scale, and visible all work great. Here is a demo of simultaneously tweening position and rotation on a mesh cube (look in the `configureMesh` method). 

 

Alas, with opacity, something is awry —   put in a `.to()` tween, the material's `opacity` property doesn't actually change (opacity demo — see `configureMesh` method). 

 

However, if a `.fromTo()` tween is used (thus explicitly indicating the start value), the opacity animates as expected (fromTo opacity demo — `configureMesh` method).

 

I stepped through the execution in the debugger but couldn't suss out why things aren't working with opacity in a `.to()` tween. Any ideas?

Link to comment
Share on other sites

Aha, I figured it out. Opacity is on a material. Three.js materials need their `needsUpdate` property set to `true` if they are modified after initialization (docs). As such, changing this line:

 

m[i].transparent = true;

...to the following fixes opacity tweening:

m[i].transparent = m[i].needsUpdate = true;

note that the syntax used there is equivalent to setting  m[i] to true on two separate lines:

m[i].transparent = true;
m[i].needsUpdate = true;

The full code for the plugin including this fix is:

let gsap;
let _coreInitted;
let PropTween;
const _getGSAP = () => gsap ||
    (typeof (window) !== 'undefined' && (gsap = window.gsap) &&
     gsap.registerPlugin && gsap);
const _contexts = {
  x: 'position',
  y: 'position',
  z: 'position',
};
const _DEG2RAD = Math.PI / 180;
const _setterVisible = (target, property, value) => {
  value = !!value;
  if (target.visible !== value) {
    target.visible = value;
    target.traverse((child) => child.visible = value);
  }
};
const _degreesToRadians = (value) =>
  ((typeof (value) === 'string' && value.charAt(1) === '=') ?
         value.substr(0, 2) + (parseFloat(value.substr(2))) :
         value) *
    _DEG2RAD;
const _initCore = (core) => {
  gsap = core || _getGSAP();
  if (gsap) {
    PropTween = gsap.core.PropTween;
    _coreInitted = 1;
  }
};

'position,scale,rotation'.split(',').forEach(
    (p) => _contexts[p + 'X'] = _contexts[p + 'Y'] = _contexts[p + 'Z'] = p);

export const ThreePlugin = {
  version: '3.0.0',
  name: 'three',
  register: _initCore,
  init(target, vars) {
    if (!_coreInitted) {
      _initCore();
    }
    let context;
    let axis;
    let value;
    let p;
    let i;
    let m;
    /* eslint-disable guard-for-in */
    for (p in vars) {
      context = _contexts[p];
      value = vars[p];
      if (context) {
        i = p.charAt(p.length - 1).toLowerCase();
        axis = ~i.indexOf('x') ? 'x' : ~i.indexOf('z') ? 'z' : 'y';
        this.add(
            target[context], axis, target[context][axis],
            ~p.indexOf('rotation') ? _degreesToRadians(value) : value);
      } else if (p === 'scale') {
        this.add(target[p], 'x', target[p].x, value);
        this.add(target[p], 'y', target[p].y, value);
        this.add(target[p], 'z', target[p].z, value);
      } else if (p === 'opacity') {
        m = (target.material.length) ? target.material : [target.material];
        i = m.length;
        while (--i > -1) {
          m[i].transparent = m[i].needsUpdate = true;
          this.add(m[i], p, m[i][p], value);
        }
      } else if (p === 'visible') {
        if (target.visible !== value) {
          this._pt = new PropTween(
              this._pt, target, p, value ? 0 : 1, value ? 1 : -1, 0, 0,
              _setterVisible);
        }
      } else {
        this.add(target, p, target[p], value);
      }
      this._props.push(p);
    }
  },
};

_getGSAP() && gsap.registerPlugin(ThreePlugin);

export {ThreePlugin as default};

 

  • Like 1
Link to comment
Share on other sites

  • 2 weeks later...
On 3/18/2018 at 10:35 AM, Dipscom said:

I would like to welcome the two of you to the Shock 'n Awe Club - Which I am the president.

 

We do a lot of skulking around and a lot of falling off our chairs by simply reading the posts here.

Where can I apply for membership? (I'll make an exception to my deeply rooted Groucho Marx conundrum in this case I guess.)

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...