Jump to content
Randall

Example: HTML Banner using Greensock JS Beta

Recommended Posts

Attached to this post is a super simple (non-optimized/minified for tutorial purposes!) HTML banner example using the Greensock JS Beta animation platform. This does not use HTML5...though it easily could.

 

There will be a lot of work (and money spent - hopefully earned by us) converting Flash banners to HTML/CSS/JavaScript in the next 1-2 years so my challenge (to myself and any other Flash/JavaScript developers) is to get up to speed quickly and see how easy it really is. The best part is, jQuery (or other framework) is NOT required, though I suppose in enhanced rich media banners that jQuery may be utilized if it already exists within the container page holding the ad, which most certainly is the case with most media advertising outlet sites serving up the ads.

 

The only real issue might be file size for all of the combined assets. I predict that the change will come soon within the industry as "they" realize 20-30k more in file size is acceptable to reach nearly 100% of all devices by using straight HTML/CSS/JavaScript as an alternate to using Flash. In fact, I personally believe the 'alternate static image' scenario will be like an 8 track cassette tape someday...a thing of the past and funny conversational topic for old schooler's such as myself, where the 'alternate' will soon be the fully animated HTML/CSS/JavaScript version of the same Flash banner.

 

Static example:

banner.zip

// TWEEN RELATED CODE
function getElem(id){ return document.getElementById(id); }
var seq = new TimelineLite();
seq.append( TweenLite.from(getElem('prg_bannerBg'), 1, {css:{alpha:0}}) );
seq.append( TweenLite.from(getElem('prg_bannerChic'), 0.3, {css:{alpha:0, left:310}}) );
seq.append( TweenLite.from(getElem('prg_bannerTitle'), 0.4, {css:{left:-300}}) );
seq.append( TweenLite.from(getElem('prg_bannerSubTitle'), 0.3, {css:{left:-300}}) );
seq.append( TweenLite.from(getElem('prg_bannerZipCodeInput'), 0.2, {css:{left:-300}}) );
seq.append( TweenLite.from(getElem('prg_bannerZipCode'), 0.2, {css:{left:-300}}) );
seq.append( TweenLite.from(getElem('prg_bannerButton'), 0.4, {css:{top:260}}) );
seq.play();

 

Dynamic example:

banner2.zip

// TWEEN RELATED CODE
function getElem(id){ return document.getElementById(id); }
var scon = getElem('bg1');
var stars = [];
var sCnt = 0;
function star(x,y){
scon.innerHTML += '<img id="star'+sCnt+'" src="star.png" style="position:absolute; left:'+x+'px; top:'+y+'px;" />';
sCnt++;
stars.push('star'+sCnt);
}
function makeStars(){
var i = 0;
var max = 40;
for(i = 0; i < max; i++){
	star( Math.floor(Math.random()*300) , Math.floor(Math.random()*140) ) ;
}
setTimeout('tweenStars()', 200);
}
function tweenStars(){
var i = 0;
var max = stars.length - 1;
var dur = 8;
var tog = true;
var s = null;
for(i = 0; i < max; i++){
	tog = !tog;
	TweenLite.to(getElem(stars[i]), (dur + Math.floor(Math.random()*12)), { css:{rotation:(tog == true ? 720 : -720)} });
}
}
makeStars();
var seq = new TimelineLite();
seq.append( TweenLite.from(getElem('bg1'), 1, {css:{alpha:0}}) );
seq.append( TweenLite.from(getElem('www'), 0.8, {css:{alpha:0}}) );
seq.append( TweenLite.from(getElem('com'), 0.8, {css:{alpha:0}}) );
seq.append( TweenLite.from(getElem('title'), 0.7, {delay:0.4, css:{alpha:0}}) );
seq.append( TweenLite.from(getElem('bg2'), 1.1, {delay:1.5, css:{top:310}}) );
seq.append( TweenLite.from(getElem('tag'), 0.7, {css:{left:-310}}) );
seq.append( TweenLite.from(getElem('ysb'), 0.6, {css:{top:310}}) );
seq.append( TweenLite.from(getElem('reg'), 0.7, {css:{top:310}}) );
seq.play();

 

Interactive example:

bannerInteractivity.zip

// TWEEN RELATED CODE
// wrapper function for element selector (could use jQuery here, but that adds more file size)
function getElem(id){ return document.getElementById(id); }
var seq = new TimelineLite();
seq.append( TweenLite.from(getElem('prg_container'), 0.6, {css:{alpha:0}}) );
seq.append( TweenLite.from(getElem('prg_logo'), 0.4, {css:{alpha:0, left:200}}) );
seq.append( TweenLite.from(getElem('prg_track'), 0.1, {css:{alpha:0}}) );
seq.append( TweenLite.from(getElem('prg_btnl'), 0.1, {css:{alpha:0}}) );
seq.append( TweenLite.from(getElem('prg_btnr'), 0.1, {css:{alpha:0}}) );
seq.append( TweenLite.from(getElem('prg_drag'), 0.2, {css:{alpha:0}}) );
seq.append( TweenLite.from(getElem('prg_bg2'), 0.2, {css:{alpha:0, top:310}}) );
seq.append( TweenLite.from(getElem('prg_zip'), 0.2, {css:{alpha:0, left:-200}}) );
seq.append( TweenLite.from(getElem('prg_btn'), 0.2, {css:{alpha:0, left:310}}) );
seq.append( TweenLite.from(getElem('prg_g1'), 0.4, {css:{alpha:0, top:300}}) );
seq.append( TweenLite.from(getElem('prg_tag1'), 0.4, {css:{alpha:0}}) );
seq.append( TweenLite.to(getElem('prg_tag1'), 0.4, {delay:0.5, css:{alpha:0}}) );
seq.append( TweenLite.to(getElem('prg_drag'), 0.5, {css:{left:110}, onComplete:function(){getElem('prg_val').value = "$50";}}) );
seq.append( TweenLite.from(getElem('prg_tag2'), 0.4, {css:{alpha:0}}) );
seq.append( TweenLite.to(getElem('prg_tag2'), 0.4, {delay:0.7, css:{alpha:0}}) );
seq.append( TweenLite.to(getElem('prg_drag'), 1, {css:{left:210}, onComplete:function(){getElem('prg_val').value = "$150";}}) );
seq.append( TweenLite.from(getElem('prg_tag3'), 0.4, {css:{alpha:0}}) );
seq.append( TweenLite.to(getElem('prg_tag3'), 0.4, {delay:0.7, css:{alpha:0}}) );
seq.append( TweenLite.to(getElem('prg_g1'), 0.2, {css:{alpha:0, left:-220}}) );
seq.append( TweenLite.from(getElem('prg_g2'), 0.2, {css:{alpha:0, left:-220}}) );
seq.append( TweenLite.from(getElem('prg_tag4'), 0.4, {css:{alpha:0}}) );
seq.append( TweenLite.to(getElem('prg_drag'), 0.8, {css:{left:160}, onComplete:function(){getElem('prg_val').value = "$100"; initInteractivity();}}) );
seq.play();
// store some global variables for the interactivity elements (could also nest this inside an object/class to avoid conflicts on container page)
var btnLeft = getElem('prg_btnl');
var btnRight = getElem('prg_btnr');
var dragger = getElem('prg_drag');
var dragVal = getElem('prg_val');
var amount = 5;
function updateDraggerDollars(){
   var x = parseInt(dragger.style.left);
   dragVal.value = "$" + (x - 60);
   setTimeout('updateDraggerDollars()', 100);
}
function initInteractivity(){
   btnLeft.onclick = tweenDraggerLeft;
   btnRight.onclick = tweenDraggerRight;
}
function tweenDraggerLeft(event){
   var x = parseInt(dragger.style.left);
   if(x > 112){TweenLite.to(dragger, 0.3, {css:{left:(x - amount)}, overwrite:true});}
}
function tweenDraggerRight(event){
   var x = parseInt(dragger.style.left);
   if(x < 207){TweenLite.to(dragger, 0.3, {css:{left:(x + amount)}, overwrite:true});}
}
updateDraggerDollars(); // sets up polling to update the $dollars as the dragger is tweened 

 

By the way, the specs for the original Flash version of this banner were 35k for example #1 and #2, and 60K for example #3. We've exceeded that by quite a bit (almost +30k), maybe not as much if the server sends the stuff GZipped. The payoff is that it works on all modern browsers/devices if JavaScript is enabled.

  • Like 4

Share this post


Link to post
Share on other sites

Just so everyone knows. This post by Randall is awesome.

  • Like 1

Share this post


Link to post
Share on other sites

Yes, indeed, this whole thread is awesome. Lots of real world example usefulness here. Also the snorkl.tv example (only thing else we could've asked for is some code to check out - but suspect you'll have more samples to come :). Anyway, thanks guys!

 

I've also been experimenting making simple banner ad examples using the different JS tweening options out there. Seems so far already that Greensock is the most robust and actually meant for these types of animations.

  • Like 1

Share this post


Link to post
Share on other sites

Hi jayy,

 

Glad you are excited about GSAP12 js and are enjoying stuff from Randall and I. I zipped up all the files for the htcBanner demo for you (see attached).

 

I didn't post them to snorkl.tv as that demo was meant to focus more on the visual output and potential of the platform than the "how it was made" side. I'm kind of hacking my way through the css/js side of things so I didn't want to unleash a mess upon a bunch of folks.

 

Feel free to poke through the files. If you have been using TimelineLite with Flash and have a little jQuery knowledge you should be able to make some sense of what is going on.

 

Will certainly be making more demos and sharing more code in the future.

 

Thanks again for your interest.

 

Carl

htcBanner_GSAP.zip

  • Like 2

Share this post


Link to post
Share on other sites

Below is another example of an expandable all-HTML banner that uses GSAP for all animations/interactivity. Note that jQuery is NOT being used here, thus saving a lot of kb. Instead, we use a jQuery-like wrapper function nested in a class for a similar syntax on selecting elements.

 

http://www.rhaws.com/banners/GM.html

[user=rhaws pass=guest]

 

And here's the code snippet for just the animation portion using GSAP for this example:

// dynamically create unique selector IDs to ensure they never pose a conflict on the page
var X = 'gm__', // set prefix for all id selectors
Z = new Date().getTime(),
sc = X + ++Z,
v1 = X + ++Z,
v1T = X + ++Z,
v2 = X + ++Z,
v2T = X + ++Z,
v3 = X + ++Z,
v3T = X + ++Z,
v4 = X + ++Z,
v4T = X + ++Z,
Lg = X + ++Z,
LgT = X + ++Z,
Fc = X + ++Z
;// end vars declaration chain
/*
code removed that creates DIV elements for all of the vars above that are tweened below
*/
function jQueryWrapper(){
// public method exposed similar syntax to jQuery id only selector (no # sign needed)
this.$ = function(selector){
	var doc = window.document;
	return doc.getElementById(selector);
};
}
// create new instance of jQuery-like selector wrapper function
var _$ = new jQueryWrapper();
// separate tween on the main container background to scroll it upwards
TweenLite.to(_$.$(sc), 9, {css:{backgroundPosition:'0px -130px'}});
// a linear approach to the seq chain - not dynamic or 'smart', just for example purposes
var T = new TimelineLite();
 T.from(_$.$(v1), 0.5, {css:{alpha:0}})
  .from(_$.$(v1T), 0.2, {css:{alpha:0, left:'-220px'}})
  .to(_$.$(v1), 0.5, {delay:1.5,css:{alpha:0}}) // delay here creates the pause between frames
  .to(_$.$(v1T), 0.2, {css:{alpha:0, top:'260px'}})
  .from(_$.$(v2), 0.5, {css:{alpha:0}})
  .from(_$.$(v2T), 0.2, {css:{alpha:0, left:'-220px'}})
  .to(_$.$(v2), 0.5, {delay:1.6,css:{alpha:0}}) // delay here creates the pause between frames
  .to(_$.$(v2T), 0.2, {css:{alpha:0, top:'260px'}})
  .from(_$.$(v3), 0.5, {css:{alpha:0}})
  .from(_$.$(v3T), 0.2, {css:{alpha:0, left:'-220px'}})
  .to(_$.$(v3), 0.5, {delay:1.7,css:{alpha:0}}) // delay here creates the pause between frames
  .to(_$.$(v3T), 0.2, {css:{alpha:0, top:'260px'}})
  .from(_$.$(v4), 0.5, {css:{alpha:0}})
  .from(_$.$(v4T), 0.2, {css:{alpha:0, left:'-220px'}})
  .to(_$.$(v4), 0.7, {delay:1.8,css:{alpha:0}}) // delay here creates the pause between frames
  .to(_$.$(v4T), 0.2, {css:{alpha:0, top:'260px'}})
  .to(_$.$(sc), 0.7, {css:{backgroundPosition:'0px -260px'}}) // now tween bg within the chain
  .from(_$.$(Lg), 0.3, {css:{alpha:0, top:'-80px'}})
  .from(_$.$(LgT), 0.2, {css:{alpha:0, top:'310px'}})
  .from(_$.$(v5), 0.4, {css:{alpha:0, top:'310px'}})
  .from(_$.$(Fc), 0.3, {css:{alpha:0, top:'310px'}}) // end of animation, expandable button is now available for further interactivity
;// end T chain

GSAP is so awesome!

  • Like 3

Share this post


Link to post
Share on other sites

Wow, that's really a very good example on how far Javascript/HTML/CSS, mixed with a bit of Greensock sweetness can go in replicating the same features that only Flash ads could do previously. Probably takes a bit longer to create than a Flash equivalent, but still..

 

An expanding ad with animation, an integrated gallery, rotations, external link, etc. Like a microsite within an ad format. Good find!

  • Like 2

Share this post


Link to post
Share on other sites

AND the original Flash version of that GM banner was a whopping ~3.75Mb across 12 dynamically loaded SWF files. The HTML banner version is only around ~683k and took just 6 hours to convert from its original Flash 8 AS2 FLA.

 

"Greensock sweetness..." - best quote of the day heyitsjayy

  • Like 2

Share this post


Link to post
Share on other sites

Here's another example where a banner element pops out (pseudo expanded) on the page. Same login info (see above). http://www.rhaws.com...ners/PUFFS.html

 

TWEEN CODE SNIPPET:

//Note:  jb var holds the main banner code and setup stuff
// ids in array point to the PNG image sequence for the character animation
jb.chars = [ci1,ci2,ci3,ci4,ci5,ci6,ci7,ci8,ci9,
 ci10,ci12,ci11,ci10,ci11,ci12,ci13,ci14,ci15,
 ci14,ci15,ci14,ci15,ci16,ci17,ci18
];;
function initCharacter(){
jb.$(jb.chars[jb.cFrame]).style.opacity = '0';
jb.startCharacter();
}
jb.ti = ti; // special scope var for tissue image reference
jb.cFrame = 1;
jb.mFrame = jb.chars.length;
jb.startCharacter = function(){
jb.$(jb.chars[(jb.cFrame - 1)]).style.opacity = '0'; // hide previous frame
jb.cFrame++; // increment PNG sequence frame number
if(jb.cFrame == 6){ // special frame bookmark to time tissue removal below
	// remove tissue from box to match PNG sequence frame image
	TweenLite.to(jb.$(jb.ti), 0.05, {css:{y:'+22'}});
}
if(jb.cFrame <= jb.mFrame){
	if(jb.cFrame != jb.mFrame){
		jb.$(jb.chars[(jb.cFrame - 1)]).style.opacity = '1'; // show current frame
		setTimeout('jb.startCharacter()', 88);
	}else{
		//end animation
		jb.$(jb.chars[(jb.cFrame - 1)]).style.opacity = '1'; // show current frame
		// put tissue back in box
		TweenLite.to(jb.$(jb.ti), 0.3, {delay:0.3, css:{y:'-1'}});
	}
}
}
// ids below use same metho as previous example in this thread; jQuery-like wrapper
var T = new TimelineLite(); // a linear approach to the chain
  T.from(jb.$(bc), 0.5, {css:{alpha:0}})
.from(jb.$(lc), 0.5, {css:{alpha:0, y:-80}})
.from(jb.$(bi), 0.4, {css:{alpha:0, x:310}})
.from(jb.$(ti), 0.2, {css:{alpha:0, y:'+22'}})
.from(jb.$(ci1), 0.5, {css:{x:-100}})
.from(jb.$(tx1), 0.5, {css:{alpha:0}, onComplete:initCharacter})
.from(jb.$(tx2), 0.5, {delay:1, css:{alpha:0}}) // tag text with delay
.from(jb.$(btn), 0.5, {css:{alpha:0, y:601}})// ending click button
;// end T chain

Note, the size of this banner example could be reduced by another 150k by chopping up the character to arms, body, head, legs and so on and then animating them independently with joint-type effects. For example purposes, a PNG sequence is used to make the animation effect where this example has a total of 18 rendered PNG frames and thus that is why the total file size is larger.

Share this post


Link to post
Share on other sites

Nice job, Randall.

 

Just one thing I'd mention: I noticed that you're using this code to hide things:

jb.$(jb.chars[jb.cFrame]).style.opacity = '0';

As far as I know, that won't work in IE8 and below. You must use an IE-only filter:alpha(opacity=0). Annoying, I know. But you could also just do a TweenLite.set() to make the opacity 0 because it automatically implements some code workarounds internally like the IE filter stuff.

 

Again, nice job and thanks for sharing!

  • Like 1

Share this post


Link to post
Share on other sites

Oh yeah, I see that now. Oh how I dislike the IE browser. I keep forgetting you have those internal checks going on along with the workarounds. Great tip on the set() method, thank you!

Share this post


Link to post
Share on other sites

So one must wonder when the mass of these banner ads will start being done in HTML/javascript.. are bigger agencies, and big clients wanting these right now? Or is that a bit in the future yet.

 

Either way, these are great examples!

Share this post


Link to post
Share on other sites

Just re-visiting this topic again, and continue to be impressed at the solutions that people have come up so far to made great banner animations, yet keep the file size in tact.

 

The jQueryWrapper selector paired with Greensock JS is impressive.

 

Has anyone come across any other recent banner style ads with Greensock JS style animation lately?

Share this post


Link to post
Share on other sites

I apologize that I am new to all of this code, most of it is beyond me. I wanted to use this for HTML 5 /JavaScript banner ads but it seems none of the sample code here, which is fantastic, didn't include the necessary code to make the ads clickable so the viewer is transported to the advertisers site. I love the effects you can do with greensock, I just wish it was easier to use. 

 

Bob

Share this post


Link to post
Share on other sites

Hi and welcome to the forums.

 

Yes unfortunately knowing at least the basis of javascript and/or JQuery is needed to do that, although is not much what you'll need in order to achieve that result.

 

There is one online tool that you should take a look at, is, as far as I know, the only WYSIWYG Greensock JS editor and is created with banners in mind and is also cross-platform which is very cool for this device era:

http://html5maker.com/

 

Also take a look at this post, there are some pointers about starting with Javascript and JQuery:

http://forums.greensock.com/topic/7311-getting-started-or-not/

 

And finally if more questions arise just keep asking.

 

Hope this helps,

Cheers,

Rodrigo.

  • Like 1

Share this post


Link to post
Share on other sites

I did get Greensock to work shortly after posting my observation, just to set the record straight.

 

Bob

  • Like 1

Share this post


Link to post
Share on other sites

Hi rhernando,

 

I just wanted to point out that there are at least *two* online WYSIWYG tools for creating animations with greensock js. :)

 

Check out our tool at http://tweenui.com/animator

 

Any feedback would be very welcome. 

 

Thanks,

Erik

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.