使用 Babylon.js 开发时如何通过 CSS 实现 UI 自适应

news/2025/1/22 23:37:06/

        本文将介绍如何在 Babylon.js 开发中,通过预先定义的 CSS 文件实现 UI 的自适应布局,确保 UI 能够根据 Canvas 元素的尺寸动态调整。

场景描述

        假设我们已经使用 HTML 和 CSS 构建了 Babylon.js 的 UI 界面,并且所有样式都定义在 CSS 文件中。现在,我们需要让这些 UI 元素能够根据 Canvas 的尺寸动态调整,以实现自适应的效果。

解决方案

1. 使用 CSS 变量(推荐)

        CSS 变量(Custom Properties)是 CSS3 引入的特性,允许我们定义可动态更新的变量。通过结合 JavaScript,我们可以根据 Canvas 的尺寸动态调整 CSS 变量,从而实现 UI 的自适应。

1.1 在 CSS 文件中定义变量

        首先,在 CSS 文件中定义一些变量,用于控制 UI 元素的尺寸、位置等属性。

:root {--ui-width: 100px; /* 默认宽度 */--ui-height: 50px; /* 默认高度 */--ui-font-size: 16px; /* 默认字体大小 */
}.ui-element {width: var(--ui-width);height: var(--ui-height);font-size: var(--ui-font-size);background-color: rgba(255, 255, 255, 0.8);text-align: center;padding: 10px;position: absolute;top: 10%;left: 10%;
}
1.2 在 JavaScript 中动态更新 CSS 变量

        接下来,通过 JavaScript 监听 Canvas 的尺寸变化,并动态更新 CSS 变量。

const canvas = document.getElementById("renderCanvas");// 监听 Canvas 尺寸变化
const observer = new ResizeObserver(entries => {for (let entry of entries) {const { width, height } = entry.contentRect;updateUIStyle(width, height);}
});
observer.observe(canvas);// 更新 CSS 变量
function updateUIStyle(width, height) {const root = document.documentElement;root.style.setProperty('--ui-width', `${width * 0.8}px`); // 80% 的 Canvas 宽度root.style.setProperty('--ui-height', `${height * 0.1}px`); // 10% 的 Canvas 高度root.style.setProperty('--ui-font-size', `${height * 0.02}px`); // 字体大小随高度变化
}// 初始设置
window.addEventListener('load', () => {updateUIStyle(canvas.width, canvas.height);
});
1.3 优点
  • 代码简洁:通过 CSS 变量,可以轻松实现样式的动态调整。
  • 易于维护:所有样式定义在 CSS 文件中,JavaScript 只负责更新变量。

2. 使用类名切换(备选)

        如果不想使用 CSS 变量,可以通过动态添加或切换类名来实现自适应。

2.1 在 CSS 文件中定义不同尺寸的类

        在 CSS 文件中定义多个类,分别对应不同的 Canvas 尺寸。

.ui-element {background-color: rgba(255, 255, 255, 0.8);text-align: center;padding: 10px;position: absolute;top: 10%;left: 10%;
}/* 小尺寸 */
.ui-element.small {width: 100px;height: 50px;font-size: 12px;
}/* 中尺寸 */
.ui-element.medium {width: 200px;height: 100px;font-size: 16px;
}/* 大尺寸 */
.ui-element.large {width: 300px;height: 150px;font-size: 20px;
}
2.2 在 JavaScript 中动态切换类名

        根据 Canvas 的尺寸动态切换 UI 元素的类名。

const canvas = document.getElementById("renderCanvas");
const uiElement = document.querySelector('.ui-element');// 监听 Canvas 尺寸变化
const observer = new ResizeObserver(entries => {for (let entry of entries) {const { width, height } = entry.contentRect;updateUIClass(width, height);}
});
observer.observe(canvas);// 根据尺寸切换类名
function updateUIClass(width, height) {if (width < 600) {uiElement.classList.remove('medium', 'large');uiElement.classList.add('small');} else if (width < 1024) {uiElement.classList.remove('small', 'large');uiElement.classList.add('medium');} else {uiElement.classList.remove('small', 'medium');uiElement.classList.add('large');}
}// 初始设置
window.addEventListener('load', () => {updateUIClass(canvas.width, canvas.height);
});
2.3 优点
  • 兼容性好:适用于不支持 CSS 变量的旧版浏览器。
  • 灵活性高:可以通过定义多个类实现复杂的自适应逻辑。

补充一个最近开发时的案例

css文件参考:

body{background-color:#000723;
}canvas{width: 100%; height: 100%; position:absolute;top:0px;left:0px;background-color: #000723;z-index: -100;
}#containerSel3DIcon {position: absolute; /* 或者使用 relative/fixed */top: 0;left: 0;width: 100%;height: 100%;pointer-events: none;overflow: hidden;
}
.Sel3DIcon{position: absolute;text-align: left;vertical-align: top;pointer-events: auto;cursor: pointer;z-index: -99;
}
.Sel3DIcon img{width: 32px;height: 32px;
}
.Sel3DIcon span{font-size: 18px;color: #fff;text-align: left;vertical-align: top;text-shadow: 2px 2px 2px rgba(0, 0, 0, 0.9);
}

js文件中UI自适应部分的代码参考:

function AdaptiveStyles(){const styleSheets = document.styleSheets;const iconSize = Math.round(canvas.height * 0.026);const contentSize = Math.round(canvas.height * 0.016);for (let i = 0; i < styleSheets.length; i++) {const styleSheet = styleSheets[i];const rules = styleSheet.cssRules;for (let j = 0; j < rules.length; j++) {const rule = rules[j];if (rule.selectorText === '.Sel3DIcon img') {console.log("img");rule.style.width = `${iconSize}px`;rule.style.height = `${iconSize}px`;}else if (rule.selectorText === '.Sel3DIcon span') {console.log("span");rule.style.fontSize = `${contentSize}px`;}}}
}AdaptiveStyles();window.addEventListener('resize', function() {engine.resize();AdaptiveStyles();
});

        在该段代码中使用了模板字符串,关于模板字符串的使用方法,请参看以下链接:

模板字符串VS普通字符串:核心区别与使用场景


http://www.ppmy.cn/news/1565335.html

相关文章

商汤善惠获金沙江创投领投A轮融资,聚焦零售AI业务

1月20日&#xff0c;商汤善惠宣布完成A轮融资&#xff0c;本轮融资由金沙江创投数千万元领投&#xff0c;微木资本、嘉实基金和金弘基金等知名资管平台和产业资本数千万元跟投&#xff0c;鞍羽资本担任长期财务顾问。 此次融资将重点投向零售AI算法研发创新、海外市场拓展战略…

一文读懂 RocketMQ:从概念到架构与应用原理概述

文章目录 概述架构说明核心组件核心概念 namesvrproducer默认实现producer启动消息发送 broker-mq核心基本模型集群模型内部模型存储机制高可用 consumerpush类型push流程pull类型 概述 随着分布式技术在业内的快速应用&#xff0c;mq&#xff08;消息队列&#xff09;做为不可…

QT的TCP通讯

目录 一、引言 二、QT 中与 TCP 通讯相关的类 1.QTcpSocket 类 1.1 常用信号 1.2常用函数 2.QTcpServer类 2.1常用函数 三、QT TCP通信的详细代码实现 1.TCP服务器端实现 2.TCP客户端实现 四、总结 一、引言 在网络编程领域&#xff0c;TCP&#xff08;Transmission…

自动化爬虫运行过程中,有没有办法提高爬虫的抓取效率?

关于在实际爬虫开发及运行过程中,我们可以深刻研究爬虫机制和网站结构,如何提高爬虫抓取效率和性能是我们运行爬虫的关键所在。关于这一点,将从多个方面展开,包括并发处理、优化网络请求、缓存策略、代理IP池、分布式爬虫等,同时提供详细的代码实现和解释。 爬虫的抓取效…

微服务学习-Nacos 作为注册中心使用

Nacos 实现服务的注册与发现 1. 作用 服务的注册与发现 2. 为什么要引入注册中心 微服务中的订单服务调用商品、库存、账户等服务的 IP 地址和端口都是硬编码&#xff0c;会存在很多问题 如果商品、库存、账户等服务的 IP 地址或端口发生了变化&#xff0c;则订单服务将变得…

SpringBoot快速接入OpenAI大模型(JDK8)

使用AI4J快速接入OpenAI大模型 本博文给大家介绍一下如何使用AI4J快速接入OpenAI大模型&#xff0c;并且如何实现流式与非流式的输出&#xff0c;以及对函数调用的使用。 介绍 由于SpringAI需要使用JDK17和Spring Boot3&#xff0c;但是目前很多应用依旧使用的JDK8版本&…

32单片机从入门到精通之测试与验证——单元测试(十五)

人生苦短&#xff0c;我们都会面临困难和挑战。但是&#xff0c;只要我们保持积极的心态和勇往直前的精神&#xff0c;我们就能战胜一切困难&#xff0c;实现自己的目标。 成功并不是一蹴而就的&#xff0c;它需要我们付出努力和坚持不懈。就像爬山一样&#xff0c;我们可能会遇…

物联网技术正在如何影响我们的生活

物联网改变生活 引言 在今天这个数字化迅猛发展的时代&#xff0c;物联网&#xff08;IoT&#xff09;已经悄然渗透了我们生活的每一个角落。想象一下&#xff0c;当你的冰箱能够自动订购牛奶时&#xff0c;你是否会感到惊喜&#xff1f;这就是物联网的魔力&#xff0c;它不仅…