H5頁面video在app內實現poster效果
阿新 • • 發佈:2022-12-08
H5頁面Video元件 在APP內 時候沒有 載入的時候 沒有封面就是poster,所以要想辦法解決,
video標籤
移動端的頁面裡如果有video標籤,根據官方文件上寫著,沒有加poster的話,就自動採用視訊第一幀作為poster。
在ios上大部分瀏覽器都不會自動載入視訊第一幀作為poster,ios上表現為一個大播放按鈕在中間,然後播放器其他區域全是空白,安卓機上則表現良好
- 查閱資料,得出解決方案是,用canvas載入video第一幀渲染一個base64的image作為poster,嘗試了後失敗,canvas報錯因為資源跨域,被汙染無法轉image,即便video設定了跨域也不行,資源的獲取上也是設定了跨域的
- 換了種思路,不使用第一幀,使用第0.1秒作為封面,只要在src後面加上#t=0.1即可自動載入到第0.1秒,實現了poster效果,比如<video src="xxxxxx.mp4#t=0.1" />,試了一下大部分ios上的移動瀏覽器都支援,支援極為良好。(這個方法推薦)
- 還有就是用 那種截圖的方式,視訊的連結後面加上一些?引數(是騰訊的提供的,當然是要付費的, )
查閱資料後得知,需要加一個監聽,實現自動播放
document.addEventListener("WeixinJSBridgeReady", function但是我要的是實現poster效果,不是自動播放,所以要在play後給他暫停(){ document.getElementById('video').play() }, false)
document.addEventListener("WeixinJSBridgeReady", function (){ document.getElementById('video').play(); document.getElementById('video').pause(); }, false)
2.於是在一對父子元件裡分別都監聽了這個事件,但是子元件一直觸發不了,父元件則能觸發,
因為子元件是通過介面返回了資料才去渲染的,
而父元件頁面一載入就有,WeixinJSBridgeReady只會觸發一次,子元件裡面設定監聽的時候,已經遲了,不會再觸發了
3.子元件需要這樣判斷去觸發,在didmount的時候去判斷,然後按照下面的去呼叫,在回撥函式裡去播放和暫停,實現poster效果
componentDidMount = () => { if (window.WeixinJSBridge) { window.WeixinJSBridge.invoke('getNetworkType', {}, e => { document.querySelector('video').play(); document.querySelector('video').pause(); }, false); } }
4.對於其他端,需要給src後面加上#t=0.1,並且設定預設內聯播放,不脫離文件流,
因為很多安卓瀏覽器都會劫持video標籤,在播放的時候自動呼叫原生播放器,提升效能,對於互動有嚴格要求的產品來說,這個是要幹掉的。
所以需要加一些屬性,由於是在字串裡面的標籤里加,如果用正則匹配替換,會非常不方便,所以用下面的方法
setVideoHTML = () => { const {innerHTML} = this.props; const div = document.createElement('div'); div.innerHTML = innerHTML; div.querySelectorAll('video').forEach(video => { video.src += '#t=0.1'; video.setAttribute('playsinline', 'true'); video.setAttribute('autoplay', 'false'); video.setAttribute('preload', 'auto'); video.setAttribute('webkit-playsInline', 'true'); video.setAttribute('x-webkit-airplay', 'allow'); video.setAttribute('x5-video-player-type', 'h5'); video.setAttribute('x5-video-player-fullscreen', 'true'); video.setAttribute('x5-video-orientation', 'portraint'); }); return div.innerHTML; }
最後需要調整
這裡好像只能用setAttribute方法,直接加沒生效,這樣子呼叫後,得到的還是一串字串,但是裡面對應的內容都被替換修改了,就可以正常用了
<div dangerouslySetInnerHTML={{__html: this.setVideoHTML()}}/>