認識兩個HTML5標籤,分別是video和source。
video標籤屬性
- autoplay:表示視訊是否就緒後馬上播放,值為autoplay
- controls:表示是否向使用者顯示控制元件,值為controls
- height:表示視訊播放器高度
- width:表示視訊播放器寬度
- loop:表示當媒介檔案完成播放後是否再次開始播放,值為loop
- preload:表示視訊是否在頁面載入時進行載入,並預備播放,若使用autoplay,則忽略該屬性,值為preload
- poster:指定視訊載入時顯示的圖片url
- src:指定要播放的視訊url
source標籤屬性
- src:指定要連結的媒介資源URL
- type:表示資源的MIME型別。比如在video標籤中支援型別有video/mp4、video/ogg和video/webm
如何製作一個簡易版彈幕視訊?
-
HTML部分
內容分為螢幕層和彈幕層,螢幕層由視訊、輸入框和按鈕組成,比較簡單。
<!--螢幕層--> <div class="screen"> <!--視訊--> <video class="screen-video" autoplay loop> <source src="./video/happy.mp4" type="video/mp4"> 您的瀏覽器不支援 video 標籤。 </video> <!--輸入框--> <input type="text" class="screen-input"> <!--傳送按鈕--> <input type="button" value="傳送" class="screen-button" onclick="send()"> </div> <!--彈幕層--> <div class="barrage"></div> 複製程式碼
-
CSS部分
佈局結合百分比佈局和REM佈局,使網頁響應式,體驗稍好。
.screen-video { width:80%; margin: 1rem 10%; border: 1px solid white; /*填充父元素,IE和Edge不支援,真頭疼!!!*/ object-fit: fill; } .screen-input { position: absolute; left:10%; height: 1.5rem; line-height: 1.5rem; font-size: 1rem; } .screen-button { position: absolute; right: 10%; height: 1.5rem; line-height: 1.5rem; letter-spacing: 0.2em; font-size: 0.8rem; cursor: pointer; } .barrage { position: absolute; left:10%; width: 80%; /*x軸方向上超過則隱藏內容*/ overflow-x: hidden; z-index: 999; } 複製程式碼
-
JavaScript部分
第一步,設定事件監聽
//視窗載入時初始化 window.addEventListener("load",init,false); //視窗大小變化時重新初始化 window.addEventListener("resize",init,false); //輸入框回車時傳送彈幕文字 content.addEventListener("keyup",function(event) { var e = event||window.event; if (e.which == "13"|| e.keyCode =="13") { send(); } },false); 複製程式碼
第二步,事件處理
-
初始化
function init(){ // 實現REM佈局需要根據視窗大小來控制根字型大小 // 瀏覽器預設字型大小是16px,最小字型是12px html.style.fontSize = parseInt(doc.clientWidth /45)+"px"; if(parseInt(html.style.fontSize)<12){ html.style.fontSize = "12px"; } //設定video的高度 video.style.height = parseInt(video.offsetWidth/16*9)+"px"; //設定input的寬度 content.style.width = parseInt(video.offsetWidth - btn_send.offsetWidth)+"px"; //設定button的位置 btn_send.style.top = (video.offsetHeight + video.offsetTop *2)+"px"; //設定barrage的位置和高度 barrage.style.top =video.offsetTop +"px"; barrage.style.height = video.offsetHeight +"px"; } 複製程式碼
以前通過獲取樣式物件進行初始化,如下,
var sstyle = screen.currentStyle||window.getComputedStyle(screen); var vstyle = video.currentStyle||window.getComputedStyle(video); 複製程式碼
之後放棄使用這種方式,一是有相容性,比如獲取margin,在Chrome和FF正常,但是到了IE和FF則不支援了,獲取marginTop、marginLeft等則正常,雖然可以解決,但是為了這點問題,折騰半天,實在沒必要。二是JS需要關注CSS是否應用了該樣式,如果沒有,那麼獲取的是預設值,比如margin預設值是auto,但是我想獲取具體的數值,這就不好處理了。總之,涉及BOM操作的還是少用比較好。
-
傳送彈幕內容
function send() { //傳送內容 var val = trim(content.value); //建立的節點 var span; //偏移量 var offset = 0; //幀ID var id; if (val != "") { //建立節點 span = document.createElement("span"); //設定文字 span.innerHTML = val; //設定樣式 span.className = "barrage-span"; //新增 barrage.appendChild(span); //設定初始位置,注意新增元素後寬度和高度才生效。 span.style.top = getRandomNumber(parseInt(video.offsetHeight-span.offsetHeight)) + "px"; span.style.left = video.offsetWidth+"px"; span.style.color = getRandomColor(); //設定監聽事件 span.addEventListener("mouseover", stop, false); span.addEventListener("mouseout", scroll, false); //預設初始文字滾動 scroll(); } content.value = ""; function scroll() { offset += 2; span.style.transform = "translateX(-" + offset + "px)"; span.style.transition = "transform 0s linear"; if (offset >= parseInt(video.offsetWidth+span.offsetWidth)) { stop(); barrage.removeChild(span); }else{ id = window.requestAnimationFrame(scroll); } } function stop(){ window.cancelAnimationFrame(id); } //去除兩邊空格 function trim(s) { return s.replace(/(^\s*)|(\s*$)/g, ""); } //指定範圍內獲取隨機數 function getRandomNumber(value) { return parseInt(Math.random() * value); } //獲取任意顏色 function getRandomColor() { var color = "#"; var j; for (var i = 0; i < 6; i++) { j = getRandomNumber(16); color += str.substring(j, j + 1); } return color; } } 複製程式碼
在處理髮送彈幕時,發現文字不時會超出彈幕層,從而出現滾動條,結果發現是下面這句程式碼出現了問題,
span.style.top = getRandomNumber(parseInt(video.offsetHeight-span.offsetHeight)) + "px"; 複製程式碼
span.offsetHeight列印結果總為0,後來把這句程式碼放在父元素新增span元素之後,即下面這句程式碼就可以了。這說明了要使元素的offsetWidth、offsetHeight等屬性值生效,需要注意元素是否已經渲染到瀏覽器上,單單建立一個元素物件,但是沒有新增到文件中,只是存放在記憶體,還沒有被瀏覽器渲染。先記錄下來,避免以後填坑,哈哈。
barrage.appendChild(span); 複製程式碼
-
附上原始碼:
https://github.com/muzhidong/frontend-demo/tree/master/barrage-video
複製程式碼