前段時間公司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="width: 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); width: 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應該是個不錯的選擇。