Yo-yo effect on animation don't work when repeat is indefinite and direction is alternate using A-frame - aframe

I'll make some indefinite animations inside my A-frame web application. My animation must play infinity and must have a yo-yo effect. Form an opacity of 0.25 to 0.75 an back each in 3000 millisecondes. For this I use next code:
let box = document.createElement('a-box');
box.setAttribute('src', '#outer');
box.setAttribute('position', '0 0 -5');
box.setAttribute('color', 'red');
let anim = document.createElement('a-animation');
anim.setAttribute('attribute', 'opacity');
anim.setAttribute('from', '0.25');
anim.setAttribute('to', '0.75');
anim.setAttribute('fill', 'both');
anim.setAttribute('repeat', 'indefinite');
anim.setAttribute('dur', '3000');
anim.setAttribute('direction', 'alternate');
box.appendChild(anim);
document.getElementsByTagName('a-scene')[0].appendChild(box);
<script src="https://aframe.io/releases/0.5.0/aframe.min.js"></script>
<a-scene></a-scene>
Like you can see this is not working. It goes from 0.25 to 0.75 in 3000 millisecondes and instantly back to 0.25 to repeat again. In the documentation of A-frame stand this:
When we define an alternating direction, the animation will go back and forth between the from and to values like a yo-yo. Alternating directions only take affect when we repeat the animation.
If I use an number (example the number x) instead of indefinite, the yo-yo effect works great but stops when it's x-times repeated.
What could I do for fix this issue?

i think it's fixed by throwing out the fill attribute
anim.setAttribute('fill', 'both');
Its supposed to handle the animation when its not playing, i guess when the replay is indefinite, its playing all the time and either tween.js or three.js don't like it.
Working demo based on Your code:
https://codepen.io/gftruj/pen/qjdZmw
I tried setting it to 'none' or whatever, but i only got it working while thrown out.

Related

How to repeat that animation in the PaperJS?

I found this interesting animation and wonder if it's possible to repeat it in the PaperJS? It seems like it could be made of a group of circles, rotated around another circle.
But the problem is - when these objects are in a group I can't use sendToBack() per each, it's not going to work. Here is the Sketch example, that doesn't work.
P.S. Here is a simplified version of how it could be achieved, but it works only for 1 element, and only for animation along one axis.
If you still want to have your object grouped, a basic solution could be to have 2 groups: one below and one above the circle and toggle items visibility.
Just to demonstrate the idea, this sketch extends your code in this way.
I think that the way you currently decide if the item should be below or above can be improved though for a better result (you could try to detect intersection between the item and the circle rather than only checking the position).

Using rotateY vs matrix3d in css3

Heyho. I just came up with a tricky question.
I did something like this: http://jsfiddle.net/LspdF/1/
As you cann see there are more than 4 sites. Thats why I did the following:
Whenevery the pic-numer is greater than the last pic-number I turn the cube left, otherwise rigt. Thats why it can happen, that the css is somewhat like this:
transform: rotateY(450deg)
Since a circle only has 360 deg it turns and turns but always in the right direction.
Now I wanted to add a nice effect. Something like this: http://jsfiddle.net/p8a2t/
For this effect I need the 14th value of the 3d matrix created by the browser (z-value of translation). Since this value is poorly not the same as translateZ(), I have to use the matrix3d()-attribute.
Thats why I calculate the rotateY myself. But as you know the sin and cos are periodic and wont work with my 450deg. They reset the cube to 90deg which makes the cube spin back very fast.
My Question: How to denie that? Is there any possibility to change the matrix for spinning more than 360deg?
PS: The effect is realized using transition. There may be code in the fiddles which isnt used since I had to create both examples at once.
PPS: Sometimes the calculation has fatal numeric errors (near zero but not rly zero). I tried to avoid that using toFixed but for some reason that wont work sometimes. Same with Math.round. Note that you can break the second example clicking many links while the animation is still not done. But thats no point here :)
Any help is appreciated!

moving a spinning 3D object across the screen, making it face the correct way when it stops

The best example of what I am trying to achieve is on this youtube video
http://www.youtube.com/watch?v=53Tk-oGL2Uo
The letters that make up the word 'Atari' fly in from the edges of the screen spinning and then line up to make the word at the end.
I know how to make an object move across the screen, but how do I calculate the spinning so that when the object gets to its end position it's facing the correct direction?
The trick is to actually have the object(s) in the right position for a specific time (say t=5.0 seconds) and then calculate backwards for the previous frames.
i.e. before 5.0 seconds you rotate the object(s) by [angular velocity] * (5.0 - t) and translate by [velocity] * (5.0 - t)
If you do this, then it will look like the objects fly together and line up perfectly. But what you've actually done is blown them apart in random directions and played the animation backwards in time :-)
The CORRECT way of doing this is using keyframes. You can create the keyframes in any 3D editor (I use MAX, but you could use Blender). You don't necessarily need to use the actual characters, even a cuboid would suffice. You will then need to export those animation frames (again, in MAX I would use ASE - COLLADA would work with Blender) and either load them up at runtime or transform them to code.
Then it's a simple matter of running that animation based on the current time.
Here's a sample from my own library that illustrates this technique. Doing this once will last you far longer and give you more benefits in the long run than figuring out how to do this procedurally.

how to find out moment after rotationX has finished

i am playing around with the rotationX/Y/Z properties available in flashplayer since version 10. for testing purpose i created a cube and put canvas objects on three sides of it (top, front, bottom) and created a tween to get the values required for turing by 90 deg. turning the cube (a canvas) using rotationX = xx works well when the three side-canvas objects are small and filled with a not-to-complex element hierarchy. when using larger and more complex content it slows down. the next idea was to remove the canvas elements content and replace it by a snapshotimage of the content instead before starting the turn, after the turn is performed the original content is put back on the sides again. this results in a good perfomance increase. using a tween the last step of rotation is done in the function that is called as the tweenEnd handler. in this function also the process of copying the canvases content back is performed. unfortunately this results in a short hang of the cube right in that last rotation step, the reason for which is that rotation and copying back takes place at the same time.
so i could wait for some time after having called cube.rotationX = endValue by using a timer or setTimeout(func, 500), but this is ugly.
so my question is: after having called cube.rotationX = endValue a period of time is required to calculate data for the rotation and do the rotation itself. is there a way to find out the point in time when the rotation has ended, so that then the copying can be started ?
thank you in advance
tyler
There's no any default event, dispatching when rotation is completed. But I think of using callLater() function to copy back content. Try it.
that is exactly the point, there is not an event indicating the end of the rotation. the solution using callLater() instead of using setTimeout() appears to be an improvement however since waiting for a certain amount of time is always invloving some 'hope it works on machine x'. thank you very much for the hint !
greetings
tyler

CSS background-position: animating and performance

I've seen many examples for animating the background-position of elements to produce nice looking scrolling backgrounds.
These examples tend to also script in reset counters to put the background-position in its original location after a certain amount of pixels.
My question is: Is it feasible to never reset the background-position for a tiled background? This would naturally produce very large background-position values over time, but if there is no significant difference in browser performance, it might be ok. I've tested IE, Firefox, and Chrome over an 8 hour period, and there didn't appear to be any negative impact, although my boxes are relatively fast.
To answer the "why not reset?" question, it just comes down to simplicity. I am animating many background elements, each with different X/Y ratios, so not having to calculate when exactly it would be pixel perfect timing to switch back would make my life easier.
Anyone have thoughts on this?
This would naturally produce very large background-position values over time
Yes, that could eventually become a problem if your code is like
el.style.backgroundPosition= '0 '+n+'px';
When n reaches a high number (typically 1000000000000000000000), its toString will switch to exponential representation, which would end up trying to set:
el.style.backgroundPosition= '0 1e21px';
which is an obvious error. It's possible some layout engines might bail out earlier, perhaps at 1<<31 pixels. But even so, if you were animating something by (say) 32 pixels 60 times a second, it would still take twelve days to reach that stage.
not having to calculate when exactly it would be pixel perfect timing to switch back would make my life easier.
Typically you'd use the modulo operator % separately on each counter rather than resetting the whole thing.
var framen1= 30; // item 1 has 30 frames of animation
var framen2= 50; // item 2 has 50 frames of animation
...
var framei1= (framei1+1)%framen1; // 0 to 29 then reset
var framei2= (framei2+1)%framen2; // 0 to 49 then reset
Or, for time-based animations:
var frametime1= 100; // item 1 updates 10 times a second
var frametime2= 40; // item 2 updates 25 times a second
...
var dt= new Date()-t0; // get time since started animation
var framei1= Math.floor(dt/frametime1) % framen1;
var framei2= Math.floor(dt/framelength2) % numberofframes2;
document.getElementById('div1').style.backgroundPosition= '0 '+(framei1*24)+'px';
document.getElementById('div2').style.backgroundPosition= '0 '+(framei2*24)+'px';
...
I would think you would hit an overflow of some sort, but if you tested it over an 8 hour period, it is unlikely that it is possible to get the browser to overflow. It is just speculation.

Resources