vue3.0 安卓和ios h5 移动端音频自定义圆环可拖拽播放(兼容微信浏览器)

这篇具有很好参考价值的文章主要介绍了vue3.0 安卓和ios h5 移动端音频自定义圆环可拖拽播放(兼容微信浏览器)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

vue3.0 安卓和ios h5 移动端音频自定义圆环可拖拽播放(兼容微信浏览器)

vue3.0 安卓和ios h5 移动端音频自定义圆环可拖拽播放(兼容微信浏览器)

安装  npm install weixin-js-sdk

引入

import wx from 'weixin-js-sdk'

<template>

    <div class="circle_box">

        <div id="content"></div>

         <img class="img_0" src="https://img.yzcdn.cn/vant/cat.jpeg" alt="">

         <img @click="changeType" class="img_1" v-show="playbool" src="@/assets/decompression/pressure_audio_play.png" alt="">

         <img @click="changeType" class="img_1" v-show="!playbool" src="@/assets/decompression/pressure_audio_pause.png" alt="">

         <div v-show="false">

            <audio ref="audio" controls @timeupdate="updateTime">

             <source src="@/assets/decompression/tiankong.mp3" type="audio/mpeg">

            </audio>

         </div>

    </div>

</template>

<script>

import wx from "weixin-js-sdk";

export default {

    data(){

        return{

            value:'',

            outColor:'',

            playbool:true,

            second:0,

            than:''

        }

    },

    mounted(){

        this.init()

        this.main()

    },

    methods:{

        init(){

            let that = this

            let u = navigator.userAgent;

            //ios手机

            var isIOS = !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/);

            if(isIOS){

                this.$nextTick(() => {

                    this.autoPlayAudio();

                })

            }else{

                this.$nextTick(() => {

                let time = setTimeout(function () {

                        let audio = that.$refs.audio;

                        //音频总时长 秒

                        that.second = audio.duration;

                        that.than = 100/audio.duration;

                        that.$parent.calculationTime(audio.duration);

                        clearInterval(time);

                    }, 500)

                })

            }

        },

        autoPlayAudio() {

            let ua = window.navigator.userAgent.toLowerCase();

            let that = this;

            let audio = this.$refs.audio;

            if(ua.match(/MicroMessenger/i) == 'micromessenger'){

                //微信浏览器

                wx.config({

                    debug: false,

                    appId: '',

                    timestamp: 1,

                    nonceStr: '',

                    signature: '',

                    jsApiList: []

                });

               wx.ready(function() {

                audio.play();

                audio.pause();

                let time = setTimeout(function () {

                        if(audio.duration>0){

                            //音频总时长 秒

                            that.second = audio.duration;

                            that.than = 100/audio.duration;

                            that.$parent.calculationTime(audio.duration);

                        }else{

                            that.autoPlayAudio();

                        }

                        clearInterval(time);

                    }, 500)

                });

            }else{

                let time = setTimeout(function () {

                    if(audio.duration>0){

                        //音频总时长 秒

                        that.second = audio.duration;

                        that.than = 100/audio.duration;

                        that.$parent.calculationTime(audio.duration);

                    }else{

                        that.autoPlayAudio();

                    }

                    clearInterval(time);

                }, 500)

            }

        },

        //监测播放进度

        updateTime(){

           let audio = this.$refs.audio;

           let time = Number(this.second)-Number(audio.currentTime);

           this.$parent.calculationTime(time);

           this.draw(this.than*audio.currentTime);

        },

        changeType(){

          this.playbool = !this.playbool;

          let audio = this.$refs.audio;

          if(this.playbool){

            //暂停

             audio.pause()

          }else{

            audio.play()

          }

        },

        event(dom) {  //事件绑定

            if(this.isMobile){

                dom.addEventListener("touchstart", this.OnMouseDown.bind(this), false);

                dom.addEventListener("touchmove", this.throttle(this.OnMouseMove.bind(this)), false);

                dom.addEventListener("touchend", this.OnMouseUp.bind(this), false);

                return

            }

            dom.addEventListener("mousedown", this.OnMouseDown.bind(this), false);

            dom.addEventListener("mousemove", this.throttle(this.OnMouseMove.bind(this)), false);

            dom.addEventListener("mouseup", this.OnMouseUp.bind(this), false);

        },

        OnMouseDown(evt) {

            let audio = this.$refs.audio;

            //暂停音频

            audio.pause()

            this.clearLocation(evt);

            let range = 10;

            let X = this.getx(evt);

            let Y = this.gety(evt);

            let P = this.P

            let minX = P.x - this.slider - range;

            let maxX = P.x + this.slider + range;

            let minY = P.y - this.slider - range;

            let maxY = P.y + this.slider + range;

            if (minX < X && X < maxX && minY < Y && Y < maxY) {   //判断鼠标是否在滑块上

            this.isDown = true;

            } else {

            this.isDown = false;

            }

        },

        main(){

            const dom = document.getElementById("content")

            const obj = {

                el: dom,

                startDeg:1.5    ,

                endDeg: 3.5,

                outColor: 'rgba(50, 50, 70, .2)',

                counterclockwise: false

            }

            this.constructor(obj)

        },

        constructor(param) {

            this.initParam(param)

            this.draw(this.value)

        },

        initParam(param) {

            const {

            el,

            startDeg = 1.5,

            endDeg = 3.5,

            outColor = "rgba(50, 50, 70, .2)",

            innerLineWidth = 1,

            outLineWidth = 5,

            counterclockwise = true,

            slider = 8,

            color = ["#ffffff", "#ffffff"],

            sliderColor = "#fff",

            sliderBorderColor = "#33aaff",

            value = 0,

            change = (v)=> {  },

            textShow = true

            } = param;

            this.el = el;

            this.width = el.offsetWidth;

            this.height = el.offsetHeight;

            this.center = this.width / 2

            this.radius = this.width / 2 - 30; //滑动路径半径

            this.initCanvas(el);

            this.startDeg = startDeg;

            this.endDeg = endDeg;

            this.outColor = outColor;

            this.innerLineWidth = innerLineWidth;

            this.outLineWidth = outLineWidth;

            this.counterclockwise = counterclockwise;

            this.slider = slider;

            this.color = color;

            this.sliderColor = sliderColor;

            this.sliderBorderColor = sliderBorderColor;

            this.value = value;

            this.textShow = textShow;

            this.change = change;

            this.isDown = false;

            this.event(el)

        },

        OnMouseMove(evt) {

            if (!this.isDown) return;

            let evpoint = {};

            evpoint.x = this.getx(evt);

            evpoint.y = this.gety(evt);

            let point = this.spotchangeXY(evpoint);

            let deg = this.XYToDeg(point.x, point.y);

            deg = this.counterclockwise ? deg : Math.PI * 2 - deg;

            let val = (deg/ Math.PI - this.startDeg) / (this.endDeg - this.startDeg)  * 100

            if(val<0) val = 100 + val;

            if(val >= 100) val = 100;

            if(val <= 0) val = 0;

            if(Math.abs (val - this.value) > 10) return;

            //音频定位播放

            let time = val/this.than;

            let audio = this.$refs.audio;

            audio.currentTime = time

            this.animate = requestAnimationFrame(this.draw.bind(this,val));

            if(this.value != Math.round(val)){

                this.value = Math.round(val);

                this.change(this.value)

            }

        },

        OnMouseUp(evt) {  //鼠标释放

            const _this = this

            cancelAnimationFrame(_this.animate);

            this.isDown = false;

            if(this.distance(evt)){

                this.playbool = false;

                let audio = this.$refs.audio;

                //播放音频

                audio.play()

            }

        },

        distance(evt){

            let x = this.getx(evt);

            let y = this.gety(evt);

            let distance = Math.abs(Math.sqrt(Math.pow(x - 135, 2) + Math.pow(y - 135, 2)));

            if(0<distance && distance<130){

                return true

            }else{

                return false

            }

        },

        //点击定位

        clearLocation(evt){

            let evpoint = {};

            evpoint.x = this.getx(evt);

            evpoint.y = this.gety(evt);

            let point = this.spotchangeXY(evpoint);

            let deg = this.XYToDeg(point.x, point.y);

            deg = this.counterclockwise ? deg : Math.PI * 2 - deg;

            let val = (deg/ Math.PI - this.startDeg) / (this.endDeg - this.startDeg)  * 100

            if(val<0) val = 100 + val;

            if(val >= 100) val = 100;

            if(val <= 0) val = 0;

            if(this.distance(evt)){

                this.animate = requestAnimationFrame(this.draw.bind(this,val));

                //音频定位播放

                let time = val/this.than;

                let audio = this.$refs.audio;

                audio.currentTime = time

                audio.play()

                audio.pause()

                if(this.value != Math.round(val)){

                    this.value = Math.round(val);

                    this.change(this.value)

                }

            }

        },

        //绘图

        draw(value) {

            this.ctx.clearRect(0, 0, this.width, this.width);

            this.ctx.save();

            let startDeg = this.counterclockwise ? Math.PI * (2 - this.startDeg) : Math.PI * this.startDeg

            let endDeg = this.counterclockwise ? Math.PI * (2 - this.endDeg) : Math.PI * this.endDeg

            // 绘制外侧圆弧

            this.ctx.beginPath();

            this.ctx.arc(this.center, this.center, this.radius, startDeg, endDeg, this.counterclockwise); // 绘制外侧圆弧

            this.ctx.strokeStyle = this.outColor;

            this.ctx.lineCap = "round";

            this.ctx.lineWidth = this.outLineWidth;

            this.ctx.stroke();

            let Deg = this.valToDeg(value)

            // 绘制可变圆弧

            let themeColor = (typeof this.color == 'String') ? this.color : this.setLinearGradient()

            this.ctx.beginPath();

            this.ctx.arc(this.center, this.center, this.radius, startDeg, Deg, this.counterclockwise); // 可变圆弧

            this.ctx.strokeStyle =  themeColor;

            this.ctx.lineCap = "round";

            this.ctx.lineWidth = this.outLineWidth;

            this.ctx.stroke();

            // 绘制滑块

            this.P = this.DegToXY(Deg)

            this.ctx.beginPath();

            this.ctx.moveTo(this.center, this.center);

            this.ctx.arc(this.P.x, this.P.y, this.slider, 0, Math.PI * 2, false); // 绘制滑块

            this.ctx.fillStyle = this.sliderColor;;

            this.ctx.fill();

        },

        initCanvas(dom) {

            this.canvas = document.createElement("canvas");

            this.canvas.setAttribute("id", "dragArc");

            this.canvas.setAttribute("width", this.width);

            this.canvas.setAttribute("height", this.width);

            dom.appendChild(this.canvas);

            this.ctx = this.canvas.getContext("2d");

            this.isMobile = /Android|webOS|iPhone|iPod|BlackBerry/i.test(navigator.userAgent);

        },

        //将值转化为弧度

        valToDeg(v) {

            let range = this.endDeg - this.startDeg;

            let val = range / 100 * v;

            if(this.counterclockwise && (val !=0) ) val = 2 -val;

            let startDeg = this.counterclockwise ? (2 - this.startDeg) : this.startDeg;

            return (startDeg + val) * Math.PI;

        },

        // 弧度转化为对应坐标值

        DegToXY(deg) {

            let d = 2 * Math.PI - deg;

            return this.respotchangeXY({

            x: this.radius * Math.cos(d),

            y: this.radius * Math.sin(d)

            })

        },

        //canvas坐标转化为中心坐标

        spotchangeXY(point) {

            const spotchangeX = (i) => {

            return i - this.center

            }

            const spotchangeY = (i) => {

            return this.center - i

            }

            return {

            x: spotchangeX(point.x),

            y: spotchangeY(point.y)

            }

        },

        //中心坐标转化为canvas坐标

        respotchangeXY(point) {

            const spotchangeX = (i) => {

            return i + this.center

            }

            const spotchangeY = (i) => {

            return this.center - i

            }

            return {

            x: spotchangeX(point.x),

            y: spotchangeY(point.y)

            }

        },

        setLinearGradient(){

            const grad  = this.ctx.createLinearGradient(0,0, 0,this.width);

            this.color.forEach((e, i) => {

                if(i == 0){

                    grad.addColorStop(0, e)

                }else  if(i == this.color.length - 1){

                    grad.addColorStop(1, e)

                }else{

                    grad.addColorStop(1/this.color.length * (i+1), e);

                }

            });

            return grad;

        },

        // 将坐标点转化为弧度

        XYToDeg(lx, ly) {

            let adeg = Math.atan(ly / lx)

            let deg;

            if (lx >= 0 && ly >= 0) {

            deg = adeg ;

            }

            if (lx <= 0 && ly >= 0) {

            deg = adeg + Math.PI;

            }

            if (lx <= 0 && ly <= 0) {

            deg = adeg + Math.PI;

            }

            if (lx > 0 && ly < 0) {

            deg = adeg + Math.PI * 2;

            }

            return deg

        },

        //获取鼠标在canvas内坐标x

        getx(ev) {

            if(!this.isMobile) return ev.clientX - this.el.getBoundingClientRect().left;

            if(ev.touches.length){

                return ev.touches[0].pageX - this.el.getBoundingClientRect().left;

            }else{

                return ev.changedTouches[0].pageX - this.el.getBoundingClientRect().left;

            }

        },

        //获取鼠标在canvas内坐标y

        gety(ev) {

            if(!this.isMobile) return ev.clientY - this.el.getBoundingClientRect().top;

            if(ev.touches.length){

                 return ev.touches[0].pageY - this.el.getBoundingClientRect().top;

            }else{

                return ev.changedTouches[0].pageY - this.el.getBoundingClientRect().top;

            }

        },

        //节流

        throttle(func) {

            let previous = 0;

            return function() {

                let now = Date.now();

                let context = this;

                let args = arguments;

                if (now - previous > 10) {

                    func.apply(context, args);

                    previous = now;

                }

            }

        },

    }

}

</script>

<style scoped>

.circle_box{

     position: relative;

     padding-top: 130px;

     top: 0;

     left: 0;

     width: 100%;

     height: 245px;

}

#content{

  position: absolute;

  left: 50%;

  transform: translateX(-50%);

  height: 240px;

  width: 270px;

}

.img_0{

  position: absolute;

  top: 175px;

  left: 50%;

  transform: translateX(-50%);

  width: 180px;

  height: 180px;

  border-radius: 50%;

  z-index: 5;

}

.img_1{

  position: absolute;

  left: 50%;

  transform: translateX(-50%);

  top: 243px;

  width: 34px;

  height: 46px;

  z-index: 10;

}

.posi{

    position: absolute;

    left: 0;

    top: 10px;

    z-index: 1000;

}

</style>文章来源地址https://www.toymoban.com/news/detail-422072.html

到了这里,关于vue3.0 安卓和ios h5 移动端音频自定义圆环可拖拽播放(兼容微信浏览器)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包赞助服务器费用

相关文章

  • vue h5 项目中与 app 安卓 or ios 进行交互 方式, h5与app交互

    vue h5 项目中与 app 安卓 or ios 进行交互 方式, h5与app交互

    vue h5 项目中与 app 安卓 or ios 进行交互 方式, h5与app交互 前端同学可以加我一起交流一起进步 案例描述:需求是 混合开发中,H5页面与原生app安卓或者ios交互(包括,调用app的方法,或者app调用 h5中定义的方法)从而实现交互 项目场景:开发帮助中心页面,帮助中心页面采

    2024年02月11日
    浏览(12)
  • vue移动端H5调起手机发送短信(兼容ios和android)

    移动端h5页面调起手机发送短信功能,ios和android的兼容写法不一样。 android  ios

    2024年02月08日
    浏览(9)
  • Vue3 如何去开发安卓 或者 ios

    Vue3 如何去开发安卓 或者 ios

    Vue3 有没有一款好用的开发原生的工具 1.uniapp 我 个人 认为uniapp 适合开发小程序之类的,用这个去开发原生应用会存在一些问题 性能限制 :由于 Uniapp 是通过中间层实现跨平台,应用在访问底层功能时可能存在性能损失。与原生开发相比,Uniapp 在处理大规模数据、复杂动画

    2024年02月15日
    浏览(9)
  • vue项目h5端判断所处环境(支付宝、微信、判断安卓和iOS环境)

    一、判断是否为支付宝坏境 isAlipayClient () {     if (navigator.userAgent.indexOf(\\\'AlipayClient\\\') -1) {       return true     }     return false   }, 二、判断安卓还是ios   phoneOs () {     var u = navigator.userAgent,       isAndroid = u.indexOf(\\\'Android\\\') -1 || u.indexOf(\\\'Linux\\\') -1,       isiOS = !!u.match(/(i[^;]+;(

    2024年02月07日
    浏览(10)
  • vue&h5获取手机前置摄像头(安卓&ios),input capture属性和navigator.mediaDevices

    调用前置摄像头 capture=\\\"user\\\" 调用后置摄像头capture=\\\"environment\\\"或其他只适用于ios 根据官网解释 iOS最遵守遵守HTML5规范,其次是X5内核,安卓的webview基本忽略了capture。 官方文档:www.w3.org/TR/2018/REC-html-media-capture-20180201/ 对于安卓,亲测capture=\\\"user\\\"效果是,第一次打开前置摄像无效

    2024年02月10日
    浏览(14)
  • vue3+wangEditor5/vue-quill自定义上传音频+视频

    vue3+wangEditor5/vue-quill自定义上传音频+视频

    这是另一个常用的富文本编辑器,它提供了许多可定制的功能和事件,并且也有一2个官方的 Vue 3 组件 wangEditor5用在Vue3中自定义扩展音频、视频、图片菜单;并扩展音频元素节点,保证音频节点的插入、读取、回写功能正常;支持动态修改尺寸 UEditor是由百度web前端研发部开

    2024年02月12日
    浏览(10)
  • vue3 + Element Plus自定义音频audio样式及控件

    vue3 + Element Plus自定义音频audio样式及控件

    由于 audio 标签原生样式不能修改UI样式,所以需要隐藏原生 audio 标签,重新写一个控件进行操作 audio 代码实现: 先封装一个组件 audioPlayer.vue 。注意:需提前安装了 Element Plus 在父组件内引用自定义组件 audioPlayer.vue 效果图:

    2024年02月06日
    浏览(7)
  • wangEditor5在Vue3中的自定义图片+视频+音频菜单

    wangEditor5在Vue3中的自定义图片+视频+音频菜单

    本文适用于wangEditor5用在Vue3中自定义扩展音频、视频、图片菜单;并扩展音频元素节点,保证音频节点的插入、读取、回写功能正常;支持动态修改尺寸。适用于初学者。 ButtonMenu:自定义扩展新功能 | wangEditor ModalMenu:自定义扩展新功能 | wangEditor 注册菜单到wangEditor:定义新

    2024年02月06日
    浏览(21)
  • 【项目复盘Vue2-移动端】IOS使用Vant表单组件输入框获取焦点后放大页面,安卓软键盘遮挡问题

    【项目复盘Vue2-移动端】IOS使用Vant表单组件输入框获取焦点后放大页面,安卓软键盘遮挡问题

    使用Vue+Vant做的移动端项目,在登录界面使用Vant的表单组件van-input时发现在真机测试IOS会出现获取焦点输入时会撑大原页面的宽度,每一个输入框获取到焦点就会页面就会放大一点点,需要双指缩放才能回到原来的比例。 经过一番百度后发现: 在移动端开发项目中,发现页

    2024年02月12日
    浏览(24)
  • vue3实现H5网页录音并上传(mp3、wav)兼容Android、iOS和PC端

    使用 Recorder插件 可以在HTML5网页中进行录音,录音完成后得到blob文件对象,然后将blob上传到服务器;项目使用的vue3.0版本(这个插件同时支持vue2.0、也支持uniapp,很强!!),录音过程中会显示可视化波形,同时能够做到兼容PC端、Android、和iOS,一次编码 到处运行,哈哈

    2024年02月08日
    浏览(18)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包