移动端h5仿微信语音功能

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta http-equiv="Content-Type" content="multipart/form-data; charset=iso-8859-1">
    <meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width">
    <script src="js/jquery-3.2.1.min.js"></script>
    <script src="js/recorder.mp3.min.js"></script><!--插件地址:https://github.com/xiangyuecn/Recorder-->
    <script>
        //rem
        (function(doc, win) {
            var docEl = doc.documentElement,
                resizeEvt = 'orientationchange' in window ? 'orientationchange' : 'resize',
                recalc = function() {
                    var clientWidth = docEl.clientWidth;
                    if(!clientWidth) return;
                    if(clientWidth >= 750) {
                        docEl.style.fontSize = '100px';
                    } else {
                        docEl.style.fontSize = 100 * (clientWidth / 750) + 'px';
                    }
                };
            if(!doc.addEventListener) return;
            win.addEventListener(resizeEvt, recalc, false);
            doc.addEventListener('DOMContentLoaded', recalc, false);
        })(document, window);
    </script>
    <style>
        *{margin: 0;padding: 0;}
        input{outline: none;}
        .press_box{
            position: fixed;
            top: 50%;
            left: 50%;
            transform:translate(-50%,-50%);
            -webkit-transform:translate(-50%,-50%);
            -moz-transform:translate(-50%,-50%);
            -ms-transform:translate(-50%,-50%);
            width: 2.5rem;
            height: 2.5rem;
            background: rgba(0,0,0,0.5);
            text-align: center;
            display: none;
        }
        .press_box2{
            position: fixed;
            top: 50%;
            left: 50%;
            transform:translate(-50%,-50%);
            -webkit-transform:translate(-50%,-50%);
            -moz-transform:translate(-50%,-50%);
            -ms-transform:translate(-50%,-50%);
            width: 2.5rem;
            height: 2.5rem;
            background: rgba(0,0,0,0.5);
            text-align: center;
            display: none;
        }
        .press_box3{
            position: fixed;
            top: 50%;
            left: 50%;
            transform:translate(-50%,-50%);
            -webkit-transform:translate(-50%,-50%);
            -moz-transform:translate(-50%,-50%);
            -ms-transform:translate(-50%,-50%);
            width: 2.5rem;
            height: 2.5rem;
            background: rgba(0,0,0,0.5);
            text-align: center;
            display: none;
        }
        .press_text3{
            color: white;
            font-size: 1rem;
            line-height: 1rem;
            margin-top: 0.5rem;
        }
        .press_text4{
            color: white;
            font-size: 0.24rem;
            margin-top: 0.3rem;
        }
        .press_main2{
            display: none;
        }
        .press_voice{
            width: 1.28rem;
            height: 1.28rem;
            display: block;
            margin-top: 0.4rem;
            margin-left: 0.2rem;
        }
        .press_voice2{
            width: 1.28rem;
            height: 1.28rem;
            display: block;
            margin: auto;
            margin-top: 0.4rem;
        }
        .press_text{
            color: white;
            font-size: 0.24rem;
            margin-top: 0.3rem;
        }
        .press_text2{
            color: white;
            font-size: 0.24rem;
            margin-top: 0.3rem;
        }
        .recpowerx{
            width: 0.4rem;
            height:0.1rem;
            max-height: 1.28rem;
            min-height: 0.1rem;
            background:white;
            position:absolute;
            right: 0.5rem;
            bottom: 0.83rem;
        }
        .add_yuyin .r_yuyin b.bofang {
            background: url(images/mobile/yuyin.png) no-repeat -.17rem -.1rem;
            -webkit-animation: bofang 1s steps(1,start) infinite;
            background-size: 1.9rem .49rem;
        }
        .add_yuyin .r_yuyin b {
            width: .27rem;
            height: .32rem;
            position: absolute;
            right: .2rem;
            top: .24rem;
            background: url(images/mobile/icon.png) no-repeat -7.14rem -3.65rem;
            background-size: 14.57rem 4.86rem;
            transform:rotate(180deg);

        }
        /** 播放录音的动画效果 **/
        @-webkit-keyframes bofang{
            25% {
                background-position:-.17rem -.1rem;
            }
            50% {
                background-position:-.66rem -.11rem;
            }
            75% {
                background-position:-1.1rem -.1rem;
            }
            100% {
                background-position:-1.51rem -.1rem;
            }
        }
        @keyframes bofang{
            25% {
                background-position:-.17rem -.1rem;
            }
            50% {
                background-position:-.66rem -.11rem;
            }
            75% {
                background-position:-1.1rem -.1rem;
            }
            100% {
                background-position:-1.51rem -.1rem;
            }
        }
        .foot_nav {
            position: fixed;
            left: 0;
            width: 100%;
            bottom: 0;
            border-top: 0.01rem solid #E6EAEF;
            box-sizing: border-box;
            -moz-box-sizing: border-box;
            -webkit-box-sizing: border-box;
        }
        .foot_navMain {
            display: -webkit-box;
            display: -webkit-flex;
            display: flex;
            -ms-flex-align: center;
            -webkit-box-align: center;
            box-align: center;
            -webkit-align-items: center;
            align-items: center;
            padding: 0 0.2rem;
            height: 1rem;
            background: #ffffff;
        }
        .foot_navLi {
            display: flex;
            justify-content: center;
            align-items: center;
            margin-left: 0;
            width: 0.8rem;
            height: 0.8rem;
            line-height: 0.8rem;
            text-align: center;
        }
        .foot_navLIcon {
            width: 0.48rem;
            height: 0.48rem;
        }
        .foot_navInpBox {
            background: #F4F4F4;
            border-radius: 0.4rem;
            -webkit-box-flex: 1;
            -webkit-flex: 1;
            flex: 1;
            padding: 0 0.3rem;
            background: none;
            display: flex;
            justify-content: center;
            align-items: center;
        }
        .foot_navInput {
            border-radius: 0.4rem;
            background: #F4F4F4;
            padding-left: 0.3rem;
            box-sizing: border-box;
            height: 0.6rem;
            line-height: 0.6rem;
            width: 100%;
        }
        .foot_talk {
            height: 0.6rem;
            line-height: 0.6rem;
            width: 100%;
            background: white;
            border-radius: 0.4rem;
            border: 1px solid #3D4A5E;
            display: none;
        }
        .send {
            color: white;
            background: #87CEFA;
            width: 0.9rem;
            height: 0.6rem;
            line-height: 0.6rem;
            border-radius: 0.4rem;
            text-align: center;
            font-size: 0.24rem;
        }
        .r_yuyin {
            display: -webkit-box;
            display: -webkit-flex;
            display: flex;
            margin-top: 0.3rem;
            align-items: flex-start;
            justify-content: flex-end;
            padding-left: 1rem;
        }
        .us_box {
            display: flex;
            justify-content: flex-end;
            width: auto;
            max-width: 60%;
            min-width: 25%;
            margin-right: 0.3rem;
            background: #87CEFA;
            color: #ffffff;
            position: relative;
            border-radius: 0.1rem;
            min-height: 0.8rem;
            height: 0.8rem;
        }
        .us_box:before {
            position: absolute;
            content: "";
            display: block;
            border-width: 0.16rem;
            top: 0.2rem;
            right: -0.32rem;
            border-style: dashed solid solid dashed;
            border-color: transparent transparent transparent #87CEFA;
        }
        .audio_time {
            font-size: 0.24rem;
            line-height: 0.8rem;
            position: absolute;
            left: 0.25rem;
        }
        .us_msgImg {
            width: 1rem;
            height: 1rem;
        }
        .us_img {
            width: 100%;
            display: block;
            border-radius: 100%;
        }
    </style>
</head>
<body>
<!--音频-->
<div class="add_yuyin" id="add_yuyin">

</div>
<!--事件-->
<div class="foot_nav">
    <ul class="foot_navMain">
        <li class="foot_navLi" onclick="recOpen()"><img class="foot_navLIcon js_voice" src="images/mobile/icon_voice1.png" alt=""></li>
        <li class="foot_navInpBox">
            <input class="foot_navInput" type="text" value="" placeholder="请输入您要咨询的问题">
            <button id="recStart" class="foot_talk">按住&nbsp;说话</button>
        </li>
        <li class="foot_navLi send">发送</li>
    </ul>
</div>
<!--按下说话-->
<div class="press_box">
    <div class="press_main">
        <img class="press_voice" src="images/mobile/icon_voice2.png" alt="">
        <div class="recpowerx"></div>
    </div>
    <div class="press_main2">
        <img class="press_voice2" src="images/mobile/icon_cancel.png" alt="">
    </div>
    <p class="press_text">手指上划,取消发送</p>
</div>
<div class="press_box2">
    <div class="press_main3">
        <img class="press_voice2" src="images/mobile/icon_hint.png" alt="">
    </div>
    <p class="press_text2">说话时间太短</p>
</div>
<div class="press_box3">
    <p class="press_text3">10</p>
    <p class="press_text4">手指上划,取消发送</p>
</div>
</body>
<script>
    $(function(){
        //点击语音
        $('.js_voice').click(function () {
            $('.js_mainMenu').removeClass('foot_mainMenu');
            $('.js_mainMenu').removeClass('foot_boxMenu');
            if ($(this).attr('src')==='images/mobile/icon_voice1.png'){
                $(this).attr('src','images/mobile/icon_key.png')
            } else {
                $(this).attr('src','images/mobile/icon_voice1.png')
            }
            if($('.foot_navInput').is(':hidden')){//如果当前隐藏
                $('.foot_navInput').show();//那么就显示div
                $('.foot_talk').hide()
            }else{
                $('.foot_navInput').hide();//否则就隐藏div
                $('.foot_talk').show()
            }

        })
        //点击发送
        $('.send').click(function () {
            $('.foot_navInput').val("")
        })

    })

    var rec;
    /**调用open打开录音请求好录音权限**/
    var recOpen=function(success){//一般在显示出录音按钮或相关的录音界面时进行此方法调用,后面用户点击开始录音时就能畅通无阻了
        rec=Recorder({
            type:"mp3",sampleRate:16000,bitRate:16 //mp3格式,指定采样率hz、比特率kbps,其他参数使用默认配置;注意:是数字的参数必须提供数字,不要用字符串;需要使用的type类型,需提前把格式支持文件加载进来,比如使用wav格式需要提前加载wav.js编码引擎
            ,onProcess:function(buffers,powerLevel){
                $(".recpowerx").css("height",powerLevel+"%");
            }
        });
        rec.open(function(){//打开麦克风授权获得相关资源
            success&&success();
        },function(msg,isUserNotAllow){//用户拒绝未授权或不支持
            alert((isUserNotAllow?"UserNotAllow,":"")+"无法录音:"+msg);
            $('.js_voice').attr('src','images/mobile/icon_voice1.png')
            $('.foot_navInput').show();
            $('.foot_talk').hide()
        });
    };

    /**开始录音**/
    var timer1 = null
    var timer2 = null
    $('#recStart').on('touchstart',function () {
        $(this).text('松开 结束')
        $('.press_box').show()
        rec.start();
        $('.press_text4').html('手指上划,取消发送')
        //说话时间已到60s
        var num = 9
        timer1 = setTimeout(function () {
            $('.press_box3').show()
            $('.press_box').hide()
            $('.press_box2').hide()
            timer2 = setInterval(function () {
                if(num==0){
                    clearInterval(timer2);
                    console.log('时间到')
                    $('.press_text4').html('说话时间已到60s')
                    setTimeout(function () {
                        $('.press_box3').hide()

                    },1000)
                    rec.stop(function(blob,duration){
                        console.log(blob,(window.URL||webkitURL).createObjectURL(blob),"时长111:"+duration+"ms");
                        var audio = (window.URL||webkitURL).createObjectURL(blob)
                        var time = Math.round(duration/1000)
                        var str = '<div class="r_yuyin">' +
                            '<div class="us_box">' +
                            '<span class="audio_time"></span>' +
                            '<audio id="audioTime" class="audio" src="'+audio+'"></audio>' +
                            '<b></b>' +
                            '</div>'+
                            '<div class="us_msgImg">'+
                            '<img src="images/tx02.jpg" class="us_img">'+
                            '</div>'+
                            '</div>'
                        $('#add_yuyin').append(str)
                        $('#add_yuyin .r_yuyin:last-child span').html(time+' ″')
                        $('#add_yuyin .r_yuyin:last-child .us_box').css("width",time+24+'%')
                    })
                }else {
                    $('.press_text3').html(num)
                    num--
                }
            },1000)
        },50000);
    })


    /**上划取消**/
    var btnElem=document.getElementById("recStart");//获取ID
    var posStart = 0;//初始化起点坐标
    var posEnd = 0;//初始化终点坐标
    var posMove = 0;//初始化终点坐标
    btnElem.addEventListener("touchstart", function(event) {
        event.preventDefault();//阻止浏览器默认行为
        posStart = 0;
        posStart = event.touches[0].pageY;//获取起点坐标
    });
    btnElem.addEventListener("touchmove", function(event) {
        event.preventDefault();
        posMove = 0;
        posMove = event.changedTouches[0].pageY;//获取终点坐标
        if(posStart - posMove > 20 ){
            $('.press_text').text('松开手指,取消发送')
            $('.press_main').hide()
            $('.press_main2').show()
        }else {
            $('.press_text').text('手指上划,取消发送')
            $('.press_main').show()
            $('.press_main2').hide()
        }
    });
    /**结束录音**/
    $('#recStart').on('touchend',function (event) {
        clearTimeout(timer1);
        clearInterval(timer2);
        $('.press_text3').html(10)
        $('.press_box3').hide()
        $(this).text('按住 说话')
        $('.press_box').hide()
        $('.press_text').text('手指上划,取消发送')
        $('.press_main').show()
        $('.press_main2').hide()
        event.preventDefault();
        posEnd = 0;
        posEnd = event.changedTouches[0].pageY;//获取终点坐标
        rec.stop(function(blob,duration){
            console.log(blob,(window.URL||webkitURL).createObjectURL(blob),"时长:"+duration+"ms");
            //播放上传
            var audio = (window.URL||webkitURL).createObjectURL(blob)
            var time = Math.round(duration/1000)
            var str = '<div class="r_yuyin">' +
                '<div class="us_box">' +
                '<span class="audio_time"></span>' +
                '<audio id="audioTime" class="audio" src="'+audio+'"></audio>' +
                '<b></b>' +
                '</div>'+
                '<div class="us_msgImg">'+
                '<img src="images/tx02.jpg" class="us_img">'+
                '</div>'+
                '</div>'
            $('#add_yuyin').append(str)
            $('#add_yuyin .r_yuyin:last-child span').html(time+' ″')
            $('#add_yuyin .r_yuyin:last-child .us_box').css("width",time+24+'%')
            //取消发送
            if (posStart - posEnd > 20) {
                if($('#add_yuyin .r_yuyin').length===1){
                    $('#add_yuyin .r_yuyin').remove()
                }else {
                    $('#add_yuyin .r_yuyin:last-child').remove()
                }
            }
            //说话时间太短
            if(duration < 500){
                $('.press_box').hide()
                $('.press_box2').show()
                if($('#add_yuyin .r_yuyin').length===1){
                    $('#add_yuyin .r_yuyin').remove()
                }else {
                    $('#add_yuyin .r_yuyin:last-child').remove()
                }
                setTimeout(function () {
                    $('.press_box2').hide()
                },500)
            }
            var TestApi="/test_request";
            var api=TestApi;
            /***方式一:将blob文件转成base64纯文本编码,使用普通application/x-www-form-urlencoded表单上传***/
            var reader=new FileReader();
            reader.onloadend=function(){
                $.ajax({
                    url:api //上传接口地址
                    ,type:"POST"
                    ,data:{
                        mime:blob.type //告诉后端,这个录音是什么格式的,可能前后端都固定的mp3可以不用写
                        ,upfile_b64:(/.+;\s*base64\s*,\s*(.+)$/i.exec(reader.result)||[])[1] //录音文件内容,后端进行base64解码成二进制
                        //...其他表单参数
                    }
                    ,success:function(v){
                        console.log("上传成功",v);
                    }
                    ,error:function(s){
                        console.error("上传失败",s);
                    }
                });
            };
            reader.readAsDataURL(blob);
            //方法二
            // var form=new FormData();
//             form.append("upfile",blob,"recorder.mp3"); //和普通form表单并无二致,后端接收到upfile参数的文件,文件名为recorder.mp3
// //...其他表单参数
//             $.ajax({
//                 url:api //上传接口地址
//                 ,type:"POST"
//                 ,contentType:false //让xhr自动处理Content-Type header,multipart/form-data需要生成随机的boundary
//                 ,processData:false //不要处理data,让xhr自动处理
//                 ,data:form
//                 ,success:function(v){
//                     console.log("上传成功",v);
//                 }
//                 ,error:function(s){
//                     console.error("上传失败",s);
//                 }
//             });
        },function(msg){
            if(msg){
                console.log("录音失败:"+msg);
            }else{
                $('.press_box').hide()
                $('.press_box2').show()
                setTimeout(function () {
                    $('.press_box2').hide()
                },500)
            }
        });
    })
    //录音播放
    $(".add_yuyin").on("click",'.r_yuyin',function () {
        let audios = $(this).find("audio")[0];
        if (audios.paused) {
            audios.play()
            $(this).find("b").addClass("bofang");
        }else {
            audios.load()
            $(this).find("b").removeClass("bofang");
        }
        // 多个语音切换
        if($(this).siblings().length>0){
            $(this).siblings().find("audio")[0].load();
            $(this).siblings().find("b").removeClass("bofang");
        }
        //语音结束动画停止
        let _this = $(this)
        audios.addEventListener('ended', function () {
            _this.find('b').removeClass("bofang");
        }, false);
    })
</script>
</html>

  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
移动端H5调用微信支付是指在手机上运行的网页应用使用微信支付进行支付交易。移动端H5通常是通过微信内置的浏览器或者第三方浏览器打开的网页应用。要实现移动端H5调用微信支付,需要进行以下步骤: 首先,开发人员需要在微信公众平台上注册并申请一个微信支付商户号。商户号是与微信支付相关联的唯一标识符。 接下来,开发人员需要在移动端H5的网页应用中引入微信支付的JSAPI。微信支付提供了一组JavaScript API,开发人员可以通过这些API来实现支付功能。 在用户点击支付按钮时,网页应用需要调用微信支付的统一下单API,向微信服务器发送支付请求。支付请求需要包括商户号、订单号、支付金额、用户的openid等必要信息。 微信服务器收到支付请求后,会返回一个prepay_id给移动端H5的网页应用。网页应用可以将这个prepay_id传递给微信支付的JSAPI,用于发起支付。 在调用微信支付的JSAPI时,需要传递一些必要的参数,如appId、timeStamp、nonceStr和签名等。这些参数是为了验证支付请求的合法性,并确保支付过程的安全性。 最后,用户确认支付后,网页应用会调用微信支付的JSAPI发起支付。微信支付会弹出一个支付窗口,用户可以在该窗口中输入支付密码完成支付。 支付过程结束后,微信服务器会将支付结果通知给网页应用。网页应用可以根据支付结果进行相应的处理,如提示用户支付成功或失败,并进行相应的操作。 总之,移动端H5调用微信支付需要开发人员在网页应用中引入微信支付的JSAPI,并按照微信支付的流程进行相应的调用和处理,以实现支付功能

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值