当前位置: 首页 > article >正文

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

        本文将介绍如何在 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.kler.cn/a/513334.html

相关文章:

  • Java虚拟机面试题:内存管理(中)
  • ubuntu系统文件查找、关键字搜索
  • 2024年度总结:从后端Java到全栈成长的蜕变
  • Linux 高级路由与流量控制-用 tc qdisc 管理 Linux 网络带宽
  • MySQL 篇 - Java 连接 MySQL 数据库并实现数据交互
  • KubeSphere部署安装,接入KubeKey安装的k8s集群
  • 算法竞赛之差分进阶——等差数列差分 python
  • 【Pytest】基础到高级功能的理解使用
  • AI时代:安全的新挑战与新机遇
  • colmap ninja 时遇到undefined reference to `TIFFFieldTag@LIBTIFF_4.0‘错误
  • vite共享选项之---css.preprocessorOptions
  • mac 安装 python2
  • 【Knife4j与Swagger的区别是什么?】
  • 「2024·我的成长之路」:年终反思与展望
  • STM32之FreeRTOS开发介绍(十九)
  • 【BUUCTF】BUU XSS COURSE 11
  • @RabbitListener处理重试机制完成后的异常捕获
  • 【脑机接口数据处理】matlab读取ns6 NS6 ns5NS5格式脑电数据
  • 前瞻2024:前沿技术的全景洞察与深度剖析
  • springboot使用logback自定义日志
  • 【RAG落地利器】向量数据库Chroma入门教程
  • 14. Vue 3 中使用 ECharts 实现仪表盘
  • 99.10 金融难点通俗解释:投资资本回报率(ROIC)
  • MFC 使用 32位带Alpha通道的位图
  • Python配置MITMPROXY中间人监听配置
  • 解决HiveSQL查询出现Java.lang.OutMemoryError.java heap space