mrdoob / three.js

JavaScript 3D Library.
https://threejs.org/
MIT License
102.77k stars 35.38k forks source link

Broken css3d renderer in Safari (r150-r155) #26529

Closed arslc closed 1 year ago

arslc commented 1 year ago

Description

Hey every one! Firstly: thx for awesome 3d library!

Secondly: starting with release 150 css3drenderer in Safari browser was broken. I think this PR (https://github.com/mrdoob/three.js/pull/25508) was the source of the bug migrating for 5 releases now.

I haven't looked into this issue in detail, but rolling back to 149 release fixes it.

I made a minimally reproducible example on jsfiddle, take a look at it via google chrome as well as safari and compare.

This example shows slight shifting of elements and incorrect rendering. But if the created application is complex, then these shifts will become catastrophic.

Perhaps I misunderstood something and I forgot to do something, but it's strange that everything is fine in google chrome. And also when you roll back to version 149 everything becomes normal

Reproduction steps

  1. Open jsfiddle in google chrome
  2. Open jsfiddle in Safari
  3. Compare

Code

<script async src="https://unpkg.com/es-module-shims@1.3.6/dist/es-module-shims.js"></script>
<script type="importmap">
    {
        "imports": {
            "three": "https://unpkg.com/three/build/three.module.js",
      "three/addons/": "https://unpkg.com/three/examples/jsm/"
        }
    }
</script>
import * as THREE from 'three'
import { CSS3DRenderer, CSS3DObject } from 'three/addons/renderers/CSS3DRenderer.js'

let cssRenderer, cssScene, camera

init()
render()

function init() {
  cssScene = new THREE.Scene()
  camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000)
  cssRenderer = new CSS3DRenderer()

  cssRenderer.setSize(window.innerWidth, window.innerHeight)
  document.body.appendChild(cssRenderer.domElement)

  camera.position.z = 1000
  camera.lookAt(cssScene.position)

  const cssElement = createCSS3DObject('<div></div>')
  cssScene.add(cssElement)
}
function createCSS3DObject(content)  {
  const wrapper = document.createElement('div')
  wrapper.innerHTML = content
  const div = wrapper.firstChild

  div.style.width = '100px'
  div.style.height = '100px'
  div.style.background = 'red'

  const object = new CSS3DObject(div)
  return object
}
function render() {
  requestAnimationFrame(render)
  cssRenderer.render(cssScene, camera)
}

Live example

Screenshots

Google chrome Safari

Version

150-155

Device

Desktop

Browser

Chrome, Safari

OS

MacOS

Mugen87 commented 1 year ago

I'm on macOS 13.4.1 and test with Safari 16.5.2. The live example looks in Safari like Chrome. Meaning the red square is exactly centered.

What version of macOS and Safari are you using?

arslc commented 1 year ago

Hm, weird...

I also tried on my iPhone (iOS 15.3.1) and see exactly the same problem

r149 r150-r155

I got this results using same code

I also noticed a relationship between window size and offset size. When changing the height of the window - offset is stronger. But the most interesting thing about this is that in the inspector the position of the square shows correctly, both effects can be seen below:

arslc commented 1 year ago

Okay, I tried to make some changes to that code.

If I comment out the line or change the value to 50%, then it starts centering correctly and works as it should.

line 109 in /three/examples/jsm/renderers/CSS3DRenderer.js

viewElement.style.transformOrigin = '0 0'; // <-- disable this line

or set 50%

viewElement.style.transformOrigin = '50% 50%';

I don't know if that functionality will work because of such changes, because did not check in detail and this is the first attempt to find out what's wrong

Results in inspector:

https://github.com/mrdoob/three.js/assets/117154548/3ae6cb96-680f-434c-8310-fe7a1f525fe0

Mugen87 commented 1 year ago

transform-origin should be supported in Safari: https://caniuse.com/?search=transform-origin

Does it work if you keep the line as it is but add the following:

viewElement.style.transformBox = 'fill-box';
arslc commented 1 year ago

No, unfortunately it doesn't change anything.

Yes, Safari supports transform-origin, so I can set any supported values like:

but any value other than center center/50% 50% moves this cube from the center.

Also changing transform-origin does nothing in google chrome and my div always centred

Mugen87 commented 1 year ago

@yomotsu Are you able to check @arslc's live example (https://jsfiddle.net/4937qkhf/) in Safari? Is the quad centered on your device?

yomotsu commented 1 year ago

Thanks for the detailed report. I tried the live example (https://jsfiddle.net/4937qkhf/) in Safari, but I can't reproduce the problem. Is there any missing to reproduce?


in Desktop Safari 16.5

Screenshot 2023-08-03 at 7 50 29 Screenshot 2023-08-03 at 7 52 08 Screenshot 2023-08-03 at 7 52 24

in iOS Safari 16.5.2

IMG_7293

WestLangley commented 1 year ago

@arslc Is your page zoom set to 100%?

arslc commented 1 year ago

@WestLangley yes, of course my zoom is 100%

Guys, i tried out another:


Simulator (16.2) Real (16.3)

Снимок экрана 2023-08-03 в 12 13 37
Safari Chrome

Safari (iOS 14) Chrome (iOS 14.7) Safari (iOS 15.4)

Mugen87 commented 1 year ago

It seems the Safari issue has been fixed since iOS 16 (and newer version of macOS).

arslc commented 1 year ago

What about Google Chrome and Google App on iOS < 16?

It's weird...

Mugen87 commented 1 year ago

Chrome like all other browsers on iOS are based on Webkit (so the browser engine of Safari).

Mugen87 commented 1 year ago

This issue is fixed in iOS 16 and iOS 17 will be released next month. The adoption rate of iOS 16 is as follows:

These data are from May 30, 2023 and directly from Apple: https://developer.apple.com/support/app-store/

Sorry, but we will not provide a fix for this in order to support older Apple devices. If you still need to support them, please use an older release of three.js or a custom version of CSS3DRenderer.