解决ios上audio不能自动播放,也不能连续播放的问题

在写实时聊天的页面的时候,有一个需求是点击完第一条开始播放后,后面如果没有播放就需要连续的往后播。新的消息来了之后需要自动播放;

由于ios的安全机制问题。不允许audio和video自动播放,所以想要获取页面上的audio标签然后给src值,然后使用自动播放那是实现不了的,即使给play()也是播放过不了;

解决方法是直接创建一个audio对象,当时问题是iOS也是不允许主动创建对象的,所以需要一个手动创建,可以选择全页面触发等

    var Xut = {};
    var isAudio = false;
    var audioOnce = null;
    var chatid = '';
    var fixaudio = function() {
        if (!isAudio) {
            isAudio = true;
            Xut.newaudio = new Audio();
            document.removeEventListener('touchstart', fixaudio, false);
        }
    };
    document.addEventListener('touchstart', fixaudio, false);

只要碰到页面就创建的了一个audio对象,然后再像这个对象中添加src地址,然后使用play()就可以播放了

            if (Xut.newaudio) {
                audio = Xut.newaudio;
                audio.src = url;
            } else {
                Xut.newaudio = new Audio();
                audio = Xut.newaudio;
                audio.src = url;
            }

这样通过动态添加src,就可以实现循环播放了

    var clickplaying = 0;
    function toplay(list, index, allUrl,allMsgID,chatId) {
        if (index > list.length - 1) {
            clickplaying = 1;
            return;
        }
        var icon = list[index].children[0];
        var url = allUrl[index];
        if (index === audioOnce) { //点击的是同一个
            if (audio.paused) { //暂停状态
                audio.autoplay = true;
                audio.play();
                icon.setAttribute('class', 'voice-icon played');
            } else {
                audio.pause();
                icon.setAttribute('class', 'voice-icon paused');
            }
        } else { //点击的不是同一个
            //其他暂停
            toPause()
            //储存播放后状态
            var readId = window.localStorage.getItem(chatId)
            if(readId){
                var setReadId = readId.split(',')
                setReadId.push(allMsgID[index]).toString()
            }else {
                var setReadId = [allMsgID[index]].toString()
            }
            window.localStorage.setItem(chatId,setReadId)

            var setRead = document.getElementsByClassName('setread')
            if(setRead[index].children[0]){
                setRead[index].children[0].setAttribute('class', '')
            }
            audioOnce = index;
            icon.setAttribute('id', 'anchor');
            console.log(url);
            console.log(Xut.newaudio);

                if (Xut.newaudio) {
                    audio = Xut.newaudio;
                    audio.src = url;
                } else {
                    Xut.newaudio = new Audio();
                    audio = Xut.newaudio;
                    audio.src = url;
                }
            audio.load();
            audio.onloadstart = function() {
                icon.setAttribute('class', 'voice-icon  playloading');
            };
            audio.oncanplaythrough = function() {
                icon.setAttribute('class', 'voice-icon played');
                audio.autoplay = true;
                audio.play();
            };
            audio.onended = function() {
                icon.setAttribute('class', 'voice-icon paused');
                toplay(list, index + 1, allUrl,allMsgID,chatId)
            }
        }
    }

我这个地方使用的vue1.0写的。所以使用了watch来监听数据的变化,如果数据有变化,分别给每个页面的ui播放按钮绑定点击事件,并且如果没有播放的情况下,来的数据是音频,那么就自动播放

 watch: {
            talkList: function() {
                var that = this;
                var list = document.getElementsByClassName("voiceSize");
                var listLength = this.talkList;
                var allUrl = [];
                var allSize = [];
                var allMsgID = [];
                for (j = 0; j < listLength.length; j++) {
                    if (listLength[j].MSG_TYPE == 'VOICE') {
                        this.showonce = 1;
                        allUrl.push(listLength[j].MEDIA_URL)
                        allSize.push(listLength[j].MEDIA_SIZE)
                        allMsgID.push(listLength[j].MSG_ID)
                    }
                };
                for (var i = 0, len = list.length; i < len; i++) {
                    list[i].style.width = size(parseFloat(allSize[i])) + '%';
                    list[i].onclick = (function(index) {
                        return function() {
                            toplay(list, index, allUrl,allMsgID,that.radioID)
                        }
                    })(i);
                };
                if(listLength.length){
                    if(listLength[listLength.length-1].MSG_TYPE == 'VOICE' && clickplaying==1){
                        toplay(list, list.length-1, allUrl,allMsgID,that.radioID)
                    }
                }
            },
            rightTalkList:function () {
                this.rightScroll()
            }
        },

当然点击不同的播放按钮的其它的都应该暂停,其实这里只需要换一下页面上的显示而已,因为页面中就只有一个audio标签,所以点击其它的不存在暂停一说,src替换了就不可能还会播放了。

//点击其他播放按钮暂停时页面状态显示
    function toPause() {
        var icon = document.getElementsByClassName('voice-icon')
        for (n = 0; n < icon.length; n++) {
            icon[n].setAttribute('class', 'voice-icon paused');
            icon[n].removeAttribute('id')
        }
    }

页面html代码也贴出来吧,方便理解

               <div v-if="item.MSG_TYPE=='VOICE'">
                    <div class="line talk voiceSize">
                        <div class="voice-icon paused">
                            <div></div>
                        </div>
                        <em class="setread">
                            <i v-if="item.READ" class="unread"></i>
                        </em>
                    </div>
                    <span class="voice-time">{{item.MEDIA_SIZE | ceil}}</span>''
                </div>

css代码

.voice-icon {
        display: inline-block;
        font-family: "Ionicons";
        height: 20px;
        width: 20px;
        position: relative;
        speak: none;
        font-style: normal;
        font-weight: normal;
        font-variant: normal;
        text-transform: none;
        text-rendering: auto;
        line-height: 1;
        -webkit-font-smoothing: antialiased;
        box-sizing: border-box;
        &.paused{
            height: 20px;
            width: 20px;
            border: 2px solid #4cd676;
            border-radius: 50%;
            -webkit-border-radius: 50%;
            -moz-border-radius: 50%;
            box-sizing: border-box;
        }
        &.paused:before {
            content: '';
            height: 0;
            width: 0;
            display: block;
            border: 5px transparent solid;
            border-right-width: 0;
            border-left-color: #4cd676;
            position: absolute;
            top: 4px;
            left: 6px;
        }
        &.played{
            height: 20px;
            width: 20px;
            border: 2px solid #4cd676;
            border-radius: 20px;
            -webkit-border-radius: 20px;
            -moz-border-radius: 20px;
            box-sizing: border-box;
        }
        &.played:before {
            content: '';
            height: 10px;
            width: 2px;
            display: block;
            background: #4cd676;
            position: absolute;
            top: 4px;
            left: 5px;
        }
        &.played:after {
            content: '';
            height: 10px;
            width: 2px;
            display: block;
            background: #4cd676;
            position: absolute;
            top: 3px;
            left: 9px;
        }
        &.playloading {
            transition: opacity .25s linear;
            opacity: 1;
        }

        &.playloading>div {
            background-color: #fff;
            border-radius: 100%;
            -webkit-animation-fill-mode: both;
            animation-fill-mode: both;
            border: 2px solid red;
            border-bottom-color: transparent;
            height: 20px;
            width: 20px;
            background: transparent !important;
            display: inline-block;
            -webkit-animation: rotate 0.75s 0s linear infinite;
            animation: rotate 0.75s 0s linear infinite;
        }


ui效果是



还有一个红色的loading旋转动画。不好截图,脑补一下就好了


  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值