2. CSS3DObject渲染HTML界面模糊的解决方案

131 阅读2分钟

问题描述

将HTML界面通过 CSS3Renderer​ 和 CSS3DObject​ 渲染到页面上后,当放大场景并旋转场景后HTML页面会变得模糊。如图:

4070045175fbac3d67b33f2d804e6b38.gif

问题代码

// 获取名称为 touchScreen 的模型
const touchScreen = model.scene.getObjectByName('touchScreen') as THREE.Mesh;

const div = document.createElement('div');
document.body.appendChild(div);

const app = createApp(touchScreenComponent);
app.mount(div);

// 将 div 转换为 CSS3DObject 对象
const css3DObject = new CSS3DObject(div);
// 设置 CSS3DObject 对象的位置
css3DObject.position.set(0, 0, 0.03);
css3DObject.scale.set(0.01, 0.01, 0.01);
css3DObject.visible = true;

// 将 CSS3DObject 对象添加到模型中
touchScreen.add(css3DObject);
<template>
    <div class="w-[65px] h-[48px] bg-black">
        <div class="text-white">你好</div>
    </div>
</template>

<script setup lang="ts">
</script>

<style scoped></style>

问题解析

HTML页面通过 CSS3DObject​ 渲染为一个3D对象,然后浏览器会将该3D对象“压平”到2D平面,这样就会导致以下问题:

  1. 透视失真:当视角旋转时,浏览器无法正确计算3D空间中的透视关系,导致元素看起来模糊或扭曲。
  2. 渲染精度降低:在2D平面上渲染3D变换的结果时,浏览器可能会对元素进行重新采样,降低渲染精度,从而导致模糊。

问题解决

div​ 以及其包裹着的HTML界面添加 transform-style: preserve-3d​ 属性

  • transform-style

    用于控制元素的子元素在 3D 空间中的呈现方式。它决定了子元素是否保留其 3D 位置和变换效果。

    • 当设置为 preserve-3d​ 时,浏览器让子元素在 3D 空间中保持其位置和变换,允许它们相对于父元素进行 3D 变换。也就是说子元素会按照其在 3D 空间中的位置进行渲染,而不是被“压平”到一个 2D 平面而导致透视失真或渲染精度降低
    • 默认值为 flat​,子元素会被扁平化到父元素的 2D 平面上,忽略 3D 变换。
// ...省略代码...
const div = document.createElement('div');
div.style.backfaceVisibility = 'hidden'; // 避免背面渲染问题
div.style.transformStyle = 'preserve-3d'; // 保持3D变换!
document.body.appendChild(div);
// ...省略代码...
<template>
    <div class="w-[65px] h-[48px] bg-black body">
        <div class="text-white">你好</div>
    </div>
</template>

<script setup lang="ts">
</script>

<style scoped>
.body{
    transform-style: preserve-3d;
}
</style>

1.gif