Your Name 2 years ago
parent
commit
a416cf7ece

+ 12
- 2
src/App.vue View File

8
   import { amapInit } from '@/utils/amap'
8
   import { amapInit } from '@/utils/amap'
9
 
9
 
10
   const [, setMapReady] = useModel('map');
10
   const [, setMapReady] = useModel('map');
11
+  const { setAudio, onEnded } = useModel('audio');
11
 
12
 
12
   const loading = ref(true);
13
   const loading = ref(true);
13
   const percent = ref(0);
14
   const percent = ref(0);
14
   const resources = ref([]);
15
   const resources = ref([]);
16
+  const audioRef = ref();
15
 
17
 
16
   amapInit().then(() => setMapReady(true));
18
   amapInit().then(() => setMapReady(true));
17
 
19
 
23
     preload(updateCallback).then((res) => {
25
     preload(updateCallback).then((res) => {
24
       loading.value = false;
26
       loading.value = false;
25
       resources.value = res.filter(x => !x.hidden);
27
       resources.value = res.filter(x => !x.hidden);
26
-    })
28
+    });
29
+
30
+    setAudio(audioRef.value);
27
   });
31
   });
28
 </script>
32
 </script>
29
 
33
 
30
 <template>
34
 <template>
35
+  <audio class="cache-audio" src="" ref="audioRef" @ended="onEnded"></audio>
31
   <Loader :loading="loading" :percent="percent" />
36
   <Loader :loading="loading" :percent="percent" />
32
   <ScrollDown />
37
   <ScrollDown />
33
   <Image v-for="res in resources" :key="res.image" :resource="res"></Image>
38
   <Image v-for="res in resources" :key="res.image" :resource="res"></Image>
34
 </template>
39
 </template>
35
 
40
 
36
-<style lang="less" scoped>
41
+<style lang="less">
42
+.cache-audio {
43
+  height: 0;
44
+  overflow: hidden;
45
+  position: absolute;
46
+}
37
 </style>
47
 </style>

+ 1
- 1
src/components/CoverBtn.vue View File

37
 <style lang="less" scoped>
37
 <style lang="less" scoped>
38
 .cover-btn {
38
 .cover-btn {
39
   position: absolute;
39
   position: absolute;
40
-  background: rgba(255, 0, 0, 0.5);
40
+  // background: rgba(255, 0, 0, 0.5);
41
   z-index: 10;
41
   z-index: 10;
42
 }
42
 }
43
 </style>
43
 </style>

+ 9
- 15
src/components/InfoBox.vue View File

5
       <div class="head">
5
       <div class="head">
6
         <div>{{ resource.name }}</div>
6
         <div>{{ resource.name }}</div>
7
         <div>
7
         <div>
8
-          <span @click="onClickAudio">
9
-            <i class="iconfont icon-playcircle" v-if="!playing"></i>
8
+          <span @click="toggle(resource.audio)">
9
+            <i class="iconfont icon-playcircle" v-if="!currentPlaying"></i>
10
             <i class="iconfont icon-pausecircle" v-else></i>
10
             <i class="iconfont icon-pausecircle" v-else></i>
11
           </span>
11
           </span>
12
           <span @click="onClickLoc"><i class="iconfont icon-map"></i></span>            
12
           <span @click="onClickLoc"><i class="iconfont icon-map"></i></span>            
14
       </div>
14
       </div>
15
       <div class="body">{{ resource.desc }}</div>  
15
       <div class="body">{{ resource.desc }}</div>  
16
     </div>
16
     </div>
17
-    <AudioVue :audio="resource.audio" ref="audioRef" @play="playing = true" @stop="playing = false" />
17
+    
18
+    <audio class="cache-audio" :src="resource.audio" preload="auto"></audio>
18
   </OverLay>
19
   </OverLay>
19
 </template>
20
 </template>
20
 
21
 
21
 <script setup>
22
 <script setup>
22
-  import { ref, watch } from 'vue';
23
+  import { ref, watch, computed } from 'vue';
24
+  import { useModel } from "@zjxpcyc/vue-tiny-store";
23
   import OverLay from './OverLay.vue';
25
   import OverLay from './OverLay.vue';
24
-  import AudioVue from './Audio.vue';
25
-
26
   
26
   
27
   const props = defineProps({
27
   const props = defineProps({
28
     visible: Boolean,
28
     visible: Boolean,
36
   const emit = defineEmits(['close']);
36
   const emit = defineEmits(['close']);
37
 
37
 
38
   const audioRef = ref();
38
   const audioRef = ref();
39
-  const playing = ref(false);
39
+  const { playing, audioSrc, toggle, stopCheck } = useModel('audio');
40
+  const currentPlaying = computed(() => audioSrc.value === props.resource.audio && playing.value);
40
 
41
 
41
-  const onClickAudio = () => audioRef.value.toggle();
42
-  const stopAudio = () => {
43
-    if (playing.value) {
44
-      audioRef.value.toggle();
45
-      playing.value = false;
46
-    }
47
-  }
48
   const onClickLoc = () => {
42
   const onClickLoc = () => {
49
     if (wx) {
43
     if (wx) {
50
       wx.openLocation({
44
       wx.openLocation({
60
 
54
 
61
   watch(() => props.visible, (val) => {
55
   watch(() => props.visible, (val) => {
62
     if (val) {
56
     if (val) {
63
-      stopAudio();
57
+      stopCheck(props.resource.audio);
64
     }
58
     }
65
   })
59
   })
66
   
60
   

+ 0
- 1
src/components/OverLay.vue View File

60
     overflow: hidden;
60
     overflow: hidden;
61
     z-index: 2000;
61
     z-index: 2000;
62
     opacity: 1;
62
     opacity: 1;
63
-    will-change: opacity;
64
     transition: opacity .1s ease-out;
63
     transition: opacity .1s ease-out;
65
 
64
 
66
     &.hidden {
65
     &.hidden {

+ 14
- 20
src/components/ScenicAudio.vue View File

3
     :center="center"
3
     :center="center"
4
     :width="width"
4
     :width="width"
5
     :height="height"
5
     :height="height"
6
-    @click="onPlayBtn"
6
+    @click="toggle(audio)"
7
   >
7
   >
8
     <AudioPlaying :style="iconStyle" />
8
     <AudioPlaying :style="iconStyle" />
9
-    <AudioVue :audio="audio" ref="audioRef" @play="onPlay" @stop="onStop" />
9
+    <audio class="cache-audio" :src="audio" preload="auto"></audio>
10
   </CoverBtn>
10
   </CoverBtn>
11
   <div v-if="showGesture" class="gesture" :class="{ hidden: gestureHide }" :style="gestureStyle">
11
   <div v-if="showGesture" class="gesture" :class="{ hidden: gestureHide }" :style="gestureStyle">
12
     <i class="iconfont icon-cc-pointer-right"></i>
12
     <i class="iconfont icon-cc-pointer-right"></i>
15
 
15
 
16
 <script setup>
16
 <script setup>
17
   import { computed, watch, ref } from 'vue';
17
   import { computed, watch, ref } from 'vue';
18
+  import { useModel } from "@zjxpcyc/vue-tiny-store";
18
   import CoverBtn from "./CoverBtn.vue";
19
   import CoverBtn from "./CoverBtn.vue";
19
   import AudioPlaying from "./AudioPlaying.vue";
20
   import AudioPlaying from "./AudioPlaying.vue";
20
-  import AudioVue from './Audio.vue';
21
 
21
 
22
   const props = defineProps({
22
   const props = defineProps({
23
     center: Array,
23
     center: Array,
28
     },
28
     },
29
   });
29
   });
30
 
30
 
31
+  const { playing, audioSrc, toggle } = useModel('audio');
31
   const width = ref(64);
32
   const width = ref(64);
32
   const height = ref(64);
33
   const height = ref(64);
33
   const audioRef = ref();
34
   const audioRef = ref();
34
-  const playState = ref(0);
35
   const gestureHide = ref(false);
35
   const gestureHide = ref(false);
36
+  const iconStyle = ref({ opacity: 0 });
37
+  const currentPlaying = computed(() => audioSrc.value === props.audio && playing.value);
36
   
38
   
37
-  const iconStyle = computed(() => ({
38
-    opacity: playState.value,
39
-  }));
40
-
41
   const gestureStyle = computed(() => {
39
   const gestureStyle = computed(() => {
42
     if (props.center && props.center.length > 1) {
40
     if (props.center && props.center.length > 1) {
43
       return {
41
       return {
49
     }
47
     }
50
   });
48
   });
51
 
49
 
52
-  const onPlay = () => {
53
-    playState.value = 1;
54
-    gestureHide.value = true;
55
-  }
50
+  watch(currentPlaying, (val) => {
51
+    if (val) {
52
+      iconStyle.value = { opacity: 1 };
53
+      gestureHide.value = true;
54
+    } else {
55
+      iconStyle.value = { opacity: 0 };
56
+    }
57
+  });
56
 
58
 
57
-  const onStop = () => {
58
-    playState.value = 0;
59
-  }
60
-  
61
-  // 点击播放
62
-  const onPlayBtn = () => {
63
-    audioRef.value.toggle();
64
-  };
65
 </script>
59
 </script>
66
 
60
 
67
 <style lang="less" scoped>
61
 <style lang="less" scoped>

+ 63
- 7
src/store/index.js View File

2
 import createStore from '@zjxpcyc/vue-tiny-store';
2
 import createStore from '@zjxpcyc/vue-tiny-store';
3
 
3
 
4
 const useAudio = () => {
4
 const useAudio = () => {
5
-  const current = ref()
5
+  const audioRef = ref();
6
+  const audioSrc = ref();
7
+  const playing = ref(false);
8
+  
9
+  const setAudio = audio => audioRef.value = audio;
10
+  const isCurrent = src => audioSrc.value === src;
11
+
12
+  const play = (src) => {
13
+    if (audioRef.value) {
14
+      if (!isCurrent(src)) {
15
+        if (playing.value) {
16
+          playing.value = false;
17
+          stop();
18
+        }
19
+
20
+        audioSrc.value = src;
21
+        audioRef.value.src = src;
22
+      }
23
+
24
+      if (playing.value) return;
6
 
25
 
7
-  const changeAudio = (aduRef) => {
8
-    current.value = aduRef;
26
+      audioRef.value.play();
27
+      playing.value = true;
28
+    }
9
   }
29
   }
10
 
30
 
11
-  return [
12
-    current,
13
-    changeAudio,
14
-  ]
31
+  const stop = () => {
32
+    if (audioRef.value) {
33
+      audioRef.value.pause();
34
+      playing.value = false;
35
+    }
36
+  }
37
+
38
+  const toggle = (src) => {
39
+    if (isCurrent(src)) {
40
+      if (playing.value) {
41
+        stop();
42
+      } else {
43
+        play(src);
44
+      }
45
+    } else {
46
+      play(src);
47
+    }
48
+  }
49
+
50
+  const stopCheck = src => {
51
+    if (!isCurrent(src) && playing.value) {
52
+      stop();
53
+    }
54
+  }
55
+
56
+  const onEnded = () => {
57
+    playing.value = false;
58
+  }
59
+
60
+  return {
61
+    setAudio,
62
+    playing,
63
+    audioSrc,
64
+    isCurrent,
65
+    play,
66
+    stop,
67
+    toggle,
68
+    stopCheck,
69
+    onEnded,
70
+  }
15
 };
71
 };
16
 
72
 
17
 const useMap = () => {
73
 const useMap = () => {

+ 1
- 1
src/style.css View File

28
 }
28
 }
29
 .amap-copyright {
29
 .amap-copyright {
30
   opacity:0;
30
   opacity:0;
31
-}
31
+}