我正在参加「掘金·启航计划」
前言
接上一篇文章,“# html页面3D模型渲染之——three.js” juejin.cn/post/722590…
本文实现另外一种3D渲染的方法
效果
直接上效果图
model-viewer
说到3d渲染不得不说一下,“Google-model-viewer”,这是由Google开发的一个开源项目,用于在Web上显示和交互三维模型,反正就是一句话,允许用户以交互方式浏览、旋转、缩放和移动模型,以便从不同的角度和距离查看模型。 这是他的官方api链接,modelviewer.dev/examples/au… 。
实现技术
本文是基于产品详情列表去实现的3D模型渲染,有产品的轮播图预览,3D预览。
上代码,
js引入
<script type="module" src="https://unpkg.com/@google/model-viewer/dist/model-viewer.min.js"></script>
这是model-viewer的js库,要实现3d渲染这个是必不可少的。
html代码
<model-viewer class="tabs__active___8IvFf modelViewer"
src="https://cdn.shopify.com/s/files/1/0551/1957/7176/files/YH-4404.glb?v=1683186253" exposure="1"
shadow-intensity="0" camera-controls="true" data-js-focus-visible="true" disable-zoom disable-tap
interaction-policy="always-allow" camera-orbit="30deg 70deg 100%" min-camera-orbit="auto auto 1m"
max-camera-orbit="auto auto 1m" loading preload="true" max-field-of-view="auto" reveal="auto"
range-request-strategy="performance"
environment-image="https://stormsend1.djicdn.com/uploads/3d/8f490eaaa02516662cbdba7233ec72bc.hdr"
ar-status="not-presenting" on-touchstart="if (this.canScale) {this.scale = 1;}">
<div slot="progress-bar"></div>
</model-viewer>
说一下各个属性的作用
- exposure: 控制环境的亮度,其值在0到1之间,1表示最亮,0表示最暗。
- shadow-intensity: 控制阴影的强度,其值在0到1之间,1表示最强,0表示没有阴影。
- camera-controls: 控制是否启用默认的相机控制器,其值为true或false。
- data-js-focus-visible: 用于指示元素是否支持键盘焦点可见性(keyboard focus visibility),其值为true或false。
- disable-zoom: 禁用缩放功能,其值为true或false。
- disable-tap: 禁用触摸功能,其值为true或false。
- interaction-policy: 控制交互策略,其值可以是"always-allow"、"allow-when-focused"或"allow-when-pointer-down"。
- camera-orbit: 控制相机绕物体的旋转角度,其值是一个包含三个参数的字符串,分别表示绕x、y、z轴旋转的角度。
- min-camera-orbit: 控制相机绕物体的最小旋转角度,其值可以是一个数字或"auto"。
- max-camera-orbit: 控制相机绕物体的最大旋转角度,其值可以是一个数字或"auto"。
- loading: 控制模型加载过程中的显示效果,其值可以是"auto"、"lazy"或"eager"。
- preload: 控制模型是否预加载,其值为true或false。
- max-field-of-view: 控制相机的最大视野,其值可以是一个数字或"auto"。
- reveal: 控制模型的出现方式,其值可以是"auto"或"interaction".
- range-request-strategy: 控制范围请求的策略,其值可以是"performance"或"load-complete"。
- environment-image: 控制环境贴图的路径,其值是一个字符串。
- ar-status: 控制AR状态,其值可以是"not-presenting"、"presenting"或"failed".
- on-touchstart: 触摸事件的回调函数,用于处理触摸事件。
js代码
class Render {
domRender() {
const viewer = document.querySelector('model-viewer');
// viewer.minScale = 0.1; // 设置最小缩放比例为50%
function loading() {
const progressBar = document.getElementById('progress');
const loadingText = document.getElementById('loading-text');
viewer.addEventListener('progress', (event) => {
const loaded = event.detail.totalProgress;
loadingText.textContent = `${(loaded * 100).toFixed(0)}%`;
});
viewer.addEventListener('load', () => {
loadingText.textContent = 'Loading Complete!';
setTimeout(() => {
document.getElementById('loading').style.display = 'none';
}, 500);
//100%后清除定时器
clearInterval(loadingInterval);
});
}
const loadingInterval = setInterval(loading, 100);
}
}
//加载3D渲染
var render = new Render();
//渲染以及绑定事件
render.domRender();
非常简单,相比于three.js,它更容易入手。 Model Viewer和Three.js都是用于在Web上创建和展示3D模型的工具。它们各有自己的优点和缺点,下面是它们的一些主要特点:
Model Viewer的优点:
- Model Viewer是基于Web Components技术实现的,易于使用和集成到Web应用程序中。
- Model Viewer支持多种3D模型格式,包括glTF、OBJ、FBX、Collada等。
- Model Viewer提供了丰富的交互功能和选项,如相机控制、阴影、环境贴图等。
- Model Viewer支持在AR和VR设备上查看3D模型,具有更广泛的应用场景。
Model Viewer的缺点:
- Model Viewer的功能相对较为简单,不支持高级的3D图形编程。
- Model Viewer的扩展性有限,不太适合开发复杂的3D应用程序。
Three.js的优点:
- Three.js是一个强大的3D图形库,支持高级的3D图形编程。
- Three.js提供了丰富的3D图形效果和功能,如阴影、纹理、光照、动画等。
- Three.js支持多种3D模型格式,可以在多个平台和设备上使用。
- Three.js有庞大的开发者社区和活跃的维护者,提供了丰富的文档和示例。
Three.js的缺点:
- Three.js需要一定的3D图形编程知识才能使用,对于初学者来说有一定的学习曲线。
- Three.js的代码相对较为复杂,需要仔细的调试和优化才能获得较好的性能。
- Three.js的兼容性有一定的局限性,需要考虑不同平台和设备的差异性。
综上所述,Model Viewer适合于快速创建和展示简单的3D模型,而Three.js适合于开发复杂的3D应用程序和游戏。
附上全部代码
粘贴即用
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="https://cdn.jsdelivr.net/jquery/latest/jquery.min.js"></script>
<title>model-viewer</title>
<style>
body {
margin: 0;
padding: 0;
}
.model{width: 600px;}
.dmodel_max {
position: relative;
}
.modelViewer,
.dmodel_max {
width: 600px !important;
height: 400px !important;
}
#loading {
position: absolute;
top: 50%;
text-align: center;
left: 0;
transform: translateY(-50%);
width: 100%;
height: 100%;
background-color: #ffffff;
z-index: 9999;
display: flex;
justify-content: center;
align-items: center;
}
.tabs_flex{
display: flex;
align-items: center;
justify-content: center;
}
.tabs_flex li{list-style: none;padding: 6px 20px;}
.tabs_flex li a{display: flex;padding: 6px 30px;border-radius: 16px;text-decoration: none;align-items: center;}
.tabs_flex li a.active{background: #660099;color: #ffffff;}
.tabs_flex li a.active .whiteicon{display: block;}
.tabs_flex li a img{margin-right: 10px;}
.tabs_flex li a.active .blockicon{display: none;}
.whiteicon{display: none;}
.tab-content {
display: none;
width: 600px !important;
height: 400px !important;
}
.tab-content.active {
display: block;
}
#loading-text {
font-size: 20px;
color: #660099;
}
</style>
</head>
<body>
<!-- 谷歌实现的一个 web component,可用于查看 Web 上的 3D 模型并与之交互 -->
<script type="module" src="https://unpkg.com/@google/model-viewer/dist/model-viewer.min.js"></script>
<div class="model">
<div id="tab1" class="tab-content active">
<img src="/image/pro3.png" alt="" style="width: 100%;height: auto;">
</div>
<div id="tab2" class="tab-content">
<div class="dmodel_max">
<div id="loading">
<div class="dmodel_flex">
<div id="progress">
<img src="/selling/lodding.gif" alt="">
</div>
<div id="loading-text"></div>
</div>
</div>
<model-viewer class="tabs__active___8IvFf modelViewer"
src="https://cdn.shopify.com/s/files/1/0551/1957/7176/files/YH-4404.glb" exposure="1"
shadow-intensity="0" camera-controls="true" data-js-focus-visible="true" disable-zoom disable-tap
interaction-policy="always-allow" camera-orbit="30deg 70deg 100%" min-camera-orbit="auto auto 1m"
max-camera-orbit="auto auto 1m" loading preload="true" max-field-of-view="auto" reveal="auto"
range-request-strategy="performance"
environment-image="https://stormsend1.djicdn.com/uploads/3d/8f490eaaa02516662cbdba7233ec72bc.hdr"
ar-status="not-presenting" on-touchstart="if (this.canScale) {this.scale = 1;}">
<div slot="progress-bar"></div>
</model-viewer>
</div>
</div>
<ul class="tabs_flex">
<li><a href="#tab1" class="active">
<img src="./image/whiteimg.png" alt="" width="24" height="24" class="whiteicon">
<img src="./image/blockimg.png" alt="" width="24" height="24" class="blockicon">
Photos
</a></li>
<li><a href="#tab2">
<img src="./image/block3d.png" alt="" width="24" height="24" class="blockicon">
<img src="./image/white3d.png" alt="" width="24" height="24" class="whiteicon">
3D</a></li>
</ul>
</div>
<script>
$(function () {
// 定义一个对象来记录每个 tab 是否已经加载过内容
var loaded = {
tab1: false,
tab2: false
};
// 绑定 tab 点击事件
$('.tabs_flex a').click(function (e) {
e.preventDefault();
// 获取当前点击的 tab 的 ID
var tabId = $(this).attr('href');
console.log(tabId)
// 如果该 tab 还未加载过内容,则加载内容
if (!loaded[tabId.substring(1)]) {
if (tabId == "#tab2") {
//加载3D渲染
var render = new Render();
//渲染以及绑定事件
render.domRender();
}
loaded[tabId.substring(1)] = true;
}
// 隐藏所有 tab 内容并移除 active 类
$('.tab-content').removeClass('active');
$('.tabs_flex a').removeClass('active');
// 显示当前点击的 tab 内容并添加 active 类
$(tabId).addClass('active');
$(this).addClass('active');
});
});
//model_list = model_list.reverse();
//封装渲染
class Render {
domRender() {
const viewer = document.querySelector('model-viewer');
// viewer.minScale = 0.1; // 设置最小缩放比例为50%
function loading() {
const progressBar = document.getElementById('progress');
const loadingText = document.getElementById('loading-text');
viewer.addEventListener('progress', (event) => {
const loaded = event.detail.totalProgress;
loadingText.textContent = `${(loaded * 100).toFixed(0)}%`;
});
viewer.addEventListener('load', () => {
loadingText.textContent = 'Loading Complete!';
setTimeout(() => {
document.getElementById('loading').style.display = 'none';
}, 500);
//100%后清除定时器
clearInterval(loadingInterval);
});
}
const loadingInterval = setInterval(loading, 100);
}
}
</script>
</body>
</html>