物聯(lián)網(wǎng)不知道喜歡小編的小伙伴們是不是有點耳熟,沒錯它是在近些年中逐漸流行的一個熱門話題,而且在生活中我們已經(jīng)開始在使用了。那么今天我們進(jìn)來講講有關(guān)于:“ 醫(yī)療物流系統(tǒng)怎么在HTML5 WebGL中實現(xiàn)? ”這個問題。
前言
物聯(lián)網(wǎng)( IoT ),簡單的理解就是物體之間通過互聯(lián)網(wǎng)進(jìn)行鏈接。世界上的萬事萬物,都可以通過數(shù)據(jù)的改變進(jìn)行智能化管理。IoT 的興起在醫(yī)療行業(yè)中具有拯救生命的潛在作用。
不斷的收集用戶信息并且實時的進(jìn)行診斷,所以未來 IoT 肯定在醫(yī)療行業(yè)的應(yīng)用會呈覆蓋性。下面是我最近做的一個醫(yī)療物流系統(tǒng),用來觀察醫(yī)療物流過程。
ht官網(wǎng)鏈接:http://www.hightopo.com/cn-index.html
demo鏈接: https://www.hightopo.com/demo/pivas/
實現(xiàn)過程
增加光源
整個原場景其實是非常暗的,所以需要使用燈光的效果照亮整個場景,使其接近真實世界的場景。
我們看下對比。
light 的一些屬性:
type 代表燈光的類型
color 代表燈光的顏色
intensity 代表燈光的強(qiáng)度(1是最大值)
range 代表范圍
addLight() {
const skyBox = this.dm.getDataByTag('skyBox')
// 限制視野在天空球之內(nèi)
this.gv.setSkyBox(skyBox)
const light = new ht.Light()
const lightSource = this.dm.getDataByTag('sunlight').p3()
const config = {
'light.type': 'point',
'light.color': 'white',
'light.intensity': 0.3,
'light.range': 10000
}
light.s(config)
light.p3(lightSource)this.dm.add(light)
}
看向物體
看到左下角的一個小窗口,其實是另一個3d場景,把它定位到左下角的,兩個場景都使用了反序列化( deserialize )。
因為要定位醫(yī)療箱移動,所以這里使用到了 flyTo 方法 。
var renderCanvas = function (medical, duration) {
ht.Default.startAnim({
duration,
easing(v, t) {
return t
},
action(v, t) {
outScreenG3d.flyTo(medical, { direction: [-5, 3, 5], distance: 300 })
}
})
}
封裝動畫
如果要實現(xiàn)這么多的動畫,首先想到的是一個個物體進(jìn)行移動的過程。醫(yī)療箱的行走、電梯的升降、傳送帶運送醫(yī)療箱等我們都可以對它們的動作進(jìn)行封裝。
如圖可以看到醫(yī)療箱總是在動,所以定義了一個行走的動畫,每次醫(yī)療箱行走的距離、行走方向、動畫的配置都進(jìn)行傳參。
這里要說明的參數(shù):
1.node(對應(yīng)的元素)
2.fn(動畫執(zhí)行完進(jìn)行回調(diào)的函數(shù))
3.config(動畫配置)
4.coord(方向軸)
// 行走動畫
walkAnim(node, fn, config, coord) {
const { duration, space } = config
const positionArray = node.p3()
let isShadow = false
let ShadowNode = null
// 如果移動的元素是icu車或者供應(yīng)車的話 獲取它的陰影跟隨元素移動
if (node.getTag() === 'supply' || node.getTag() === 'icuCar') {
isShadow = true
ShadowNode = this.dm.getDataByTag(`${node.getTag()}Shadow`)
}
ht.Default.startAnim({
duration,
easing: function (t) {
return t
},
action(v, t) {
if (coord === 'x') {
node.p3(positionArray[0] + t * space, positionArray[1], positionArray[2])
isShadow && ShadowNode.p3(positionArray[0] + t * space, positionArray[1], positionArray[2])
} else if (coord === 'y') {
node.p3(positionArray[0], positionArray[1] + t * space, positionArray[2])
isShadow && ShadowNode.p3(positionArray[0], positionArray[1] + t * space, positionArray[2])
} else {
node.p3(positionArray[0], positionArray[1], positionArray[2] + t * space)
isShadow && ShadowNode.p3(positionArray[0], positionArray[1], positionArray[2] + t * space)
}
},
finishFunc() {
typeof fn === 'function' && fn(node)
}
})
}
物體之間的影響
電梯的升降會影響很多東西,比如頻臺的移動會帶著傳送帶和醫(yī)療箱,這里我用到了 sethost 吸附方法(吸附:節(jié)點指定宿主,宿主進(jìn)行改變會影響節(jié)點)。
很多場景下非常合適,我需要電梯升降的過程中帶用醫(yī)療箱和頻臺一起上升,還有醫(yī)療箱放到傳送帶的時候,醫(yī)療箱要動起來,感覺是這真的傳送帶在帶動醫(yī)療箱進(jìn)行運動。
這里要說明的參數(shù):
1.node(操作的電梯元素)
2.medicalKit(醫(yī)療箱)
3.fn(動畫執(zhí)行完進(jìn)行回調(diào)的函數(shù))
4.status (電梯上升和下降的狀態(tài))
5.config(動畫配置)
// 電梯升降動畫
elevatorAnim(node, medicalKit, fn, status, config) {
const self = this
// 獲取電梯的index 讓對應(yīng)的頻臺也跟著動
const elevatorIndex = node.getTag().replace(/[^0-9]/ig, '') - 0
// 獲取醫(yī)療箱的index 控制電梯升降的距離
const medicalKitIndex = medicalKit.getTag().replace(/[^0-9]/ig, '') - 0
const positionArray = node.p3()
const station = self.dm.getDataByTag(`station${elevatorIndex}`)
//吸附宿主
station.setHost(node)
medicalKit.setHost(node)
// 設(shè)置升降狀態(tài)
if (elevatorIndex === 3) self.elevatorRunning = true
// 升降距離 status 為 0 的時候是下降 最低部位的距離是固定的 所以只需要控制上升的距離
const medicalKitLevel = self.returnMedicalKitLevel(medicalKitIndex)
// 電梯的屬性
// 最低點的位置 Lowest
// 如果有軌道的話 就去軌道的位置 否則就按照層數(shù) orbitalP
// 第一層的位置 distance
let space
const addSpace = medicalKitIndex === 7 ? 100 : 0
if (status == 1) {
space = config.orbitalP ? config.orbitalP : config.distance + addSpace + (400 * medicalKitLevel)
} else {
space = config.Lowest
}
// 下降狀態(tài)時 醫(yī)療箱不會做動作
if (status === 0) {
medicalKit.setHost()
}
return ht.Default.startAnim({
duration: config.orbitalP ? 2000 : (medicalKitLevel === 0 && elevatorIndex == 3 ? 700 : 2500 + (medicalKitLevel * 1000)),
action(v, t) {
node.p3(
positionArray[0],
positionArray[1] + ((space - positionArray[1]) * t),
positionArray[2]
)
},
finishFunc() {
station.setHost()
typeof fn === 'function' && fn(node)
}
})
}
動畫方法
動畫的過程中有個問題需要處理就是等待電梯的動畫,醫(yī)療箱在動畫過程中,需要判斷電梯是否在上升,如果不在地面的話,需要等待。
我的思路是,當(dāng)醫(yī)療箱走到離電梯一點距離的時候,需要判斷電梯是否在上升狀態(tài),如果是的話,需要調(diào)用動畫暫停的方法。
當(dāng) elevatorRunning 為 false 的時候代表電梯沒有運動,否則在運動中。
電梯動畫開始的時候設(shè)置為 true,結(jié)束后設(shè)置變量為 false, 就可以監(jiān)控它的狀態(tài)了。
ht.Default.startAnim 方法返回一個實例,利用 action 方法, 實現(xiàn)輪詢監(jiān)聽動畫狀態(tài),然后進(jìn)行操作。
當(dāng) elevatorRunning 為 true 的話, 使用 anim.pause() 暫停當(dāng)前動畫。
當(dāng) elevatorRunning 為 false 的話, 使用 anim.resume() 繼續(xù)當(dāng)前動畫。
const anim = ht.Default.startAnim({
duration,
action(v, t) {
node.p3(
positionArray[0],
positionArray[1],
positionArray[2] - (tpMax - positionArray[2]) * t
);
if (index > 1 && self.elevatorRunning === true) {
if (node.p3()[2] <= stopMax) {
anim.pause();
const t = setInterval(() => {
if (self.elevatorRunning === false) {
anim.resume();
clearInterval(t);
}
}, 100);
}
}
},
finishFunc() {
typeof fn === "function" && fn();
}
});
事件監(jiān)聽(發(fā)布、訂閱)
因為需要監(jiān)聽某個當(dāng)前動畫的結(jié)束,然后進(jìn)行相機(jī)位移。
如圖,我需要監(jiān)聽第一個 3d 場景中顯示提示文字動畫結(jié)束,然后執(zhí)行第二個 3d 場景的顯示。因為2個是不同的場景,是不能用回調(diào)的方法監(jiān)聽到的,所以這里就用到了 eventBus 事件總線。
下面是 eventBus 的使用,第一個參數(shù)代表要監(jiān)聽的注冊函數(shù)名,第二個是回調(diào)函數(shù)。
// 事件總線 監(jiān)聽事件
eventbus.on('animation1', _ => {
const medical = dm.getDataByTag('medicalKit1')
renderView(medical, dm, gv)
})
下面是 eventBus 發(fā)射的使用,第一個參數(shù)代表要觸發(fā)的函數(shù)名,第二個是發(fā)射給函數(shù)的參數(shù)。
// 觸發(fā)事件
eventbus.emit("animation1", null);
總結(jié)
以上就是我們今天分享的有關(guān)于:“醫(yī)療物流系統(tǒng)怎么在HTML5 WebGL中實現(xiàn)?”這個問題的實現(xiàn)方法,當(dāng)然了我們可以通過html5實現(xiàn)的地方還是比較多的,如果你對于html5有興趣的話我們可以在W3Cschool中進(jìn)行深度學(xué)習(xí)!希望小編的分享對大家有所幫助!