• H5 video踩坑实录


          前段时间公司APP做了一个APP论坛会议,嵌入了h5播放器。我以为很简单,没想到,这正是我踩进泥潭的开始。。。

        (想要吸取经验的小伙伴可以慢慢往下看,想要解决方案的直接看最后!)

        一、一开始我以为直接用H5原生video就可以直接实现。

          

    <video src="url" poster="video.png" width="100%" height = "9rem"></video>

          src :视频地址,

          poster:视频封面,

          obj.play() :播放,

          obj.pause():暂停。

          到这里我以为就大功告成了,没想到啊,

          首先没有控制条,其次苹果浏览器默认全屏,而且苹果不能直接播放和加载。后来Google发现苹果不允许直接播放视频,除非用户主动点击(这是什么混蛋逻辑)。

          

        二、改变思路,把图片放在video上层,点击触发video播放。同时添加controls,设置playsinline不全屏播放

          html:

          <div id = "myvideo">
    
            <img src = "video.png">
    
            <video src="url" poster="video.png" width="100%" height = "9rem" controls="controls" ></video>
    
          </div>

          js:

                IMG.addEventListener ('click',function(){
    
             img.style.display='none';
    
             video.style.display = 'block';
    
           });
    
            video.addEventListener ('click',function(){
    
              video[0].play();
    
            })        

            ……

          css就不放出来了,小伙伴们自行前往git上下载。

          运行一下发现原生的控制条也太丑了。

                      

          而且还发现这玩意的全屏在移动端无法全屏,点击全屏没有反应。

        三、痛定思痛决定重写video组件,一方面优化这丑陋的原生ui,另一方面通过js方法看看能不能支持全屏。

          html:  

          

          <div class="myvideo">
            <img src="images/video.jpg" style=" 100%;height:100%;" class="img">
            <video class="video" 
             playsinline="isiPhoneShowPlaysinline" x5-video-player-type="h5-page" webkit-playsinline="isiPhoneShowPlaysinline" x-webkit-airplay="" preload="none" 
             src="https://blz-videos.nosdn.127.net/1/HearthStone/f6cd63b590d416821d3e27e0.mp4" poster="images/video.jpg"></video>
            <div class="play">
              <svg t="1561619557935" class="iconPause" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="6167" width="2.2rem" height="2.2rem" >
                <path d="M844.704269 475.730473L222.284513 116.380385a43.342807 43.342807 0 0 0-65.025048 37.548353v718.692951a43.335582 43.335582 0 0 0 65.025048 37.541128l622.412531-359.342864a43.357257 43.357257 0 0 0             0.007225-75.08948z" fill="#ffffff" p-id="6168"></path>
              </svg>
              <svg t="1562137769830" class="iconPlay" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3655" width="2.2rem" height="2.2rem" style="display: none;">
                <path d="M319.618435 145.655358c-30.518061 0-55.258535 24.740474-55.258535 55.258535l0 622.170169c0 30.518061 24.740474 55.258535 55.258535 55.258535s55.258535-24.740474 55.258535-55.258535l0-  622.170169C374.876969 170.395832 350.136495 145.655358 319.618435 145.655358z" p-id="3656" fill="#ffffff"></path><path d="M704.381565 145.655358c-30.518061 0-55.258535 24.740474-55.258535 55.258535l0 622.170169c0 30.518061 24.740474             55.258535 55.258535 55.258535s55.258535-24.740474 55.258535-55.258535l0-622.170169C759.6401 170.395832 734.899626 145.655358 704.381565 145.655358z" p-id="3657" fill="#ffffff"></path>
              </svg>
            </div>
            <div class="playShade">
              <div class="progressFather">
                <div class="realTime">00:00</div>
                <div id="progress">
                  <span class="timeBar"></span>
                </div>
                <div class="endTime">00:00</div>
                <div class="all">
                  <svg t="1561625645528" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1999" width="1.6rem" height="1.6rem">
                  <path d="M576 213.333333c0 12.8 8.533333 21.333333 21.333333 21.333334h162.133334l-202.666667 202.666666c-8.533333 8.533333-8.533333 21.333333 0 29.866667 8.533333 8.533333 21.333333 8.533333 29.866667               0l202.666666-202.666667V426.666667c0 12.8 8.533333 21.333333 21.333334 21.333333s21.333333-8.533333 21.333333-21.333333V213.333333c0-12.8-8.533333-21.333333-21.333333-21.333333H597.333333c-12.8               0-21.333333 8.533333-21.333333 21.333333z m-138.666667 343.466667L234.666667 759.466667V597.333333c0-12.8-8.533333-21.333333-21.333334-21.333333s-21.333333 8.533333-21.333333 21.333333v213.333334c0               12.8 8.533333 21.333333 21.333333 21.333333h213.333334c12.8 0 21.333333-8.533333 21.333333-21.333333s-8.533333-21.333333-21.333333-21.333334h-162.133334l202.666667-202.666666c8.533333-8.533333               8.533333-21.333333 0-29.866667-6.4-8.533333-21.333333-8.533333-29.866667 0z" p-id="2000" fill="#ffffff"></path>
                  </svg>
                </div>
              </div>
            </div>
          </div>

        js:

        

    //初始时间,进度显示
    function strTime() {
    starTime[0].innerHTML = timeFormat(mvideo[0].currentTime);
    endTime[0].innerHTML = timeFormat(mvideo[0].duration);
    var currentTime = mvideo[0].currentTime;
    var duration = mvideo[0].duration;
    var percent = 100 * currentTime / duration;
    timeBar[0].style.width = percent + '%';
    //dropProgress();
    };
    //播放
    function videoPlay() {
    mvideo[0].play();
    iconPlay[0].style.display = 'block';
    iconPause[0].style.display = 'none';
    }
    //暂停
    function videoPause() {
    mvideo[0].pause();
    iconPlay[0].style.display = 'none';
    iconPause[0].style.display = 'block';
    }
    //时长转换
    function timeFormat(seconds) {
    var minite = Math.floor(seconds / 60);
    if (minite < 10) {
    minite = "0" + minite;
    }
    var second = Math.floor(seconds % 60);
    if (second < 10) {
    second = "0" + second;
    }
    return minite + ":" + second;
    }
    //更新进度条
    function updateProgress(x, width) {
    var position = x / width;
    mvideo[0].currentTime = position * mvideo[0].duration;
    timeBar[0].style.width = position * 100 + '%';
    }
    
    //全屏
    function all() {
    // console.log(width, height);
    // ovideo[0].style.transform = 'rotate(90deg) translate(' + (height - width) / 2 + 'px,' + (height - width) / 2 + 'px)';
    // ovideo[0].style.zIndex = 2;
    // ovideo[0].style.heigt = width + 'px';
    // ovideo[0].style.width = height + 'px';
    // ovideo[0].style.marginTop = -2 + 'px';
    // ltitle[0].style.display = 'none';
    // lcontent[0].style.display = 'none';
    requestFullScreen(ovideo[0]);
    };
    //全屏
    function requestFullScreen(element) {
    var el = element;
    if (el.requestFullscreen) {
    el.requestFullscreen()
    } else if (el.mozRequestFullScreen) {
    el.mozRequestFullScreen()
    } else if (el.webkitRequestFullscreen) {
    el.webkitRequestFullscreen(Element.ALLOW_KEYBOARD_INPUT)
    } else if (player.video.webkitSupportsFullscreen) {
    player.video.webkitEnterFullscreen()
    } else if (el.msRequestFullscreen) {
    el.msRequestFullscreen()
    } else {
    util.addClass(el, 'xgplayer-fullscreen-active')
    }
    }
    //退出全屏
    function exitFullscreen() {
    var el = document;
    if (document.exitFullscreen) {
    document.exitFullscreen()
    } else if (document.webkitExitFullscreen) {
    document.webkitExitFullscreen()
    } else if (document.mozCancelFullScreen) {
    document.mozCancelFullScreen()
    } else if (document.msExitFullscreen) {
    document.msExitFullscreen()
    } else {
    util.removeClass(el, 'xgplayer-fullscreen-active')
    }
    }
    //取消全屏
    function quitAll() {
    // ovideo[0].style.transform = 'rotate(360deg) translate(' + (height - width) / 2 + 'px,' + (height - width) / 2 + 'px)';
    // ovideo[0].style = 'none';
    // ltitle[0].style = 'none';
    // lcontent[0].style = 'none';
    // alert(123);
    exitFullscreen();
    }

     css请前往git自行下载。

    发现iOS无法全屏,查询发现iOS移动浏览器已经禁用了fullScreen组件。崩溃了要。。。

    四、继续改,lz整个伪全屏出来,

      逻辑就是判断浏览器宽高,点击全屏的时候旋转屏幕,然后赋值宽高,慢慢调整,返回全屏时js动态奖video的style设置为空。

      

    var conW = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;
    var conH = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight;
    // transform: rotate(90deg);  667px; height: 375px;transform-origin:28% 50%;
    //var iosTopHe = 0;//若有其他样式判断,写于此
    
    $("#video").css({
    "transform":"rotate(90deg) translate("+((conH-conW)/2)+"px,"+((conH-conW)/2)+"px)",
    "width":conH+30+"px",
    "height":conW+35+"px",
    //"margin-top":iosTopHe+"px",
    // "border-left":iosTopHe+"px solid #000",
    "transform-origin":"center center",
    "-webkit-transform-origin": "center center",
    "z-index":"11111",
    "margin-top":"2.2rem"
    });
    $("#myvideo").css({
    "width":conH+"px",
    "height":conW+"px",
    "margin-top":"0rem",
    "z-index":"11111"
    });
    $('.psVideo-shade').css({
    "z-index":"1111111",
    "width":conH+"px",
    "height":conW+"px",
    //"marginTop":"12rem"
    });
    $('.psVideo-progress').css({
    "width":conH+"px",
    "height":"0.2rem"
    });
    $('.psVideo-btn').css({
    "margin-left":"12rem",
    //"height":"0.2rem"
    })
    $('.psVideo-play-footer').css({
    "margin-bottom":"-0.2rem",
    //"height":"0.2rem"
    })
    width = conH;
    var lw = $('.psVideo-timeBar').width();
    var progresses = $('.psVideo-progress');
    var pw = $('.psVideo-progress')
    var rlw = lw*pw/width;
    $('.psVideo-timeBar').css('width', rlw+'px');
    qenableProgressDrag();
    //updateProgress(rlw);
    quan = true;

    实现起来一言难尽。还是上效果吧。

    你也看见了,状态栏收不回去。没办法,慢慢找别的思路吧。

    五、我在找资料的时候,突然想起来,我上一版的页面在微信,钉钉上都能正常显示,浏览器上好像也能(safari除外)。

      我翻过头去研究之前那一版代码,半天也没有思路,我突然发现video还有第三方插件

      腾讯:https://cloud.tencent.com/document/product/454/7503

      阿里:https://help.aliyun.com/document_detail/51991.html

      七牛:https://developer.qiniu.com/pili/sdk/4621/web-player-sdk

      头条(西瓜):http://h5player.bytedance.com/api/#%E5%AE%9E%E4%BE%8B%E5%8C%96%E5%AE%8C%E6%88%90

      然并卵,在app上仍然无法正常显示,真的要崩溃了。

    六、转机(重点)

      我在漫无目的的找资料的时候,偶然点进去一个安卓webview解决办法,看的时候发现播放器好像没有这么麻烦。嘿嘿嘿,功夫不怕有心人。

      原来移动端嵌套webview时候可以引进ui控件。

      我又去看了一下移动端的ui控件,原来如此。

      安卓iOS引入webview ui控件(移动端又称内核,简单来说就是一个sdk),它可以劫持webview里的h5组件然后渲染,

      微信,钉钉包括我的华为浏览器用的都是这种办法,微信引入了x5内核,钉钉引得啥内核,我不知道,反正事情发展到这出现了转机,我问我之前的安卓同事,从他口里听见了肯定的回复之后,我终于放松了。

      总的来说,对于混合开发APP来说,其实播放器没有那么复杂,H5写入一个video组件即可,ui控件(sdk)会直接帮你渲染。(安卓,ios)统一样式需要他们去解决了,毕竟有的sdk不太支持iOS(比如X5)。

      对于webApp来说,H5Plus应该是个不错的选择。

  • 相关阅读:
    P1855 榨取kkksc03
    P1359 租用游艇
    P1656 炸铁路
    P1536 村村通
    P3367 【模板】并查集
    P3395 路障(洛谷)
    P1135 奇怪的电梯(洛谷)
    P1331 海战(洛谷)
    conda安装和pip安装的国内镜像配置
    cvpr2020 | 图像增强与恢复论文盘点
  • 原文地址:https://www.cnblogs.com/shoucigongkai/p/11231378.html
Copyright © 2020-2023  润新知