水纹效果(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,{
            width:"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>

猜你喜欢

转载自www.cnblogs.com/loganlu/p/11242621.html
ES6