const info = wx.getSystemInfoSync(); const dpi = info.pixelRatio; const width = info.windowWidth * dpi; const height = info.windowHeight * dpi; Component({ scene: null, properties: {}, data: { width: width, height: height, loaded: false, arReady: false, placed: false, gateClosed: false }, lifetimes: { attached() { wx.reportEvent("xr_frame", { "xr_page_path": '/pages/scene-last-record/index', "xr_last_record_click": 1 }); }, detached() { this.bgm.stop(); wx.setKeepScreenOn({keepScreenOn: false}); } }, methods: { handleReady({detail}) { this.scene = detail.value; this.scene.event.add('tick', this.handleTick.bind(this)); this.inRealWorld = true; this.texts = {}; this.textsIndex = {}; this.bgm = wx.createInnerAudioContext({}); this.bgm.src = 'https://mmbizwxaminiprogram-1258344707.cos.ap-guangzhou.myqcloud.com/xr-frame/demo/xr-frame-team/bgm.mp3'; this.bgm.loop = true; }, handleAssetsProgress: function ({detail}) { console.log('assets progress', detail.value); }, handleARReady() { this.setData({arReady: true}); }, handleAssetsLoaded: function ({detail}) { console.log('assets loaded', detail.value); this.records = JSON.parse(this.scene.assets.getAsset('raw', 'records')); this.note = this.scene.assets.getAsset('raw', 'note'); this.setData({loaded: true}); }, handleTick(dt) { this.syncTexts(); if (!this.data.placed || !this.inRealWorld) { return; } const xrSystem = wx.getXrFrameSystem(); const mainCamEl = this.scene.getElementById('main-camera'); const mainTrs = mainCamEl.getComponent(xrSystem.Transform); const door = this.scene.getElementById('door').getComponent(xrSystem.Transform); let forward = door.worldForward; forward = xrSystem.Vector2.createFromNumber(forward.x, forward.z); let diff = mainTrs.worldPosition.sub(door.worldPosition); diff = xrSystem.Vector2.createFromNumber(diff.x, diff.z); const preDiff = this.diff || diff; this.diff = diff; const dis = diff.length(); const preDis = preDiff.length(); const dir = forward.dot(diff); this.startDis = this.startDis || dis; const blurAsset = this.scene.assets.getAsset('post-process', 'blur'); const vignetteAsset = this.scene.assets.getAsset('post-process', 'vignette'); const bloomAsset = this.scene.assets.getAsset('post-process', 'bloom'); const edgeEnv1 = 0.5; const edgeEnv2 = 0.8; const edgeDoor1 = 0.3; const edgeDoor2 = 0.7; if (this.blurDuration) { this.blurDuration = Math.max(0, this.blurDuration - dt); const p = 1 - this.blurDuration / this.blurTotal; if (p <= edgeEnv1) { const progress = xrSystem.noneParamsEaseFuncs['ease-in-out'](p / edgeEnv1); vignetteAsset.data.intensity = progress * 2; blurAsset.data.radius = progress * 86 + 10; } else if (p > edgeEnv2) { const progress = xrSystem.noneParamsEaseFuncs['ease-in-out']((1 - p) / (1 - edgeEnv2)); vignetteAsset.data.intensity = progress * 2; blurAsset.data.radius = progress * 96; } if (p >= edgeDoor1 && p < edgeDoor2) { const progress = xrSystem.noneParamsEaseFuncs['ease-in-out']((p - edgeDoor1) / (edgeDoor2 - edgeDoor1)); door.scale.setValue(progress, 1, 1); } } else if (this.blurTotal) { let progress = (1 - Math.max(0, Math.min(dis / this.startDis, 0.8))); if (progress >= 0.2) { progress = (progress - 0.2) / 0.6; blurAsset.data.radius = progress * 96; vignetteAsset.data.intensity = progress * 2; bloomAsset.data.threshold = 0.5 + progress * 2; } } //@todo: 等待物理加上碰撞检测,替换 if (dir >= 0 || preDis <= 0.2 || dis > 0.2) { return; } ['sky', 'scene-mesh', 'hikari', 'roam', 'xinyi'].forEach(id => { this.scene .getElementById(id) .getComponent(xrSystem.GLTF).meshes.forEach(mesh => mesh.material.setRenderState('stencilComp', 0)); }); mainCamEl.getComponent(xrSystem.Camera).setData({ renderTarget: null, postProcess: ['tone'] }); this.setData({gateClosed: true}); this.inRealWorld = false; }, handleShowDoor({detail}) { if (detail.value.camera.el.id !== 'main-camera') { return; } const success = this.scene.ar.placeHere('setitem', true); if (!success) { return; } setTimeout(() => { this.blurTotal = this.blurDuration = 1700; }, 300); wx.setKeepScreenOn({keepScreenOn: true}); this.bgm.play(); this.setData({placed: true}); }, handleResume() { if (this.data.placed) { this.bgm.play(); } }, handleTouchNote({detail}) { if (detail.value.camera.el.id !== 'main-camera') { return; } this.triggerEvent('showNote', this.note); }, handleTouchObj({detail}) { if (detail.value.camera.el.id !== 'main-camera') { return; } const xrSystem = wx.getXrFrameSystem(); const {el, value} = detail; const {camera, target} = value; const id = target.id; let text = this.texts[id]; const camTrs = camera.el.getComponent(xrSystem.Transform); const targetTrs = target.getComponent(xrSystem.Transform); const diff = camTrs.worldPosition.sub(targetTrs.worldPosition); const distance = Math.sqrt(diff.x * diff.x + diff.z * diff.z); if (!this.records[id]) { return; } const {y, d, texts: records} = this.records[id]; if (distance > (d || 1.5)) { return; } if (text) { clearTimeout(text.timerId); } let index = this.textsIndex[id] === undefined ? -1 : this.textsIndex[id]; if (index >= records.length - 1) { index = 0; } else { index += 1; } this.textsIndex[id] = index; this.texts[id] = { content: records[index], camera, target, y, timerId: setTimeout(() => { delete this.texts[id]; }, 4000) }; }, syncTexts: function() { const texts = Object.keys(this.texts).map(id => { const {camera, target, content, y} = this.texts[id]; const xrSystem = wx.getXrFrameSystem(); const trs = target.getComponent(xrSystem.Transform); const tmp = trs.worldPosition.clone(); tmp.y += y; const clipPos = camera.convertWorldPositionToClip(tmp); const {frameWidth, frameHeight} = this.scene; return { content, id, x: ((clipPos.x + 1) / 2) * frameWidth, y: (1 - (clipPos.y + 1) / 2) * frameHeight }; }); this.triggerEvent('changeTexts', texts); } } })