ThreeJS CSS3DRenderer / CSS Animation Issue - css

i was looking for a way to display plain text ( 2d or 3d ) in a threeJS Scene , and apply some css effects to them , i looked around for a while and i came across this . probably what i wanted ..
now the problem is that when i aplly a animate.css ( well knows css animation library ) class to html element , the position of my CSS3D Object is reseted and fliped ( can't explain why )
'http://jsfiddle.net/kd9Tc/4/'
note :
-i think this code example illustrates pretty well what i am trying to do , apply css text effects in webGL Scene ( i need all the camera movement and tweening ) .
i tried THREE.TextGeometry first , but i wanted the text to be in a language other than english and converting the font properly let to nowhere ( displayd ' ?????? ' in all my tests ) and beside that , i've been using css transforms for a while now and i'm pretty comfortable with them , and working with them is much easier for me .
overall the main reason i'm using threeJS is camera movement capability .
i'm glad that i used threeJS beacuse it open's the door to many other features as well , but yet , i'm not sure i;m using ther right tool here :-?
thanks

When you apply a CSS transform on an element drawn by ThreeJS' CSS3DRenderer, it overrides an initial translation and rotation originally set by the renderer itself.
After looking at your fiddle and then looking at the CSS3DRenderer in GitHub I can assess that the renderer does some toying around with the CSS translation and rotation of the elements within, before drawing them, in order to show what you'd expect out of the box (versus what's logical taking into account the way TheeJS handles its coordinates).
Here are the specific lines which I'm referring to. (ThreeJS GitHub)
In order to apply CSS transforms effectively across CSS3DRenderer be sure to not override the translation and rotation transforms. Simply put, take the following into account as the relative origin to every transform:
translate3d(-50%, -50%, 0) rotateX(180deg) rotateY(180deg)
For example this:
-webkit-transform: none;
transform: none;
Would become this:
-webkit-transform: translate3d(-50%, -50%, 0) rotateX(180deg) rotateY(180deg);
transform: translate3d(-50%, -50%, 0) rotateX(180deg) rotateY(180deg);
Here's a modified version of your fiddle which now works somewhat as expected.
(I didn't take the time to correct the X-axis translates, but you should get the gist of what I'm saying.)
Another way of working around this problem would be to somehow extend the CSS3DRenderer so that it corrects the rotate transforms on the fly instead of only at instantiation.
Why is the renderer doing this?
My best guess is that when the renderer was coded, they were expecting transforms to be applied via JavaScript and not CSS.
If you're truly more comfortable with CSS transforms I'd say go right ahead with what you are using. On the other hand if you feel a little more adventurous I'd suggest using TweenJS for animations with ThreeJS. They play quite well together. I use them on my website (link on my profile).
P.S.
#KianP Kudos on the fiddle you've put up. I can honestly say you are working on some pretty interesting stuff and you're using a set of tools that I wouldn't have thought of using together (Animate.css and ThreeJS) but seem to work quite well (Taking into account you correct the positioning as explained above).

Related

How to run CSS animation while elements are added to page?

I have noticed that when angular updates a page by adding a lot of elements even CSS animations stop running. I created a stackblitz here https://stackblitz.com/edit/angular-fefvpa to highlight the issue. When you hit the "Add Elements" button, the red square stops moving for about half a second. What can I do to circumvent that?
One solution i can think of that might help you is to use transform: translateX in the animation instead of left.
your anim would look like
#keyframes mymove {
from {transform: translateX(0)}
to {transform: translateX(400px)}
}
You can also add transform:translateZ(0) to the #box itself
The animation will use less ' GPU ' and by adding transform:translateZ(0) you will also make the browser use more GPU for that animation. So it might run smoother.
I tested it on my pc and it doesn't ' freeze ' anymore when adding items.
You can't really avoid that.
You're appending a thousand children, which is a rather important process.
This kind of operation should be done in small chunks, something like this.
Javascript is a monothread script language, which means most of the operations are blocking. When you do them one by one, then sure, it's pretty. But when you run a thousand operations at the same time (well, one after the other without any break), you face this kind of issues. Especially with DOM manipulation.

CSS transform: rotate does not take effect

So I made this site that shows the planets and their moons from a birds eye view. Now, I know Pluto is not a planet, but I included it because it has lots of moons and it is extremely interesting because of this fact: Pluto and its largest moon Charon orbit EACH OTHER around a point well outside the SURFACE of Pluto. So they do this dance where they have the same orbital period, they are always the same distance away from each other, and always on opposite sides of their orbits (so the distance between them is always maximized). Ok, enough science lecture, onto my problem.
Take a look at the site here: http://distantfuturejosh.com/endomoons/ . You will have to press the right arrow a few times to land on Pluto, then once you do, press the "lock" icon (which constrains the scale) and zoom in for a better view of Pluto and Charon NOT in the right configuration. If you click any where on screen they will begin to orbit for your viewing pleasure.
I can throw Pluto to the opposite side of his orbit by doing a little absolute positioning and margining, but the problem with that is the amount of margin necessary will change as the user scales. I could fix that probably with an if statement but I'd rather not write code that checks every time if the planet (dwarf planet) is Pluto or not.
I would like to solve this with a CSS transform. The problem is, when I apply transform: rotate(180deg); (with appropriate prefixes) it doesn't take. Inspect element doesn't show that it's being overridden (its not crossed out) but it just doesn't budge. I don't know what's causing it to fail and therefore I don't know how to fix it.
If I understood the question correctly, you want to move Pluto to the opposite side of its orbit. I would suggest getting rid of the calculated margin-top and margin-left and using percentages instead, as it scales better. Try the following after removing the calculated margins:
#Pluto {
margin-top: 100%;
transform: translate(-50%, -50%); /* add vendor prefixed ones as well */
}
Update: below is a working demo of a very simplified version of your site. I'm using em for lengths. This way you could zoom in/out by simply changing the font-size in JS (or even in your browser). I hear your concern about rounding, I'm not a 100% sure, but I think browsers that round lengths are going to round your 2244.608px anyway.
Working example: http://jsbin.com/aqiMUxI/5

Composing CSS animations with transforms

I want to compose two separate CSS keyframe animations to make an image vibrate and rotate (see http://jsfiddle.net/3zAeZ/). The problem I believe I'm running into is: I'm setting the transform attribute in both keyframe rules, therefore one rule is clobbering the other.
I know this works using top & left instead of translate, but the keyframes rule will be much easier to reuse in the future if I do a transform (for example, in case I ever need to position the image differently).
I'm stumped. Can I do this? Is there a better way I should be doing it?
You can use multiple transforms like
transform: rotate(1337deg) scale(1.5) translate(6em, 300px);
Now I realize that you need two different animation durations as well.
So the best I can come up with is using two elements http://jsfiddle.net/3zAeZ/1/

CSS Frame Image over another image to create a painting like effect

i have from the Website Designer the follwoing result : http://mp-books.ru/html/img/result_03.jpg
The ideea is that the stamp-like frame will remain on the page, but the person picture will change from case to case, will be take from the database.
I have arrived at this result : http://jsfiddle.net/alexpeta/MUpk8/1/ but thats the best i can do.
I have experimented with rotate like
-webkit-transform: rotate(-18deg);
-moz-transform: rotate(-18deg);
transform:rotate(-18deg);
-o-transform:rotate(-18deg);
but IE will not allow this transformation becuse it has Filter with an exact number of degrees : eg: 45, 90, 180 etc... and the customer wants the pic titled in each browser.
Any help on this brain-buster?
Regards,
Alex
You can use a MATRIX transformation on the image
filter: progid:DXImageTransform.Microsoft.Matrix(sizingMethod='auto expand',
M11=0.951, M12=0.309,
M21= -0.309, M22=0.951);
would correspond to 18 degrees
The calculations:
[cos(18) sin(18)]
[-sin(18) cos(18)]
The best solution for compatibility would be to transform the image on the server side using System.Drawing. As for the frame overlay, I think you're over-complicating things: if you know what the background will always look like, don't cut the frame out as a transparent image, cut it out with the background in it so it hides any overflow from the picture.
The CSS transform property allows developers to rotate, scale, and skew blocks of HTML via CSS. Although you can do the same thing with images in Photoshop or The GIMP, using CSS transforms allows developers to do the same thing with any HTML markup and allows users to select the text within the transformed object.
checkout this solution

How to force re-render after a WebKit 3D transform in Safari

I'm using CSS 3D transformations to zoom a div, for example:
-webkit-transform: scale3d(2,2,1);
The scaling itself works fine in any WebKit browser. However, when using this on Safari (mobile or Windows), the content of the div is not re-rendered. The result is that the content gets blurred after scaling.
This effect only occurs when using 3D transformations. Everything works fine when using
-webkit-transform: scale(2);.
In order to exploit hardware acceleration on iPhone/iPad, it would be nice to use the 3D transformations.
Does anybody know how to tell Safari to re-render a div with the new scale?
The reason why the text is blurry is because Webkit is treating the text as an image, I guess it's the price of being hardware accelerated. I'm assuming you are using transitions or animation keyframes in your ui, otherwise the performance gains are negligible and you should switch to non-3d transforms.
You can either:
• Add an eventlistener for transitionend and then replace the 3d transform for a standard transform, such as...
element.addEventListener("transitionend", function() {
element.style.webkitTransform = 'scale(2,2)'
},false);
• Since Webkit treats stuff as an image, it's better to start big and scale down. So, write your css in your "end state" and scale it down for your normal state...
#div {
width: 200px; /*double of what you really need*/
height: 200px; /*double of what you really need*/
webkit-transform: scale3d(0.5, 0.5, 1);
}
#div:hover {
webkit-transform: scale3d(1, 1, 1);
}
And you get a crispy text on hover. I made a demo here (works on iOS too):
http://duopixel.com/stack/scale.html
I found when trying to force a redraw of a div in safari for other reasons (recalculate text-overflow on hover), that is simple:
selector {
/* your rules here */
}
selector:hover {
/* your rules here */
}
selector:hover:after {
content:"";
}
I did something on hover that changes the padding to accommodate some buttons, but in safari/chrome it doesn't recalculate the content correctly, adding the :after pseudo-class did the trick.
I'm trying to do the same thing. I think what's happening here is that Safari is just scaling pixels. That is, it does all its "normal" browser rendering and then scales the pixels of the result.
Example: Place a relatively high quality image (say 1000x1000 pixels) in a small div (200x200 pixels) and set the image to 100% width and height. When you 3D transform the div to scale 5 times, the result will be blurry in Safari and crisp in Chrome. Use a 2D transform and the image will appear crisp in both.
A workaround is to convert to a 2D transform after you are done with the 3D. However, I've found there is a slight delay when converting between transforms so this isn't working too well for me.
I couldn't find a fix for making zoom-ins not blur in Safari (desktop v7.0.2 and the one included in iOS 6.1.3 and 7.0.6) but I did at some point, notice that I got a sharp png when I set the scale to 5. I don't know why, since that version of my code is lost in all the subsequent changes I made. All other scale factors were blurry.
Since the iPhone and iPad are target devices for this project I ended up abandoning scale transform and animating image height instead. I'm disappointed that the Safari team decided to implement transforms in a way that make them an unviable option in so many cases.
Hmmm... I'm getting the same issue trying to scale up google maps images (hidpi) with Chrome 53.
The only solution I've found so far is to hide the image (or a div that contains the images) and then show it again. Can be with opacity=0 or visibility=hidden, but it actually has to be invisible for at least a frame or two.
This, BTW, isn't even a 3d transform. Just 2D stuff.
Hmmm... I'm getting the same issue trying to scale up google maps images (hidpi) with Chrome 53.
One solution is to hide (opacity, visibility) the image for a few frames (or a container wrapping the image/images/whatever it is)... the better solution which I found in another post on SO was this (issued on the containing DIV):
e.style.transform = 'translateZ(0) scale(1.0, 1.0)'
BTW, my stuff was just ordinary 2d stuff, the translateZ seems to make the difference though, even though I never touched anything 3d.

Resources