Realization of video barrage with canvas
As usual, first look at the renderings, and then study happily~
What is canvas?
Canvas (canvas) can use Javascript to draw graphics and images in web pages. Basic structure:
<canvas id="" width="" height=""></canvas>
Width: defines the width of the canvas
Height: defines the height of the canvas
Basic use of canvas
The basic drawing steps are as follows:
let cvs = document.getElementById('canvas'); // Gets the context object used to draw 2D images let ctx = cvs.getContext('2d'); // Call relevant API s to draw images ctx.fillStyle = 'red' ctx.fillRect(x, y, width, height);
Method of canvas element:
let ctx = cvs.getContext(type);
Type context type:
2d returns CanvasRenderingContext2D. Used to draw two-dimensional images.
webgl returns WebGLRederingContext. Used to render 3D images. (three.js)
Basic drawing API canvas
fill
ctx.fillStyle = 'red' // Set fill color ctx.fillRect(x,y,width,height); // Fill rectangle
Stroke
ctx.strokeStyle = 'blue' // Sets the color of the stroke ctx.strokeRect(x,y,width,height); // Stroke rectangle
Draw text
ctx.font = '25px Microsoft YaHei ' // Set font ctx.fillText('Text content', x, y); // Fill text ctx.strokeText('Text content', x, y); // Stroke text
Canvas path drawing API
Path is a graph formed by connecting the preset coordinate points in order.
To draw a path:
- Through CTX Beginpath() opens a new path.
- Through CTX Moveto (x, y) moves the brush to the specified position.
- Start drawing the path through the relevant methods of ctx (classic method: lineTo(x, y)).
- Finally, through CTX stroke(),ctx. The fill () method strokes or fills the path.
After understanding the basics, let's watch the realization of the video barrage
Canvas animation
The essence of animation is to redraw the canvas at regular intervals (very fast 1 / 60 second [60 frames per second]). As long as 60 frames can be guaranteed, animation effect will appear due to visual residue.
window.setInterval(()=>{ Repaint UI }, 1000/60)
Case: realize barrage.
-
Put a layer of canvas over the video tag.
-
Add input and button to realize the function of sending barrage.
Not only need to send the barrage, but also need to move it. But you can't start a timer for each barrage because it consumes too much resources. A timer to manage the animation of all barrages is enough. In this way, you can no longer click the send button to start the timer, but after the page is loaded, you can start the only timer. What the timer does is to update the positions of all barrages and draw them together.
This means that sending a barrage is actually just adding a barrage object to the barrage array, and you don't need to care about drawing.
- Prepare an array to store barrage objects: dmlist = {}.
- When sending the barrage, the barrage contents, x and y are encapsulated into objects and stored in dmlist.
- After the page is loaded, start a timer to continuously (60 frames per second) execute the callback method. Each time the callback method is executed, load dmlist, read each bullet screen information, update the x coordinate of the bullet screen, and redraw all bullet screen contents in canvas.
Specific implementation steps
1. Locate the canvas of canvas on the video tag. The html and css styles are as follows
<div> <video id="video" src="https://huazizhanye.oss-cn-beijing.aliyuncs.com/catmovie.mp4" width="640" height="360" style="background: black;"> </video> <canvas id="canvas" width="640" height="360"></canvas> <input id="range" type="range" min="0" value="0" max="100"> <div class="time"> <span class="left">00:00</span> <span class="right">00:00</span> </div> <button id="btn_play">play/suspend</button> <button id="btn_vp">volume+</button> <button id="btn_vm">volume-</button> <button id="btn_05">0.5 Double speed</button> <button id="btn_1">1 Double speed</button> <button id="btn_2">2 Double speed</button> <br><br> <button id="btn_fc">Full screen display</button> <input id='input' type="text" placeholder="Fill in the barrage content"> <button id="send">Send barrage</button> </div>
.container { width: 400px; border: 1px solid #ddd; text-align: center; padding-bottom: 10px; } .container p{ font-size: 1.3em; font-weight: bold; text-align: center; } .container img{ width: 340px; height: 340px; border-radius: 50%; } .container input{ width: 340px; display: block; margin: 10px auto; } .container .time{ width: 340px; height: 30px; margin: 0px auto; } .container .time .left{ float: left; } .container .time .right{ float: right; } canvas{ width: 640px; height: 360px; position: absolute; top: 0; left: 0; } .container{ position: relative; }
Just add a button and ~ look at the picture
– after clicking the send button, the position of the bullet screen will be randomized, and the information of each item will be push ed into the declared array
// Send barrage send.addEventListener('click', ()=>{ let content = input.value; // Contents of the text box // Encapsulated as dm object and stored in dmlist dmlist.push({ content: content, x: 600, y: (Math.floor(Math.random() * 12)+1) * 30 }); console.log(dmlist); })
– implement the core timer. Clear the timer every time a new Barrage is sent, otherwise the timer will accumulate and cause a card!. Then traverse the data push ed in the array and draw it on the page
// Start a timer to execute 60 times per second and redraw the UI window.setInterval(()=>{ // Clear all the pixels in the canvas and redraw ctx.clearRect(0, 0, 640, 360); // Traverse dmlist and draw in canvas dmlist.forEach(item=>{ //item: barrage object ctx.fillStyle = "white"; ctx.font = '20px Microsoft YaHei '; item.x--; ctx.fillText(item.content, item.x, item.y); }) }, 1000/60);
The complete code is as follows. I like to remember collection
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>video_player.html</title> <style> .container { width: 400px; border: 1px solid #ddd; text-align: center; padding-bottom: 10px; } .container p{ font-size: 1.3em; font-weight: bold; text-align: center; } .container img{ width: 340px; height: 340px; border-radius: 50%; } .container input{ width: 340px; display: block; margin: 10px auto; } .container .time{ width: 340px; height: 30px; margin: 0px auto; } .container .time .left{ float: left; } .container .time .right{ float: right; } canvas{ width: 640px; height: 360px; position: absolute; top: 0; left: 0; } .container{ position: relative; } </style> </head> <body> <div class="container"> <video id="video" src="https://huazizhanye.oss-cn-beijing.aliyuncs.com/catmovie.mp4" width="640" height="360" style="background: black;"> </video> <canvas id="canvas" width="640" height="360"></canvas> <input id="range" type="range" min="0" value="0" max="100"> <div class="time"> <span class="left">00:00</span> <span class="right">00:00</span> </div> <button id="btn_play">play/suspend</button> <button id="btn_vp">volume+</button> <button id="btn_vm">volume-</button> <button id="btn_05">0.5 Double speed</button> <button id="btn_1">1 Double speed</button> <button id="btn_2">2 Double speed</button> <br><br> <button id="btn_fc">Full screen display</button> <input id='input' type="text" placeholder="Fill in the barrage content"> <button id="send">Send barrage</button> </div> <script src="assets/moment.js"></script> <script> let dmlist = []; // Store barrage objects let cvs = document.getElementById('canvas'); let ctx = cvs.getContext('2d'); // function step(){ // ctx.clearRect(0, 0, 640, 360); // //Traverse dmlist and draw in canvas // dmlist. Foreach (item = > {/ / item: barrage object // ctx.fillStyle = "white"; // ctx.font = '20px Microsoft YaHei'; // item.x--; // ctx.fillText(item.content, item.x, item.y); // }) // //Inform you to execute step again the next time you draw the UI // window.requestAnimationFrame(step); // } // window.requestAnimationFrame(step); // Start a timer to execute 60 times per second and redraw the UI window.setInterval(()=>{ // Clear all the pixels in the canvas and redraw ctx.clearRect(0, 0, 640, 360); // Traverse dmlist and draw in canvas dmlist.forEach(item=>{ //item: barrage object ctx.fillStyle = "white"; ctx.font = '20px Microsoft YaHei '; item.x--; ctx.fillText(item.content, item.x, item.y); }) }, 1000/60); // Send barrage send.addEventListener('click', ()=>{ let content = input.value; // Contents of the text box // Encapsulated as dm object and stored in dmlist dmlist.push({ content: content, x: 600, y: (Math.floor(Math.random() * 12)+1) * 30 }); console.log(dmlist); }) // Create an audio player let player = document.getElementById('video'); btn_fc.addEventListener('click', ()=>{ // player.requestFullscreen(); // Full screen display of dom elements btn_fc.requestFullscreen(); }) // After dragging the progress bar, the playback will continue from the end of dragging range.addEventListener('change', ()=>{ player.currentTime = range.value; }) // Total update time after resource loading player.addEventListener('loadedmetadata', ()=>{ let right=document.getElementsByClassName('right')[0]; let tt=moment.unix(player.duration).format('mm:ss'); right.innerHTML= tt; }) // Process the progress bar // Capture the continuously triggered timeupdate event during music playback player.addEventListener('timeupdate', ()=>{ console.log('timeupdated...'); // Set max value min of range range.max = player.duration; // Total duration range.value = player.currentTime; // Current duration // Processing time text content uses momentjs to convert strings let left=document.getElementsByClassName('left')[0]; let right=document.getElementsByClassName('right')[0]; let tt=moment.unix(player.duration).format('mm:ss'); let ct=moment.unix(player.currentTime).format('mm:ss'); left.innerHTML = ct; right.innerHTML= tt; }); // Set playback speed btn_05.addEventListener('click', ()=>{ player.playbackRate = 0.5; }) btn_1.addEventListener('click', ()=>{ player.playbackRate = 1; }) btn_2.addEventListener('click', ()=>{ player.playbackRate = 2; }) // Modify volume btn_vp.addEventListener('click', ()=>{ player.volume = Math.min(1, player.volume+0.1); console.log(player.volume); }) btn_vm.addEventListener('click', ()=>{ player.volume = Math.max(0, player.volume-0.1); console.log(player.volume); }) // Direct access to btn_play, you can find id = BTN_ dom object of play btn_play.addEventListener('click', ()=>{ if(player.paused){ player.play(); }else{ player.pause(); } }) </script> </body> </html>