|
@@ -1,16 +1,25 @@
|
|
|
<template>
|
|
|
- <span>
|
|
|
- <audio
|
|
|
- v-show="shouldShowAudio"
|
|
|
- :key="src"
|
|
|
- controls
|
|
|
- preload="auto"
|
|
|
- controlsList="nodownload"
|
|
|
- :name="name"
|
|
|
- :src="src"
|
|
|
- style="width: 290px"
|
|
|
- v-on="$listeners"
|
|
|
- ></audio>
|
|
|
+ <span style="display: flex; align-items: center; ">
|
|
|
+ <span v-show="shouldShowAudio" @click="play">
|
|
|
+ <Button
|
|
|
+ v-if="!playing"
|
|
|
+ type="primary"
|
|
|
+ shape="circle"
|
|
|
+ icon="ios-play"
|
|
|
+ :disabled="playCount === 0"
|
|
|
+ ></Button>
|
|
|
+ <Button
|
|
|
+ v-else
|
|
|
+ type="primary"
|
|
|
+ shape="circle"
|
|
|
+ icon="md-pause"
|
|
|
+ style="cursor: not-allowed;"
|
|
|
+ ></Button>
|
|
|
+ </span>
|
|
|
+
|
|
|
+ <span v-show="shouldShowAudio">
|
|
|
+ {{ formatTime(currentTime) }} / {{ formatTime(duration) }}
|
|
|
+ </span>
|
|
|
|
|
|
<span v-if="!shouldShowAudio" style="color: blueviolet;">
|
|
|
音频下载中{{ downloadPercent }}%
|
|
@@ -19,6 +28,8 @@
|
|
|
</template>
|
|
|
|
|
|
<script>
|
|
|
+import moment from "moment";
|
|
|
+
|
|
|
export default {
|
|
|
name: "QuestionAudio",
|
|
|
props: {
|
|
@@ -30,70 +41,106 @@ export default {
|
|
|
type: String,
|
|
|
required: true,
|
|
|
},
|
|
|
+ playCount: {
|
|
|
+ type: Number,
|
|
|
+ required: true,
|
|
|
+ },
|
|
|
},
|
|
|
data() {
|
|
|
return {
|
|
|
done: false,
|
|
|
downloadPercent: 0,
|
|
|
+ currentTime: 0,
|
|
|
+ duration: 0,
|
|
|
+ playing: false,
|
|
|
+ context: null,
|
|
|
+ buffer: null,
|
|
|
};
|
|
|
},
|
|
|
computed: {
|
|
|
shouldShowAudio() {
|
|
|
- let chromeVersion = window.navigator.userAgent
|
|
|
- .split(" ")
|
|
|
- .find(v => v.startsWith("Chrome/"));
|
|
|
- if (chromeVersion) {
|
|
|
- chromeVersion = +chromeVersion.replace("Chrome/", "").split(".")[0];
|
|
|
- }
|
|
|
- return (
|
|
|
- chromeVersion < 76 ||
|
|
|
- this.done ||
|
|
|
- !navigator.serviceWorker ||
|
|
|
- !navigator.serviceWorker.controller ||
|
|
|
- // 在某些情况下,caches 没有定义,这时候不做cache. 暂时注释
|
|
|
- // !window.caches ||
|
|
|
- this.downloadPercent === 100
|
|
|
- );
|
|
|
+ return this.downloadPercent === 100;
|
|
|
},
|
|
|
},
|
|
|
async created() {
|
|
|
- this.cacheInterval = setInterval(() => {
|
|
|
- if (!this.done && window.caches) {
|
|
|
- window.caches
|
|
|
- .open("audios")
|
|
|
- .then(caches => caches.match(this.src))
|
|
|
- .then(e => e && (this.done = true));
|
|
|
- }
|
|
|
- }, 100);
|
|
|
+ this.loadData();
|
|
|
+ },
|
|
|
+ beforeDestroy() {
|
|
|
+ this.source && this.source.stop();
|
|
|
+ },
|
|
|
+ methods: {
|
|
|
+ formatTime(seconds) {
|
|
|
+ return moment.utc(seconds * 1000).format("mm:ss");
|
|
|
+ },
|
|
|
+ loadData() {
|
|
|
+ this.context = new AudioContext();
|
|
|
+ this.buffer;
|
|
|
|
|
|
- this.handleMSG = event => {
|
|
|
- // console.log("Client 1 Received Message: " + event.data);
|
|
|
- if (event.data[0] === this.src)
|
|
|
- this.downloadPercent = Math.floor(
|
|
|
- (event.data[1] / event.data[2]) * 100
|
|
|
- );
|
|
|
- };
|
|
|
- navigator.serviceWorker.addEventListener("message", this.handleMSG);
|
|
|
+ const loadDogSound = url => {
|
|
|
+ var request = new XMLHttpRequest();
|
|
|
+ request.open("GET", url, true);
|
|
|
+ request.responseType = "arraybuffer";
|
|
|
|
|
|
- let chromeVersion = window.navigator.userAgent
|
|
|
- .split(" ")
|
|
|
- .find(v => v.startsWith("Chrome/"));
|
|
|
- if (chromeVersion) {
|
|
|
- chromeVersion = +chromeVersion.replace("Chrome/", "").split(".")[0];
|
|
|
- }
|
|
|
- if (chromeVersion >= 76) {
|
|
|
- if (!window.caches) {
|
|
|
- window._hmt.push([
|
|
|
- "_trackEvent",
|
|
|
- "音频播放",
|
|
|
- "chromeVersion >= 76 && window.caches 为空",
|
|
|
- ]);
|
|
|
+ // Decode asynchronously
|
|
|
+ request.onload = () => {
|
|
|
+ this.context.decodeAudioData(
|
|
|
+ request.response,
|
|
|
+ buffer => {
|
|
|
+ this.buffer = buffer;
|
|
|
+ this.duration = Number(this.buffer.duration).toFixed(0);
|
|
|
+ this.downloadPercent = 100;
|
|
|
+ // console.log("load ... ");
|
|
|
+ },
|
|
|
+ () => {
|
|
|
+ console.log("error load audio");
|
|
|
+ }
|
|
|
+ );
|
|
|
+ };
|
|
|
+ request.onprogress = e => {
|
|
|
+ // console.log(e);
|
|
|
+ // console.log(e.loaded / e.total);
|
|
|
+ this.downloadPercent = Number((e.loaded / e.total) * 100).toFixed(2);
|
|
|
+ };
|
|
|
+ request.send();
|
|
|
+ };
|
|
|
+
|
|
|
+ loadDogSound(this.src);
|
|
|
+ },
|
|
|
+ play() {
|
|
|
+ if (this.playCount <= 0) {
|
|
|
+ console.log("无播放次数");
|
|
|
+ return;
|
|
|
}
|
|
|
- }
|
|
|
- },
|
|
|
- beforeDestroy() {
|
|
|
- clearInterval(this.cacheInterval);
|
|
|
- navigator.serviceWorker.removeEventListener("message", this.handleMSG);
|
|
|
+ if (this.playing) {
|
|
|
+ console.log("正在播放,无法暂停");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ this.$emit("played");
|
|
|
+ // var audio = new Audio();
|
|
|
+ // this.source = this.context.createMediaElementSource(audio); // creates a sound source
|
|
|
+ this.source = this.context.createBufferSource(); // creates a sound source
|
|
|
+ this.source.buffer = this.buffer; // tell the source which sound to play
|
|
|
+ this.source.connect(this.context.destination); // connect the source to the context's destination (the speakers)
|
|
|
+ this.source.start(0); // play the source now
|
|
|
+ // audio.play();
|
|
|
+ this.playing = true;
|
|
|
+ const progress = () => {
|
|
|
+ // console.log(context.currentTime, buffer.duration);
|
|
|
+ this.currentTime = Number(this.context.currentTime).toFixed(0);
|
|
|
+ if (this.context.currentTime < this.duration) {
|
|
|
+ requestAnimationFrame(progress);
|
|
|
+ } else if (this.context.currentTime > this.duration) {
|
|
|
+ this.currentTime = 0;
|
|
|
+ }
|
|
|
+ };
|
|
|
+ requestAnimationFrame(progress);
|
|
|
+ // note: on older systems, may have to use deprecated noteOn(time);
|
|
|
+ this.source.onended = () => {
|
|
|
+ // console.log(e, "ended");
|
|
|
+ this.playing = false;
|
|
|
+ // this.$emit("ended", this.name);
|
|
|
+ };
|
|
|
+ },
|
|
|
},
|
|
|
};
|
|
|
</script>
|