效果:(左邊是canvas繪制的視頻,右邊是經過濾鏡處理后的canvas視頻)
幾個關鍵點:
requestAnimationFrame 用於重復繪制圖像,形成動態視頻
ctx.drawImage 在canvas中繪制圖像(支持跨域)
getImageData 獲取canvas內的圖像數據
putImageData 圖像數據付給canvas
源碼:
html:2個canvas,2個按鈕事件
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>使用canvas繪制視頻流</title> <script src="./vue.js"></script> <style> .canvas { width: 300px; height: 300px; background-color: #000; border: 1px solid #000; } </style> </head> <body> <div id="app"> <canvas ref='preview' class="canvas"></canvas> <canvas ref='preview2' class="canvas"></canvas> <div> <button @click="btnplay">播放</button> <button @click="btnpause">暫停</button> </div> </div> <script src="3.js"></script> </body> </html>
js:
new Vue({ el: '#app', mounted() { //canvas ctx對象 this.ctx = this.$refs.preview.getContext('2d'); //濾鏡的canvas ctx對象 this.ctx2 = this.$refs.preview2.getContext('2d'); //創建video對象 this.video = document.createElement('video'); this.video.src = './movie.mp4'; //canvas寬高 this.previewWidth = this.$refs.preview.width this.previewHeight = this.$refs.preview.height //重復執行 // this.animationFrame() requestAnimationFrame(this.animationFrame.bind(this)); }, methods: { //播放 btnplay() { this.video.play() }, //暫停 btnpause() { this.video.pause() }, //繪制視頻到canvas animationFrame() { this.ctx.drawImage(this.video, 0, 0, this.previewWidth, this.previewHeight)//繪制圖片 這個是支持跨域的 /** * getImageData/putImageData 只支持同源 不支持跨域 */ const imageData = this.ctx.getImageData(0, 0, this.previewWidth, this.previewHeight);//獲取canvas內的圖像數據 let imageData2 = this.ctx2.createImageData(imageData.width, imageData.height)//創建一個空的canvas圖像數據 //拷貝canvas1中的數據並改成黑白顏色 const data = imageData.data for (let i = 0; i < data.byteLength; i += 4) { let c = Math.floor((data[i] + data[i + 1] + data[i + 2]) / 3) imageData2.data[i] = c //r imageData2.data[i + 1] = c //g imageData2.data[i + 2] = c //b imageData2.data[i + 3] = 255 //a } //改成反轉顏色 const data2 = imageData2.data for (var i = 0; i < data2.length; i += 4) { imageData2.data[i] = 255 - data2[i]; imageData2.data[i + 1] = 255 - data2[i + 1]; imageData2.data[i + 2] = 255 - data2[i + 2]; imageData2.data[i + 3] = 255; } this.ctx2.putImageData(imageData2, 0, 0);//圖像數據付給canvas2 requestAnimationFrame(this.animationFrame.bind(this)); }, }, })