基于 HTML5 WebGL 实现的垃圾分类系统


Posted in HTML / CSS onOctober 08, 2019

前言

垃圾分类,一般是指按一定规定或标准将垃圾分类储存、分类投放和分类搬运,从而转变成公共资源的一系列活动的总称。分类的目的是提高垃圾的资源价值和经济价值,力争物尽其用。垃圾在分类储存阶段属于公众的私有品,垃圾经公众分类投放后成为公众所在小区或社区的区域性准公共资源,垃圾分类搬运到垃圾集中点或转运站后成为没有排除性的公共资源。从国内外各城市对生活垃圾分类的方法来看,大致都是根据垃圾的成分、产生量,结合本地垃圾的资源利用和处理方式来进行分类的。到2019年6月25日,生活垃圾分类制度将入法。一套应用于工业物联网的智能一体化的垃圾分类机械臂将随之而来,由此,我应用 HT for Web  的图型化编辑工具打造了一款形象生动的例子:Garbage classification,也借此机会与大家一起分享和学习。

代码实现

基于 HTML5 WebGL 实现的垃圾分类系统

(注:gif 的上传大小有限,实际效果与还请参考 demo 链接)

首先,我应用已经精心布置好的 3D 场景,为了有更好的操作体验感,我们要从它的基本设置开始:

gv.setMovableFunc(() => { return false }) // 禁止拖动
gv.getWireframe = (d) => { d.s('wf.visible', false) }  // 隐藏选中边框
gv.setEye([583, -212, -789]) // 设置眼睛
gv.setCenter([-76, -654, -133]) // 设置中心点
gv.setFar(100000) // 设置远端位置
gv.setNear(10) // 设置近端位置
gv.setInteractors([ new ht.graph3d.MapInteractor(gv) ]) // 设置交互限制
gv.setSkyBox(dm.getDataByTag('skyBox')) // 设置天空球
window.document.oncontextmenu = () => { return false } // 全局设置右键菜单禁用
gv.scene = { // 复制初始位置
    eye: ht.Default.clone(gv.getEye()),
    center: ht.Default.clone(gv.getCenter()),
    far: ht.Default.clone(gv.getFar()),
    near: ht.Default.clone(gv.getNear()),
}

 

我复制了一下整个场景的初始视角情况方便我做稍后的处理,我监听了部分鼠标事件来形成自己的操作风格(比如双击背景还原视角以及双击模型拉近视角):

gv.mi(e => {
    let data = e.data
    let kind = e.kind
    if (kind === 'doubleClickBackground') { // 双击背景
        gv.moveCamera(this.gv.scene.eye, this.gv.scene.center, {duration : 1000}) // 恢复视角
    }
    else if (kind === 'doubleClickData') { // 双击模型
        gv.flyTo(data, {animation : {duration : 500}, distance : 800}) // 拉近视角
    }
})

 

基于 HTML5 WebGL 实现的垃圾分类系统

好了,准备工作做好了,下面来实现动画部分,除了了解 垃圾分类 的方式外我还参考了网上很多机械臂的视频,学习它的运动模式和动作细节,对每个结构和部位的动画进行步骤的排序和构思。这里我挑选几处动画的实现方式来展示:

 

function mechanicalArmAnim1() {
ht.Default.startAnim({


duration: 1000,


easing: (t) => { return t },


action: (v, t) => {



postbrachium.r3(degrees(0) + (degrees(20) - degrees(0)) * v, postbrachium.r3()[1], postbrachium.r3()[2]) // 后臂向下移


},


finishFunc: () => {



setTimeout(() => {




mechanicalArmAnim2()



}, 300)


}

})
}
function mechanicalArmAnim2() {

ht.Default.startAnim({


duration: 1000,


easing: (t) => { return t },


action: (v, t) => {



postbrachium.p3(-208 + (-184 + 208) * v, postbrachium.p3()[1], postbrachium.p3()[2]) // 后臂前伸



hydraulicRod1.r3(degrees(0) + (degrees(8) - degrees(0)) * v, hydraulicRod1.r3()[1], hydraulicRod1.r3()[2]) // 液压杆1倾斜



extensionRod1.r3(degrees(0) + (degrees(8) - degrees(0)) * v, extensionRod1.r3()[1], extensionRod1.r3()[2]) // 伸长杆1倾斜



extensionRod1.p3(-169 + (-185 + 169) * v, -516 + (-511 + 516) * v, extensionRod1.p3()[2]) // 伸长杆1伸长



hydraulicRod2.r3(degrees(0) + (degrees(-8) - degrees(0)) * v, hydraulicRod2.r3()[1], hydraulicRod2.r3()[2]) // 液压杆2倾斜



extensionRod2.r3(degrees(0) + (degrees(-8) - degrees(0)) * v, extensionRod2.r3()[1], extensionRod2.r3()[2]) // 伸长杆2倾斜



extensionRod2.p3(-169 + (-185 + 169) * v, -516 + (-511 + 516) * v, extensionRod2.p3()[2]) // 伸长杆2伸长


},


finishFunc: () => {



setTimeout(() => {




mechanicalArmAnim3()



}, 300)


}

})
}
function mechanicalArmAnim3() {

let oldValue = antebrachium.r3()[0]

ht.Default.startAnim({


duration: 1000,


easing: (t) => { return t },


action: (v, t) => {



hydraulicRod1.r3(degrees(8) + (degrees(7) - degrees(8)) * v, hydraulicRod1.r3()[1], hydraulicRod1.r3()[2]) // 液压杆1倾斜



extensionRod1.r3(degrees(8) + (degrees(7) - degrees(8)) * v, extensionRod1.r3()[1], extensionRod1.r3()[2]) // 伸长杆1倾斜



extensionRod1.p3(-185 + (-186 + 185) * v, -511 + (-507 + 511) * v, extensionRod1.p3()[2]) // 伸长杆1伸长



hydraulicRod2.r3(degrees(-8) + (degrees(-7) - degrees(-8)) * v, hydraulicRod2.r3()[1], hydraulicRod2.r3()[2]) // 液压杆2倾斜



extensionRod2.r3(degrees(-8) + (degrees(-7) - degrees(-8)) * v, extensionRod2.r3()[1], extensionRod2.r3()[2]) // 伸长杆2倾斜



extensionRod2.p3(-185 + (-186 + 185) * v, -511 + (-507 + 511) * v, extensionRod2.p3()[2]) // 伸长杆2伸长



postbrachium.r3(degrees(20) + (degrees(25) - degrees(20)) * v, postbrachium.r3()[1], postbrachium.r3()[2]) // 后臂向下移



antebrachium.r3(oldValue + (degrees(-40) - oldValue) * v, antebrachium.r3()[1], antebrachium.r3()[2]) // 前臂向下移



claw1.r3(degrees(-20) + (degrees(-60) - degrees(-20)) * v, claw1.r3()[1], claw1.r3()[2]) // 上爪抓取



claw2.r3(degrees(-60) + (degrees(-30) - degrees(-60)) * v, claw2.r3()[1], claw2.r3()[2]) // 下爪抓取


},


finishFunc: () => {



mechanicalArmAnim4()


}

})
}

 

基于 HTML5 WebGL 实现的垃圾分类系统

这一段动画是机械臂从初始化状态到向下抓取的一个过程,我将每段动画分成函数来写比较方便后续管理,每一处也代表了一个步骤。这其中最复杂且细微的步骤要数液压杆的运动了,为了让动画看起来更加真实,我除了将手臂单独运动的过程中加入了延时执行下一段动画以体现机器运动的特点外,也把液压杆的部分也做了动画,如果不做处理,那么机械臂在上下移动的时候就会有不科学的效果出现。动画函数 在这种 demo 中应用的最广,而且里面也包含了一些缓动函数,有兴趣的博友们可以 点此处 自己亲自动手玩一玩~

基于 HTML5 WebGL 实现的垃圾分类系统基于 HTML5 WebGL 实现的垃圾分类系统

这里面的拾取垃圾步骤还应用了我过去介绍过的 吸附 功能,这个方法非常的适合抓取物体的动作,通过 setHost 使节点吸附于宿主,这样就相当于子节点跟随父节点移动,此时只需要对机械臂进行偏移和旋转的操作,垃圾便会随之一起运动了,大大减少了工作量!

基于 HTML5 WebGL 实现的垃圾分类系统

还有一部分更酷的属性设置给大家展示一下,可以让 3D 场景整体有更真实的阴影处理效果。首先我们要注意将无关的节点阴影通过 node.s('shadow.cast', false) 关闭,比如编组用的box,背景,地板和面板等。

最后我们就把阴影的细节做下调整,达到比较好的效果:

 

gv.enableShadow(true, {
degreeX : 0,       // 投影 x 轴角度

degreeZ : -25,      // 投影 z 轴角度

intensity : 0.3,    // 阴影强度, 1 为黑色

quality : 'high',  // low / medium / high / ultra / 4096数值, 质量

type : 'soft',     // none / hard / soft

radius : 0.2,      // type 为 hard / soft 时,补充的边缘厚度,用来提供更柔和的边缘

bias : -0.003     // 深度浮点偏差补足
})

总结

更多动画 demo 以及工业化领域的文章请继续关注我的博客,感谢大家的支持!

医疗站(https://www.cnblogs.com/htdaydayup/p/11558748.html)

基于 HTML5 WebGL 实现的垃圾分类系统

在工业物联网从婴儿走到青年的成熟道路上,一定会有更多的潜力和挑战在等着我们,等待我们去开发,等待我们去创造!相信我们的技术成为国际水准会指日可待!同时在十一国庆后的第一个工作日祝大家精神饱满,工作顺利!

总结

以上所述是小编给大家介绍的基于 HTML5 WebGL 实现的垃圾分类系统,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!
如果你觉得本文对你有帮助,欢迎转载,烦请注明出处,谢谢!

HTML / CSS 相关文章推荐
css3实现背景图片拉伸效果像桌面壁纸一样
Aug 19 HTML / CSS
详解CSS3选择器的使用方法汇总
Nov 24 HTML / CSS
详解CSS透明opacity和IE各版本透明度滤镜filter的最准确用法
Dec 20 HTML / CSS
详解css3使用transform出现字体模糊的解决办法
Oct 16 HTML / CSS
html5的localstorage详解
May 09 HTML / CSS
使用Canvas操作像素的方法
Jun 14 HTML / CSS
使用CSS实现弹性视频html5案例实践
Dec 26 HTML / CSS
HTML5 拖放功能实现代码
Jul 14 HTML / CSS
详解HTML5中表单验证的8种方法介绍
Dec 19 HTML / CSS
高清屏下canvas重置尺寸引发的问题的解决
Oct 14 HTML / CSS
详解淘宝H5 sign加密算法
Aug 25 HTML / CSS
萌新的HTML5 入门指南
Nov 06 HTML / CSS
HTML5移动端开发遇见的东西
Oct 11 #HTML / CSS
分享一个页面平滑滚动小技巧(推荐)
Oct 23 #HTML / CSS
分享一个H5原生form表单的checkbox特效代码
Feb 26 #HTML / CSS
利用HTML5+css3+jquery+weui实现仿微信聊天界面功能
Jan 08 #HTML / CSS
canvas基础之图形验证码的示例
Jan 02 #HTML / CSS
HTML5实现分享到微信好友朋友圈QQ好友QQ空间微博二维码功能
Jan 03 #HTML / CSS
html5 canvas绘制放射性渐变色效果
Jan 04 #HTML / CSS
You might like
php判断类是否存在函数class_exists用法分析
2014/11/14 PHP
jquery 插件 人性化的消息显示
2008/01/21 Javascript
javascript中encodeURI和decodeURI方法使用介绍
2013/05/06 Javascript
JQuery中使用Ajax赋值给全局变量失败异常的解决方法
2014/08/18 Javascript
jQuery数据缓存用法分析
2015/02/20 Javascript
JQuery标签页效果实例详解
2015/12/24 Javascript
JS代码防止SQL注入的方法(超简单)
2016/04/12 Javascript
JS实现登录页面记住密码和enter键登录方法推荐
2016/05/10 Javascript
js利用正则表达式检验输入内容是否为网址
2016/07/05 Javascript
JavaScript原生数组Array常用方法
2017/04/06 Javascript
JavaScript循环_动力节点Java学院整理
2017/06/28 Javascript
Vue异步组件处理路由组件加载状态的解决方案
2018/09/07 Javascript
浅谈HTTP 缓存的那些事儿
2018/10/17 Javascript
Windows下Node爬虫神器Puppeteer安装记
2019/01/09 Javascript
使用layui 的layedit定义自己的toolbar方法
2019/09/18 Javascript
uni-app实现获取验证码倒计时功能
2020/11/01 Javascript
python中引用与复制用法实例分析
2015/06/04 Python
Python实现感知器模型、两层神经网络
2017/12/19 Python
wxPython的安装图文教程(Windows)
2017/12/28 Python
Python决策树之基于信息增益的特征选择示例
2018/06/25 Python
Python使用os.listdir()和os.walk()获取文件路径与文件下所有目录的方法
2019/04/01 Python
Django的性能优化实现解析
2019/07/30 Python
Django中create和save方法的不同
2019/08/13 Python
利用Python裁切tiff图像且读取tiff,shp文件的实例
2020/03/10 Python
在Python中使用K-Means聚类和PCA主成分分析进行图像压缩
2020/04/10 Python
css3学习之2D转换功能详解
2016/12/23 HTML / CSS
HTML5 WebSocket实现点对点聊天的示例代码
2018/01/31 HTML / CSS
英国最大的独立家具零售商:Furniture Village
2016/09/06 全球购物
安全的后院和健身蹦床:JumpSport
2019/07/15 全球购物
英国领先的新鲜松露和最好的松露产品供应商:TruffleHunter
2019/08/26 全球购物
碧欧泉法国官网:Biotherm法国
2019/10/23 全球购物
Set里的元素是不能重复的,那么用什么方法来区分重复与否呢? 是用==还是equals()? 它们有何区别?
2014/07/27 面试题
资料员岗位职责
2013/11/17 职场文书
闭幕式主持词
2014/04/02 职场文书
大连导游词
2015/02/12 职场文书
详解nginx.conf 中 root 目录设置问题
2021/04/01 Servers