HTML uses canvas to implement bullet screen function

HTML uses canvas to implement bullet screen function

Introduction

Recently, I needed to make a barrage player when doing a big assignment. I borrowed someone else's source code and re-implemented it myself. The demonstration is as follows

The main functions are

Send barrage Set the color, speed and type of barrage Display barrage

Known defects:

Cannot full screen

The canvas is not adaptive, the player controls are not customized, the corresponding barrage is not displayed according to the playback time, and the barrage cannot be hovered. Known defects will be improved in the future. The source code of the barrage player that can be found on the Internet generally only has scrolling barrage but no static barrage. Here I have specially added the implementation of static barrage.

Canvas draws text and text scrolling effect

The core of the entire player is to draw text and animate text scrolling. There is no good animation support for text in canvas, so we can only implement it by ourselves. The idea is to continuously clear the screen and rewrite the text. When the frequency of clearing the screen and rewriting reaches 24fps, it will be a smooth animation.

First add the video tag and canvas tag to the HTML file

<div id="barrageplayer">
    <canvas id="cv_video" width="900px" height="450px"></canvas>
    <video id="v_video" src="test.MP4" controls type="video/mp4"></video>
</div>

Set the position style of the canvas tag to position:absolute and then the video and canvas will overlap, making it look like a bullet screen player. Then add bullet-screen related content to the canvas. First, get the relevant information of the canvas and set the font size and font style of the canvas.

var c=document.getElementById("cv_video");
//Get the canvas size var c_height=c.height;
var c_width=c.width;
//Get the canvas ctx=c.getContext("2d");
//Set the font style ctx.font="25px DengXian";
The canvas information has been obtained and set. A good cook cannot cook without rice. Next, we need to construct the barrage object. The construction mode used is the dynamic prototype mode // barrage object function Barrage (content, color, type, speed) {
    this.content=content;
    this.color=color;
    this.type=type;
    this.speed=speed;
    if(this.type=="default"){
        this.height=parseInt(Math.random()*c_height)+10;
    }else if (this.type=="static top"){
        this.height=parseInt((c_height/2)-Math.random()*c_height/2)+10;
    }else if (this.type=="static bottom"){
        this.height=parseInt((c_height/2)+Math.random()*c_height/2)+10;
    }
    if(typeof this.move!="function"){
        Barrage.prototype.move=function(){
            if(this.type=="default"){
                this.left=this.left-this.speed;
            }
        }
    }
}

The constructed barrage object initializes various parameters, including content, color, motion type and speed, and defines the move() method to control the easing of the barrage. Each time the move() method is triggered, it scrolls left by one pixel of unit speed.
After the barrage object is constructed, we will enter the theme and animation production, and directly put the code

//Loop and write the canvas to achieve animation effect setInterval(function(){
    ctx.clearRect(0,0,c_width,c_height);
    ctx.save();
    for(var i=0;i<msgs.length;i++){
        if(msgs[i]!=null){
            if(msgs[i].type=="default"){
                handleDefault(msgs[i]);
            }else{
                handleStatic(msgs[i]);
           }
        }
    }
},20)

The erase is performed every 20ms. ctx.clearRect(0,0,c_width,c_height); clears the entire current canvas, and then uses ctx.save() to save the current canvas. Then, the bullet list is traversed (msgs is the bullet list, and each time a bullet is sent, the bullet instance will be added to the list), and then processed according to the default style or static style bullet. If it is a default style bullet comment, it will be processed as follows

//Handle the default barrage style function handleDefault(barrage){
    if(barrage.left==undefined||barrage.left==null){
        barrage.left=c.width;
    }else{
         if(barrage.left<-200){
            barrage=null;
        }else{
            barrage.move()
            ctx.fillStyle=barrage.color;
            ctx.fillText(barrage.content,barrage.left,barrage.height)
            ctx.restore();
        }
    }  
}

First, if the bullet message instance does not have a left attribute set, assign it the width of the canvas. If the bullet message instance has exited the canvas, set it to null to save memory. Otherwise, call the move() method of the bullet message instance to change the value of the left attribute, then set the color of the text, write new text, and restore the canvas. This completes one frame of animation.

The implementation method for static barrage is as follows

//Handle static barrage style function handleStatic(barrage){
    ctx.moveTo(c_width/2,barrage.height);
    ctx.textAlign="center";
    ctx.fillStyle=barrage.color;
    ctx.fillText(barrage.content,c_width/2,barrage.height);
    if(barrage.left==undefined||barrage.left==null){
        barrage.left=c.width;
    }else{
        if(barrage.left<-200){
            ctx.fillText("",c_width/2,barrage.height);                
            barrage=null;
            //ctx.restore();
            ctx.clearRect(0,0,c_width,c_height);        
        }else{
            barrage.left=barrage.left-6;
        }
    }
}

First, move the base point of the canvas to the center of the canvas. It should be noted that a new canvas is generated at this time, and the clearRect() method of the original canvas is no longer applicable to this canvas. Then set the text alignment to center, set the text style, and fill in the text. Because the barrage is static, there is no need for easing. However, the static barrage will also disappear, so a flag needs to be set to make it disappear at a certain time. In order not to occupy extra attributes here, we directly use the left attribute as the flag, and also decrement the left attribute, but do not reflect the decrement in the canvas. When the left reaches the threshold, the ctx.clearRect() method is used to clear the bullet comment. This realizes the processing of static barrage.

As for other settings about colors and styles, those who have a certain foundation should be able to master them easily, so I will not introduce them in detail here. Just read the executable code part to understand it.

Summarize

This project mainly uses canvas to draw text and realize text slow animation. The main methods used are

canvasDom.getContext()
canvas.save()/canvas.restore()
canvas.clearRect()
canvas.moveTo()

I used to not understand save() and restore(), but now I have some understanding. When you change the canvas state, the current canvas is no longer the original canvas, so save the canvas state before modifying it, switch the canvas state, and after completing the work, restore it to the original canvas state to continue working. For example, when I deal with static barrage, I change the base point of the canvas. Then the clearing method of the original canvas is no longer applicable to the current canvas. I have to use another clearing method in the current canvas. Then restore to the original canvas.

Runnable code

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<style type="text/css">
    .pickdiv{
        width: 30px;
        height: 30px;
        cursor: pointer;
        border: 2px solid gray;
        display: inline-block;
    }
    #white{
        background: white;
    }
    #red{
        background:#ff6666;
    }
    #yellow{
        background:#ffff00;
    }
    #blue{
        background:#333399;
    }
    #green{
        background:#339933;
    }
    #cv_video{
        position: absolute;
        z-index: 1;
    }
    #barrageplayer{
        position: relative;
        display: block;
        width: 900px;
        height: 500px;
    }
    #v_video{
        position: absolute;
        width: 100%;
        height: 100%;
        z-index: 0;
    }
</style>
<body>
    <div id="barrageplayer">
        <canvas id="cv_video" width="900px" height="450px"></canvas>
        <video id="v_video" src="test.MP4" controls type="video/mp4"></video>
    </div>
    <div id="barrageinput">
        <div>
            <input type="text" id="smsg" placeholder="Please enter the content of the bullet comment"/>
            <button id="send">Send</button>
        </div>
        <div id="colorpick">
            <div class="pickdiv" id="white"></div>
            <div class="pickdiv" id="red"></div>
            <div class="pickdiv" id="yellow"></div>
            <div class="pickdiv" id="blue"></div>
            <div class="pickdiv" id="green"></div>
        </div>
        <div id="typepick">
            <input type="radio" name="type" value="default">Default<input type="radio" name="type" value="static top">Static top<input type="radio" name="type" value="static bottom">Static bottom</div>
        <div id="speedpick">
            <input type="radio" name="speed" value="1">1X
            <input type="radio" name="speed" value="2">2X
            <input type="radio" name="speed" value="3">3X
        </div>
        <div id="stylepick"></div>
    </div>
    <script>
        var c=document.getElementById("cv_video");
        var typeDom = document.getElementsByName("type");
        var speedDom = document.getElementsByName("speed");
        var colorpick = document.getElementById("colorpick");
        var smsg = document.getElementById("smsg");
        var color="#white";
        var speed=1;
        var type="default";
        var msgs = [];
        //Get the canvas size var c_height=c.height;
        var c_width=c.width;
        //Get the canvas ctx=c.getContext("2d");
        ctx.font="25px DengXian";
        //Processing color selection colorpick.addEventListener('click',function(event){
            switch(event.target.id){
                case "white":
                    color="white";
                    break;
                case "red":
                    color="#ff6666";
                    break;
                case "yellow":
                    color="#ffff00";
                    break;
                case "green":
                    color="#339933";
                    break;
                case "blue":
                    color="#333399";
                    break;
            }
        })
        //Processing sending bullet screen document.getElementById("send").onclick=function(){
            var text=smsg.value;
            for(var i=0;i<typeDom.length;i++){
                if (typeDom[i].checked){
                    type=typeDom[i].value;
                    break;
                }
            }
            for(var i=0;i<speedDom.length;i++){
                if(speedDom[i].checked){
                    speed=2*parseInt(speedDom[i].value);
                    break;
                }
            }
            var tempBarrage = new Barrage(text,color,type,speed);
            msgs.push(tempBarrage);
        }
        //
        //Part of the barrage function code//
        //Barrage object function Barrage(content,color,type,speed){
            this.content=content;
            this.color=color;
            this.type=type;
            this.speed=speed;
            if(this.type=="default"){
                this.height=parseInt(Math.random()*c_height)+10;
            }else if (this.type=="static top"){
                this.height=parseInt((c_height/2)-Math.random()*c_height/2)+10;
            }else if (this.type=="static bottom"){
                this.height=parseInt((c_height/2)+Math.random()*c_height/2)+10;
            }
            if(typeof this.move!="function"){
                Barrage.prototype.move=function(){
                    if(this.type=="default"){
                        this.left=this.left-this.speed;
                    }
                }
            }
        }
        //Loop and write the canvas to achieve animation effect setInterval(function(){
            ctx.clearRect(0,0,c_width,c_height);
            ctx.save();
            for(var i=0;i<msgs.length;i++){
                if(msgs[i]!=null){
                    if(msgs[i].type=="default"){
                        handleDefault(msgs[i]);
                    }else{
                        handleStatic(msgs[i]);
                    }
                }
            }
        },20)
    //Handle the default barrage style function handleDefault(barrage){
        if(barrage.left==undefined||barrage.left==null){
            barrage.left=c.width;
        }else{
            if(barrage.left<-200){
                barrage=null;
            }else{
                barrage.move()
                ctx.fillStyle=barrage.color;
                ctx.fillText(barrage.content,barrage.left,barrage.height)
                ctx.restore();
            }
        }  
    }
    //Handle static barrage style function handleStatic(barrage){
        ctx.moveTo(c_width/2,barrage.height);
        ctx.textAlign="center";
        ctx.fillStyle=barrage.color;
        ctx.fillText(barrage.content,c_width/2,barrage.height);
        if(barrage.left==undefined||barrage.left==null){
            barrage.left=c.width;
        }else{
            if(barrage.left<-200){
                ctx.fillText("",c_width/2,barrage.height);                
                barrage=null;
                //ctx.restore();
                ctx.clearRect(0,0,c_width,c_height);        
            }else{
                barrage.left=barrage.left-6;
            }
        }
    }
    </script>
</body>
</html>

The above is what I introduced to you about how to use canvas in HTML to realize the barrage function. I hope it will be helpful to you. If you have any questions, please leave me a message and I will reply to you in time. I would also like to thank everyone for their support of the 123WORDPRESS.COM website!

<<:  Detailed explanation of JavaScript prototype and examples

>>:  Use CSS3 to implement button hover flash dynamic special effects code

Recommend

MySQL Series 3 Basics

Table of contents Tutorial Series 1. Introduction...

Teach you to implement a simple promise step by step

Table of contents Step 1: Build the framework Ste...

Sample code for implementing markdown automatic numbering with pure CSS

The origin of the problem The first time I paid a...

JavaScript to achieve a simple carousel effect

What is a carousel? Carousel: In a module or wind...

Detailed explanation of the execution order of JavaScript Alert function

Table of contents question analyze solve Replace ...

Specific usage of Vue's new toy VueUse

Table of contents Preface What is VueUse Easy to ...

Usage and demonstration of ref in Vue

ref definition: used to register reference inform...

Vue uses better-scroll to achieve horizontal scrolling method example

1. Implementation principle of scrolling The scro...

Multiple solutions for cross-domain reasons in web development

Table of contents Cross-domain reasons JSONP Ngin...

Node and Python two-way communication implementation code

Table of contents Process Communication Bidirecti...

Secondary encapsulation of element el-table table (with table height adaptation)

Preface During my internship at the company, I us...

Mysql classic high-level/command line operation (quick) (recommended)

Since I need to learn how to build servers and da...

Detailed explanation of tcpdump command examples in Linux

Preface To put it simply, tcpdump is a packet ana...