I'm posting this with an assumption that the JsFiddle is missing something since it throws a "setTween is not a function" error. But given your code...
What you really want is a factory object, which gets provided some config data. Perhaps something in this format:
{
"tween": {
"duration": 0.7,
"options": {
"opacity": 0
}
},
"scene": {
"options": {
"triggerHook": "onEnter",
"offset": 500,
"reverse": true
}
}
}
Let's just call this "animation factory" AnimationFactory
:
function AnimationFactory() {
this.controller = new ScrollMagic.Controller();
this.scenes = [];
}
AnimationFactory.prototype = {
controller: null,
scenes: null,
constructor: AnimationFactory,
createAnimation: function(element, args) {
element = typeof element === "string"
? document.getElementById(element)
: element;
var tween = TweenMax.to(element, args.tween.duration, args.tween.options),
scene = new ScrollMagic.Scene(args.scene.options);
scene.setTween(tween)
scene.addTo(this.controller)
scene.addIndicators();
this.scenes.push(scene);
return this;
}
};
Then to use it:
var animationFactory = new AnimationFactory();
window.onload = function() {
animationFactory
.createAnimation("animation1", {
tween: {
duration: 0.7,
options: {
opacity: 1
}
},
scene: {
options: {
offset: 200,
reverse: true
}
}
})
.createAnimation( ... );
};
Not you've got a nice clean API to use. But you said there are 50 of them on the page, and I imagine that number could change. Additionally, you have a disconnect between the animations and the elements that require them. Why not marry the two in wedded bliss using HTML5 custom data attributes?
function AnimationFactory() {
this.controller = new ScrollMagic.Controller();
this.scenes = [];
}
AnimationFactory.prototype = {
controller: null,
scenes: null,
constructor: AnimationFactory,
createAnimation: function(element, args) {
...
},
createAnimations: function(element) {
var tween = null,
scene = null,
elements = element.querySelectorAll("[data-animation]"),
i = 0,
args;
for (i; i < elements.length; i++) {
args = JSON.parse(elements[i].getAttribute("data-animation"));
this.createAnimation(elements[i], args);
}
}
};
And to use this:
var animationFactory = new AnimationFactory();
window.onload = function() {
animationFactory.createAnimations(document.body);
};
And a little HTML for good measure:
<h1 data-animation='{
"tween": {
"duration": 0.7,
"options": {
"opacity": 1
}
},
"scene": {
"options": {
"offset": 200,
"reverse": true
}
}
}'>Animation 1</h1>
<h1 data-animation='{
"tween": {
"duration": 0.7,
"options": {
"opacity": 0
}
},
"scene": {
"options": {
"triggerHook": "onEnter",
"offset": 500,
"reverse": true
}
}
}'>Animation 2</h1>
This gives you unlimited potential. The configs for creating the animations are embedded right in the markup. If different pages had different animations, no need to keep different JavaScript files around. Every page can be different.
Since the AnimationFactory
encapsulates all of the animations, you can tweak the work flow behind the scenes if you run into performance problems, like staggering the creation of the Tween
s so you don't have 50 opacity tweens run all at once on the page (which I image might draw enough electricity from the CPU to power a small Tesla).
If you AJAX in some HTML, then insert it into a DIV after page load, the AnimationFactory#createAnimations
method can be called, and pass in the HTML element that just had its innerHTML
replaced and you'll get animations after AJAX, not just on page load.
// xhr is an XMLHttpRequest object that just got some HTML from the server
var div = $("#someDiv").html(xhr.responseText);
animationFactory.createAnimations(div[0]);
ScreenMagic.Scene
doesn't have asetTween
method at all. I verified that in the browser with Firefox. \$\endgroup\$