How to send video barrage using canvas? Learn from H5 Canvas

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:

  1. Through CTX Beginpath() opens a new path.
  2. Through CTX Moveto (x, y) moves the brush to the specified position.
  3. Start drawing the path through the relevant methods of ctx (classic method: lineTo(x, y)).
  4. 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.

  1. Put a layer of canvas over the video tag.

  2. 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.

    1. Prepare an array to store barrage objects: dmlist = {}.
    2. When sending the barrage, the barrage contents, x and y are encapsulated into objects and stored in dmlist.
    3. 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>

Keywords: Javascript html canvas H5

Added by zyrolasting on Tue, 04 Jan 2022 06:41:16 +0200