Reputation: 1706
I use Raphael JS to create and animate an SVG
The idea :
Step 1
When the user scroll down each time a new polyline is being created and added to the canvas/paper. The line when is being added is being animated also from opacity 0 to 1. So it makes the illusion that the lines follows the user scrolling with a delay.
Step 2
Then when the user is scrolling up the lines one by one from the bottom to top they are being removed.
Example : http://codepen.io/anon/pen/onclB
The problem :
I have managed to make the first step but I can't make the second step.
I can't find a way to animate the last inserted line and then remove it. So far when the user scroll up I take the bottom element, I animate it to opacity 0 and then with a callback function inside the animate function, I remove it. The problem is that when the user scrolls up again the animation haven't finished yet so the last element is the element that is being animated at the moment and not the previous one.
One solution I could make is to track the id's of the elements and make my own bottom element the one that I want to animate no matter if the other element have finished / removed or not.
But I was wondering if there is an easier solution like
paper.remove().animate(...)
// I know there isn't. Just for illustrating the needs.
So is it possible to animate the removed item ;
Also I notice that when I use the R.bottom.remove();
(R is the Raphael object) it removes the first element and not the last!
The code so far
HTML
<div id="canvas">
</div>
<div class="container">
<h1>SVG Animation Testing</h1>
</div>
<div class="container">
<p>Long long long text</p>
</div>
JS
var R, winW, winH, anglex, lastScrollTop;
jQuery(function($){
$window = $(window);
winW = $window.width();
winH = $window.height();
anglex = 1 + Math.floor(Math.random() * winW);
lastScrollTop = 0;
$(window).load(function() {
R = Raphael('canvas', '100%', '100%');
});
$window.scroll(function() {
var top = $(window).scrollTop();
if(top > lastScrollTop){
var polygonPoints = '0,0 ' + anglex + ',' + top + ' '+winW+',0';
var convertedPath = polygonPoints.replace(/([0-9.]+),([0-9.]+)/g, function($0, x, y) {
return 'L ' + Math.floor(x) + ',' + Math.floor(y) + ' ';
}).replace(/^L/, 'M'); // replace first L with M (moveTo)
R.path(convertedPath).attr({
'fill': 'none',
'stroke': '#662F8F',
'stroke-width': '4px',
'opacity': '0'
}).animate({opacity: 0.5}, 2000, 'bounce');
}else{
R.bottom.animate({opacity: 0}, 2000, 'bounce', function() {
this.remove();
});
}
lastScrollTop = top;
});
});
CSS
#canvas{
top: 0;
left: 0;
width: 100%;
height: 100%;
position: absolute;
position: fixed;
z-index: -1000;
}
.container{
max-width: 960px;
width: 100%;
margin: 0 auto;
text-align: center;
}
Upvotes: 1
Views: 728
Reputation: 34084
I find the solution to most Raphael problems like this is in creating some kind of object and array structure around the Raphael-specific code to store and manage the elements. Raphael's not like jQuery where you can easily find elements with selectors - its own functions for selecting elements are very limiting.
If I've understood the problem right, you're trying to select then remove the latest Raphael element which completed its fade-in animation (is this right?), and you've tried using paper.bottom
, which doesn't give you much control. I'd suggest instead creating a structure outside of Raphael which allows you to get the elements you need when you need them.
One simple approach would be to, in the callback function on your fade-in animation, push the element to an array, which will then contain all faded-in elements in order. Then you can always get the latest completed animation by getting the last item of the array, and you could work backwards through the array if needed.
You'd also have extra control e.g. you could remove it from the array immediately, then begin a fade out animation which removes the element in the callback - so it's immediately no longer the latest element you're interested in and won't be selected again, but isn't removed from the DOM until the animation has completed.
You might also want to record somewhere whether the last user action was scroll up or down, and check this in this fade-in callback function: if at the time the animation finishes it was scroll down, push to the array, while if it was scroll up, it might be better to immediately fade it out then remove it without it ever going in the array, to avoid timing issues.
In most complex Raphael projects, I end up with a selection of cross-referencing objects, arrays and Raphael sets that give me a variety of project-specific ways to access Raphael elements.
Upvotes: 1