index.js 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. const info = wx.getSystemInfoSync();
  2. const dpi = info.pixelRatio;
  3. const width = info.windowWidth * dpi;
  4. const height = info.windowHeight * dpi;
  5. Component({
  6. scene: null,
  7. properties: {},
  8. data: {
  9. width: width,
  10. height: height,
  11. loaded: false,
  12. arReady: false,
  13. placed: false,
  14. gateClosed: false
  15. },
  16. lifetimes: {
  17. attached() {
  18. wx.reportEvent("xr_frame", {
  19. "xr_page_path": '/pages/scene-last-record/index',
  20. "xr_last_record_click": 1
  21. });
  22. },
  23. detached() {
  24. this.bgm.stop();
  25. wx.setKeepScreenOn({keepScreenOn: false});
  26. }
  27. },
  28. methods: {
  29. handleReady({detail}) {
  30. this.scene = detail.value;
  31. this.scene.event.add('tick', this.handleTick.bind(this));
  32. this.inRealWorld = true;
  33. this.texts = {};
  34. this.textsIndex = {};
  35. this.bgm = wx.createInnerAudioContext({});
  36. this.bgm.src = 'https://mmbizwxaminiprogram-1258344707.cos.ap-guangzhou.myqcloud.com/xr-frame/demo/xr-frame-team/bgm.mp3';
  37. this.bgm.loop = true;
  38. },
  39. handleAssetsProgress: function ({detail}) {
  40. console.log('assets progress', detail.value);
  41. },
  42. handleARReady() {
  43. this.setData({arReady: true});
  44. },
  45. handleAssetsLoaded: function ({detail}) {
  46. console.log('assets loaded', detail.value);
  47. this.records = JSON.parse(this.scene.assets.getAsset('raw', 'records'));
  48. this.note = this.scene.assets.getAsset('raw', 'note');
  49. this.setData({loaded: true});
  50. },
  51. handleTick(dt) {
  52. this.syncTexts();
  53. if (!this.data.placed || !this.inRealWorld) {
  54. return;
  55. }
  56. const xrSystem = wx.getXrFrameSystem();
  57. const mainCamEl = this.scene.getElementById('main-camera');
  58. const mainTrs = mainCamEl.getComponent(xrSystem.Transform);
  59. const door = this.scene.getElementById('door').getComponent(xrSystem.Transform);
  60. let forward = door.worldForward;
  61. forward = xrSystem.Vector2.createFromNumber(forward.x, forward.z);
  62. let diff = mainTrs.worldPosition.sub(door.worldPosition);
  63. diff = xrSystem.Vector2.createFromNumber(diff.x, diff.z);
  64. const preDiff = this.diff || diff;
  65. this.diff = diff;
  66. const dis = diff.length();
  67. const preDis = preDiff.length();
  68. const dir = forward.dot(diff);
  69. this.startDis = this.startDis || dis;
  70. const blurAsset = this.scene.assets.getAsset('post-process', 'blur');
  71. const vignetteAsset = this.scene.assets.getAsset('post-process', 'vignette');
  72. const bloomAsset = this.scene.assets.getAsset('post-process', 'bloom');
  73. const edgeEnv1 = 0.5;
  74. const edgeEnv2 = 0.8;
  75. const edgeDoor1 = 0.3;
  76. const edgeDoor2 = 0.7;
  77. if (this.blurDuration) {
  78. this.blurDuration = Math.max(0, this.blurDuration - dt);
  79. const p = 1 - this.blurDuration / this.blurTotal;
  80. if (p <= edgeEnv1) {
  81. const progress = xrSystem.noneParamsEaseFuncs['ease-in-out'](p / edgeEnv1);
  82. vignetteAsset.data.intensity = progress * 2;
  83. blurAsset.data.radius = progress * 86 + 10;
  84. } else if (p > edgeEnv2) {
  85. const progress = xrSystem.noneParamsEaseFuncs['ease-in-out']((1 - p) / (1 - edgeEnv2));
  86. vignetteAsset.data.intensity = progress * 2;
  87. blurAsset.data.radius = progress * 96;
  88. }
  89. if (p >= edgeDoor1 && p < edgeDoor2) {
  90. const progress = xrSystem.noneParamsEaseFuncs['ease-in-out']((p - edgeDoor1) / (edgeDoor2 - edgeDoor1));
  91. door.scale.setValue(progress, 1, 1);
  92. }
  93. } else if (this.blurTotal) {
  94. let progress = (1 - Math.max(0, Math.min(dis / this.startDis, 0.8)));
  95. if (progress >= 0.2) {
  96. progress = (progress - 0.2) / 0.6;
  97. blurAsset.data.radius = progress * 96;
  98. vignetteAsset.data.intensity = progress * 2;
  99. bloomAsset.data.threshold = 0.5 + progress * 2;
  100. }
  101. }
  102. //@todo: 等待物理加上碰撞检测,替换
  103. if (dir >= 0 || preDis <= 0.2 || dis > 0.2) {
  104. return;
  105. }
  106. ['sky', 'scene-mesh', 'hikari', 'roam', 'xinyi'].forEach(id => {
  107. this.scene
  108. .getElementById(id)
  109. .getComponent(xrSystem.GLTF).meshes.forEach(mesh => mesh.material.setRenderState('stencilComp', 0));
  110. });
  111. mainCamEl.getComponent(xrSystem.Camera).setData({
  112. renderTarget: null,
  113. postProcess: ['tone']
  114. });
  115. this.setData({gateClosed: true});
  116. this.inRealWorld = false;
  117. },
  118. handleShowDoor({detail}) {
  119. if (detail.value.camera.el.id !== 'main-camera') {
  120. return;
  121. }
  122. const success = this.scene.ar.placeHere('setitem', true);
  123. if (!success) {
  124. return;
  125. }
  126. setTimeout(() => {
  127. this.blurTotal = this.blurDuration = 1700;
  128. }, 300);
  129. wx.setKeepScreenOn({keepScreenOn: true});
  130. this.bgm.play();
  131. this.setData({placed: true});
  132. },
  133. handleResume() {
  134. if (this.data.placed) {
  135. this.bgm.play();
  136. }
  137. },
  138. handleTouchNote({detail}) {
  139. if (detail.value.camera.el.id !== 'main-camera') {
  140. return;
  141. }
  142. this.triggerEvent('showNote', this.note);
  143. },
  144. handleTouchObj({detail}) {
  145. if (detail.value.camera.el.id !== 'main-camera') {
  146. return;
  147. }
  148. const xrSystem = wx.getXrFrameSystem();
  149. const {el, value} = detail;
  150. const {camera, target} = value;
  151. const id = target.id;
  152. let text = this.texts[id];
  153. const camTrs = camera.el.getComponent(xrSystem.Transform);
  154. const targetTrs = target.getComponent(xrSystem.Transform);
  155. const diff = camTrs.worldPosition.sub(targetTrs.worldPosition);
  156. const distance = Math.sqrt(diff.x * diff.x + diff.z * diff.z);
  157. if (!this.records[id]) {
  158. return;
  159. }
  160. const {y, d, texts: records} = this.records[id];
  161. if (distance > (d || 1.5)) {
  162. return;
  163. }
  164. if (text) {
  165. clearTimeout(text.timerId);
  166. }
  167. let index = this.textsIndex[id] === undefined ? -1 : this.textsIndex[id];
  168. if (index >= records.length - 1) {
  169. index = 0;
  170. } else {
  171. index += 1;
  172. }
  173. this.textsIndex[id] = index;
  174. this.texts[id] = {
  175. content: records[index],
  176. camera, target, y,
  177. timerId: setTimeout(() => {
  178. delete this.texts[id];
  179. }, 4000)
  180. };
  181. },
  182. syncTexts: function() {
  183. const texts = Object.keys(this.texts).map(id => {
  184. const {camera, target, content, y} = this.texts[id];
  185. const xrSystem = wx.getXrFrameSystem();
  186. const trs = target.getComponent(xrSystem.Transform);
  187. const tmp = trs.worldPosition.clone();
  188. tmp.y += y;
  189. const clipPos = camera.convertWorldPositionToClip(tmp);
  190. const {frameWidth, frameHeight} = this.scene;
  191. return {
  192. content, id,
  193. x: ((clipPos.x + 1) / 2) * frameWidth,
  194. y: (1 - (clipPos.y + 1) / 2) * frameHeight
  195. };
  196. });
  197. this.triggerEvent('changeTexts', texts);
  198. }
  199. }
  200. })