Highlighted

animated snow within snowglobe (mask html5 canvas)

Community Beginner ,
Oct 03, 2018

Copy link to clipboard

Copied

Hello,

I'm creating a winter ecard with a snow globe.

I use Adobe Animate and need to export it as HTML5 Canvas. So actionscript is not working.

Inside the snow globe it should snow. Is there a ready snow animation, which one I can use and where I can change only the symbol (snowflake). There are several scripts for snow, but since I only want it to snow inside the snow globe and not over the whole stage, I don't think that's possible, isn't it? I have now created a mask and would like to arrange a finished snow animation below the mask. That should work, right?
Can anyone help me?

Adobe Community Professional
Correct answer by JoãoCésar | Adobe Community Professional

Hi.

While Clay doesn't give you a proper answer, to fill up the whole screen at the beginning just remove the minus sign when the y position is set.

Instead of this:

snow.y = -stage.canvas.height * Math.random();

Write this:

snow.y = stage.canvas.height * Math.random();

To randomize the snow flakes, create an array with the classes you want (the class name must be set in the linkage column of the Library panel). Then get a random index out of this array. Like this:

var snow;

var snowTypes = [lib.Snow, lib.Square, lib.Star];

...

snow = new snowTypes[Math.floor(Math.random() * snowTypes.length)]();

Anyway, I played with your code a bit. Here is the result (please ignore the GIF speed and other limitations):

animate_cc_html5_snow.gif

JS code:

const SNOW_NUM = 200;

var container = this.globe.container;

var snowTypes = [lib.Snow, lib.Square, lib.Star];

var snowA = [];

function start()

{

     createSnowF();

     createjs.Ticker.timingMode = createjs.Ticker.RAF;

     createjs.Ticker.addEventListener("tick", animateSnowF);

     container.alpha = 0;

     createjs.Tween.get(container).to({alpha:1}, 2000);

}

function createSnowF()

{

     var snow;

     for (var i = 0; i < SNOW_NUM; i++)

     {

          snow = new snowTypes[Math.floor(Math.random() * snowTypes.length)]();

          snow.scaleX = snow.scaleY = 0.5 + Math.random() * 0.5;

          snow.alpha = snow.scaleX;

          snow.x = stage.canvas.width * Math.random();

          snow.baseX = snow.x;

          snow.angle = 0;

          snow.angleSpeed = Math.random() * 0.05;

          snow.rangeX = 15 * Math.random();

          snow.y = stage.canvas.height * Math.random();

          snow.rot = 2 * Math.round(Math.random()) - 1;

          snow.sp = 1 + Math.random() * 1;

          container.addChild(snow);

          snowA = snow;

     }

}

function animateSnowF()

{

     for (var i = SNOW_NUM - 1; i >= 0; i--)

     {

          var snow = snowA;

          snow.rotation += 5 * snow.rot;

          snow.x = snow.baseX + Math.cos(snow.angle) * snow.rangeX;

          snow.y += snow.sp;

          snow.angle += snow.angleSpeed;

          if (snow.y > stage.canvas.height / stage.scaleY + snow.nominalBounds.height)

          {

               snow.x = (stage.canvas.width / stage.scaleX) * Math.random();

               snow.y = -snow.nominalBounds.height;

          }

     }

}

start();

FLA download:

animate_cc_html5_snow.zip - Google Drive

Notice that I didn't use an actual mask for performance sake.

Regards,

JC

Views

1.2K

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more

animated snow within snowglobe (mask html5 canvas)

Community Beginner ,
Oct 03, 2018

Copy link to clipboard

Copied

Hello,

I'm creating a winter ecard with a snow globe.

I use Adobe Animate and need to export it as HTML5 Canvas. So actionscript is not working.

Inside the snow globe it should snow. Is there a ready snow animation, which one I can use and where I can change only the symbol (snowflake). There are several scripts for snow, but since I only want it to snow inside the snow globe and not over the whole stage, I don't think that's possible, isn't it? I have now created a mask and would like to arrange a finished snow animation below the mask. That should work, right?
Can anyone help me?

Adobe Community Professional
Correct answer by JoãoCésar | Adobe Community Professional

Hi.

While Clay doesn't give you a proper answer, to fill up the whole screen at the beginning just remove the minus sign when the y position is set.

Instead of this:

snow.y = -stage.canvas.height * Math.random();

Write this:

snow.y = stage.canvas.height * Math.random();

To randomize the snow flakes, create an array with the classes you want (the class name must be set in the linkage column of the Library panel). Then get a random index out of this array. Like this:

var snow;

var snowTypes = [lib.Snow, lib.Square, lib.Star];

...

snow = new snowTypes[Math.floor(Math.random() * snowTypes.length)]();

Anyway, I played with your code a bit. Here is the result (please ignore the GIF speed and other limitations):

animate_cc_html5_snow.gif

JS code:

const SNOW_NUM = 200;

var container = this.globe.container;

var snowTypes = [lib.Snow, lib.Square, lib.Star];

var snowA = [];

function start()

{

     createSnowF();

     createjs.Ticker.timingMode = createjs.Ticker.RAF;

     createjs.Ticker.addEventListener("tick", animateSnowF);

     container.alpha = 0;

     createjs.Tween.get(container).to({alpha:1}, 2000);

}

function createSnowF()

{

     var snow;

     for (var i = 0; i < SNOW_NUM; i++)

     {

          snow = new snowTypes[Math.floor(Math.random() * snowTypes.length)]();

          snow.scaleX = snow.scaleY = 0.5 + Math.random() * 0.5;

          snow.alpha = snow.scaleX;

          snow.x = stage.canvas.width * Math.random();

          snow.baseX = snow.x;

          snow.angle = 0;

          snow.angleSpeed = Math.random() * 0.05;

          snow.rangeX = 15 * Math.random();

          snow.y = stage.canvas.height * Math.random();

          snow.rot = 2 * Math.round(Math.random()) - 1;

          snow.sp = 1 + Math.random() * 1;

          container.addChild(snow);

          snowA = snow;

     }

}

function animateSnowF()

{

     for (var i = SNOW_NUM - 1; i >= 0; i--)

     {

          var snow = snowA;

          snow.rotation += 5 * snow.rot;

          snow.x = snow.baseX + Math.cos(snow.angle) * snow.rangeX;

          snow.y += snow.sp;

          snow.angle += snow.angleSpeed;

          if (snow.y > stage.canvas.height / stage.scaleY + snow.nominalBounds.height)

          {

               snow.x = (stage.canvas.width / stage.scaleX) * Math.random();

               snow.y = -snow.nominalBounds.height;

          }

     }

}

start();

FLA download:

animate_cc_html5_snow.zip - Google Drive

Notice that I didn't use an actual mask for performance sake.

Regards,

JC

Views

1.2K

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Oct 03, 2018 1
Adobe Community Professional ,
Oct 03, 2018

Copy link to clipboard

Copied

Modify the script to create snow inside a movieclip instead of on the root timeline.

Mask the movieclip.

Fin.

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Reply
Loading...
Oct 03, 2018 2
Community Beginner ,
Oct 03, 2018

Copy link to clipboard

Copied

Hi Fin, thanks.
You have a script that is working?
It must work as HTML5 Canvas, so no actionscript, right?

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Reply
Loading...
Oct 03, 2018 0
Community Beginner ,
Oct 03, 2018

Copy link to clipboard

Copied

I found this script and it is working, but I want to choose 2 symbols: Snow and Snow2.
What do I need to change in the script to use both symbols? Right now only Snow is working.

var snowA = [];

var tl = this;

var snowNum = 100;

var snow;

createSnowF();

var animateSnowI = setInterval(animateSnowF,100);

function createSnowF(){

for(var i=0;i<snowNum;i++){

snow = new lib.Snow;

snow.x = stage.canvas.width*Math.random();

snow.y = -stage.canvas.height*Math.random();

snow.rot = 2*Math.round(Math.random())-1;

snow.sp = 5*Math.round(Math.random())+5;

tl.addChild(snow);

snowA.push(snow);

}

}

function animateSnowF(){

for(var i=0;i<snowNum;i++){

snowA.rotation+=5*snowA.rot;

snowA.y+=snowA.sp;

if(snowA.y>stage.canvas.height+snowA.nominalBounds.height){

snowA.y=-snowA.nominalBounds.height;

}

}

}

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Reply
Loading...
Oct 03, 2018 0
Community Beginner ,
Oct 03, 2018

Copy link to clipboard

Copied

And can you also change the script so that the snow doesn't have to fill the screen first, but the whole screen is full right from the start, Is that possible? You undersatnd what I mean?

So 2 different snowflakes (can I make movieclip with random?) and screnn should be full from the start.

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Reply
Loading...
Oct 03, 2018 0
Adobe Community Professional ,
Oct 04, 2018

Copy link to clipboard

Copied

Hi.

While Clay doesn't give you a proper answer, to fill up the whole screen at the beginning just remove the minus sign when the y position is set.

Instead of this:

snow.y = -stage.canvas.height * Math.random();

Write this:

snow.y = stage.canvas.height * Math.random();

To randomize the snow flakes, create an array with the classes you want (the class name must be set in the linkage column of the Library panel). Then get a random index out of this array. Like this:

var snow;

var snowTypes = [lib.Snow, lib.Square, lib.Star];

...

snow = new snowTypes[Math.floor(Math.random() * snowTypes.length)]();

Anyway, I played with your code a bit. Here is the result (please ignore the GIF speed and other limitations):

animate_cc_html5_snow.gif

JS code:

const SNOW_NUM = 200;

var container = this.globe.container;

var snowTypes = [lib.Snow, lib.Square, lib.Star];

var snowA = [];

function start()

{

     createSnowF();

     createjs.Ticker.timingMode = createjs.Ticker.RAF;

     createjs.Ticker.addEventListener("tick", animateSnowF);

     container.alpha = 0;

     createjs.Tween.get(container).to({alpha:1}, 2000);

}

function createSnowF()

{

     var snow;

     for (var i = 0; i < SNOW_NUM; i++)

     {

          snow = new snowTypes[Math.floor(Math.random() * snowTypes.length)]();

          snow.scaleX = snow.scaleY = 0.5 + Math.random() * 0.5;

          snow.alpha = snow.scaleX;

          snow.x = stage.canvas.width * Math.random();

          snow.baseX = snow.x;

          snow.angle = 0;

          snow.angleSpeed = Math.random() * 0.05;

          snow.rangeX = 15 * Math.random();

          snow.y = stage.canvas.height * Math.random();

          snow.rot = 2 * Math.round(Math.random()) - 1;

          snow.sp = 1 + Math.random() * 1;

          container.addChild(snow);

          snowA = snow;

     }

}

function animateSnowF()

{

     for (var i = SNOW_NUM - 1; i >= 0; i--)

     {

          var snow = snowA;

          snow.rotation += 5 * snow.rot;

          snow.x = snow.baseX + Math.cos(snow.angle) * snow.rangeX;

          snow.y += snow.sp;

          snow.angle += snow.angleSpeed;

          if (snow.y > stage.canvas.height / stage.scaleY + snow.nominalBounds.height)

          {

               snow.x = (stage.canvas.width / stage.scaleX) * Math.random();

               snow.y = -snow.nominalBounds.height;

          }

     }

}

start();

FLA download:

animate_cc_html5_snow.zip - Google Drive

Notice that I didn't use an actual mask for performance sake.

Regards,

JC

__________________________________________
HTML5, JSFL, and AS3 samples: http://bit.ly/2mJgDoG

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Reply
Loading...
Oct 04, 2018 1
New Here ,
Dec 02, 2019

Copy link to clipboard

Copied

Hi JoãoCésar, this snow is great!  How can it be stopped at 30 seconds?  I know there should be a timeout or setInterval, but not sure exactly what to change to stop the animation.

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Reply
Loading...
Dec 02, 2019 0
Adobe Community Professional ,
Dec 03, 2019

Copy link to clipboard

Copied

Hi! I'm glad you liked it!

 

If you just want to stop it (meaning freezing it) you can add a timeout in the start funcion body and remove the tick event listener. Like this:

 

setTimeout(function()
{
    createjs.Ticker.removeEventListener("tick", animateSnowF);
}, 30000);

 

 

But if you want the snow flakes to stop falling naturally you can create a boolean variable at the top called respawn, for example, set to true initially and add it to the if condition in the animateSnowF function and then set this variable to false in the interval added in the start function. Like this:

 

const SNOW_NUM = 200;

var container = this.globe.container;
var snowTypes = [lib.Snow, lib.Square, lib.Star];
var snowA = [];
var respawn = true; // NEW

function start()
{
    createSnowF();
    createjs.Ticker.timingMode = createjs.Ticker.RAF;
    createjs.Ticker.addEventListener("tick", animateSnowF);
    container.alpha = 0;
    createjs.Tween.get(container).to({alpha:1}, 2000);
	
    setTimeout(function() // NEW
    {
        respawn = false;
    }, 30000);
}

function createSnowF()
{
    var snow;
	
    for (var i = 0; i < SNOW_NUM; i++)
    {
        snow = new snowTypes[Math.floor(Math.random() * snowTypes.length)]();
        snow.scaleX = snow.scaleY = 0.5 + Math.random() * 0.5;
        snow.alpha = snow.scaleX;
        snow.x = stage.canvas.width * Math.random();
        snow.baseX = snow.x;
        snow.angle = 0;
        snow.angleSpeed = Math.random() * 0.05;
        snow.rangeX = 15 * Math.random();
        snow.y = stage.canvas.height * Math.random();
        snow.rot = 2 * Math.round(Math.random()) - 1;
        snow.sp = 1 + Math.random() * 1;
        container.addChild(snow);
        snowA[i] = snow;
    }
}

function animateSnowF()
{
    for (var i = SNOW_NUM - 1; i >= 0; i--)
    {
        var snow = snowA[i];
		
        snow.rotation += 5 * snow.rot;
        snow.x = snow.baseX + Math.cos(snow.angle) * snow.rangeX;
        snow.y += snow.sp;		
        snow.angle += snow.angleSpeed;

        if (respawn && snow.y > stage.canvas.height / stage.scaleY + snow.nominalBounds.height) // EDITED
        {
            snow.x = (stage.canvas.width / stage.scaleX) * Math.random();
            snow.y = -snow.nominalBounds.height;
        }			
    }
}

start();

 

 

I hope it helps.

 

 

Regards,

JC

__________________________________________
HTML5, JSFL, and AS3 samples: http://bit.ly/2mJgDoG

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Reply
Loading...
Dec 03, 2019 0
New Here ,
Dec 03, 2019

Copy link to clipboard

Copied

Awesome, thanks!

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Reply
Loading...
Dec 03, 2019 0
New Here ,
Dec 03, 2019

Copy link to clipboard

Copied

Quick question.  This script seems to effect the frame rate of the entire Animate file (it now ignores the frame rate set in the properties panel), how/where can I change this?

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Reply
Loading...
Dec 03, 2019 0
New Here ,
Dec 03, 2019

Copy link to clipboard

Copied

Oh wait it's this part: "createjs.Ticker.timingMode = createjs.Ticker.RAF;". Is there a way to apply this only to the snow, while keeping the rest of the timeline animation at a lower frame rate?

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Reply
Loading...
Dec 03, 2019 0
New Here ,
Dec 03, 2019

Copy link to clipboard

Copied

Another question, if I want to show the snow on mouseover, is there a way to clear all the existing snow so that it doesn't keep multiplying each time the mouseover occurs?

 

Setting respawn = false; in the mouseout function stops the animation nicely, but doesn't make the snow disappear, so it can really pile up if you keep mousing in and out.

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Reply
Loading...
Dec 03, 2019 0
New Here ,
Dec 03, 2019

Copy link to clipboard

Copied

Okay sorry for all the posts.  Found a sort of solution for the piling up snow issue with container.removeAllChildren();

 

What I'm a bit stuck on now, is if I want to have the animation play automatically in the begining, but then add athe rollover effect (where the animation can repeat again) after the initial animation ends, without repeating a lot of the same code.  If I just try to call start(); again on mouseover (later in the timeline), there's a scope issue and it says it's not defined.

 

Appreciate any suggestions!

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Reply
Loading...
Dec 03, 2019 0
Adobe Community Professional ,
Dec 04, 2019

Copy link to clipboard

Copied

Hi. I modified the code to include hover interaction. You're gonna need to add an invisible button (a button that only has a single shape in the Hit frame) in front of the globe. The code also removes the offscreen snow flakes from the display list for performance sake.

const SNOW_NUM = 200;

var root = this;
var container = root.globe.container;
var hit = root.hit;
var snowTypes = [lib.Snow, lib.Square, lib.Star];
var snowA = [];
var respawn = true;

function start()
{
	root.stop();
	createSnowF();
	container.alpha = 0;
	createjs.Tween.get(container).to({alpha:1}, 2000);	
	createjs.Ticker.timingMode = createjs.Ticker.RAF;
	createjs.Ticker.addEventListener("tick", animateSnowF);
	hit.on("mouseover", startSnowing);
	hit.on("mouseout", stopSnowing);
}

function startSnowing(e)
{
	respawn = true;
}

function stopSnowing(e)
{
	respawn = false;
}

function createSnowF()
{
	var snow;
	
	for (var i = 0; i < SNOW_NUM; i++)
	{
		snow = new snowTypes[Math.floor(Math.random() * snowTypes.length)]();
		snow.scaleX = snow.scaleY = 0.5 + Math.random() * 0.5;
		snow.alpha = snow.scaleX;
		snow.x = stage.canvas.width * Math.random();
		snow.baseX = snow.x;
		snow.angle = 0;
		snow.angleSpeed = Math.random() * 0.05;
		snow.rangeX = 15 * Math.random();
		snow.y = stage.canvas.height * Math.random();
		snow.rot = 2 * Math.round(Math.random()) - 1;
		snow.sp = 1 + Math.random() * 1;
		container.addChild(snow);
		snowA[i] = snow;
	}
}

function animateSnowF()
{
	for (var i = SNOW_NUM - 1; i >= 0; i--)
	{
		var snow = snowA[i];
		
		if (snow.stage)
		{
			snow.rotation += 5 * snow.rot;
			snow.x = snow.baseX + Math.cos(snow.angle) * snow.rangeX;
			snow.y += snow.sp;		
			snow.angle += snow.angleSpeed;	
		}
		
		if (snow.y > stage.canvas.height / stage.scaleY + snow.nominalBounds.height)
		{
			if (respawn)
			{
				container.addChild(snow);
				snow.x = (stage.canvas.width / stage.scaleX) * Math.random();
				snow.y = -snow.nominalBounds.height;
			}
			else
				container.removeChild(snow);
		}
	}	
}

start();

 

Please let me know if this helps.

 

Regards,

JC

__________________________________________
HTML5, JSFL, and AS3 samples: http://bit.ly/2mJgDoG

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Reply
Loading...
Dec 04, 2019 1
New Here ,
Oct 27, 2020

Copy link to clipboard

Copied

Hi Joao,

This snow effect was exactly whar I was looking for.

But I have question:

 

I have a timeline that loops 6 times.

And now the problem is, this snow scripts looks 6 times as well, resulting in too much snow which also drags the performance down.

What function can I add to the script, I have tried with various ways with various IF and FUNCTIONS but cant make it work, im still a Javascript rookie 🙂

 

Regards,

Mikkel

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Reply
Loading...
Oct 27, 2020 1
Adobe Community Professional ,
Oct 27, 2020

Copy link to clipboard

Copied

Hi, Mikkel!

 

Really glad to know that this snippet is helpful!

 

A quick fix you can apply is to create a custom boolean flag in the end when we call the start function. Like this:

if (!this.started)
{
	start();
	this.started = true;
}

 

In this way, the whole proccess to initialize the particles will run only once.

 

Please let me know if this works for you.

 

Regards,

JC

__________________________________________
HTML5, JSFL, and AS3 samples: http://bit.ly/2mJgDoG

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Reply
Loading...
Oct 27, 2020 0
New Here ,
Oct 28, 2020

Copy link to clipboard

Copied

Hi Joao,

Thanks so much for your quick answer.

I solved the problem by moving all layers in the timeline 1 frame forward and inserted "this.gotoAndPlay(1) in the end. By then I bypass the first frame which includes the snow script. Actually I can see I don't even have to move the layers forward, as JS count 0 as the first frame - Animate count 1 as the first.

Your soultion seems much more flexible and usable, but if I console.log the (const SNOW_NUM) I can still see it duplicates the script everytime the movie restarts.

I replaced the start (); at the end of the code with your new IF statement, thats what I was supposed to do right?

 

Regards,

Mikkel

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Reply
Loading...
Oct 28, 2020 0
Community Beginner ,
Nov 05, 2020

Copy link to clipboard

Copied

I have a very similar question... I want to change the CONST variable with buttons - but farther down the timeline - how can I accomplish this?  ie flurry, snow, blizzard  and all I want to do is change the SNOW_NUM and recall start - but I get invalid function...

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Reply
Loading...
Nov 05, 2020 0