123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482 |
- <template>
- <div :class="['Audio', mp3Source && mp3Source == 'tts' ? 'Audio-tts' : '']">
- <div v-if="!hideSlider" class="audioLine">
- <div
- class="play"
- :class="[
- audio.loading ? 'loadBtn' : audio.playing ? 'playBtn' : 'pauseBtn',
- ]"
- @click="PlayAudio"
- />
- <template v-if="!isRepeat">
- <el-slider
- v-model="playValue"
- :style="{ width: sliderWidth + 'px', height: '2px' }"
- :format-tooltip="formatProcessToolTip"
- @change="changeCurrentTime"
- />
- <span
- ><template v-if="audio.playing">-</template
- >{{
- audio.maxTime
- ? realFormatSecond(audio.maxTime - audio.currentTime)
- : ""
- }}</span
- >
- </template>
- </div>
- <div v-else class="audioLine2">
- <div
- :class="[
- 'play-icon',
- audio.loading
- ? 'loadBtn'
- : audio.playing
- ? 'playBtn-icon'
- : 'pauseBtn-icon',
- type == 'full' ? 'play-icon-big' : '',
- ]"
- @click="PlayAudio"
- />
- </div>
- <audio
- :id="audioId"
- :ref="audioId"
- :src="mp3"
- preload="meta"
- @loadedmetadata="onLoadedmetadata"
- @timeupdate="onTimeupdate"
- @canplaythrough="oncanplaythrough"
- />
- </div>
- </template>
- <script>
- // 这里可以导入其它文件(比如:组件,工具js,第三方插件js,json文件,图片文件等等)
- // 例如:import 《组件名称》from ‘《组件路径》';
- export default {
- // import引入的组件需要注入到对象中才能使用
- components: {},
- props: [
- "mp3",
- "mp3Source",
- "getCurTime",
- "stopAudio",
- "width",
- "isRepeat",
- "themeColor",
- "hideSlider",
- "ed",
- "bg",
- "audioId",
- "type",
- ],
- data() {
- // 这里存放数据
- return {
- playValue: 0,
- audio: {
- // 该字段是音频是否处于播放状态的属性
- playing: false,
- // 音频当前播放时长
- currentTime: 0,
- // 音频最大播放时长
- maxTime: 0,
- isPlaying: false,
- loading: false,
- },
- audioAllTime: null, // 展示总时间
- duioCurrentTime: null, // 剩余时间
- count: 0,
- loading: null,
- isClick: false,
- };
- },
- // 计算属性 类似于data概念
- computed: {
- sliderWidth() {
- let width = 0;
- if (this.width) {
- width = this.width;
- } else {
- width = 662;
- }
- return width;
- },
- },
- // 监控data中数据变化
- watch: {
- stopAudio: {
- handler(val, oldVal) {
- const _this = this;
- if (val) {
- _this.$refs[_this.audioId].pause();
- _this.audio.playing = false;
- }
- },
- // 深度观察监听
- deep: true,
- },
- "audio.playing": {
- handler(val) {
- this.$emit("playChange", val);
- if (val) this.$emit("handleChangeStopAudio");
- },
- },
- },
- // 生命周期 - 创建完成(可以访问当前this实例)
- created() {},
- // 生命周期 - 挂载完成(可以访问DOM元素)
- mounted() {
- let _this = this;
- let audioId = _this.audioId;
- _this.$refs[audioId].addEventListener("loadstart", function () {});
- _this.$refs[audioId].addEventListener("play", function () {
- _this.audio.playing = true;
- _this.audio.isPlaying = true;
- _this.audio.loading = false;
- });
- _this.$refs[audioId].addEventListener("pause", function () {
- _this.audio.playing = false;
- if (_this.hideSlider && _this.audio.currentTime * 1000 + 500 > _this.ed) {
- _this.$emit("sentPause", true);
- }
- _this.$emit("handleListenRead", false);
- });
- _this.$refs[audioId].addEventListener("ended", function () {
- _this.audio.playing = false;
- _this.audio.isPlaying = false;
- _this.$emit("handleListenRead", false);
- _this.isClick = false;
- });
- this.$nextTick(() => {
- document
- .getElementsByClassName("el-slider__button-wrapper")[0]
- .addEventListener("mousedown", function () {
- _this.$refs[audioId].pause();
- _this.audio.playing = false;
- });
- });
- },
- // 生命周期-挂载之前
- beforeMount() {},
- // 生命周期-更新之后
- updated() {},
- // 如果页面有keep-alive缓存功能,这个函数会触发
- activated() {},
- // 方法集合
- methods: {
- PlayAudio() {
- let audioId = this.audioId;
- let audio = document.getElementsByTagName("audio");
- audio.forEach((item) => {
- if (item.src == this.mp3) {
- if (item.id !== audioId) {
- item.pause();
- }
- } else {
- item.pause();
- }
- });
- let video = document.getElementsByTagName("video");
- video.forEach((vItem) => {
- vItem.pause();
- });
- if (this.audio.playing) {
- this.$refs[audioId].pause();
- this.audio.playing = false;
- this.$emit("handleListenRead", false);
- this.isClick = false;
- } else {
- if (this.count == 0) {
- this.audio.loading = true;
- this.count++;
- }
- if (this.hideSlider) {
- this.$refs[audioId].play();
- this.onTimeupdateTime(this.bg / 1000);
- } else {
- this.$refs[audioId].play();
- }
- this.$emit("handleChangeStopAudio");
- this.$emit("handleListenRead", true);
- this.isClick = true;
- }
- },
- oncanplaythrough() {
- let _this = this;
- // setTimeout(() => {
- _this.audio.loading = false;
- // }, 10000);
- },
- // 点击 拖拽播放音频
- changeCurrentTime(value) {
- let audioId = this.audioId;
- this.$refs[audioId].play();
- this.audio.playing = true;
- this.$refs[audioId].currentTime = parseInt(
- (value / 100) * this.audio.maxTime
- );
- },
- mousedown() {
- let audioId = this.audioId;
- this.$refs[audioId].pause();
- this.audio.playing = false;
- },
- // 进度条格式化toolTip
- formatProcessToolTip(index) {
- index = parseInt((this.audio.maxTime / 100) * index);
- return this.realFormatSecond(index);
- },
- // 音频加载完之后
- onLoadedmetadata(res) {
- this.audio.maxTime = parseInt(res.target.duration);
- this.audioAllTime = this.realFormatSecond(this.audio.maxTime);
- },
- // 当音频当前时间改变后,进度条也要改变
- onTimeupdate(res) {
- let audioId = this.audioId;
- this.audio.currentTime = res.target.currentTime;
- this.getCurTime(res.target.currentTime);
- this.playValue = (this.audio.currentTime / this.audio.maxTime) * 100;
- if (this.type == "audioLine") {
- if (!this.isClick && this.audio.currentTime * 1000 > this.ed) {
- this.$refs[audioId].pause();
- this.$emit("emptyEd");
- }
- } else {
- if (this.audio.currentTime * 1000 > this.ed) {
- this.$refs[audioId].pause();
- }
- }
- },
- onTimeupdateTime(res, playFlag) {
- if (!res) return;
- let audioId = this.audioId;
- this.$refs[audioId].currentTime = res;
- this.playValue = (res / this.audio.maxTime) * 100;
- if (playFlag) {
- let audio = document.getElementsByTagName("audio");
- audio.forEach((item) => {
- if (item.id !== audioId) {
- item.pause();
- }
- });
- this.$refs[audioId].play();
- }
- },
- // 将整数转换成 时:分:秒的格式
- realFormatSecond(value) {
- let theTime = parseInt(value); // 秒
- let theTime1 = 0; // 分
- let theTime2 = 0; // 小时
- if (theTime > 60) {
- theTime1 = parseInt(theTime / 60);
- theTime = parseInt(theTime % 60);
- if (theTime1 > 60) {
- theTime2 = parseInt(theTime1 / 60);
- theTime1 = parseInt(theTime1 % 60);
- }
- }
- let result = String(parseInt(theTime));
- if (result < 10) {
- result = "0" + result;
- }
- if (theTime1 > 0) {
- result = String(parseInt(theTime1)) + ":" + result;
- if (theTime1 < 10) {
- result = "0" + result;
- }
- } else {
- result = "00:" + result;
- }
- if (theTime2 > 0) {
- result = String(parseInt(theTime2)) + ":" + result;
- if (theTime2 < 10) {
- result = "0" + result;
- }
- } else {
- // result = "00:" + result;
- }
- return result;
- },
- },
- // 生命周期-创建之前
- beforeCreated() {},
- // 生命周期-更新之前
- beforUpdate() {},
- // 生命周期-销毁之前
- beforeDestory() {},
- // 生命周期-销毁完成
- destoryed() {},
- };
- </script>
- <style lang="scss" scoped>
- /* @import url(); 引入css类 */
- .Audio {
- width: 100%;
- .audioLine {
- display: flex;
- align-items: center;
- width: 100%;
- height: 40px;
- background: #ffffff;
- // border: 1px solid rgba(0, 0, 0, 0.1);
- // box-shadow: 0px 2px 6px rgba(0, 0, 0, 0.1);
- box-sizing: border-box;
- border-radius: 4px;
- .play {
- margin-right: 12px;
- margin-left: 8px;
- width: 16px;
- min-width: 16px;
- height: 16px;
- cursor: pointer;
- display: block;
- }
- span {
- font-size: 16px;
- line-height: 19px;
- color: #000;
- margin-left: 8px;
- margin-right: 12px;
- min-width: 56px;
- text-align: right;
- }
- }
- .audioLine2 {
- .play-icon {
- width: 16px;
- height: 16px;
- cursor: pointer;
- &-big {
- width: 24px;
- height: 24px;
- }
- &.playBtn-icon {
- background: url("../../../assets/icon/pauseC-24-normal-red.png")
- no-repeat left top;
- background-size: 100% 100%;
- }
- &.pauseBtn-icon {
- background: url("../../../assets/NPC/compare-pause-red-24.png")
- no-repeat left top;
- background-size: 100% 100%;
- }
- }
- }
- .loadBtn {
- background: url("../../../assets/NPC/loading-red.png") no-repeat left top;
- background-size: 100% 100%;
- }
- }
- </style>
- <style lang="scss">
- .Audio {
- .el-slider__bar {
- height: 2px;
- background: #de4444;
- }
- .el-slider__button {
- background: #de4444;
- border: none;
- }
- .el-slider__button-wrapper {
- width: 25px;
- }
- .el-slider__button-wrapper {
- position: relative;
- z-index: 0;
- }
- .el-slider__button {
- width: 8px;
- height: 8px;
- top: 12px;
- position: absolute;
- }
- .el-slider__runway {
- margin: 0;
- padding: 0;
- background: #e5e5e5;
- border-radius: 0px;
- height: 2px;
- }
- .el-slider {
- position: relative;
- }
- }
- .NPC-Book-Sty {
- .Audio {
- .el-slider__bar {
- height: 2px;
- background: #de4444;
- }
- .el-slider__button {
- background: #de4444;
- border: none;
- }
- }
- }
- .NPC-Big-Book-preview-green {
- .Audio {
- .el-slider__bar {
- background: #24b99e !important;
- }
- .el-slider__button {
- background: #24b99e !important;
- }
- .audioLine2 {
- .play-icon {
- &.playBtn-icon {
- background: url("../../../assets/icon/pauseC-16-normal-Green.png")
- no-repeat left top;
- background-size: 100% 100%;
- }
- &.pauseBtn-icon {
- background: url("../../../assets/NPC/compare-pause-green.png")
- no-repeat left top;
- background-size: 100% 100%;
- }
- }
- }
- .loadBtn {
- background: url("../../../assets/NPC/loading-green.png") no-repeat left
- top;
- background-size: 100% 100%;
- }
- }
- }
- .NPC-Big-Book-preview-brown {
- .Audio {
- .el-slider__bar {
- background: #bd8865 !important;
- }
- .el-slider__button {
- background: #bd8865 !important;
- }
- .audioLine2 {
- .play-icon {
- &.playBtn-icon {
- background: url("../../../assets/icon/pauseC-16-normal-Brown.png")
- no-repeat left top;
- background-size: 100% 100%;
- }
- &.pauseBtn-icon {
- background: url("../../../assets/NPC/compare-pause-brown.png")
- no-repeat left top;
- background-size: 100% 100%;
- }
- }
- }
- .loadBtn {
- background: url("../../../assets/NPC/loading-brown.png") no-repeat left
- top;
- background-size: 100% 100%;
- }
- }
- }
- </style>
|