web實戰:video結合canvas實現視訊線上截圖

newbeehh發表於2018-06-22

給大家講解下我前幾天看到的一個有趣小demo:視訊線上截圖。以下是我修改和新增了新功能後的效果圖:

web實戰:video結合canvas實現視訊線上截圖

是不是很酷,其實挺簡單的,下面就給大家講講怎麼弄哈。

這裡主要分為三大塊功能,首先是第一個:

利用URL物件獲取視訊連結並展示:

js的URL物件有個createObjectURL方法,它可以獲取一個檔案(File物件)的url,然後插入到video元素的src特性中,這樣就可以實現視屏的展示了。當然如何獲取File物件呢,方法有種,比如使用input元素,或者使用拖動的方式。一個完整的程式碼段:

<input type="file"/>
複製程式碼
document.querySelector('input[type="file"]').addEventListener('change',function () {
    document.querySelector('video').src = window.URL.createObjectURL(this.files[0])
})複製程式碼

當然原始碼中我並不是這樣寫的,僅僅是為了給大家一個演示而已。關於URL更加具體的使用,大家可以看看這篇文章或者MDN。

利用canvas實現視訊截圖:

接下來就是關鍵步驟了,但也很簡單,那就是使用canvasdrawImage方法,大家如果翻到高程三的第15.2.6節,就會發現drawImage的方法的使用描述得非常詳細,但漏講了一個,那就是video元素也可傳入drawImage方法中,並且繪製圖形。具體程式碼段:

var canvas = document.createElement("canvas");
var canvasCtx = canvas.getContext("2d");
var video=document.querySelector('video');複製程式碼
//坐原影象的x,y軸座標,大小,目標影象的x,y軸標,大小。
canvasCtx.drawImage(video, 0, 0, videoWidth, videoHeight, 0, 0, imgWidth, imgHeight);
//把圖示base64編碼後變成一段url字串
var dataUrl = canvas.toDataURL("image/png");
//插入圖片得src特性中
document.createElement('img').src=dataUrl;複製程式碼

繪製完成影象後,再呼叫canvastoDataURl方法把影象變成base64編碼的url,就可插入到img元素中展示,一個縮略的圖的製作便完成了。關於圖片和base64的關係,具體的同學們可以看下這篇文章

實現動畫效果:

該動畫實現的主要原理是:先在視訊原處建立一張大小和視訊一致的大圖片,設定為絕對佈局(position:absolut),在實際放置縮圖處建立一張小圖片,設定為不可見(visibility:hidden),然後大圖片通過lefttop實現位移,widthheight實現縮小,至實際放置縮圖處,並形成動畫效果。最後大圖片刪除,小圖片顯示即可。具體程式碼段:

function getOffset(elem) {
    var pos = {x: elem.offsetLeft, y: elem.offsetTop};
    var offsetParent = elem.offsetParent;
    while (offsetParent) {
        pos.x += offsetParent.offsetLeft;
        pos.y += offsetParent.offsetTop;
        offsetParent = offsetParent.offsetParent;
    }
    return pos;
}複製程式碼

該函式是獲取小圖片距viewport(視口)的距離,並提供給大圖片作為位移引數的,高程三的12.2.3節有段幾乎一模一樣的程式碼,並附有詳細說明,以及替代方案getBoundingClientRect函式也有提到,具體的大家翻書看看哈。

下面的程式碼便是建立大圖片和小圖片並實現動畫效果了。為了方便易懂,我這兒使用了JQuery

var $imgBig = $("<img/>");
//設定大圖片的初始位置,就是原視訊處。
$imgBig.css({
    position: "absolute",
    left: video.offsetLeft,
    top: video.offsetTop,
    width: video.offsetWidth+ "px",
    height: video.offsetHeight+ "px"
}).attr("src", dataUrl);複製程式碼
var $img = $("<img/>");
$img.hide();
//獲取小圖片的距離引數,實現大圖片的動畫效果。
var offset = getOffset($img[0]);
//新增動畫效果
$imgBig.animate({
    left: offset.x + "px",
    top: offset.y + "px",
    width: $img.width() + "px",
    height: $img.height() + "px"
}, 500, function () {
    $img.show();
    $imgBig.remove();
});複製程式碼

恩恩,主要的程式碼部分到這就講完啦,當然具體的實現還有很多細節上的問題以及其他的功能可能沒有展示,我就不一一說明了,具體的大家看完原始碼後可以再提問。

下面是我的原始碼地址,大家可以試試哈:

在github上的demo

還有就是我參考的那片文章


相關文章