ホームページ  >  記事  >  ウェブフロントエンド  >  HTMLを使ってスクロール連打機能を実装する方法

HTMLを使ってスクロール連打機能を実装する方法

php中世界最好的语言
php中世界最好的语言オリジナル
2018-01-17 09:55:1410748ブラウズ


今回は、HTMLを使用してスクロール弾幕機能を実装する方法を説明します。HTMLでスクロール弾幕機能を実装する場合の注意事項は何ですか?実際の事例を見てみましょう。

主な機能は次のとおりです: 弾幕の送信、弾幕の色、速度、種類の設定、および弾幕の表示

既知の欠陥: フルスクリーンにできません

キャンバスは適応しません

カスタム プレーヤー コントロールはありません
対応するベースの再生はありませんその時点で弾幕が表示されます
弾幕はホバリングできません
既知の不具合は今後改善される予定です。インターネット上で見つかる弾幕プレイヤーのソース コードは、通常、ローリング弾幕のみを作成し、静的な弾幕を作成しません。ここでは、特別に静的な弾幕の実装を追加しました。

キャンバスはテキストとテキストスクロール効果を描画します

プレーヤー全体の核となるのは、テキストを描画し、テキストスクロールをアニメーション化することです。キャンバス内のテキストに対する優れたアニメーションサポートはなく、これは自分でのみ実現できます。実装は連続して画面をクリアしてからテキストを書き換えます。画面のクリアと書き換えの頻度が 24fps に達すると、アニメーションが滑らかになります。

まずHTMLファイルにvideo

videoタグとcanvasタグを追加します

<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>
canvasタグの位置スタイルをposition:absoluteに設定すると、videoとcanvasが重なって弾幕プレイヤーのようになります。次に、弾幕関連のコンテンツをキャンバスに追加します。まず、キャンバスの関連情報を取得し、キャンバスのフォント サイズとフォント スタイルを設定します。

var c=document.getElementById("cv_video");
//获取画布大小
var c_height=c.height;
var c_width=c.width;
//获取画布
ctx=c.getContext("2d");
//设置字体样式
ctx.font="25px DengXian";
画布信息已经获取和设置,巧妇难为无米之炊,接着我们就要构造弹幕对象,使用的构造模式是动态原型模式
//弹幕对象
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;
            }
        }
    }
}

構築された弾幕オブジェクトは、コンテンツ、色、動きの種類、およびなどのさまざまなパラメーターを初期化します。速度、定義 move() メソッドは、弾幕のイージングを制御するために使用されます。 move() メソッドが起動されるたびに、単位速度の 1 ピクセルずつ左にスクロールします。

弾幕オブジェクトの構築が完了したら、テーマとアニメーション制作を入力し、コードを直接入力します

//循环擦写画布实现动画效果
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)

20ms ごとに消去を実行し、ctx.clearRect(0,0,c_width,c_height) は現在のキャンバス全体をクリアします。次に、ctx.save() を使用して現在のキャンバスを保存し、弾幕リスト (msgs は弾幕リストです。弾幕が送信されるたびに弾幕インスタンスがリストに追加されます) を走査し、デフォルトのスタイルに従います。弾幕の弾幕または静止スタイルの弾幕は個別に処理されます。デフォルトスタイルの弾幕の場合は以下のメソッドで処理されます

//处理默认弹幕样式
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();
        }
    } 
}

まず、弾幕インスタンスにleft属性が設定されていない場合は、キャンバスの幅が代入されます。キャンバスを終了すると、メモリを節約するために null に設定されます。それ以外の場合は、barrage インスタンスの move() メソッドを呼び出して left 属性の値を変更し、テキストの色を設定して、最初のレベルに新しいテキストを書き込みます。をクリックしてキャンバスを復元します。これで 1 フレームのアニメーションが完成します。

静的弾幕の実装方法は以下の通りです

//处理静止弹幕样式
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;
        }
    }
}

まずキャンバスの基点をキャンバスの中心に移動します。なお、このとき新しいキャンバスが生成され、clearRect()メソッドが実行されます。元のキャンバスはこのキャンバスには適用されなくなります。次に、テキストの配置を中央揃えに設定し、

テキスト スタイル

を設定して、テキストを塗りつぶします。静止弾幕なので緩和する必要はありませんが、定期的に静止弾幕も消えるフラグを立てる必要があります。ここで追加の属性を占有しないようにするために、 left 属性をフラグとして直接使用します。 left 属性もデクリメントしますが、 left がしきい値に達した場合、 ctx.clearRect() メソッドを使用します。弾幕をクリアします。このようにして、静的弾幕の処理が実現される。 色やスタイルの設定に一定の基礎を持っている人は、ここでは詳しく説明しませんが、実行可能なコード部分を見て理解するだけで十分です。

概要

このプロジェクトは主にテキストの描画とテキストのイージングアニメーションにキャンバスを使用します。使用される主なメソッドは

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


です。save() とrestore() を理解できないことがわかりました。キャンバスの状態を変更すると、現在のキャンバスは元のキャンバスではなくなるため、キャンバスの状態を変更する前に、キャンバスの状態を保存し、キャンバスの状態を切り替え、作業が完了したら元のキャンバスに戻します。キャンバスの状態は引き続き機能します。たとえば、静的な弾幕に対処してキャンバスの基点を変更すると、元のキャンバスのクリア方法は現在のキャンバスに適用されなくなり、現在のキャンバスでは別のクリア方法のみを使用できます。その後、元のキャンバスに戻ります。

実行可能なコード

<!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="请输入弹幕内容"/>
            <button id="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">默认
            <input type="radio" name="type" value="static top">静止顶部
            <input type="radio" name="type" value="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=[];
        //获取画布大小
        var c_height=c.height;
        var c_width=c.width;
        //获取画布
        ctx=c.getContext("2d");
        ctx.font="25px DengXian";
        //处理颜色选择
        colorpick.addEventListener(&#39;click&#39;,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;
            }
        })
        //处理发送弹幕
        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);
        }
        //
        //弹幕功能部分代码
        //
        //弹幕对象
        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;
                    }
                }
            }
        }
        //循环擦写画布实现动画效果
        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)
    //处理默认弹幕样式
    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();
            }
        } 
    }
    //处理静止弹幕样式
    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>

これらの事例を読んだ後は、方法を習得したと思います。さらに興味深い情報については、php 中国語 Web サイトの他の関連記事に注目してください。

関連記事:

HTML Web ページにビデオを挿入する方法


HTML テキスト ボックスを読み取り専用効果にする方法


HTML+CSS を使用して 2 番目のメニューを表示する方法バーの上でマウスをスワイプしてください

以上がHTMLを使ってスクロール連打機能を実装する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。