ThreeJS 3D看板UI优化
主要优化点如下:
- 添加一个整体的遮罩层、可以在遮罩层添加任意数据
- 给 3D 看板添加背景图,不再使用单独的背景颜色
1、优化前后后对比
优化前: 具体信息请前往 上一篇文章 查看。
优化后: 相对于优化前还是不错的,主要是没找到合适的背景图和没有UI给设计图,自己实在设计不出好看的UI界面,勉强凑合着用。
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
}