Jump to content

z-index is overlapping css 3d transform position in FireFox


silentimp
 Share

Recommended Posts

Hi.

I creating game on the base of css 3d transforms and some js as a proof of concept.

This is game field:


In the -webkit- everything fine.

But in the -moz- (Firefox 19) z-index have priority to 3d-transforms.

So last element in the DOM always will overlap first element no matter what 3d positions they have.

Is there any way to fix it?

Set z-index for every element and recalculate them for any rotation is my worst nightmare. 

 

You may rotate scene with keyboard arrows.

 

With all best regards.

Link to comment
Share on other sites

  • 1 month later...

Have you tried varying where preserve-3d is declared in the stacking context of elements? FF doesn't inherit this between elements the same way that webkit browsers do.

Also it is good that your demo worked in both Chrome and Safari because there are rendering differences between these also to be aware of. Chrome and FF draw elements on top of each other whilst Safari performs proper full 3d clipping of intersecting elements as described in this example from stackoverflow -

http://stackoverflow.com/questions/12756922/why-does-this-3d-css-overlap-instead-of-clip

 

It's a shame that it doesn't look like Safari will be continued for Windows.

Link to comment
Share on other sites

  • 2 months later...

That's some complex CSS, I would be tempted to create it programmatically from JS.

 

Anyway, I'm pretty certain it is the stacking context and where preserve-3d is declared being different in FF because if you remove it from ".plane-model .cabin-long" and ".plane-model .connector" the objects rotate correctly, though a couple of things disappear.

Link to comment
Share on other sites

Well sorry I stand corrected it does appear to be a bug - or at least poor performance.

Normally FF seems to rotate plenty of objects fine, but I wasn't able to get that demo working so made a little test to see how many objects it can handle, and the rendering goes wonky at 34 cubes. as well as being jerky and aliasing. Webkit browsers can all run a full screen of 128 cubes smoothly and without error (apart from some crazy artifacts in the latest Chrome Canary on my machine)

<html><head><style type="text/css">@-webkit-keyframes spin{100%{-webkit-transform:rotateY(360deg)}}@-moz-keyframes spin{100%{-moz-transform:rotateY(360deg)}}#wrapper{height:100%;width:100%;-webkit-perspective:1000px;-webkit-transform-origin:50% 50%;-moz-perspective:1000px;-moz-transform-origin:50% 50%;overflow:hidden;}#inner{left:0%;top:0%;height:100%;width:100%;-webkit-transform-style:preserve-3d;-webkit-animation:spin 15s infinite linear;-moz-transform-style:preserve-3d;-moz-animation:spin 15s infinite linear;}.cube{position:absolute;height:40px;width:40px;-moz-transform-style:preserve-3d;}.side{position:absolute;height:100%;width:100%;-webkit-backface-visibility:hidden;-moz-backface-visibility:hidden;}</style></head><body><button onclick="inc();">+</button><button onclick="dec();">-</button><div id="num"></div><div id="wrapper"><div id="inner"></div></div>	<script type="text/javascript">var t,col = "yellow,blue,red,black,brown,orange".split(','),tf = "rotateY(0deg) translateZ(20px),rotateY(270deg) translateZ(20px),rotateY(180deg) translateZ(20px),rotateY(90deg) translateZ(20px),rotateX(90deg) translateZ(20px),rotateX(270deg) translateZ(20px)".split(','),a = document.getElementById("inner"),c = 32,d = document.getElementById("num");('webkitTransform' in document.body.style)?t='webkitTransform':t='MozTransform';d.textContent = c;create();function create(){	var x = 1;	for (var i = 10; i<90; i+=10){		for (var j = 10; j<90; j+=5){			var e = document.createElement("div");			e.id = "cube"+x;e.className = "cube";e.style.top = i+"%";e.style.left = j+"%";a.appendChild(e);			for (var k = 0; k<6; k++){				var e2 = document.createElement("div");e2.id = "side"+(k+1);e2.className = "side";e2.style.backgroundColor = col[k];e2.style[t] = tf[k];e.appendChild(e2);			}			x++;			if(x>c){				break;			}		}		if(x>c){		break;		}	}}function destroy(){	while(a.firstChild){a.removeChild(a.firstChild);}	create();}function inc(){	(c<128)?c++:c=128;d.textContent = c;destroy();}function dec(){	(c>1)?c--:c=1;d.textContent = c;destroy();}</script>			</body></html> 

.

Link to comment
Share on other sites

Chrome renders using webGL and zIndex is not required. A slight change to the code above shows that in Firefox the zIndex is ignored when rotating up to 199 transformed elements but more than this and zIndex is needed. If you are keeping track of the position and rotation of your objects then you could try changing the zIndex each frame.

An alternative is using CSS matrix3d. Even with a couple of objects Firefox needs the zIndex setting but fortunately we can use the z-translation from the 3d transformation matrix. This should work in most cases though can go wrong depending on the origin point the z-translation refers to, in which case a more complicated z calculation will be needed.

Below is an example using this technique which rotates 128 cubes and works in Firefox, the z-translation value is the at centre of each element.

<html><head></head><body style="overflow:hidden;"><div id="clock"></div><div id="wrapper" style="-webkit-perspective:1000px;-moz-perspective:1000px;-webkit-transform-style:preserve-3d;-moz-transform-style:preserve3d;height:100%;width:100%;-webkit-transform-origin:50% 50%;-moz-transform-origin:50% 50%;"></div><script type="text/javascript">var cx = window.innerWidth/2;var cy = window.innerHeight/2;var col = ["yellow","blue","orange","red","black","purple"];var tf=('webkitTransform' in document.body.style)?'webkitTransform':'MozTransform';var t;var f = [];f[0]=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,20,1];f[1]=[0,0,-1,0,0,1,0,0,1,0,0,0,20,0,0,1];f[2]=[-1,0,0,0,0,1,0,0,0,0,-1,0,0,0,-20,1];f[3]=[0,0,1,0,0,1,0,0,-1,0,0,0,-20,0,0,1];f[4]=[1,0,0,0,0,0,1,0,0,-1,0,0,0,-20,0,1];f[5]=[1,0,0,0,0,0,-1,0,0,1,0,0,0,20,0,1];function rotYm(a,{	var c = Math.cos(a);	var s = Math.sin(a);	var m = [];	var d = [c,0,-s,0,0,1,0,0,s,0,c,0,0,0,0,1]	m[0] = b[0]*c + b[2]*s;	m[1] = b[1];	m[2] = b[0]*-s + b[2]*c;	m[3] = b[3];	m[4] = b[4]*c + b[6]*s;	m[5] = b[5];	m[6] = b[4]*-s + b[6]*c;	m[7] = b[7];	m[8] = b[8]*c + b[10]*s;	m[9] = b[9];	m[10] = b[8]*-s + b[10]*c;	m[11] = b[11];	m[12] = b[12]*c + b[14]*s;	m[13] = b[13];	m[14] = b[12]*-s + b[14]*c;	m[15] = b[15];	return m;}function tl(a,{	var m = [];	m[0] = a[0];m[1] = a[1];m[2] = a[2];m[3] = a[3];	m[4] = a[4];m[5] = a[5];m[6] = a[6];m[7] = a[7];	m[8] = a[8];m[9] = a[9];m[10] = a[10];m[11] = a[11];	m[12] = a[12] + b[0];m[13] = a[13] + b[1];	m[14] = a[14];m[15] = a[15];	return m;}var a = document.getElementById("wrapper");var pos = [];for (var y = 0; y<8; y++){	for (var x = 0; x<16; x++){		pos[x+y*16] = [-500+x*70,-250+y*60];	}}var s = "style";for (var i = 0; i<128; i++){	for (var j = 0; j<6; j++){		var e = document.createElement("div");		t = tl(f[j%6], pos[i]);		for (var k = 0; k<16; k++){			if (Math.abs(t[k])<0.000001){				t[k] = 0;			}		}		e.mat = t;		e[s][tf] = "matrix3d("+t.join()+")";		e[s].position = "absolute";		e[s]['webkitBackfaceVisibility'] = "hidden";		e[s]['MozBackfaceVisibility'] = "hidden";		e[s].backgroundColor = col[j];		e[s].top = cy - 10 + "px";		e[s].left = cx - 10 + "px";		e[s].height = "40px";		e[s].width = "40px";		t = Math.round(t[14]);		e[s].zIndex = t;		a.appendChild(e);			}}function spin(){	var e = a.firstChild;	for (var i = 0; i<768; i++){		t = e.mat;		t = rotYm(0.02, t);		for (var k = 0; k<16; k++){				if (Math.abs(t[k])<0.000001){					t[k] = 0;				}			}		e.mat = t;		e[s][tf] = "matrix3d("+t.join()+")";		t = Math.round(t[14]);		e[s].zIndex = t;		e = e.nextSibling;	}		raf(spin);}var raf = window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame;raf(spin);</script></body></html>
Link to comment
Share on other sites

  • 1 year later...

This problem still exists. Where did you get the information that Chrome uses WebGl for css transitions? I'd quite like to read it if possible.

 

I don't think using matrix transformation is the best way to go.  I've issues with it cross browser. It wipes out zoom functionality of page, which is annoying if you want to embed an animation within html content page.

 

Has anyone managed to get any futher with this?

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...