How to use Mina in Snap svg? - javascript

This is an animation code using Snap svg:
var s = Snap(3000,3000);
var circle7 = s.circle(130,90,5);
var circle8 = s.circle(155,90,5);
var circle9 = s.circle(180,90,5);
var circle10 = s.circle(205,90,5);
var circle11 = s.circle(230,90,5);
var circle12 = s.circle(255,90,5);
circle.attr({fill:"#ffffff",opacity:0});
circle1.attr({fill:"#ffffff",opacity:0});
circle2.attr({fill:"#ffffff",opacity:0});
circle3.attr({fill:"#ffffff",opacity:0});
circle4.attr({fill:"#ffffff",opacity:0});
circle5.attr({fill:"#ffffff",opacity:0});
circle6.attr({fill:"#ffffff",opacity:0});
circle7.attr({fill:"#ffffff",opacity:0});
circle8.attr({fill:"#ffffff",opacity:0});
circle9.attr({fill:"#ffffff",opacity:0});
circle10.attr({fill:"#ffffff",opacity:0});
circle11.attr({fill:"#ffffff",opacity:0});
circle12.attr({fill:"#ffffff",opacity:0});
circle.animate({fill:"#0000FF",opacity:1},4500);
circle1.animate({fill:"#0000FF",opacity:1},4000);
circle2.animate({fill:"#0000FF",opacity:1},3500);
circle3.animate({fill:"#0000FF",opacity:1},3000);
circle4.animate({fill:"#0000FF",opacity:1},2500);
circle5.animate({fill:"#0000FF",opacity:1},2000);
circle6.animate({fill:"#0000FF",opacity:1},1500);
circle7.animate({fill:"#0000FF",opacity:1},4500);
circle8.animate({fill:"#0000FF",opacity:1},5000);
circle9.animate({fill:"#0000FF",opacity:1},5500);
circle10.animate({fill:"#0000FF",opacity:1},6000);
circle11.animate({fill:"#0000FF",opacity:1},6500);
circle12.animate({fill:"#0000FF",opacity:1},7000);
var cloud = s.image("D:/DigiMKey/login page_files/cloud.png", 0 , 260, 180,
125);
cloud.attr({opacity:0,width:100,height:65});
cloud.animate({opacity:1,width:200,height:125},1000)
var school =s.image("D:/DigiMKey/images/School-Icon.png", 265, 50, 100,100);
school.attr({opacity:0,width:80,height:80});
school.animate({opacity:1,width:100,height:100},2000)
I want to animate these objects using Mina so that they can be executed one after another.
Objects should fade in one by one.
how to do that?
This code gives no errors, however they all come at once instead of one after another.

There is a callback in animate function, use it to call the next animation.
var
s = Snap(300,300),
circle7 = s.circle(130,90,5).attr({fill:"#fff",opacity:0}),
circle8 = s.circle(155,90,5).attr({fill:"#fff",opacity:0}),
circle9 = s.circle(180,90,5).attr({fill:"#fff",opacity:0}),
circle10 = s.circle(205,90,5).attr({fill:"#fff",opacity:0}),
circle11 = s.circle(230,90,5).attr({fill:"#fff",opacity:0}),
circle12 = s.circle(255,90,5).attr({fill:"#fff",opacity:0}),
duration = 500,
props = {fill:"#00f",opacity:1};
/*
var anim = function() { circle.animate({fill:"#00f",opacity:1}, duration,mina.linear,anim1);}
var anim1 = function() { circle1.animate({fill:"#00f",opacity:1},duration,mina.linear,anim2);}
var anim2 = function() { circle2.animate({fill:"#00f",opacity:1},duration,mina.linear,anim3);}
var anim3 = function() { circle3.animate({fill:"#00f",opacity:1},duration,mina.linear,anim4);}
var anim4 = function() { circle4.animate({fill:"#00f",opacity:1},duration,mina.linear,anim5);}
var anim5 = function() { circle5.animate({fill:"#00f",opacity:1},duration,mina.linear,anim6);}
var anim6 = function() { circle6.animate({fill:"#00f",opacity:1},duration,mina.linear,anim7);}
*/
var anim7 = function() { circle7.animate(props,duration,mina.linear,anim8);}
var anim8 = function() { circle8.animate(props,duration,mina.linear,anim9);}
var anim9 = function() { circle9.animate(props,duration,mina.linear,anim10);}
var anim10= function() { circle10.animate(props,duration,mina.linear,anim11);}
var anim11= function() { circle11.animate(props,duration,mina.linear,anim12);}
var anim12= function() { circle12.animate(props,duration,mina.linear);};
anim7();
<script src="https://cdnjs.cloudflare.com/ajax/libs/snap.svg/0.4.1/snap.svg-min.js"></script>

There is nothing there that makes them animate in a sequence.
The way to animate in a sequence is to use a callback, which is part of the animate() method. So you can do...
circle1.animate({ fill:"#0000FF" }, 1000, mina.linear, callbackFunc2 );
function callbackFunc2() {
circle2.animate({ fill:"#0000FF" }, 1000, mina.linear, callbackFunc3 );
}
function callbackFunc3()...
And so on. Naturally that can feel a bit clunky when you have a lot, so I find it useful to add a sequence plugin to help. For example here
function nextFrame ( el, frameArray, whichFrame ) {
if( whichFrame >= frameArray.length ) { return }
el.animate( frameArray[ whichFrame ].animation, frameArray[ whichFrame ].dur, nextFrame.bind( null, el, frameArray, whichFrame + 1 ) );
}
I also extended it a bit and suggested it here (see the jsfiddle) which may be of use, if you're doing a lot of them.

Related

Snap SVG: Creating a scratch animation

I'm new to Snap SVG and I'm trying to make a pointer which scratches and make a trail of that scratch path. These are the few issues that I'm trying to fix:
The animation starts from the bottom instead of the top.
The pointer moves along the path and reaches the top and return back to where it started. It need not have to return to the origin.
Need some suggestions to animate the scratch path, it should appear only after the pointer passed through it.
Here is the code:
HTML
<svg id="svgout" width="550px" height="550px"></svg>
JS
var s = Snap("#svgout");
var scratchPathSVG = '<path class="cls-1" d="M224.58,215.86c-11.57,11.56-23.13,22.08-33.81,33.64C181,259,159.64,286.3,147.19,287.35c-26.69,1.05,0-32.59,7.12-41L189,202.19c21.35-27.33,43.59-53.62,64.94-79.9,9.79-12.62,23.13-24.18,26.69-41,0-2.1,0-4.21-.89-5.26C268.18,63.42,245.93,88.65,237,96c-49.82,44.15-97,94.62-144.12,144-6.23,6.31-28.47,22.08-31.14,31.54C64.45,260,85.8,239,92,231.63l64.05-82c10.68-13.67,69.39-65.18,61.38-88.31-.89-3.15-4.45-7.36-8-5.26-22.24,10.51-40,34.69-57.83,52.56-15.12,15.77-31.14,30.49-46.26,46.26C93.81,166.45,60,211.65,45.77,211.65c11.57,0,56.94-71.49,70.28-87.26C139.18,96,172.1,67.63,189,34c8.9-17.87,10.68-36.79-11.57-33.64C157,2.45,133,36.09,116.94,50.81c-33.81,31.54-66.72,63.08-98.75,95.67C7.51,157,22.64,174.86,33.31,164.35c36.48-36.79,73-73.59,111.2-108.28,10.68-10.51,23.13-18.92,33.81-30.49-.89-2.1-2.67-3.15-3.56-5.26-5.34,7.36-9.79,13.67-15.12,21-16,21-33.81,41-49.82,61C100,114.94,2.17,213.76,35.09,233.73c13.34,7.36,33.81-17.87,41.81-26.28,19.57-18.92,39.14-39.95,57.83-59.92,17.79-18.92,45.37-36.79,58.72-59.92,9.79-16.82,1.78-7.36-5.34,0-10.68,11.56-19.57,24.18-29.36,36.79-16,20-31.14,39.95-46.26,59.92C91.14,212.71,52.88,247.4,44,285.24c-.89,2.1,0,5.26,1.78,7.36.89,1.05,1.78,1.05,1.78,2.1,2.67,2.1,4.45,2.1,7.12,1.05,24.91-12.62,45.37-43.1,64.94-64.13,28.47-29.44,57.83-58.87,87.18-88.31,8.9-8.41,58.72-48.36,57.83-53.62.89,13.67-21.35,32.59-28.47,42.05-28.47,36.79-56.94,74.64-84.52,112.49-5.34,7.36-38.25,44.15-22.24,54.67,19.57,11.56,85.4-72.54,95.19-83.05.89,0,.89-1.05,0,0Z" />';
var pathToScratch = s.path("M224.58,215.86c-11.57,11.56-23.13,22.08-33.81,33.64C181,259,159.64,286.3,147.19,287.35c-26.69,1.05,0-32.59,7.12-41L189,202.19c21.35-27.33,43.59-53.62,64.94-79.9,9.79-12.62,23.13-24.18,26.69-41,0-2.1,0-4.21-.89-5.26C268.18,63.42,245.93,88.65,237,96c-49.82,44.15-97,94.62-144.12,144-6.23,6.31-28.47,22.08-31.14,31.54C64.45,260,85.8,239,92,231.63l64.05-82c10.68-13.67,69.39-65.18,61.38-88.31-.89-3.15-4.45-7.36-8-5.26-22.24,10.51-40,34.69-57.83,52.56-15.12,15.77-31.14,30.49-46.26,46.26C93.81,166.45,60,211.65,45.77,211.65c11.57,0,56.94-71.49,70.28-87.26C139.18,96,172.1,67.63,189,34c8.9-17.87,10.68-36.79-11.57-33.64C157,2.45,133,36.09,116.94,50.81c-33.81,31.54-66.72,63.08-98.75,95.67C7.51,157,22.64,174.86,33.31,164.35c36.48-36.79,73-73.59,111.2-108.28,10.68-10.51,23.13-18.92,33.81-30.49-.89-2.1-2.67-3.15-3.56-5.26-5.34,7.36-9.79,13.67-15.12,21-16,21-33.81,41-49.82,61C100,114.94,2.17,213.76,35.09,233.73c13.34,7.36,33.81-17.87,41.81-26.28,19.57-18.92,39.14-39.95,57.83-59.92,17.79-18.92,45.37-36.79,58.72-59.92,9.79-16.82,1.78-7.36-5.34,0-10.68,11.56-19.57,24.18-29.36,36.79-16,20-31.14,39.95-46.26,59.92C91.14,212.71,52.88,247.4,44,285.24c-.89,2.1,0,5.26,1.78,7.36.89,1.05,1.78,1.05,1.78,2.1,2.67,2.1,4.45,2.1,7.12,1.05,24.91-12.62,45.37-43.1,64.94-64.13,28.47-29.44,57.83-58.87,87.18-88.31,8.9-8.41,58.72-48.36,57.83-53.62.89,13.67-21.35,32.59-28.47,42.05-28.47,36.79-56.94,74.64-84.52,112.49-5.34,7.36-38.25,44.15-22.24,54.67,19.57,11.56,85.4-72.54,95.19-83.05.89,0,.89-1.05,0,0Z").attr({ fill: "none", opacity: "0" });
var pointer = s.path("M26.4,182.43c.63.63,1.46.49,1.52-.31.1-1.56-10.56-23.52-11-25.81s0-4.6,2.15-5.7c2.92-1.53,4.54.06,5.82,2.26s6.34,12.55,8.43,17.22c3.09,6.89,10.38,26.09,12.14,26.09,2.75,0,1.41-4.18,1.41-4.18s-2.45-4.1-2.29-5.54a2.75,2.75,0,0,1,3-2.71c2,.35,5.39,2.8,7,5.48,2.63,4.47,9.56,23-7.72,36.29C29.26,239,18.67,227,14.25,221.79A75.28,75.28,0,0,1,3.42,205.33C.25,199-.13,198.64.11,195.81c.26-3.11,4.25-6,9.69.65.59.73,2.18-.18,1.19-1.58-1.53-2.15-5.34-7.65-1.7-10,4.47-2.93,6.42,2.74,8.63,4.16.51.33,1.53-.36,1.42-.86-.53-2.34-4.41-5.15-2.93-8.59a4.18,4.18,0,0,1,6.2-2C24,178.8,25.09,181.13,26.4,182.43Z").attr({ fill: "#666"});
pointer.drawAtPath( pathToScratch, 10000, );
function Drawing( svgString, transformString, timeBetweenDraws ) {
this.fragment = Snap.parse( svgString );
this.pathArray = this.fragment.selectAll('path');
this.group = s.g();
this.timeBetweenDraws = timeBetweenDraws;
};
Drawing.prototype.init = function( svgString, transformString ) {
this.group.clear();
this.currentPathIndex = 0;
};
Drawing.prototype.endReached = function() {
if( this.currentPathIndex >= this.pathArray.length ) {
return true;
};
};
Drawing.prototype.callOnFinished = function() {
}
Drawing.prototype.initDraw = function() {
this.init();
this.draw();
};
Drawing.prototype.quickDraw = function() {
this.init();
this.timeBetweenDraws = 0;
this.draw();
};
Drawing.prototype.draw = function() { // this is the main animation bit
if( this.endReached() ) {
if( this.callOnFinished ) {
this.callOnFinished();
return
};
};
var myPath = this.pathArray[ this.currentPathIndex ] ;
this.leng = myPath.getTotalLength();
this.group.append( myPath );
myPath.attr({
fill: 'none',
"stroke-dasharray": this.leng + " " + this.leng,
"stroke-dashoffset": this.leng
});
this.currentPathIndex++;
myPath.animate({"stroke-dashoffset": 0}, this.timeBetweenDraws, mina.easeout, this.draw.bind( this ) );
};
var myDrawing1 = new Drawing( scratchPathSVG, 't0, 0, s1.8', 800 );
myDrawing1.initDraw();
Js Fiddle
Any ideas /suggestions will be appreciated :)
Thanks in Advance.

Tips to enhance javascript code

Was doing a nice-dropping navigation using css3 transforms.
Also written some javascript for this purpose.
But unfortunately it looks a bit untidy.
Would you guys please give me some tips to optimize javascript code.
The pen --> http://codepen.io/rokki_balboa/pen/doOqqv?editors=001
var bar = document.querySelector('.fa-bars');
var lis = document.getElementsByTagName('li');
bar.onclick = function() {
var delayIn = 0;
var delayOut = 1500;
if (!(lis[0].classList.contains('accordion'))) {
console.log(lis[5]);
[].forEach.call(lis, function(el) {
setTimeout(function() {
el.classList.add('accordion');
}, delayOut);
delayOut -= 300;
});
} else {
[].forEach.call(lis, function(el) {
setTimeout(function() {
el.classList.remove('accordion');
}, delayIn);
delayIn += 300;
});
}
};
If you're simply looking to reduce duplication, this might help:
var bar = document.querySelector('.fa-bars');
var lis = document.getElementsByTagName('li');
bar.onclick = function() {
var delay = {in: 0, out: 1500};
var adding = !(lis[0].classList.contains('accordion'));
[].forEach.call(lis, function(el) {
setTimeout(function() {
el.classList[adding ? 'add' : 'remove']('accordion');
}, delay[adding ? 'out' : 'in']);
delay[adding ? 'out' : 'in'] += (adding ? -300 : 300);
});
};
But it does so at some expense in readability. You'd have to make the call for your codebase as to which seems more maintainable.
In the future, https://codereview.stackexchange.com/ is a good place for code review help.

create fn function with callback

I did the following little plugIn (to add to query.transit by Rico St Cruz):
$.fn.translateLeft = function( left, duration, easing, callback ) {
var $this = $(this);
var currentLeftPx = parseInt( $this.css('left') );
var parentWidth = $this.parent().width();
// final left layout destination in px
var finalLeftPx = parentWidth/100 * left;
// actual distances to final left layout destination in px
var distanceLeftPx = currentLeftPx - finalLeftPx;
$this.transition( { x: -distanceLeftPx }, duration, easing, function() {
$this.stop(true).css( { left: left +'%', x: 0 } );
callback();
} );
}
I used it (without the callback I tried to implement it worked well so far) so:
$("#someElement").translateLeft( 10.5, 300, 'easeOutSine', function() {
// do something else
} );
This helps to make smooth x translate instead of left, yet keeps the possibility to set % values that refer to the parent (which is not possible with x alone which refers alway to the element). This only for explanation.
And as I said it works very good, yet my inserted callback does not.
Did I do something wrong here semantically?
Thanks for advice!
Garavani
EDIT:
Thanks so far for your comments that made me think. Actually even in my (beginner) fn code the callback actually works if I put for example alert( "Callback" ) in there instead of the other code. So it seems it is not possible to mix up my plugIn with any kind of code. To complete my question here is the whole code involved even if I am quite aware that it is quite complicated and will make you run out of nerves.:
This is the function IN which I liked to use my plugIn:
function switchMenuItem( id ) {
var $menuItem = $("#"+ id );
var $menu = $menuItem.parent();
var $menuImg = $menu.children(); //all siblings including selected element by id
var $prev = $menuItem.prev();
// calculate animation values
var index = $menuImg.index( $menuItem );
var ww = $(window).width();
var cssLeftPx = parseInt( $menuItem.css('left') );
var cssLeftPercent = 100 * cssLeftPx/ww;
if ( index == 1 ) { var dur = ww/2.4; };
if ( index == 2 ) { var dur = ww/1.5; };
$menuItem .stop(true)
.animate( { left: '10.5%' }, dur, 'easeOutSine', function() {
$(this) .prependTo($menu );
} );
$menuImg .first()
.stop(true)
.animate( { left: cssLeftPercent+'%' }, dur, 'easeOutSine', function() {
$(this) .insertAfter( $prev );
$menuItem.siblings()
.animate( { opacity: 1 }, 150, 'linear' )
.css( { cursor: 'pointer' } );
switchComplete = true;
subReady = true;
} );
…
}
and I would love to get rid of the query animate and substitute it with a smooth x translate with the help of Rico St Cruz transit plugIn (in the way I did successfully before with my kind of plugIn:
$.fn.translateLeft = function( left, duration, easing, callback ) {
var $this = $(this);
var currentLeftPx = parseInt( $this.css('left') );
var parentWidth = $this.parent().width();
// final left layout destination in px
var finalLeftPx = parentWidth/100 * left;
// actual distances to final left layout destination in px
var distanceLeftPx = currentLeftPx - finalLeftPx;
$this.transition( { x: -distanceLeftPx }, duration, easing, function() {
$this.stop(true).css( { left: left +'%', x: 0 } );
callback();
} );
}
So instead of „animate“ I want to use „translate Left“ which uses a smooth x translate and then return at the end a „cleaned up“ css position so that it is ready for other window resizing etc.
Did I explain myself? Any advice is appreciated a lot. Thank you in advance!

Using tween on class object, function definiton?

I am trying to do scene effects opening and closing scenes. But something is wrong with my self and this values. It says not defined or not working. How can ı define these functions.
Ways I tried to define
First way:
var tween = createjs.Tween.get(this.scene).to({alpha : 0}, 5000).call(menuOutCompleted(nextScreen,isNextScreenPopUp));
It is throwing "menuOutCompleted is not defined";
Second way:
var tween = createjs.Tween.get(this.scene).to({alpha : 0}, 5000).call(self.menuOutCompleted(nextScreen,isNextScreenPopUp));
It is not throwing any exception but does not do tween. It directly execute menuOutCompleted.
Third way:
var tween = createjs.Tween.get(this.scene).to({alpha : 0}, 5000).call(this.menuOutCompleted(nextScreen,isNextScreenPopUp));
It works like second way.
My js class
function CreditsScreen(SceneContainer)
{
var closePopUp_Button, background;
this.name = "CreditsScreen";
var self = this;
this.scene = new createjs.Container();
this.loadScreen = function()
{
background = new createjs.Shape();
background.graphics.beginBitmapFill(loader.getResult("coronaLogo")).drawRect(0,0,512,512);
background.x = 200;
background.y = 0;
closePopUp_Button = new createjs.Sprite(buttonData, "exitIdle");
closePopUp_Button.framerate = 30;
closePopUp_Button.x = 400;
closePopUp_Button.y = 22;
// play.addEventListener("click", handleClickPlay);
this.scene.alpha = 0;
this.scene.addChild(background);
this.scene.addChild(closePopUp_Button);
}
this.menuIn = function()
{
console.log("menuIn CreditsScreen" );
stage.addChild(this.scene);
//ptoblemetic part with self.menuInCompleted?
var tween = createjs.Tween.get(this.scene).to({y : 0, x : 0, alpha : 1}, 5000).call(self.menuInCompleted);
}
this.menuInCompleted = function()
{
console.log("menuInCompleted CreditsScreen" );
self.addButtonEventListeners();
}
this.menuOut = function(nextScreen,isNextScreenPopUp)
{
console.log("menuOut CreditsScreen" );
self.removeButtonEventListeners();
if(isNextScreenPopUp == true)
{
self.menuOutCompleted(nextScreen,isNextScreenPopUp);
}
else
{
//problematic part with menuInCompleted?
var tweenSplash = createjs.Tween.get(this.scene).to({alpha : 0}, 5000).call(menuOutCompleted(nextScreen,isNextScreenPopUp));
}
}
this.menuOutCompleted = function(nextScreen,isNextScreenPopUp)
{
console.log("menuOutCompleted CreditsScreen" );
if (isNextScreenPopUp)
{
}
else
{
stage.removeChild(this.scene);
this.scene.x = 0;
this.scene.y = 0;
this.scene.alpha = 1;
}
changeMenu(nextScreen, this.name, isNextScreenPopUp, true);
}
Ok. I solved the problem. Itis my call function. I send the parameters like menuoutcompleted(a,b) but in tween structure it must be (menuoutCompleted,[a,b]).
Now, It works :)

Scope issue with a sequence of fadeIn's

I the following code I have a UL with x3 LI's. I want the LI's to fadeIn in a sequence but am loosing scope somewhere I think. The problem is that only the last item in the sequence is run. I initially thought this was to do with a loop, so I removed all of them. Any help would be great.
Thanks is Advance.
function Sequence() {
var sequence = [];
var pos = 0;
Sequence.prototype.add = function(obj) {
sequence.push(obj);
};
Sequence.prototype.start = function() {
sequence[pos].run();
};
Sequence.prototype.next = function() {
pos++;
sequence[pos].run();
};
};
function fadeIn(params) {
this.id = params.id;
this.onComplete = params.onComplete;
var self = this;
var timer;
var i = params.opacity;
fadeIn.prototype.run = function(){
timer = setInterval(function() {
params.element.style.opacity = i / 10;
i++;
if (i / 10 == 1) {
clearInterval(timer);
self.onComplete();
}
}, params.fps);
}
};
var sequence = new Sequence();
var fader = document.getElementById('fader1');
var items = fader.getElementsByTagName("li");
sequence.add(new fadeIn({
"id": "instance_0",
"element": items[0],
"opacity": 0,
"fps": 80,
"onComplete": function() {
sequence.next();
}
}));
sequence.add(new fadeIn({
"id": "instance_1",
"element": items[1],
"opacity": 0,
"fps": 80,
"onComplete": function() {
sequence.next();
}
}));
sequence.start();
Yes, this is a scope issue. The problem is in the line:
fadeIn.prototype.run = function(){
When you define a method on the prototype, you're defining the method on all instances of the fadeIn class. So each time you call the constructor, you're redefining the method with the new params in the closure.
The solution is to define the method on this (or, as you've renamed it, self), which is the new instance, rather than the class:
self.run = function(){
Working example here: http://jsfiddle.net/nrabinowitz/wrQMa/3/

Categories

Resources