Jump to content
Search Community

Randall last won the day on May 11 2014

Randall had the most liked content!

Randall

Members
  • Posts

    41
  • Joined

  • Last visited

  • Days Won

    6

Everything posted by Randall

  1. Carl, you have yourself a pretty sweet and rockin' example out there too: http://www.snorkl.tv...red-javascript/
  2. 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.
  3. And, if you for some reason don't want the jQuery ui version, or even a custom jQuery version where you do your own drag code, here's a minimalist example of drag-n-drop that you can start with. The only trick is to ensure your mouseup and mouseout events ARE handled somewhere in the scope for cases where the mouse leaves the target (AKA currently dragging) element. Think about it in terms of ActionScript, where when things are dragged quickly and off the stage, etc. certain mouse events may not fire that you intend once the dragging is supposed to stop. It pretty much works the same for the most part in JavaScript, though I like to use window events for mouseup most of the time so I can be certain a drag stop event handler fires off reliably drag-n-drop.zip <!-- you may need to change the path to your Greensock script files --> <script src="uncompressed/easing/EasePack.js"></script> <script src="uncompressed/plugins/CSSPlugin.js"></script> <script src="uncompressed/TweenLite.js"></script> <div id="containerDrag" style="position:absolute; width:50px; height:50px; left:0px; top:0px; background-color:#ccc; cursor:pointer;"></div> <script> var dragContainer = document.getElementById('containerDrag'); function startDrag(event){ event.preventDefault(); dragContainer.onmousedown = null; window.onmousemove = doDrag; window.onmouseup = stopDrag; } function stopDrag(event){ window.onmousemove = null; window.onmouseup = null; dragContainer.onmousedown = startDrag; } function doDrag(event){ var xOffset = event.pageX - 25; var yOffset = event.pageY - 25; TweenLite.to(dragContainer, 0.5, { css:{left:xOffset, top:yOffset}, overwrite:true } ); } dragContainer.onmousedown = startDrag; </script>
  4. Randall

    Mouse Events

    General rule of thumb, is place your Tween related stuff within the function/methods scope that are assigned to or are invoked from within other methods or event handlers. There is what's known as a 'literal' approach where you declare objects/functions on the fly 'literally with no name reference' and then there is the more refined approach of named or referenced objects where you declare (or nest) the the object within another object's scope. To illustrate, see the three examples below. A mix of these examples is what most developers are resolved to use because of time and complexity, but ideally, the named approach where you can control 'scope' of the objects and their named properties/methods, etc. is a more robust and trouble-free solution. It also ensures more readable and compact events code and logic for objects/elements that might have a lot going on, especially if doing custom drag-n-drop stuff. EXAMPLE LITERAL SCOPE #1: <canvas id="myCanvas" style="position:absolute; width:400px; height:150px; left:0px; top:0px; background-color:#CCCCCC; cursor:pointer;"></canvas> <script> // this is generally considered a "global" scope property var canvas = document.getElementById("myCanvas"); // set the onclick handler to the canvas element in the "global" scope by way of a 'literal' function object declartion (un-named) canvas.onclick = function(){ TweenLite.to(canvas, 0.4, {css:{left:'+=20', top:'+=20'}}); }; // each click on the canvas "invokes" animate method </script> EXAMPLE OOP #2 (mixed scopes): <script> // this is generally considered a "global" scope property var canvas = document.getElementById("myCanvas"); // this is generally considered a "global" scope class reference to the AnimateClass object var animateClass = new AnimateClass(); // this is generally considered a "global" scope class (also a method) because it requires instantiation (the new keyword) function AnimateClass(){ // this property is public once AnimateClass is instantiated this.tweenCount = 0; // a number property // this method is public once AnimateClass is instantiated this.animate = function(){ // invokes the TweenLite method to() with the pertinent CSS properties to animate TweenLite.to(canvas, 0.4, {css:{left:'+=20', top:'+=20'}}); this.tweenCount++; // increments the tween count to keep track of how many times clicked }; } // this is generally considered a "global" scope method that is not instantiated but merely invoked function animate(event){ // new AnimateClass scope is now instantiated into the animateClass property animateClass.animate(); // simply invoke the animateClass.animate() method to fire off the tween } // set the onclick handler to the canvas element in the "global" scope canvas.onclick = animate; // each click on the canvas "invokes" animate method </script> EXAMPLE OOP #3 (contained scope): <canvas id="myCanvas" style="position:absolute; width:400px; height:150px; left:0px; top:0px; background-color:#CCCCCC; cursor:pointer;"></canvas> <script> // this is generally considered a "global" scope class (also a method) because it requires instantiation (the new keyword) function AnimateClass(){ // this property is public once AnimateClass is instantiated and holds a reference to the canvas element this.canvas = document.getElementById("myCanvas"); // this property is public once AnimateClass is instantiated this.tweenCount = 0; // a number property // this method is public once AnimateClass is instantiated this.animate = function(event){ // invokes the TweenLite method to() with the pertinent CSS properties to animate TweenLite.to(animateClass.canvas, 0.4, {css:{left:'+=20', top:'+=20'}}); this.tweenCount++; // increments the tween count to keep track of how many times clicked }; } // this is generally considered a "global" scope class reference to the AnimateClass object var animateClass = new AnimateClass(); // set the onclick handler to the canvas element in the "animateClass" class object scope animateClass.canvas.onclick = animateClass.animate; // each click on the canvas "invokes" animateClass.animate method As you can see, the #1 literal approach is a lot less code, which is fine for small and simple integrations. However, as you start getting more complex with the interactivity, you can probably see the advantages of creating objects to hold your tween logic and to have a more reliable location to update in one or two places as opposed to all over the place searching for 'un-named' literal functions (AKA anonymous functions). I personally favor the "composition" approach, where some of the key properties and methods are in the global scope and then I have other objects (like classes and nested properties/methods within those classes) handle the more complex tweening.
  5. Randall

    Html5 Canvas

    This might be an approach for example purposes, not for real live production, assuming you meant to tween the canvas as a whole: <canvas id="myCanvas" style="position:absolute;"></canvas> <script> var canvas = document.getElementById("myCanvas"); var context = canvas.getContext("2d"); function animate(myRectangle){ context.beginPath(); context.rect(myRectangle.x, myRectangle.y, myRectangle.width, myRectangle.height); context.fillStyle = "#8ED6FF"; context.fill(); TweenLite.to(canvas, 1.5, {css:{left:'100px', top:'200px'}}); } function doAnimation(){ var theRectangle = { x: 0, y: 50, width: 100, height: 100 }; var date = new Date(); var time = date.getTime(); animate(theRectangle); }; setTimeout('doAnimation()', 2000); </script> If you want to animate/move individual elements within the canvas, then it gets more complex/tedious, but it's not that daunting. There's a cool tutorial here http://simonsarris.c...5-canvas-useful that explains some traditional moving of elements on the canvas. As for tweening elements in the canvas, I've not yet worked that out to any degree of reliability. And, here http://lamberta.org/doodle-js/ is another variation of animating on the HTML5 canvas - perhaps the Greensock JS Animation Platform could be integrated just as well in similar fashion?
  6. Randall

    parallax scrolling

    Great, I can now pull one of my feet out of the grave I was digging for myself!
  7. Randall

    Tween Nano

    I have wondered about this too, because there is a trend now with rich media ad units, that are non-Flash banners and only HTML/JavaScript, that restrict the included JavaScript code size to less than 35k or even smaller. Granted, 30k-35k of minified JavaScript is quite a lot of code, but I wonder if there's a hybrid approach where perhaps a hybrid minified JavaScript include file could have a couple of ease types, the basic stock CSS tweenable props and of course the core nano tween engine? Currently, file size is sitting at: ~3.9k for EasePack.min.js ~20.0k for TweenLite.min.js ~12.8k for CSSPlugin.min.js Total ~36.8k +/- Unless the nano version can be crunched down to 20k or less and still perform up to the par standard, it's probably not a worthwhile conversion/endeavor. I'm happy just knowing that for less than ~40k, the base minified animation platform as it stands now is super swanky and solid.
  8. Randall

    processing js

    That's a tricky one because the draw method in processing.js is continuously called and is generally only controlled by noLoop(), redraw(), loop(), or if the program is stopped completely. I would think though, you could 'parameterize' the variables that the draw method references and externally check them with Tween-related logic that responds accordingly based on the values, or even sets values for any given reason. Perhaps even setting left/right boundaries in variables that trigger 'Tweens' to do stuff in conjunction with or independently of whatever the draw method loop executes. One example might be if you're tracking the yPos variable in the application scope and the draw method does something like yPos += 1 and then externally you have a check that when the yPos is say greater than 200, you TweenLite.to back to yPos = 0 (possibly setting a flag toggle that the draw method stops adding 1 to the yPos while tweening back to 0) and then use the TweenLite onComplete to set back the flag toggle back and thus create a unique effect of some element moving down 1 step every draw loop and then tweens back to 0 and starts the process all over again.
  9. Randall

    Query engine

    I'm working on mobile JavaScript menu and not using jQuery. The only trick is to ensure that you tween valid objects/elements. In the case where you use associative type selectors (those that require some engine or logic to 'acquire' a reference to the object/element) you just have to make sure you pass in a valid object/element. So, like in Flash, you can refer to an object via an associative nature: // IF someMovieClipName instance name exists in this, it works TweenLite.to(this['someMovieClipName'], 1, {prop:value}); In JavaScript, without a selector engine finding the object/element reference, you'll like need to create a wrapper function yourself that gets it, or leverage whatever engine you're using and then pass that object/element reference into the tween, such as with jQuery selectors, which makes things super easy by $('#someElementId'). // PROBABLY WON'T WORK TweenLite.to('someElementName', 1, {css:{prop:value}}); // PROBABLY WILL WORK, IF THE 'someElementName' EXISTS function getInstance(idSelector){ return document.getElementById(idSelector); } TweenLite.to(getInstance('someElementName'), 1, {css:{prop:value}}); // OR ALTERNATIVELY, USE VARIABLE HOLDERS IN THE APPLICATION SCOPE var theElement = document.getElementById('someElementName'); TweenLite.to(theElement, 1, {css:{prop:value}});
  10. There's sort of a workaround, though it is quite ugly, where you set the CSS properties for mouse/pointer events to none at the end of the tween. There's probably a better way to achieve that with 100% reliability though so you don't have to keep track of the pointer/mouse state of the element.
  11. There's also a post in another area of the forum about the ActionScript to JavaScript stuff, where there's a starter template for simulating a type of 'class' structure - may or may be applicable, but there are some additional links in that thread that are well worth a read through. http://forums.greens...dpost__p__21263
  12. Randall

    parallax scrolling

    Pretty much just a base starter example of the concept behind the parallax. Sorry everyone, I didn't include all of the necessary imports [CSSPlugin.js was required too]. A new ZIP is attached below and the code updated in my earlier post. Just throw the Greensock files in the appropriate js/greensock/ folder and you should be good to go. parallax.zip
  13. Randall

    parallax scrolling

    Yes! It's totally possible. In fact, with most jQuery parallax type plugins/fx you can merely substitute the jQuery animation calls with TweenLite/TweenMax calls and have better/smoother performance all the way around. The main thing to work out is the math of the layers from back to front and their max widths in relation to the left/right movement or parallax effect. In this example, it's simple hard-coded values, but can easily be made 'dynamic' with a little math work on the layers. Here's my starter parallax JS Code that uses simple TweenLite calls. parallax.zip <!-- Assumes jQuery is loaded first! --> <script type="text/javascript" src="js/jQuery/jquery-1.7.2.min.js"></script> <script type="text/javascript" src="js/greensock/easing/EasePack.js"></script> <script type="text/javascript" src="js/greensock/plugins/CSSPlugin.js"></script> <script type="text/javascript" src="js/greensock/TweenLite.js"></script> <script type="text/javascript" > function doParallax(){ var backLayer = document.getElementById('depthB'); var middleLayer = document.getElementById('depthM'); var frontLayer = document.getElementById('depthF'); $('#viewPort').mousemove( function(event){ var bMouse = event.pageX / 7.7; TweenLite.to(backLayer, 1, { css:{left:'-' + bMouse + 'px'}, overwrite:true } ); var mMouse = event.pageX / 2.5; TweenLite.to(middleLayer, 1, { css:{left:'-' + mMouse + 'px'}, overwrite:true } ); var fMouse = event.pageX / 1.4; TweenLite.to(frontLayer, 1, { css:{left:'-' + fMouse + 'px'}, overwrite:true } ); } ); } setTimeout('doParallax()', 2000); </script> <!-- sample html for above --> <div id="viewPort" style="position:absolute; border-style:solid; border-color:#FF0000; border-width:thin; width:700px; height:170px; z-index:4; left:0px; top:15px;">View Port</div> <div id="depthB" style="position:absolute; background-color:#666666; width:794px; height:200px; z-index:3; left:0px; top:0px; opacity:0.2;">Layer Back</div> <div id="depthM" style="position:absolute; background-color:#888888; width:982px; height:150px; z-index:2; left: 0px; top: 50px; opacity:0.2;">Layer Middle</div> <div id="depthF" style="position:absolute; background-color:#bbbbbb; width:1202px; height:100px; z-index:1; left: 0px; top: 100px; opacity:0.2;">Layer Front</div>
  14. Just ran into something that hopefully would be an easy new feature tweak...with regards to external data files (containing text) with odd and uncommon file extensions. I have this game that loads a .lmz file, which is nothing more than a simple text file with an uncommon file extension that contains the special delimited game data in a compressed tabular format. If we could set a property inside a TXTLoader class indicating that the file to be loaded should be treated as 'text' despite not having a .txt file extension, then we could have the ability to load various text related files (with any extension) and simply return the loaded contents as a raw text string. I saw another post regarding supporting CSS files http://forums.greensock.com/viewtopic.php?f=6&t=2908. Since CSS text files are style sheet related and parsed, perhaps CSS files would then be the only exception to what I'm proposing? LoaderMax is about to become the 800 lb gorilla of loaders in the room.
  15. First off, fantastic job on this Jack! Great work as always and I'm glad to see some similar loading features that I've used in the past finally make it into your platform. What follows is more likely a request for features instead of a specific bug or other problem. After several tests, loading every possible file type for an externally loaded asset, I noticed that there were error events (though they were handled in the bundled ErrorEvent) when I purposefully configured the asset to not load or cause a loading problem - something we all see in the real world on live sites and without notice or forewarning. I believe a more strict approach to unbundled error events would be a super huge bonus, specifically the ones that follow below. I think we the developers could then add applicable and more granular evaluation code to the type of error and how to gracefully handle it, all the while keeping a smooth 'handled' movement to the system errors encountered during various loading processes. [*:yb3jbit3]IOErrorEvent.IO_ERROR by asset type/file type with additional internal function _ioErrorEvent [*:yb3jbit3]HTTPStatusEvent.HTTP_STATUS by asset type/file type with internal function _httpStatusHandler [*:yb3jbit3]SecurityErrorEvent.SecurityError by asset type/file type with internal function _securityErrorHandler Jack, other than a few unbundled error events, the system you have in place seems solid and quite powerful. Brilliant.
×
×
  • Create New...