1. Advertising
    y u no do it?

    Advertising (learn more)

    Advertise virtually anything here, with CPM banner ads, CPM email ads and CPC contextual links. You can target relevant areas of the site and show ads based on geographical location of the user if you wish.

    Starts at just $1 per CPM or $0.10 per CPC.

JavaScript Snowfall

Discussion in 'JavaScript' started by scu8a, Dec 14, 2019.

  1. #1
    I used JavaScript to create a snowfall script for web pages. It's just for fun, and I thought I would share. I'm testing it at https://chromosphere.com and you can take a look at it in action. I designed the script to run on any page using just one line of HTML.

    To add my snowfall to your page, visit https://chromosphere.com/snow/ and copy the HTML text and paste it within your web page's <head> section. It should run automatically.

    You can view the JavaScript code, here: https://chromosphere.com/scripts/snow/snow_0003.js

    Merry Christmas! 2019
    -Steve
     
    Solved! View solution.
    scu8a, Dec 14, 2019 IP
  2. hdewantara

    hdewantara Well-Known Member

    Messages:
    536
    Likes Received:
    47
    Best Answers:
    25
    Trophy Points:
    155
    #2
    hdewantara, Dec 14, 2019 IP
  3. #3
    1) wrong area for JavaScript

    2) @hdewantara has a good idea of using requestAnimationFrame.

    3) telling people to put scripting into <head> is bad advice, since putting scripts in <head> is outdated nonsense that just makes pages load slower.

    4) There is zero legitimate reason to EVER put an ID on a script tag.

    5) you might want to learn to evaluate results and use condensed operators. For example where you have:

    
    function rotate_degrees_left(x) {
        x = x - 1;
        if (x < 1) {
            x = 360;
        }
        return x;
    }
    
    Code (markup):
    That would be a lot simpler as:

    
    function rotate_degrees_left(x) {
      return (x-- >= 0) ? x : 359;
    }
    
    Code (markup):
    NOT that you even seem to call these routines, but given how simple said check is, why even bother wasting the bloat and overhead of a function on it?

    You have some REALLY derpy code in your radians conversion:

    
    function degrees_to_radians(x) {
        var return_x = null;
        return_x = x * (Math.PI / 180);
        return return_x;
    }
    
    Code (markup):
    IF that warranted a function, it doesn't even need a variable. Just return.

    
    function degrees_to_radians(x) {
        return = x * (Math.PI / 180);
    }
    
    Code (markup):
    But honestly you'd be better off with a global that's just Math.PI / 180;

    
    var deg2Rad = Math.PI / 180;
    
    Code (markup):
    So then when you want to change a variable -- let's say "myDegrees" to radians, just:

    myDegrees *= deg2Rad;

    dodging the wasteful processing overhead of a function and still being pretty clear what's going on. Don't make "variables for nothing" or "functions for nothing" on short one-line routines.

    Even just this:

    
    var snowflake = this;
    snowflake.addEventListener("load", function () {
        begin_snow()
    });
    
    function begin_snow() {
    Code (markup):
    Is kind of silly, since why waste time making a variable that's equivalent to "window" if it's not even going to save typing or fix scoping, much less since begin_snow has no reason to be called more than once, why not just make it anonymous right then and there... or even just pass begin_snow instead of derping it into an anonymous function?

    Just:

    
    window.addEventListener("load", function (
      // don't even need begin_snow, put its content here!
    
    Code (markup):
    I'd also suggest trapping window resize, since enlarging the window leaves large areas without your snow animation.

    In general I think you got way too complicated. If I have time later I'll take a stab at making a cleaned up version so you can see what I mean.
     
    deathshadow, Dec 15, 2019 IP
  4. scu8a

    scu8a Greenhorn

    Messages:
    81
    Likes Received:
    20
    Best Answers:
    0
    Trophy Points:
    15
    #4
    Interesting... I'm not familiar with requestAnimationFrame(), but I'll look into it. It's possible it might be more efficient, but I'm wondering about compatibility issues for older browsers. Thanks for the tip, hdewantara!

    Wow, thanks for the extensive critique, deathshadow. I could go through and explain to you all of your points, but keep in mind that I intentionally do things that will certainly appear as anomalies, or one might think is a mistake.

    I can take a moment to address your initial points, but I haven't the time available to address each question on your post. To answer your initial points, in reference to point 1, if JavaScript isn't suited to make the web page snowfall script, then what is? Java, and Flash are out of the question. Those are horrible options. What other scripting language would you recommend for this? For an interpreted language, JavaScript runs extremely fast, as all browsers are looking to compete for the fastest and most efficient script interpreter as multimedia continues to be more demanding over time.

    On point two, why do you believe requestAnimationFrame is superior to setInterval? What can you tell me about the differences in advantage and disadvantage for the two methods? I do know that utilizing setTimeout can potentially be used for certain exploits, but is requestAnimationFrame a better option? Why so?

    On point 3, I don't mean to come across as rude, but what you're saying is preposterous. It's completely untrue.

    On point 4, If there is no point to place an ID attribute into a script tag, then why did I do it? I'll tell you, there is a very legitimate reason it's there. Do you know why?

    On point 5, How do I learn to "evaluate results" and use condensed operators when I learned how to do that in the 1990s? I don't understand what you mean by evaluate results. It's far too vague. Are you talking about quality assurance testing, sanitising data, adding more conditional operators, seeking out a focus group for feedback? I don't understand what you're talking about there.

    I do appreciate your feedback and opinions, I really do. However, you need to know that some of the critique points you touched upon are incorrect. Don't assume things without digging deeper in this case. Make sure you learn from legitimate sources and verify the facts. There is so much misinformation out there, and worse yet, disinformation disseminated by hackers to fool developers into writing code that is easily exploited on a broad scale. I know all about how it's done. Be careful out there, and thanks again for taking time to share your thoughts :)
     
    Last edited by a moderator: Dec 21, 2019
    scu8a, Dec 15, 2019 IP
  5. Spoiltdiva

    Spoiltdiva Acclaimed Member

    Messages:
    7,739
    Likes Received:
    2,896
    Best Answers:
    53
    Trophy Points:
    520
    #5
    OMG! You have no idea what you have done. You've unleashed both the Kraken and the hounds of hell. Just wait until he comes back on. Be afraid...be very afraid.:rolleyes:
     
    Spoiltdiva, Dec 15, 2019 IP
  6. scu8a

    scu8a Greenhorn

    Messages:
    81
    Likes Received:
    20
    Best Answers:
    0
    Trophy Points:
    15
    #6
    @hdewantara and @deathshadow are both correct. Turns out requestAnimationFrame has advantages in specific situations, but in this case, I'm going to stick with the setInterval method as requestAnimationFrame has not been fully established and defined by the W3C as of yet, and the ability of older or incompatible web clients to utilize the requestAnimationFrame method isn't yet widespread enough.

    requestAnimationFrame is interesting because it defaults to a 60 fps interval, which is high quality for animation, but keep in mind, television frame rates are standard at 29.97 fps, and as few as 11 fps is all it takes for the human brain to see frames as movement. I can't adequately control the frame rate with requestAnimationFrame. 30fps usually suffices well. It's not too quick to be a heavy demand on processing, and it's not slow enough for animation to appear jagged.

    Here is an interesting article I found on requestAnimationFrame vs. setInterval/setTimeout: https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame
     
    scu8a, Dec 15, 2019 IP
  7. scu8a

    scu8a Greenhorn

    Messages:
    81
    Likes Received:
    20
    Best Answers:
    0
    Trophy Points:
    15
    #7
    Uh, oh. Should I flee for Mexico?!
     
    scu8a, Dec 15, 2019 IP
  8. qwikad.com

    qwikad.com Illustrious Member Affiliate Manager

    Messages:
    7,151
    Likes Received:
    1,656
    Best Answers:
    29
    Trophy Points:
    475
    #8
    Almost everyone at one time or another resisted what deathshadow had to say when it comes to coding. In the end he was always right. Pride doesn't let some coders accept the fact that they may need some help. I am pretty sure he's going to go ahead and make a js snowfall page. You'll be blown away how simple it will be. I am still using some of the codes he shared when I needed help. They were just better solutions compared to the codes other (also experienced) coders shared.
     
    qwikad.com, Dec 15, 2019 IP
    mmerlinn likes this.
  9. scu8a

    scu8a Greenhorn

    Messages:
    81
    Likes Received:
    20
    Best Answers:
    0
    Trophy Points:
    15
    #9
    I wasn't aware I was competing, but yes, I would very much like to see what his version would be like. He does have extensive knowledge, but based on the suggestions, not all of his knowledge is accurate/complete. If he has that much experience, why is he making mistakes in his criticism? Also, if he makes a "better" script, which I'm not sure how that would be defined.... faster running? More aesthetically pleasing? More simple? Faster coding? If he's going to do it, he's got 3 hours. That's the same amount of time it took to create this. It's only fair. If he does create something better, that's great - how else do you learn new things, right?

    You're right about the whole pride aspect of programmers and their personalities. So many relatively inexperienced programmers have such a big ego. The best software engineers I know who are well experienced have abandoned that mindset years ago. I guess it's just part of the learning process.
     
    scu8a, Dec 15, 2019 IP
  10. deathshadow

    deathshadow Acclaimed Member

    Messages:
    9,732
    Likes Received:
    1,998
    Best Answers:
    253
    Trophy Points:
    515
    #10
    Well you want to time, I'm just clear of one client, waiting on another (who probably won't get back to me tonight) so I'll squeeze it in now. This is maybe 20 minutes of coding work, so let's see how it goes.

    one thing is that if you're going to use objects, use them... in that way instead of slopping a bunch of nodes into the page in a DIV with "ID's and names for nothing" on them, you're MAKING THEM so store a reference on each snowflake object. That way you can make a "pointered list" out of them with a next attribute removing the nodeList / iterable overhead since those are painfully slow in JavaScript. Just walk a pointer list instead sibling after sibling. The sibling list with a counter could also be used to reduce the number of snowflakes by screen size since on really small displays you get all 64 shoved into almost no space as a blizzard, but at 1440p it's a mild flurry. Multiply the width by height of the window, divide by say 2 megapixels, and use that to scale against the max number of stars to show. This lets one dodge the resize issue if you randomize them when they hit bottom.

    Alright, starting the clock.
     
    deathshadow, Dec 15, 2019 IP
  11. deathshadow

    deathshadow Acclaimed Member

    Messages:
    9,732
    Likes Received:
    1,998
    Best Answers:
    253
    Trophy Points:
    515
    #11
    ... and took me 25 minutes, and that's with a bathroom break.

    https://cutcodedown.com/for_others/scu8a/

    Gimme a while and I'll document the how/what/why of it... and maybe add a polyfill for RAF in old browsers. I have one pre-written here somewhere.

    -- edit --

    Actually I added a "legacy" version that polyfills, and a version using settimeout.

    Mine has a lot more flakes and depth which brings IE to its knees as it's just not fast enough to keep up, and even edge struggles. There are ... other issues that I'll discuss in my writeup with the entire concept, and why I'd NEVER put this type of "gee ain't it neat BS" on a live website.

    Might be a bit before I document, client ACTUALLY got back to me.
     
    Last edited: Dec 15, 2019
    deathshadow, Dec 15, 2019 IP
  12. deathshadow

    deathshadow Acclaimed Member

    Messages:
    9,732
    Likes Received:
    1,998
    Best Answers:
    253
    Trophy Points:
    515
    #12
    Ok, client needs tome to decide, so back at this to kill time.

    The "fancy' verison with hundreds of stars, opacity and epth sizing, and other fancy stuff -- including requestAnimationFrame is indeed great -- in FF and Chrome.

    ... and it brings IE to its knees as it's just too much for it, and even Edge chokes on it bad. Hence, there are versions in that directory labelled "exact" -- which isn't "exactly" what you had, but it tries to be closer in terms of the number of flakes and the blur effects rather than going batshit.

    Testing in FF and Chrome made me go a bit overboard at 384 stars for 1920x1080 or higher -- it happens.

    In any case, let's use the version that's "closest" to the original script and break it down:

    https://cutcodedown.com/for_others/scu8a/snowfall.exact.html
    https://cutcodedown.com/for_others/scu8a/snowfall.exact.js

    Which at 2.4k is almost a quarter the code.

    I start out with a IIFE that is passed document as a parameter. This isolates the scope so that we have very few worries about cross-scripting namespace collisions or other worries, so we don't have to type the big long "document" all the time, and moving document into local scope so the reference evaluates faster. Google does it, it's good enough for me. If we can avoid pissing on the global namespace, mad excellent!

    I like to put user configurable values at the top to control things like speed. Variable names should be self explanatory, but if you're gonna let normal people dick with it an extra commend doesn't hurt.

    The Snowflake object starts out with a constructor which sets all the static values, and calls its own "reset" method to set up the values. Notice I switched to a TT tag since someone might have something like "body > div" in their CSS selectors which could cause your script to go all wonky. Even though it's not deprecated NOBODY seems to use the teletype tag, so it's an excellent choice for our generated "flakes".

    Notice said tag is added directly to body, we don't need no stinking wrapper. By storing it on our Snowflake object, we won't need to do any of that slow getElementsBy nonsense. It's called leveraging the DOM. ...and it's why 99% of the time people talk about how they're using the DOM, they AREN'T!

    to make it a bit nicer I added a radial gradiant to make them more 'fluffy'. The outer edge is set to 70% because radial gradients diameter is measured DIAGONALLY.

    We then extend the snowflake constructor's prototype with the following methods.

    Snowflake.reset -- used to initialize a snowflake. If the "newY" parameter is true, it will get a random screen y, if not it will be placed off the top. (so they can come in from off-screen).

    Snowflake.x and Snowflake.y are our calculated origin, Snowflake.counter is used to drive the Math.sin offset of the x, with the counterInc scaling its random core. The opacity and blur are scaled to the illusion of depth, but are otherwise static so set those here. Finally the width and height gets scaled to help with the illusion of depth.

    Snowflake.update -- updates the element's location during a frame draw. Move it down the screen at the speed * the distance scale, so the smalller more opaque ones in the "distance" appear to move more slowly enhancing the illusion of depth. If that move pushes them off screen, reset them to off the top with a new X, scale, and so forth.

    Then increment the counter by the scaled increment, use it to position the element according to the SIN wave sway, and of course finally set the top.

    Snowflake.makeSibling -- used during construction of all our stars to not just make another star, but automatically assign it as "next" on the current star.

    From there we just need to make a flake, create a reference to that flake, then loop for however many stars we want walking to the last on each and everyone.

    
    	var
    		firstFlake = new Snowflake(),
    		walk = firstFlake,
    		oldLastFlake = 0;
    	
    	for (var i = 1; i < maxFlakes; i++) walk = walk.makeSibling();
    
    Code (markup):
    This dodges the "need' for a for loop and results in a tighter and faster loop when it comes time to update their positions.

    The update() function is called by our timeouts and simply walks through all our flakes to call update.

    	function update() {
    		var walk = firstFlake;
    		do {
    			walk.update();
    		} while (walk = walk.next); 
    		setTimeout(update, 30);
    	} // update
    Code (markup):
    We then can simply call update() as our load event.

    Again, using objects to do what objects do REALLY cuts the amount of code needed to next to nothing. Sure it's not a 1:1, but it's close enough for government work.

    I also provided all the different ways of doing it, some more powerful but with varying levels of legacy support. As you can see in PROPERLY supported browsers they're capable of so much more -- but as you rightly noted the performance in legacy browsers leaves a LOT to be desired, even with a polyfill.

    I should probably do one more that's like "exact" but uses requestAnimationFrame with the legacy polyfill.
     
    deathshadow, Dec 15, 2019 IP
  13. deathshadow

    deathshadow Acclaimed Member

    Messages:
    9,732
    Likes Received:
    1,998
    Best Answers:
    253
    Trophy Points:
    515
    #13
    ... and here, a version using requestAnimationFrame with the polyfill fallback so it works to at least IE9.

    https://cutcodedown.com/for_others/scu8a/snowfall.exact.raf.html
    https://cutcodedown.com/for_others/scu8a/snowfall.exact.raf.js

    Otherwise identical. On modern browsers the animation is SO much smoother and nicer, but it degrades successfully to IE9. Since yours wouldn't work in IE8/earlier, I tried to draw the line at the same point.

    So... 25 minutes for a fancier version, then some dicking around with different flavors just for fun and to show all the different approaches.

    You know, might be fun to try instead of using gradients or blur or all that, to apply this to something like the UTF-8 snowflake character.
     
    deathshadow, Dec 15, 2019 IP
  14. mmerlinn

    mmerlinn Prominent Member

    Messages:
    3,197
    Likes Received:
    818
    Best Answers:
    7
    Trophy Points:
    320
    #14
    mmerlinn, Dec 15, 2019 IP
  15. deathshadow

    deathshadow Acclaimed Member

    Messages:
    9,732
    Likes Received:
    1,998
    Best Answers:
    253
    Trophy Points:
    515
    #15
    Hah, check this out:

    https://cutcodedown.com/for_others/scu8a/snowfall.utf8.html
    https://cutcodedown.com/for_others/scu8a/snowfall.utf8.js

    That's fun.

    Oh, I mentioned I would NEVER deploy this -- ANY version or approach -- on any real website? Why?

    Because when the flakes are over an anchor or form element you can't click on them as the flake is in the way. That's why these effects usually utterly and totally piss off users. Setting aside the waste of battery power or waste of cpu time, or waste of bandwidth, pissing off users is where you need to draw the line.

    BUT it's an excellent learning exercise.
     
    deathshadow, Dec 15, 2019 IP
  16. deathshadow

    deathshadow Acclaimed Member

    Messages:
    9,732
    Likes Received:
    1,998
    Best Answers:
    253
    Trophy Points:
    515
    #16
    Uhm... no. READ the MDN page you linked to. It's set in stone as part of the Living Standard, as specified right there on the page:

    https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame#Specification

    or in the specification itself:
    https://html.spec.whatwg.org/multipage/imagebitmap-and-animations.html#animation-frames

    ... and if you check my demos it's easy to polyfill and have work if you use the timestamps for throttling.

    	var browserPrefixes = [ 'ms', 'moz', 'o', 'webkit'];
    	
    	function browserFix(target, methodName, altMethodName) {
    		if (target[methodName]) return false;
    		if (!altMethodName) altMethodName =  methodName.charAt(0).toUpperCase() + methodName.substr(1);
    		for (var i = 0, j, k; j = browserPrefixes[i]; i++)
    			if (target[k = j + altMethodName]) {
    				target[methodName] = target[k];
    				return true;
    			}
    		return true;
    	} // browserFix
    	
    	var
    		perfLastTime = 0,
    		perf = false == 'performance' in w ? window.performance = {} : window.performance;
    
    	if (false == 'now' in perf) {
    		if (perf.webkitNow) perf.now = perf.webkitNow; else {
    			var nowOffset = (
    				perf.timing && perf.timing.navigationStart
    			) ? perf.timing.navigationStart : Date.now();
    			perf.now = function() { return Date.now() - nowOffset; };
    		}
    	}
    
    	if (
    		browserFix(window, 'requestAnimationFrame')
    	) window.requestAnimationFrame = function(callback, now, elapsed) {
    		perfLastTime = (
    			elapsed = Math.max(0, 50/3 - (now = perf.now()) - perfLastTime)
    		) + now;
    		return setTimeout( function() { callback(perfLastTime); }, elapsed);
    	};
    
    	if (
    		browserFix(window, 'cancelAnimationFrame') &&
    		browserFix(window, 'cancelAnimationFrame', 'CancelRequestAnimationFrame')
    	) window.cancelAnimationFrame = clearTimeout;
    
    Code (markup):
    Fixes both IE9 and older versions of Safari. Gives you the crappy framerate on old browsers, full speed on modern ones.
     
    deathshadow, Dec 15, 2019 IP
  17. scu8a

    scu8a Greenhorn

    Messages:
    81
    Likes Received:
    20
    Best Answers:
    0
    Trophy Points:
    15
    #17
    Excellent job @deathshadow, very nice work! You didn't have to take the time to do all that, but you did and I thank you!

    I'm especially interested in the performance of requestAnimationFrame as it runs the animation in a very smooth manner. Granted, it runs at 60 fps given adequate resources, but if I were to use the setInterval method, I wonder how well it would perform in comparison. When I wrote my script, I was mostly considering the compatibility issues for different web clients and the conflicts that may occur when embedded into a third-party user's page. Just by looking at my source code, it's plainly obvious I didn't pay much attention to efficiency and performance. Regardless of your modifications, the snow script is still a resource hog, however, your version demands 30% less in terms of resources. There are additional things that can be done to make it function more efficiently, but that's an entirely different thread.

    When it comes to IE, or Edge, or whatever Microsoft is screwing around with, I pay very little attention. Just about anything brings their web clients to their knees. I've found Google Chrome to be exceptional in its quality. I haven't checked the market share of the most used web clients lately, but typically if a browser has less than 15% market share, I'm not going to worry about its performance. As you mentioned, you have to draw the line somewhere. I didn't bother catering to mobile devices, either. This type of side project is something I made just for fun. As you had mentioned, it's an excellent learning project.

    I'm going to remake the script again to see how "good" I can make it. We still haven't decided what defines "good" - in my view the best script is one that emulates the snow falling as though it were real. Your idea to use the snowflake characters was great. They look good, but I think what that animation needs is to have the snowflakes individually rotate. That might be too much of a drain on resources, though. I'm going to add in some wind shear functionality in addition to relatively static wind on my script. The funny thing is that I spent those few hours creating the script but it's still not finished. It lacks depth, and the falling speed of the flakes need to be adjusted so that the effect of perspective/depth can be achieved.

    It's not difficult to address the problem with snowflakes interfering with the UX. There are several ways to go about it. Granted, I know it can piss people off to see snow interfering with their usage of a web page, but it's not difficult to correct the interference problem you had mentioned.

    I think I'm going to address another performance issue. It may also be a good idea to stop the animation when the end user switches focus to another window. Once focus is returned, restart the animation. Otherwise, it's doing nothing more than wasting resources.

    We can also improve performance by using integer values as opposed to floating point numbers with 3 decimal places. Granted, it's nice to have precision when it comes to these types of things, but working in units that measure down to 1/1000th of a pixel is a little bit silly if we're concerned a great deal about performance.

    I'll work on it some today if I have time, and once it's presentable, I'll post it here.
     
    scu8a, Dec 16, 2019 IP
  18. Spoiltdiva

    Spoiltdiva Acclaimed Member

    Messages:
    7,739
    Likes Received:
    2,896
    Best Answers:
    53
    Trophy Points:
    520
    #18
    Smooth, very smooth. Have you ever considered getting into politics? The Kraken is now back in it's underwater cave, and all the hounds of hell have been neutered......smooth.;)
     
    Spoiltdiva, Dec 16, 2019 IP
  19. scu8a

    scu8a Greenhorn

    Messages:
    81
    Likes Received:
    20
    Best Answers:
    0
    Trophy Points:
    15
    #19
    lol, I'm just giving credit where credit is due. @deathshadow managed to redeem himself quite well. Very few programmers have that level of aptitude and that's something I respect. Maybe one day he'll be as good as I am. ;) The Kraken and the neutered hounds of hell will inevitably return soon. The saga continues.
     
    scu8a, Dec 16, 2019 IP
    Spoiltdiva likes this.
  20. deathshadow

    deathshadow Acclaimed Member

    Messages:
    9,732
    Likes Received:
    1,998
    Best Answers:
    253
    Trophy Points:
    515
    #20
    Which should be a non-issue since again, this should NEVER be deployed on a real website because when the flakes are over user-interactables -- anchor, form elements, etc -- you cannot click on said elements. Yours or mine completely screws accessibility and usability, hence it means jack-all how well it works on ANY page.

    There are ways around that, like anchor-holders (also called a-ho's) but that easily breaks depending on page complexity. A-Ho's are where you parse every single interactable element on the page, create a clone of it that is empty/opacity 0, and absolute position them over the animation. It's fragile becuase you have to re-do it on every refresh, it's a lot of wasted code, and if you have other triggered effects like modals or drop-down menus it all goes bits-up face-down real quick.

    Hence I do not consider the entire CONCEPT of this animation to be real world deployable, and would advise AGAINST EVER adding this nonsense to a real website. It's the exact same reason you DON'T see this crap on legitimate sites or if you do it's for a background, not in the foreground. These types of animations having gone the way of the dodo twenty years ago when people first started screwing around with what could and could not be done with JS back when it was new... and in this case it turned out to be an accessibility /FAIL/.

    That part is easy to handle though, it's 90% of the way there, and my first couple examples actually does it. All you need to do is decrease the number of flakes based on the number of pixels on the screen.

    NONE if it is any good as it's a usability and accessibility disaster that's just going to royally piss off users on MOST pages the moment the flakes get in the way of using anchors and forms. Good simply isn't a word that comes to mind with these types of animations.

    Though I do have an interesting idea of where it MIGHT be useful, I need to play with it.

    Each one has its own timer, and given the nature of gimbel lock if we set their starting point to something other than zero, they're out of sync enough it should appear different... enough. Adjusting the rotational multipliers in the rotate3d() routine could do a lot for that. A separate timer for the rotation from the sway could help... one thing I was thinking of was adding rotational wind of a sin/atan combination... this would change all of their X coordinates (distance scaled) separate from the rest of the animations. Could even change depth/scale to have it look like they're going away/towards the user. Notice also that I set the increment speed value to also go negative, so they can rotate in their "sway" opposite directions. If a second axis of sway were applied as depth as cos instead of sin, that alone would enhance the 'depth' appearance of things.

    Which were the first things I added to mine.

    You'd be surprised. Modern pages have a LOT of things most of the "fixes" for this issue just don't work on, or require custom changes to the page you're applying it to.

    Which is a good idea.

    JavaScript doesn't do integers. No joke, ALL math is floating point. The moment it's a number and not a string, it's a float... well, not ENTIRELY true any more as there are pure integers now, but the MOMENT you do math on them it converts them back or operates on them same. This isn't C where typecasting ACTUALLY matters... much less said pure integers limit browser support as they're so new. As a friend of mine calls them, they're a "Chrome Luxury".

    The places I think mine would see the best optimizations would be to move the speed*this.scale and swayMax*this.scale into properties ahead of time, as those values do not change significantly during the update(), and perhaps move Snowflake.update into the regular update() routine to remove the method call overhead.

    -- edit -- actually I take that back, the method is faster than the unroll? Must be a scope overhead issue where "this.value" is faster than "localVariable.value"
     
    deathshadow, Dec 16, 2019 IP