网站主管们! 3招 进到 3D Web
2014-08-01
在这篇文章中,我们将学习如何将 Blend4Web 创建的 3D 内容放置到网站。
方法 1︰嵌入 HTML 文件
将整个场景从 Blender 导出到单独的 HTML 文件,而无需依赖外部的方法,是 Blend4Web 相当令人兴 奋的特点之一。此类文件是全功能的Web网页,它可通过标准的浏览器打开并用任何方式分享。您可以 设置尺寸和其他受支持的属性,利用 iframe 容器,将其嵌入到网站中。
<!DOCTYPE html>
<html>
<head>
<title>Apple</title>
</head>
<body>
<iframe width="800" height="500" allowfullscreen src="/tutorials/examples/web_page_integration/apple.html"></iframe>
</body>
</html>
该方法的主要优点是它的简单性。初级 Blend4Web 用户可以按照下列步骤操作:
- 下载 并安装 Blender 插件 (见 视频 或 用户手册);
- 导出预先创建的场景 File > Export > Blend4Web (.html);
- 配置生成的 HTML 文件到 iframe 容器中。
方法2:网络播放器 Web Player
第二种方式是第一种的替代版本。其结果是一个嵌入 3D 内容与控制组件,被显示在页面上。
然而这种实现嵌入与前一个本质上不同:不是单一的 HTML 文件用于网络播放器和加载的 JSON 场景文件组合。
<!DOCTYPE html>
<html>
<head>
<title>Apple</title>
</head>
<body>
<iframe src="/apps/webplayer/webplayer.html?load=/tutorials/examples/web_page_integration/apple.json&show_fps"></iframe>
</body>
</html>
您可以从 from the Blend4Web SDK 发行的目录中,复制包含 web player 文件 deploy/apps/webplayer 并将 其部署在 web 站点上。
JSON 场景文件导出可以利用与 HTML 文件相同的方式 File > Export > Blend4Web (.json) 选项。 您可在您的 web 站点上指定路径 (绝对或相对) 放置生成的文件和 加载 web player 参数.
在此示例中除了强制性 加载 参数外,我们用另一种选项 ︰show_fps 用于显示帧速率。
你可以通过阅读相应的 用户手册,自己熟悉 web player。
注意
若要从本地文件系统运行 web player(即使没有 web server) 您需要设置您的浏览器加载本地资源。
虽然此方法看起来比第一个复杂点,但提供一堆好处︰
- 场景文件格式是简洁的 - 因此他们的加载速度更快;
- 场景是异步加载,不会阻塞加载的页面本身;
- 场景数据分散存储于 web player,来允许他们使用在其他应用程序中。
方法 3: Web 应用程序
最后我们可以将 web 页本身转换成一个交互式的 3D 应用程序!让我们用一个简单的例子证明︰我们放置一个按钮,它被按下时,会在此页播放有趣的动画效果。
免费的 Blend4Web SDK 发行版包含 独立的应用程序 ,來简化学习和调试。
瞧:页面内容不仅可以通过无形的 画布查看, 而背后半透明的 3D 对象移动时亦有高光动态的变化。
我们将在下一篇文章中,谈论这个动画效果如何创建。现在让我们瞧瞧它如何挂到到该页上。我们将见到 ,做类似的东西,不比在 jQuery 或 Flash 里边复杂
首先我们将链接从 Blend4Web 发行的脚本引擎 (b4w.min.js) 。 我们会在 example.js 文件中编写示例代 码。 我们将在 example.css 文件中编写 CSS 样式 ︰
<link rel="stylesheet" type="text/css" href="example.css">
<script type="text/javascript" src="b4w.min.js"></script>
<script type="text/javascript" src="example.js"></script>
然后我们在网页里替选 渲染区域canvas_cont 和 效果发射按钮run_button 准备一个容器。将所有的元素包裹到 父级容器wrapper_container 中,以简化内容:
<div id="wrapper_container">
<div id="canvas_cont"></div>
<div id="run_button" class="en"></div>
</div>
了解 CSS 应用程序:
#canvas_cont {
position: absolute;
width: 1200px;
height: 1200px;
bottom: -350px;
pointer-events: none;
}
div#wrapper_container {
position: relative;
}
@media screen and (min-width: 1000px) and (max-width: 1200px) {
#canvas_cont {
height: 1000px;
width: 1000px;
}
}
@media screen and (max-width: 1000px) {
#canvas_cont {
width: 100vw;
height: 100vw;
bottom: 0;
}
}
div#run_button.ru,
div#run_button.en {
width: 236px;
height: 60px;
margin: 0 auto;
cursor: pointer;
background-image: url(interface/button.png);
background-size: 472px 120px;
}
div#run_button.en {
background-position: -236px 0;
}
div#run_button.ru:hover {
background-position: 0 -60px;
}
div#run_button.en:hover {
background-position: -236px -60px;
}
设置渲染区域的 宽width 高height 和 位置position。相对于之于父级元素,下移容器 bottom 350px像素. 设置 事件点pointer-events 属性为 无none. 该属性允许元素不接收 悬停hover / 点击click 事件, 取而代之的,事件将发生在它背后的任何状况下 ︰
#canvas_cont {
position: absolute;
width: 1200px;
height: 1200px;
bottom: -350px;
pointer-events: none;
}
注意
有关 pointer-events 属性的详细信息,请跟随链接 developer.mozilla.org/en-US/docs/Web/CSS/pointer-events。
设置 div#wrapper_container 元素的相对位置。有必要保持父级容器中的子元素 ︰
div#wrapper_container {
position: relative;
}
修正一点宽度、 高度、 位置,来符合较小屏幕的设备 ︰
@media screen and (min-width: 1000px) and (max-width: 1200px) {
#canvas_cont {
height: 1000px;
width: 1000px;
}
}
@media screen and (max-width: 1000px) {
#canvas_cont {
width: 100vw;
height: 100vw;
bottom: 0;
}
}
设置了启动按钮的 CSS 样式:
div#run_button.ru,
div#run_button.en {
width: 236px;
height: 60px;
margin: 0 auto;
cursor: pointer;
background-image: url(interface/button.png);
background-size: 472px 120px;
}
div#run_button.en {
background-position: -236px 0;
}
div#run_button.ru:hover {
background-position: 0 -60px;
}
div#run_button.en:hover {
background-position: -236px -60px;
}
在此列出全部的 example.js代码︰
"use strict";
b4w.register("example_main", function(exports, require) {
var m_anim = require("animation");
var m_app = require("app");
var m_data = require("data");
var m_main = require("main");
var m_scs = require("scenes");
var m_sfx = require("sfx");
exports.init = function() {
m_app.init({
canvas_container_id: "canvas_cont",
callback: init_cb,
physics_enabled: false,
alpha: true,
report_init_failure: false,
media_auto_activation: false
});
}
function init_cb(canvas_elem, success) {
if (!success) {
console.log("b4w init failure");
return;
}
if (window.web_page_integration_dry_run)
m_data.load("flying_letters.json", load_cb);
else
m_data.load("/tutorials/examples/web_page_integration/flying_letters.json", load_cb);
resize();
window.addEventListener("resize", resize);
}
function resize() {
m_app.resize_to_container();
}
function load_cb(root) {
var letters_arm = m_scs.get_object_by_name('beads_armature');
m_anim.stop(letters_arm);
run_button.addEventListener("mousedown", demo_link_click, false);
}
function demo_link_click(e) {
m_data.activate_media();
var letters_arm = m_scs.get_object_by_name('beads_armature');
var spk = m_scs.get_object_by_name("Speaker");
m_sfx.play_def(spk);
m_anim.apply(letters_arm, "flying_letters");
m_anim.play(letters_arm, letters_obj_cb);
}
function letters_obj_cb(obj) {
m_anim.apply(obj, "flying_letters_idle");
m_anim.set_behavior(obj, m_anim.AB_CYCLIC);
m_anim.play(obj);
}
});
b4w.require("example_main").init();
注意 init 参数 - 我们打开渲染区域透明度 alpha:
exports.init = function() {
m_app.init({
canvas_container_id: "canvas_cont",
callback: init_cb,
physics_enabled: false,
alpha: true,
report_init_failure: false,
media_auto_activation: false
});
}
加载场景:
if (window.web_page_integration_dry_run)
m_data.load("flying_letters.json", load_cb);
else
m_data.load("/tutorials/examples/web_page_integration/flying_letters.json", load_cb);
注意
在独立的应用程序中检查 web_page_integration_dry_run 變量的執行,來設置正確的 JSON 路徑。也就是 JSON 路徑在應用程序中是為 "flying_letters.json",但在當前頁面是 "/tutorials/examples/web_page_integration/flying_letters.json".
下面是将变量添加到 web_page_integration_dry_run 成 html 文件的示例 ︰
<script type="text/javascript">
window.web_page_integration_dry_run = true;
</script>
添加浏览器窗口调整大小事件的监听器 window.addEventListener。然后调用 resize() 函数使它生效︰
window.addEventListener("resize", resize);
resize();
如他的父级容器, resize()函数使用 resize_to_container() 的方法,设置当前元素的宽度和高度:
function resize() {
m_app.resize_to_container();
}
场景加载,执行 load_cb() 函数后。在它里边我们停止动画,因为我们已经为它在 Blender 里启用了 auto-run自动运行 模式。然后我们将 mousedown 事件附加到 #run_button 元素里 ︰
var letters_arm = m_scs.get_object_by_name('beads_armature');
m_anim.stop(letters_arm);
run_button.addEventListener("mousedown", demo_link_click, false);
当单击 #run_button 时会调用 demo_link_click() 函数。 在它里边我们播放声音和运行气球飞行动画 ︰
m_data.activate_media();
var letters_arm = m_scs.get_object_by_name('beads_armature');
var spk = m_scs.get_object_by_name("Speaker");
m_sfx.play_def(spk);
m_anim.apply(letters_arm, "flying_letters");
m_anim.play(letters_arm, letters_obj_cb);
当飞行动画完成后 letters_obj_cb() 被调用。 在此我们启动气球摇摆的循环动画 ︰
m_anim.apply(obj, "flying_letters_idle");
m_anim.set_behavior(obj, m_anim.AB_CYCLIC);
m_anim.play(obj);
就是这样!
结论
WebGL 给了一个独一无二的机会,无缝的与其他 web 技术集成交互式 3D 内容。在 Blender 里您可以 轻松地创建此类内容给 Blend4Web 、 部署在 web 页里和从逻辑上,它将与任何 HTML 元素相结合。
更新日志
[2014-08-01] 首次发布。
[2014-10-22] 更新文件路径
[2014-10-30] 更新 web player 的链接。添加 allowfullscreen 属性。删除过时的 bg 参数。
[2014-12-03] 添加声音
[2015-04-23] Webplayer 源文件的路径更新。更新变量和动画名称。从 m_app.init() 函数中,删除 deferred_rendering 和 context_antialias 参数。
[2015-05-15] 添加 CSS 样式描述。把渲染区域大小调整逻辑,从脚本替换到 CSS 数据表中。替独立的应用程序添加链 接。添加了 resize() function 功能描述。
[2015-12-10] 删除 app.js 模块。
[2016-02-11] 修正 css。