Your Name 2 年前
父节点
当前提交
a416cf7ece
共有 7 个文件被更改,包括 100 次插入47 次删除
  1. 12
    2
      src/App.vue
  2. 1
    1
      src/components/CoverBtn.vue
  3. 9
    15
      src/components/InfoBox.vue
  4. 0
    1
      src/components/OverLay.vue
  5. 14
    20
      src/components/ScenicAudio.vue
  6. 63
    7
      src/store/index.js
  7. 1
    1
      src/style.css

+ 12
- 2
src/App.vue 查看文件

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

+ 1
- 1
src/components/CoverBtn.vue 查看文件

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

+ 9
- 15
src/components/InfoBox.vue 查看文件

@@ -5,8 +5,8 @@
5 5
       <div class="head">
6 6
         <div>{{ resource.name }}</div>
7 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 10
             <i class="iconfont icon-pausecircle" v-else></i>
11 11
           </span>
12 12
           <span @click="onClickLoc"><i class="iconfont icon-map"></i></span>            
@@ -14,15 +14,15 @@
14 14
       </div>
15 15
       <div class="body">{{ resource.desc }}</div>  
16 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 19
   </OverLay>
19 20
 </template>
20 21
 
21 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 25
   import OverLay from './OverLay.vue';
24
-  import AudioVue from './Audio.vue';
25
-
26 26
   
27 27
   const props = defineProps({
28 28
     visible: Boolean,
@@ -36,15 +36,9 @@
36 36
   const emit = defineEmits(['close']);
37 37
 
38 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 42
   const onClickLoc = () => {
49 43
     if (wx) {
50 44
       wx.openLocation({
@@ -60,7 +54,7 @@
60 54
 
61 55
   watch(() => props.visible, (val) => {
62 56
     if (val) {
63
-      stopAudio();
57
+      stopCheck(props.resource.audio);
64 58
     }
65 59
   })
66 60
   

+ 0
- 1
src/components/OverLay.vue 查看文件

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

+ 14
- 20
src/components/ScenicAudio.vue 查看文件

@@ -3,10 +3,10 @@
3 3
     :center="center"
4 4
     :width="width"
5 5
     :height="height"
6
-    @click="onPlayBtn"
6
+    @click="toggle(audio)"
7 7
   >
8 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 10
   </CoverBtn>
11 11
   <div v-if="showGesture" class="gesture" :class="{ hidden: gestureHide }" :style="gestureStyle">
12 12
     <i class="iconfont icon-cc-pointer-right"></i>
@@ -15,9 +15,9 @@
15 15
 
16 16
 <script setup>
17 17
   import { computed, watch, ref } from 'vue';
18
+  import { useModel } from "@zjxpcyc/vue-tiny-store";
18 19
   import CoverBtn from "./CoverBtn.vue";
19 20
   import AudioPlaying from "./AudioPlaying.vue";
20
-  import AudioVue from './Audio.vue';
21 21
 
22 22
   const props = defineProps({
23 23
     center: Array,
@@ -28,16 +28,14 @@
28 28
     },
29 29
   });
30 30
 
31
+  const { playing, audioSrc, toggle } = useModel('audio');
31 32
   const width = ref(64);
32 33
   const height = ref(64);
33 34
   const audioRef = ref();
34
-  const playState = ref(0);
35 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 39
   const gestureStyle = computed(() => {
42 40
     if (props.center && props.center.length > 1) {
43 41
       return {
@@ -49,19 +47,15 @@
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 59
 </script>
66 60
 
67 61
 <style lang="less" scoped>

+ 63
- 7
src/store/index.js 查看文件

@@ -2,16 +2,72 @@ import { ref } from 'vue';
2 2
 import createStore from '@zjxpcyc/vue-tiny-store';
3 3
 
4 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 73
 const useMap = () => {

+ 1
- 1
src/style.css 查看文件

@@ -28,4 +28,4 @@ img {
28 28
 }
29 29
 .amap-copyright {
30 30
   opacity:0;
31
-}
31
+}