zoukankan      html  css  js  c++  java
  • 水纹效果(ES6)

     1 /**
     2  * Created by EricXie on 2019/6/19.
     3  */
     4 export  default class Vertex {
     5     static BASE_Y = 150;
     6     static BASE_R = 10;
     7     static  FRICTION = 0.1;//波形抖动后回复到正常状态的速率指数
     8     static  DECELERATION = 0.95;
     9     static  SPEED_OF_BASE_WAVE = 3;
    10     theta = 0;
    11     goalY = 0;
    12     amp = 0;
    13     x;
    14     y;
    15 
    16     constructor(prmID, parent) {
    17         this.theta = 360 * prmID / ( parent.NUM - 1);//角度的弧度值。根据NUM值将舞台上分为NUM块,然后将2π的弧度分配给各块,这样舞台上平静的时候正好是一段完整的波形。
    18         this.x = prmID * parent.STAGE_W / (parent.NUM - 1);
    19         this.y = Vertex.BASE_Y + Vertex.BASE_R * Math.sin(this.theta * Math.PI / 180);
    20     }
    21 
    22     //让波形不断波动的函数,不断更新各点的y坐标
    23     updatePos(diffVal) {
    24         this.theta += Vertex.SPEED_OF_BASE_WAVE;
    25         if (this.theta >= 360) {
    26             this.theta -= 360;
    27         }
    28         this.goalY = Vertex.BASE_Y + Vertex.BASE_R * Math.sin(this.theta * Math.PI / 180);
    29         this.goalY += diffVal;
    30         this.amp += this.goalY - this.y;
    31         this.y += this.amp * Vertex.FRICTION;//y坐标以FRICTION的缓冲速率缓冲到正常状态
    32         this.amp *= Vertex.DECELERATION;
    33     }
    34 }
    /**
     * Created by EricXie on 2019/6/19.
     */
    import Vertex from "./Vertex.js";
    export default class Wave{
        STAGE_W=800;
        STAGE_H=300;
        NUM=800;
        MOUSE_DIFF_RATIO=1;
        AUTO_INTERVAL=3000;
        vertexes=[];
        mdlPt=[];
        diffPt=[[],[]];
        startIndex=[0,0];
        mouseOldY;
        mouseNewY;
        mouseDiff=0;//mouseDiffGoal的缓冲
        mouseDiffGoal=0;//鼠标拖动后产生的位相差
        autoTimer;
        autoDiff=0;//计时器自动生成的位相差
        mouseY=0;
        mouseX=0;
        constructor(){
            this.canvas=this.createCanvas();
            this.ctx=this.canvas.getContext("2d");
            this.init();
            this.animation();
        }
        createCanvas(){
            if(this.canvas) return this.canvas;
            let canvas=document.createElement("canvas");
            Object.assign(canvas.style,{
                "800px",
                height:"300px",
                backgroundColor:"#FFFFFF",
                margin:"auto"
            });
    
            canvas.addEventListener("mousemove",this.mouseHandler.bind(this));
            return canvas;
        }
        mouseHandler(e){
            this.mouseX=e.clientX;
            this.mouseY=e.clientY;
        }
        appendTo(parent){
            parent.appendChild(this.canvas);
        }
        animation(){
            requestAnimationFrame(this.animation.bind(this));
            this.updateMouseDiff();
            this.updateWave();
        }
        init(){
            for (let i=0; i<this.NUM; i++) {
                let vertex=new Vertex(i,this);
                this.vertexes.push(vertex);
                //中点作成
                if (i>1) {
                    this.mdlPt.push( {x:(this.vertexes[i-1].x+this.vertexes[i].x)*0.5,y:(this.vertexes[i-1].y+this.vertexes[i].y)*0.5});
                }
                //差分
                this.diffPt[0].push( 0 );
                this.diffPt[1].push( 0 );
            }
            this.mouseNewY=this.mouseY;
            if (this.mouseNewY<0) {
                this.mouseNewY=0;
            } else if (this.mouseNewY > this.STAGE_H) {
                this.mouseNewY=this.STAGE_H;
            }
            this.mouseOldY=this.mouseNewY;
            setInterval(this.generateAutoWave.bind(this),this.AUTO_INTERVAL);
        }
    
        updateMouseDiff(){
            this.mouseOldY=this.mouseNewY;
            this.mouseNewY=this.mouseY;
            if (this.mouseNewY<0) {
                this.mouseNewY=0;
            } else if (this.mouseNewY > this.STAGE_H) {
                this.mouseNewY=this.STAGE_H;
            }
            this.mouseDiffGoal = (this.mouseNewY - this.mouseOldY) * this.MOUSE_DIFF_RATIO;
        }
    
        updateWave(){
            this.ctx.clearRect(0,0,this.STAGE_W,this.STAGE_H);
            this.mouseDiff -= (this.mouseDiff - this.mouseDiffGoal)*0.3;
            this.autoDiff-=this.autoDiff*0.9;//波形自动波动时的速率
            let mX=this.mouseX;
            if (mX<0) {
                mX=0;
            } else if (mX > this.STAGE_W-2) {
                mX=this.STAGE_W-2;
            }
            this.startIndex[0] = 1+Math.floor( (this.NUM-2) * mX / this.STAGE_W );//startIndex[0]表示波形图上,鼠标拖动的那个点,用Math.floor是
                                                                   //可以取到NUM个点里面x坐标小于当前鼠标x坐标的最大值
            this.diffPt[0][this.startIndex[0]] -= ( this.diffPt[0][this.startIndex[0]] - this.mouseDiff )*0.99;
            //自动波
            this.diffPt[1][this.startIndex[1]] -= ( this.diffPt[1][this.startIndex[1]] - this.autoDiff )*0.99;
    
            let d;
            let i;
            for ( i=this.startIndex[0]-1; i >=0; i--) {
                d=this.startIndex[0]-i;
                if (d>15) {
                    d=15;
                }
                this.diffPt[0][i] -= ( this.diffPt[0][i] - this.diffPt[0][i+1] )*(1-0.01*d);
            }
    
            for ( i=this.startIndex[0]+1; i < this.NUM; i++) {
                d=i-this.startIndex[0];
                if (d>15) {
                    d=15;
                }
                this.diffPt[0][i] -= ( this.diffPt[0][i] - this.diffPt[0][i-1] )*(1-0.01*d);
            }
    
            for ( i=this.startIndex[1]-1; i >=0; i--) {
                d=this.startIndex[1]-i;
                if (d>15) {
                    d=15;
                }
                this.diffPt[1][i] -= ( this.diffPt[1][i] - this.diffPt[1][i+1] )*(1-0.01*d);
            }
    
            for ( i=this.startIndex[1]+1; i < this.NUM; i++) {
                d=i-this.startIndex[1];
                if (d>15) {
                    d=15;
                }
                this.diffPt[1][i] -= ( this.diffPt[1][i] - this.diffPt[1][i-1] )*(1-0.01*d);
            }
    
            for ( i=0; i < this.NUM; i++) {
                this.vertexes[i].updatePos( this.diffPt[0][i]+this.diffPt[1][i]);//更新波形上各点的位相,位相差等于鼠标抖动的和自动产生的,即为diffPt[0][i]+diffPt[1][i]
            }
    
            for ( i=0; i < this.NUM-2; i++) {
                this.mdlPt[i].y = (this.vertexes[i+1].y + this.vertexes[i+2].y)*0.5;//更新波形图上两点中点的位相,使波形图看起来更流畅
            }
            this.drawWave();
        }
        drawWave(){
            this.ctx.fillStyle="#666666";
            this.ctx.beginPath();
            this.ctx.moveTo(this.STAGE_W, this.STAGE_H);
            this.ctx.lineTo(0, this.STAGE_H);
            this.ctx.lineTo(this.vertexes[0].x, this.vertexes[0].y-50);
            this.ctx.quadraticCurveTo(this.vertexes[1].x, this.vertexes[1].y-50, this.mdlPt[0].x, this.mdlPt[0].y-50);
            for (let i=2; i<this.NUM-2; i++) {
                this.ctx.quadraticCurveTo(this.vertexes[i].x, this.vertexes[i].y-50, this.mdlPt[i-1].x, this.mdlPt[i-1].y-50);
            }
            this.ctx.quadraticCurveTo( this.vertexes[this.NUM-2].x, this.vertexes[this.NUM-2].y-50, this.vertexes[this.NUM-1].x, this.vertexes[this.NUM-1].y-50);
            this.ctx.closePath();
            this.ctx.fill();
        }
    
        generateAutoWave(){
            this.autoDiff=200;//自动生成100的位相差
            this.startIndex[1] = Math.round( Math.random()*(this.NUM-1) );
        }
    
    }
    

      

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
        <script type="module">
            import Wave from "./js/wave.js";
    
            let wave=new Wave();
            wave.appendTo(document.body);
    </script>
    </body>
    </html>
    改变生活从我做起,自己改变了想法改变了,用你的思想你的行动映响你身边的人,改变周边熟悉的环境,生活自然就慢慢不同了。
  • 相关阅读:
    如何解决aws解绑银行卡问题?
    如何解决macbook pro摄像头不工作的问题
    Window安装AutoCAD
    Mac应用程序无法打开,提示不明开发者或文件损坏的处理方法
    Android硬件抽象层(HAL)深入剖析(三)【转】
    Android硬件抽象层(HAL)深入剖析(二)【转】
    Android硬件抽象层(HAL)深入剖析(一)【转】
    Glide的用法
    Gradle-5.3:依赖-管理依赖的版本(传递(transitive)排除(exclude)强制(force)动态版本(+))
    Android 7.0 FileProvider 使用说明
  • 原文地址:https://www.cnblogs.com/loganlu/p/11242621.html
Copyright © 2011-2022 走看看