| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898 |
- Component({
- behaviors: [require('../common/share-behavior').default],
- properties: {
- markerImg: {
- type: String
- },
- },
- data: {
- loaded: false,
- arReady: false,
- isStartPlay1: false,
- adlScale: '0 0 0',
- adlPos: '-0.1 -0.5 -0.05',
- sunReady: false,
- tigerReady: false,
- item1Loaded: false,
- item2Loaded: false,
- assetsProgress: 0
- },
- lifetimes: {
- attached() {
- },
- detached() {
- this.stopSunRotation();
- this.stopTiger();
- }
- },
- methods: {
- emitLoadState(extra) {
- const payload = Object.assign({
- arReady: !!this.data.arReady,
- assetsLoaded: !!this.data.loaded,
- item1Loaded: !!this.data.item1Loaded,
- item2Loaded: !!this.data.item2Loaded,
- assetsProgress: typeof this.data.assetsProgress === 'number' ? this.data.assetsProgress : 0,
- }, extra || {});
- this.triggerEvent('loadState', payload);
- },
- pauseSunRotationSoft() {
- if (this.sunRotationTimer) {
- clearInterval(this.sunRotationTimer);
- this.sunRotationTimer = null;
- }
- this.sunFrameLoading = false;
- },
- pauseTigerSoft() {
- this.stopTigerAppearWatch();
- if (this.tigerRotationTimer) {
- clearInterval(this.tigerRotationTimer);
- this.tigerRotationTimer = null;
- }
- this.tigerFrameLoading = false;
- this.pauseTigerAudio();
- },
- pauseTigerAudio() {
- if (!this.tigerAudioCtx) return;
- try {
- this.tigerAudioCtx.pause();
- } catch (e) {
- }
- },
- resumeTigerSoft() {
- if (!this.tigerShouldRun) return;
- if (this.tigerCompleted) return;
- if (!this.tigerMeshes || !this.tigerMeshes.length) return;
- const visibleMeshes = this.getVisibleTigerMeshes();
- if (visibleMeshes && visibleMeshes.length) this.tigerTargetMeshes = visibleMeshes;
- if (this.tigerAudioCtx) {
- try {
- this.tigerAudioCtx.volume = 1;
- } catch (e) {
- }
- try {
- this.tigerAudioCtx.play();
- } catch (e) {
- }
- }
- if (this.tigerRotationTimer) return;
- const intervalMs = this.getTigerFrameIntervalMs();
- this.tigerRotationTimer = setInterval(() => this.updateTigerFrame(), intervalMs);
- },
- tryStartEntryAnimation() {
- if (!this._isTracking) return;
- if (!this.data.loaded) return;
- if (this.data.isStartPlay1) return;
- if (!this.animator1 || !this.animator2) return;
- this.setData({ isStartPlay1: true }, () => {
- this.playitem1Action();
- });
- },
- handleReady({
- detail
- }) {
- const xrScene = this.scene = detail.value;
- // console.log('xr-scene', xrScene);
- this.emitLoadState({ sceneReady: true });
- },
- handleAssetsProgress: function ({
- detail
- }) {
- const v = detail && detail.value;
- let progress = 0;
- if (v && typeof v.progress === 'number') {
- progress = Math.round(Math.max(0, Math.min(1, v.progress)) * 100);
- } else if (v && typeof v.loaded === 'number' && typeof v.total === 'number' && v.total > 0) {
- progress = Math.round(Math.max(0, Math.min(1, v.loaded / v.total)) * 100);
- }
- const now = Date.now();
- if (!this._lastProgressEmitAt) this._lastProgressEmitAt = 0;
- if (!this._lastProgressValue && this._lastProgressValue !== 0) this._lastProgressValue = -1;
- const shouldEmit = (progress === 100) || (progress !== this._lastProgressValue && now - this._lastProgressEmitAt >= 120);
- if (!shouldEmit) return;
- this._lastProgressEmitAt = now;
- this._lastProgressValue = progress;
- this.setData({ assetsProgress: progress }, () => this.emitLoadState());
- },
- handleAssetsLoaded: function ({
- detail
- }) {
- console.log('assets loaded', detail.value);
- this.setData({
- loaded: true,
- assetsProgress: 100
- }, () => {
- this.emitLoadState();
- if (this._pendingPlay || this._isTracking) this.play();
- });
- },
- handleARReady: function ({
- detail
- }) {
- console.log('arReady');
- this.setData({
- arReady: true
- }, () => {
- this.emitLoadState();
- })
- },
- handleItem1Loaded({ detail }) {
- const el = detail.value.target;
- const animator = el.getComponent("animator");
- this.animator1 = animator
- console.log('animator1', animator)
- const gltf = el.getComponent("gltf");
- this.bgGltf = gltf;
- this.sunMeshes = this.resolveSunMeshesFromBG(gltf);
- this.setData({ sunReady: !!(this.sunMeshes && this.sunMeshes.length) });
- if (this.sunShouldRun) this.startSunRotation();
- this.tigerMeshes = this.resolveTigerMeshesFromBG(gltf);
- this.setData({ tigerReady: !!(this.tigerMeshes && this.tigerMeshes.length) });
- if (this.tigerShouldRun && this.tigerStartRequested) this.scheduleTigerStart();
- if (!this.data.item1Loaded) {
- this.setData({ item1Loaded: true }, () => this.emitLoadState());
- }
- this.tryStartEntryAnimation();
- },
- handleItem2Loaded({ detail }) {
- const el = detail.value.target;
- const animator = el.getComponent("animator");
- this.animator2 = animator;
- if (!this.data.item2Loaded) {
- this.setData({ item2Loaded: true }, () => this.emitLoadState());
- }
- this.tryStartEntryAnimation();
- },
- handleARTrackerState1({
- detail
- }) {
- // 事件的值即为`ARTracker`实例
- const tracker = detail.value;
- // 获取当前状态和错误信息
- console.log('tracker', tracker)
- const {
- state,
- } = tracker;
- this._lastTrackerState = state;
- this._isTracking = state == 2;
- if (state == 2) {
- this.play()
- } else {
- this.pause()
- }
- },
- play() {
- if (!this.data.loaded) {
- this._pendingPlay = true;
- return;
- }
- this._pendingPlay = false;
- this.sunShouldRun = true;
- this.startSunRotation();
- this.tigerShouldRun = true;
- if (!this.data.isStartPlay1) this.tigerStartRequested = false;
- this.prepareTigerAudio();
- this.prepareTigerFrames();
- this.tryStartEntryAnimation();
- if (this.tigerHasStarted) {
- this.resumeTigerSoft();
- } else if (this.tigerStartRequested) {
- this.scheduleTigerStart();
- }
- },
- pause() {
- this.sunShouldRun = false;
- this.pauseSunRotationSoft();
- this.tigerShouldRun = false;
- this._pendingPlay = false;
- this.pauseTigerSoft();
- },
- resolveSunMeshesFromBG(gltf) {
- if (!gltf || !this.scene) return [];
- const candidates = this.getSunNameCandidates();
- const uniqueCandidates = [];
- for (const name of candidates) {
- if (name && !uniqueCandidates.includes(name)) uniqueCandidates.push(name);
- }
- for (const name of uniqueCandidates) {
- if (typeof gltf.getPrimitivesByNodeName === 'function') {
- const meshes = gltf.getPrimitivesByNodeName(name);
- if (meshes && meshes.length) return meshes;
- }
- if (typeof gltf.getPrimitivesByMeshName === 'function') {
- const meshes = gltf.getPrimitivesByMeshName(name);
- if (meshes && meshes.length) return meshes;
- }
- }
- if (typeof gltf.getMeshes === 'function') {
- const meshes = gltf.getMeshes() || [];
- const meshNames = meshes.map(m => m && (m.name || m.el && m.el.name)).filter(Boolean);
- console.warn('sun mesh not found, available mesh names:', meshNames);
- } else {
- console.warn('sun mesh not found');
- }
- return [];
- },
- getSunNameCandidates() {
- const defaultCandidates = ['Sun', 'sun', 'SUN', '太阳', 'Taiyang', 'taiyang'];
- if (!this.scene) return defaultCandidates;
- const gltfAsset = this.scene.assets && this.scene.assets.getAsset && this.scene.assets.getAsset('gltf', 'bg');
- const jsonRaw = gltfAsset && gltfAsset.jsonRaw;
- if (!jsonRaw) return defaultCandidates;
- const names = [];
- const addIfMatch = (n) => {
- if (!n || typeof n !== 'string') return;
- if (/Sun/i.test(n) || n.includes('太阳')) names.push(n);
- };
- if (Array.isArray(jsonRaw.nodes)) {
- for (const node of jsonRaw.nodes) addIfMatch(node && node.name);
- }
- if (Array.isArray(jsonRaw.meshes)) {
- for (const mesh of jsonRaw.meshes) addIfMatch(mesh && mesh.name);
- }
- return names.length ? names.concat(defaultCandidates) : defaultCandidates;
- },
- startSunRotation() {
- if (!this.scene) return;
- if (!this.sunShouldRun) return;
- if (!this.sunMeshes || !this.sunMeshes.length) return;
- if (this.sunRotationTimer) return;
- this.sunFrameCount = 159;
- this.sunFrameIndex = this.sunFrameIndex || 1;
- this.sunTextureCacheLimit = 12;
- if (!this.sunTextureCache) this.sunTextureCache = new Map();
- if (!this.sunTextureQueue) this.sunTextureQueue = [];
- this.updateSunFrame();
- this.sunRotationTimer = setInterval(() => this.updateSunFrame(), 80);
- },
- stopSunRotation() {
- if (this.sunRotationTimer) {
- clearInterval(this.sunRotationTimer);
- this.sunRotationTimer = null;
- }
- this.sunFrameLoading = false;
- if (this.scene && this.scene.assets && this.scene.assets.releaseAsset && this.sunTextureQueue) {
- for (const assetId of this.sunTextureQueue) {
- this.scene.assets.releaseAsset('texture', assetId);
- }
- }
- this.sunTextureCache = null;
- this.sunTextureQueue = null;
- },
- async updateSunFrame() {
- if (this.sunFrameLoading) return;
- if (!this.scene || !this.sunMeshes || !this.sunMeshes.length) return;
- if (!this.sunShouldRun) return;
- this.sunFrameLoading = true;
- try {
- const frame = this.sunFrameIndex;
- this.sunFrameIndex = frame >= this.sunFrameCount ? 1 : frame + 1;
- const frameStr = String(frame).padStart(3, '0');
- const assetId = `sun-${frameStr}`;
- const src = `https://ossxiaoan.4dage.com/hq-eduction-vr/sun/Sun_${frameStr}.png`;
- let texture = this.sunTextureCache && this.sunTextureCache.get(assetId);
- if (!texture) {
- const result = await this.scene.assets.loadAsset({ type: 'texture', assetId, src });
- texture = result && result.value;
- if (texture) {
- if (this.sunTextureCache) this.sunTextureCache.set(assetId, texture);
- if (this.sunTextureQueue) this.sunTextureQueue.push(assetId);
- while (this.sunTextureQueue && this.sunTextureQueue.length > this.sunTextureCacheLimit) {
- const oldAssetId = this.sunTextureQueue.shift();
- if (oldAssetId) {
- this.scene.assets.releaseAsset('texture', oldAssetId);
- if (this.sunTextureCache) this.sunTextureCache.delete(oldAssetId);
- }
- }
- }
- }
- if (texture) {
- for (const mesh of this.sunMeshes) {
- if (mesh && mesh.material && typeof mesh.material.setTexture === 'function') {
- mesh.material.setTexture('u_baseColorMap', texture);
- }
- }
- }
- } catch (e) {
- console.warn('updateSunFrame failed', e);
- } finally {
- this.sunFrameLoading = false;
- }
- },
- resolveTigerMeshesFromBG(gltf) {
- if (!gltf || !this.scene) return [];
- const candidates = this.getTigerNameCandidates();
- const uniqueCandidates = [];
- for (const name of candidates) {
- if (name && !uniqueCandidates.includes(name)) uniqueCandidates.push(name);
- }
- for (const name of uniqueCandidates) {
- if (typeof gltf.getPrimitivesByNodeName === 'function') {
- const meshes = gltf.getPrimitivesByNodeName(name);
- if (meshes && meshes.length) return meshes;
- }
- if (typeof gltf.getPrimitivesByMeshName === 'function') {
- const meshes = gltf.getPrimitivesByMeshName(name);
- if (meshes && meshes.length) return meshes;
- }
- }
- if (typeof gltf.getMeshes === 'function') {
- const meshes = gltf.getMeshes() || [];
- const meshNames = meshes.map(m => m && (m.name || m.el && m.el.name)).filter(Boolean);
- console.warn('tiger mesh not found, available mesh names:', meshNames);
- } else {
- console.warn('tiger mesh not found');
- }
- return [];
- },
- getTigerNameCandidates() {
- const defaultCandidates = ['Tiger', 'tiger', 'TIGER', '老虎', '虎', 'Laohu', 'laohu', 'hu'];
- if (!this.scene) return defaultCandidates;
- const gltfAsset = this.scene.assets && this.scene.assets.getAsset && this.scene.assets.getAsset('gltf', 'bg');
- const jsonRaw = gltfAsset && gltfAsset.jsonRaw;
- if (!jsonRaw) return defaultCandidates;
- const names = [];
- const addIfMatch = (n) => {
- if (!n || typeof n !== 'string') return;
- if (/tiger/i.test(n) || /laohu/i.test(n) || n.includes('虎')) names.push(n);
- };
- if (Array.isArray(jsonRaw.nodes)) {
- for (const node of jsonRaw.nodes) addIfMatch(node && node.name);
- }
- if (Array.isArray(jsonRaw.meshes)) {
- for (const mesh of jsonRaw.meshes) addIfMatch(mesh && mesh.name);
- }
- return names.length ? names.concat(defaultCandidates) : defaultCandidates;
- },
- scheduleTigerStart() {
- if (!this.scene) return;
- if (!this.tigerShouldRun) return;
- if (!this.tigerStartRequested) return;
- if (this.tigerCompleted) return;
- if (this.tigerRotationTimer) return;
- if (!this.tigerMeshes || !this.tigerMeshes.length) return;
- if (this.tigerAppearTimer) return;
- this.tigerAppearTimer = setInterval(() => {
- if (!this.tigerShouldRun || this.tigerCompleted) {
- this.stopTigerAppearWatch();
- return;
- }
- const visibleMeshes = this.getVisibleTigerMeshes();
- if (!visibleMeshes.length) return;
- this.stopTigerAppearWatch();
- this.tigerTargetMeshes = visibleMeshes;
- this.startTigerAudio();
- this.startTigerAnimation();
- }, 100);
- },
- stopTigerAppearWatch() {
- if (!this.tigerAppearTimer) return;
- clearInterval(this.tigerAppearTimer);
- this.tigerAppearTimer = null;
- },
- isTigerVisible() {
- return this.getVisibleTigerMeshes().length > 0;
- },
- getVisibleTigerMeshes() {
- if (!this.tigerMeshes || !this.tigerMeshes.length) return [];
- const visible = [];
- for (const mesh of this.tigerMeshes) {
- const el = mesh && mesh.el;
- if (!el || typeof el.getComponent !== 'function') continue;
- try {
- const transform = el.getComponent('transform');
- const scale = transform && transform.scale;
- if (!scale) continue;
- if (typeof scale === 'string') {
- const parts = scale.split(/\s+/).map(Number);
- const maxV = Math.max(...parts.filter(n => Number.isFinite(n)));
- if (Number.isFinite(maxV) && maxV > 0.001) visible.push(mesh);
- continue;
- }
- if (typeof scale === 'object') {
- const sx = typeof scale.x === 'number' ? scale.x : undefined;
- const sy = typeof scale.y === 'number' ? scale.y : undefined;
- const sz = typeof scale.z === 'number' ? scale.z : undefined;
- const maxV = Math.max(sx || 0, sy || 0, sz || 0);
- if (maxV > 0.001) visible.push(mesh);
- }
- } catch (e) {
- }
- }
- return visible;
- },
- startTigerAnimation() {
- if (!this.scene) return;
- if (!this.tigerShouldRun) return;
- if (!this.tigerMeshes || !this.tigerMeshes.length) return;
- if (this.tigerCompleted) return;
- if (this.tigerRotationTimer) return;
- this.tigerHasStarted = true;
- this.tigerFrameStart = 1;
- this.tigerFrameEnd = 460;
- this.tigerFrameCount = 460;
- const skipFrames = 29;
- this.tigerPlayedFrames = Math.min(skipFrames, this.tigerFrameCount);
- this.tigerTextureCacheLimit = 48;
- if (!this.tigerTextureCache) this.tigerTextureCache = new Map();
- if (!this.tigerTextureQueue) this.tigerTextureQueue = [];
- this.prepareTigerFrames();
- this.updateTigerFrame();
- const intervalMs = this.getTigerFrameIntervalMs();
- this.tigerRotationTimer = setInterval(() => this.updateTigerFrame(), intervalMs);
- },
- getTigerFrameIntervalMs() {
- const durationMs = Number.isFinite(this.tigerAudioDurationMs) && this.tigerAudioDurationMs > 0
- ? this.tigerAudioDurationMs
- : 46000;
- const frameCount = typeof this.tigerFrameCount === 'number' && this.tigerFrameCount > 0 ? this.tigerFrameCount : 460;
- const raw = Math.round(durationMs / frameCount);
- return Math.min(500, Math.max(16, raw));
- },
- stopTiger() {
- this.stopTigerAppearWatch();
- if (this.tigerRotationTimer) {
- clearInterval(this.tigerRotationTimer);
- this.tigerRotationTimer = null;
- }
- this.tigerFrameLoading = false;
- this.tigerTargetMeshes = null;
- this.tigerHasStarted = false;
- if (this.scene && this.scene.assets && this.scene.assets.releaseAsset && this.tigerTextureQueue) {
- for (const assetId of this.tigerTextureQueue) {
- if (assetId === this.tigerLastAssetId) continue;
- this.scene.assets.releaseAsset('texture', assetId);
- }
- }
- this.tigerTextureCache = null;
- this.tigerTextureQueue = null;
- this.stopTigerAudio();
- this.stopTigerFramesPreload();
- },
- prepareTigerFrames() {
- if (this.tigerFramesPrepared || this.tigerFramesPreparing) return;
- this.tigerFramesPreparing = true;
- this.tigerFramesAbort = false;
- if (!this.tigerFrameTempPaths) this.tigerFrameTempPaths = Object.create(null);
- if (!this.tigerFrameDownloadTasks) this.tigerFrameDownloadTasks = Object.create(null);
- const startNo = 39;
- const endNo = 460;
- const maxConcurrent = 6;
- let nextNo = startNo;
- let inFlight = 0;
- const pump = () => {
- if (this.tigerFramesAbort) return;
- while (inFlight < maxConcurrent && nextNo <= endNo && !this.tigerFramesAbort) {
- const frameNo = nextNo++;
- const frameStr = String(frameNo).padStart(3, '0');
- const assetId = `tigerx-${frameStr}`;
- if (this.tigerFrameTempPaths[assetId]) continue;
- inFlight += 1;
- const task = wx.downloadFile({
- url: `https://ossxiaoan.4dage.com/hq-eduction-vr/tiger/Tigerx_${frameStr}.png`,
- success: (res) => {
- if (this.tigerFramesAbort) return;
- const tempPath = res && res.statusCode === 200 ? res.tempFilePath : '';
- if (tempPath) this.tigerFrameTempPaths[assetId] = tempPath;
- },
- complete: () => {
- inFlight -= 1;
- if (this.tigerFrameDownloadTasks) delete this.tigerFrameDownloadTasks[assetId];
- if (nextNo > endNo && inFlight <= 0) {
- this.tigerFramesPrepared = true;
- this.tigerFramesPreparing = false;
- return;
- }
- pump();
- }
- });
- if (task && typeof task.abort === 'function') this.tigerFrameDownloadTasks[assetId] = task;
- }
- };
- pump();
- },
- stopTigerFramesPreload() {
- this.tigerFramesAbort = true;
- this.tigerFramesPrepared = false;
- this.tigerFramesPreparing = false;
- if (this.tigerFrameDownloadTasks) {
- for (const k of Object.keys(this.tigerFrameDownloadTasks)) {
- const task = this.tigerFrameDownloadTasks[k];
- if (task && typeof task.abort === 'function') {
- try {
- task.abort();
- } catch (e) {
- }
- }
- }
- }
- this.tigerFrameDownloadTasks = null;
- this.tigerFrameTempPaths = null;
- },
- async updateTigerFrame() {
- if (this.tigerFrameLoading) return;
- if (!this.scene || !this.tigerMeshes || !this.tigerMeshes.length) return;
- if (!this.tigerShouldRun) return;
- if (this.tigerCompleted) return;
- this.tigerFrameLoading = true;
- try {
- const frameCount = typeof this.tigerFrameCount === 'number' && this.tigerFrameCount > 0 ? this.tigerFrameCount : 460;
- const durationMs = Number.isFinite(this.tigerAudioDurationMs) && this.tigerAudioDurationMs > 0
- ? this.tigerAudioDurationMs
- : 46000;
- const played = this.tigerPlayedFrames || 0;
- let desiredPlayed = played + 1;
- const audioCtx = this.tigerAudioCtx;
- if (audioCtx && this.tigerAudioStarted) {
- const currentTime = Number(audioCtx.currentTime);
- if (Number.isFinite(currentTime) && currentTime >= 0) {
- const p = Math.floor((currentTime * 1000 / durationMs) * frameCount) + 1;
- desiredPlayed = Math.max(desiredPlayed, p);
- }
- }
- if (desiredPlayed <= played) return;
- if (desiredPlayed >= frameCount) desiredPlayed = frameCount;
- if (played >= frameCount) {
- this.completeTigerAnimation();
- return;
- }
- const start = typeof this.tigerFrameStart === 'number' ? this.tigerFrameStart : 1;
- const end = typeof this.tigerFrameEnd === 'number' ? this.tigerFrameEnd : frameCount;
- const rangeLen = Math.max(1, end - start + 1);
- const frameNo = start + ((desiredPlayed - 1) % rangeLen);
- this.tigerPlayedFrames = desiredPlayed;
- const frameStr = String(frameNo).padStart(3, '0');
- const assetId = `tigerx-${frameStr}`;
- const localSrc = this.tigerFrameTempPaths && this.tigerFrameTempPaths[assetId];
- const src = localSrc || `https://ossxiaoan.4dage.com/hq-eduction-vr/tiger/Tigerx_${frameStr}.png`;
- let texture = this.tigerTextureCache && this.tigerTextureCache.get(assetId);
- if (!texture) {
- const result = await this.scene.assets.loadAsset({ type: 'texture', assetId, src });
- texture = result && result.value;
- if (texture) {
- if (this.tigerTextureCache) this.tigerTextureCache.set(assetId, texture);
- if (this.tigerTextureQueue) this.tigerTextureQueue.push(assetId);
- while (this.tigerTextureQueue && this.tigerTextureQueue.length > this.tigerTextureCacheLimit) {
- const oldAssetId = this.tigerTextureQueue.shift();
- if (oldAssetId) {
- this.scene.assets.releaseAsset('texture', oldAssetId);
- if (this.tigerTextureCache) this.tigerTextureCache.delete(oldAssetId);
- }
- }
- }
- }
- if (texture) {
- this.tigerLastAssetId = assetId;
- const targets = (this.tigerTargetMeshes && this.tigerTargetMeshes.length) ? this.tigerTargetMeshes : this.tigerMeshes;
- for (const mesh of targets) {
- if (mesh && mesh.material && typeof mesh.material.setTexture === 'function') {
- mesh.material.setTexture('u_baseColorMap', texture);
- }
- }
- }
- if (this.tigerPlayedFrames >= this.tigerFrameCount) {
- this.completeTigerAnimation();
- }
- } catch (e) {
- console.warn('updateTigerFrame failed', e);
- } finally {
- this.tigerFrameLoading = false;
- }
- },
- completeTigerAnimation() {
- if (this.tigerRotationTimer) {
- clearInterval(this.tigerRotationTimer);
- this.tigerRotationTimer = null;
- }
- this.tigerCompleted = true;
- },
- prepareTigerAudio() {
- if (this.tigerAudioCtx || this.tigerAudioPreparing) return;
- const url = 'https://ossxiaoan.4dage.com/hq-eduction-vr/tiger/tiger.mp3';
- this.tigerAudioPrepared = false;
- this.tigerAudioStartPending = !!this.tigerAudioStartPending;
- this.tigerAudioStarted = false;
- this.tigerAudioPreparing = true;
- const createAudioCtx = (src) => {
- const audioCtx = wx.createInnerAudioContext();
- audioCtx.src = src;
- audioCtx.loop = false;
- audioCtx.volume = 0;
- audioCtx.onCanplay(() => {
- if (this.tigerAudioPrepared) return;
- this.tigerAudioPrepared = true;
- if (this.tigerAudioStarted) return;
- const updateDuration = () => {
- if (!this.tigerAudioCtx) return;
- const d = Number(audioCtx.duration);
- if (Number.isFinite(d) && d > 0) this.tigerAudioDurationMs = Math.round(d * 1000);
- };
- updateDuration();
- setTimeout(updateDuration, 300);
- try {
- audioCtx.volume = 0;
- } catch (e) {
- }
- try {
- audioCtx.play();
- } catch (e) {
- }
- setTimeout(() => {
- if (!this.tigerAudioCtx) return;
- if (this.tigerAudioStarted) return;
- try {
- audioCtx.pause();
- } catch (e) {
- }
- try {
- if (Number(audioCtx.currentTime) > 0.1) audioCtx.seek(0);
- } catch (e) {
- }
- if (this.tigerAudioStartPending) this.startTigerAudio();
- }, 200);
- });
- audioCtx.onEnded(() => {
- this.stopTigerAudio();
- this.completeTigerAnimation();
- });
- this.tigerAudioCtx = audioCtx;
- this.tigerAudioPreparing = false;
- try {
- audioCtx.play();
- } catch (e) {
- }
- };
- if (this.tigerAudioTempPath) {
- createAudioCtx(this.tigerAudioTempPath);
- return;
- }
- wx.downloadFile({
- url,
- success: (res) => {
- const tempPath = res && res.statusCode === 200 ? res.tempFilePath : '';
- if (tempPath) this.tigerAudioTempPath = tempPath;
- createAudioCtx(tempPath || url);
- },
- fail: () => {
- createAudioCtx(url);
- }
- });
- },
- startTigerAudio() {
- if (this.tigerAudioStarted) return;
- if (!this.tigerAudioCtx) {
- this.tigerAudioStartPending = true;
- this.prepareTigerAudio();
- }
- if (!this.tigerAudioCtx) return;
- if (this.tigerAudioStarted) return;
- const audioCtx = this.tigerAudioCtx;
- const requestedOffsetSec = typeof this.tigerAudioStartOffsetSec === 'number' ? this.tigerAudioStartOffsetSec : 2;
- const startOffsetSec = Math.max(0, Math.min(3, requestedOffsetSec));
- const startNow = () => {
- if (!this.tigerAudioCtx) return;
- if (this.tigerAudioStarted) return;
- try {
- audioCtx.volume = 1;
- } catch (e) {
- }
- try {
- const t = Number(audioCtx.currentTime);
- if (startOffsetSec > 0) {
- if (!Number.isFinite(t) || Math.abs(t - startOffsetSec) > 0.2) audioCtx.seek(startOffsetSec);
- } else {
- if (Number.isFinite(t) && t > 0.1) audioCtx.seek(0);
- }
- } catch (e) {
- }
- try {
- audioCtx.play();
- this.tigerAudioStarted = true;
- } catch (e) {
- this.tigerAudioStarted = false;
- }
- };
- if (this.tigerAudioPrepared) {
- this.tigerAudioStartPending = false;
- startNow();
- return;
- }
- this.tigerAudioStartPending = true;
- startNow();
- },
- stopTigerAudio() {
- if (!this.tigerAudioCtx) return;
- this.tigerAudioCtx.stop();
- this.tigerAudioCtx.destroy();
- this.tigerAudioCtx = null;
- this.tigerAudioPrepared = false;
- this.tigerAudioStartPending = false;
- this.tigerAudioStarted = false;
- this.tigerAudioPreparing = false;
- this.tigerAudioDurationMs = null;
- },
- playitem1Action() {
- if (!this.animator1 || !this.animator2) return;
- console.log('start animator1');
- this.animator1.play('All Animations', {
- loop: 0
- });
- setTimeout(() => {
- console.log('start animator2');
- this.animator2.pause();
- const duration = 1500;
- const startTime = Date.now();
- const startScale = 0;
- const endScale = 0.38;
- const startPX = -0.1
- const endPX = 0
- const startPY = -0.5
- const endPY = 0
- const startPZ = -0.05
- const endPZ = 0
- const step = () => {
- const now = Date.now();
- let t = (now - startTime) / duration;
- if (t > 1) t = 1;
- const s = startScale + (endScale - startScale) * t;
- const scaleStr = `${s} ${s} ${s}`;
- const p = `${startPX + (endPX - startPX) * t} ${startPY + (endPY - startPY) * t} ${startPZ + (endPZ - startPZ) * t}`;
- if (t >= 0.5 && !this.isStartPlay2) {
- this.isStartPlay2 = true;
- this.animator2.play('All Animations', {
- loop: 0
- });
- }
- this.setData({
- adlScale: scaleStr,
- adlPos: p
- });
- if (t < 1) {
- setTimeout(step, 16); // 60fps
- } else {
- const audioUrl = 'https://houseoss.4dkankan.com/project/hq-eduction-vr/public/%E5%AE%89%E5%BE%B7%E7%83%88.mp3';
- if (!this.audioCtx) {
- const audioCtx = wx.createInnerAudioContext();
- audioCtx.src = audioUrl;
- audioCtx.play();
- audioCtx.onEnded(() => {
- const hideDuration = 1000;
- const hideStartTime = Date.now();
- const startScaleHide = 0.38;
- const endScaleHide = 0;
- const hideStep = () => {
- const now = Date.now();
- let t = (now - hideStartTime) / hideDuration;
- if (t > 1) t = 1;
- const s = startScaleHide + (endScaleHide - startScaleHide) * t;
- const scaleStr = `${s} ${s} ${s}`;
- this.setData({
- adlScale: scaleStr
- });
- if (t < 1) {
- setTimeout(hideStep, 16);
- } else {
- this.animator2 = null;
- if (this.audioCtx) {
- this.audioCtx.destroy();
- this.audioCtx = null;
- }
- this.tigerStartRequested = true;
- this.scheduleTigerStart();
- }
- };
- hideStep();
- });
- }
- }
- };
- this.setData({
- adlScale: '0 0 0'
- });
- step();
- }, 1500);
- }
- }
- })
|