ThreeJS 3D看板UI优化

212 阅读3分钟

ThreeJS 3D看板UI优化

主要优化点如下:

  • 添加一个整体的遮罩层、可以在遮罩层添加任意数据
  • 给 3D 看板添加背景图,不再使用单独的背景颜色

1、优化前后后对比

优化前: 具体信息请前往 上一篇文章 查看。 image.png

优化后: 相对于优化前还是不错的,主要是没找到合适的背景图和没有UI给设计图,自己实在设计不出好看的UI界面,勉强凑合着用。 image.png

2、遮罩层

  • 使用绝对定位并继承父元素的高度和宽度,可以通过 z-index: 999; 确保在最上方。
  • 重点属性:pointer-events: none;,作用是让该元素不响应任何鼠标事件,所有点击、悬停等事件都会“穿透”到其下方的元素。这样可以让整个遮罩层单纯起到遮罩的作用,完全不影响继续操作其下层的元素。
  • 同理,那两个图表也是一样的处理方式,不再做过多描述。
  • box-shadow: inset 0 0 20px 1px rgba(0, 153, 255, 0.59);,因为没找到合适的背景图,所以使用 inset 属性产生向内的阴影效果,有UI设计师的话,可以找UI给你一张中间透明的gif图,效果更佳,更高大上。
<template>
    <div class="BorderEffects">
        <span>3D 设备看板</span>
    </div>
</template>

<script setup lang="ts">

</script>

<style lang="scss" scoped>
.BorderEffects {
    width: 100%;
    height: 100%;
    background-size: 100% 100%;
    position: absolute;
    pointer-events: none;
    text-align: center;
    box-shadow: inset 0 0 20px 1px rgba(0, 153, 255, 0.59);
    padding-top: 15px;

    span {
        font-size: 2rem;
        font-weight: bold;
        color: #fff;
        padding: 0px 50px 10px 50px;
        text-shadow: 0px 1px 0px #c0c0c0,
            0px 2px 0px #b0b0b0,
            0px 3px 0px #a0a0a0,
            0px 4px 0px #909090,
            0px 5px 10px rgba(0, 0, 0, .9);
        background: url('/src/assets/images/machineStatus/m_h_bg2.png') no-repeat;
        background-size: 100% 100%;
    }
}
</style>

3、3D 看板添加背景图

  • 调整了布局,添加了内边距,添加的背景图,把下方代码替换原 create3DBoard 函数即可。
  • kanbanBg 为import导入进来的图片路径
import kanbanBg from '@/assets/images/machineStatus/m_h_bg2.png' // 顶部导入图片
// 新增:创建3D看板的函数
const create3DBoard = (text: string) => {
    const device = deviceArr.find((el: any) => el.name === text);
    const canvas = document.createElement('canvas')
    canvas.width = 316
    canvas.height = 158
    const ctx = canvas.getContext('2d')!

    // 使用import导入的图片
    const bgImg = new Image()
    bgImg.src = kanbanBg // 直接赋值为import进来的图片路径
    bgImg.onload = () => {
        ctx.drawImage(bgImg, 0, 0, canvas.width, canvas.height)
        ctx.fillStyle = device?.status == 0 ? 'rgba(32, 147, 246,0)' : 'rgba(255, 0, 0,0)'
        ctx.fillRect(0, 0, canvas.width, canvas.height)
        ctx.font = 'bold 20px Microsoft YaHei'
        ctx.fillStyle = '#fff'
        ctx.textAlign = 'center'
        ctx.textBaseline = 'middle'
        const lines = [
            text,
            '设备状态:' + ((device?.status == 0) ? '运行中' : '关闭'),
            '达成率:' + ((device!.now / device!.total) * 100).toFixed(2) + '%',
            '当前报工数:' + device?.now,
            '总报工数:' + device?.total,
        ]
        const lineHeight = 30
        const startY = 20
        lines.forEach((line, i) => {
            ctx.fillText(line, canvas.width / 2, startY + i * lineHeight)
        })
        texture.needsUpdate = true
    }

    const texture = new THREE.CanvasTexture(canvas)
    const material = new THREE.MeshBasicMaterial({
        map: texture,
        transparent: true,
        side: THREE.DoubleSide
    })
    // 与 canvas 宽高一致比,否则会拉伸
    const geometry = new THREE.PlaneGeometry(10, 5)
    const mesh = new THREE.Mesh(geometry, material)
    mesh.name = '3dBoard'
    mesh.renderOrder = 999
    mesh.scale.set(0, 0, 0)
    return mesh
}