美文网首页
Js Canvas实现 迎风而上的气球效果

Js Canvas实现 迎风而上的气球效果

作者: 小白彡 | 来源:发表于2021-07-02 21:38 被阅读0次

上图:

001.gif
前面有用Java写过一个粒子爆炸烟花效果,和这个思路是一样的,不过是Android程序,有兴趣的可以看看:
Android 粒子爆炸 烟花效果
现在这个是用Html Canvas + Js写的。

重点记录:
1.Html Canvas中不存在 Invalidate, 所以想要界面重新渲染,必须手动调用canvas.clearRect(0, 0, cn.width, cn.height);清除画布再重新绘制。
2.Js ES6以前没有Class类,所以得使用function的方式实例化类。
3.在Android中我们调用Invalidate来刷新Canvas,让程序陷入递归,不停的绘制,不停得刷新, 但在Js中我发现使用递归刷新的方式不得行,所以改用定时器setInterval的方式,每30毫秒重绘一次画布。

注意点就这些,下面就是实现了, 先看看单个气球的草图:


002.png

可以看到,单个气球由三部分构成:
1.气球头。
2.气球中间扭动线。
3.气球尾部摆动线。

开始,当然是面向对象编程啦:
先给他定义这三个类出来:

//气球实体  centerX:圆心x  centerY:圆心y  raduis:半径  color:颜色 speed:运动速度  line:贝塞尔曲线  tailLine:尾部直线
    function Cirecle(centerX, centerY, raduis, color, speed, line, tailLine) {
        this.centerX = centerX;
        this.centerY = centerY;
        this.raduis = raduis;
        this.color = color;
        this.speed = speed;
        this.line = line;
        this.tailLine = tailLine;
    }

    //贝塞尔曲线实体
    function Line(lineOnePointX, lineOnePointY, lineTwoPointX, lineTwoPointY, lineEndPointX, lineEndPointY, onePointLeftMove, twoPointLeftMove, onePointSpeed, twoPointSpeed) {
        this.lineOnePointX = lineOnePointX;
        this.lineOnePointY = lineOnePointY;
        this.lineTwoPointX = lineTwoPointX;
        this.lineTwoPointY = lineTwoPointY;
        this.lineEndPointX = lineEndPointX;
        this.lineEndPointY = lineEndPointY;
        this.onePointLeftMove = onePointLeftMove;
        this.twoPointLeftMove = twoPointLeftMove;
        this.onePointSpeed = onePointSpeed;
        this.twoPointSpeed = twoPointSpeed;
    }

    //尾线实体
    function TailLine(startX, startY, endX, endY){
            this.startX = startX;
            this.startY = startY;
            this.endX = endX;
            this.endY = endY;
    }

因为写的时候思维带入到粒子爆炸去了,所以头部和气球这个整体放在一个类了,其实应该把头部单独拉出一个新类的。

有了这些实体,下面就可以将他们实例化然后绘制到Cnavas上了:
1.html中定义画布:

<body>
    <canvas id="canvas" width="800px" height="500px"></canvas>
</body>

2.Js中获取画布:

 var cn = document.getElementById("canvas");
    var canvas = cn.getContext("2d");

3.鼠标点击时生成气球:

cn.onclick = function (e) {
        var centerX = e.offsetX;
        var centerY = e.offsetY;
        var color = getRandomColor();
        var speed = Math.floor(Math.random() * 2 + 1);

        var onePointSpeed = 4;
        var twoPointSpeed = 4;

        console.log(onePointSpeed);
        console.log(twoPointSpeed);

        var line = new Line(centerX - raduis, centerY + raduis * 2, centerX + raduis, centerY + raduis * 3, centerX, centerY + raduis * 4, false, false, onePointSpeed, twoPointSpeed);
        var tailLine = new TailLine(line.lineEndPointX, line.lineEndPointY, line.lineOnePointX, centerY + raduis * 4.5);
        var circle = new Cirecle(centerX, centerY, raduis, color, speed, line, tailLine);

        circlrs.push(circle);

        drawCircle();
    }

ok, 到这里我们每次点击鼠标的时候就会生成一个气球,然后存在我们的circlrs里了,下面就只要把circlrs里的气球绘制在Canvas上面就好了。
4.气球的绘制:

  //画一个实心圆
                    canvas.beginPath();
                    canvas.shadowBlur = 20;
                    canvas.shadowOffsetX = 10100;
                    canvas.shadowOffsetY = 10100;
                    canvas.fillStyle = circle.color;//填充颜色,默认是黑色
                    canvas.arc(circle.centerX, circle.centerY, circle.raduis, 0, Math.PI * 2, false);
                    canvas.fill();//画实心圆

                    canvas.strokeStyle = circle.color;//填充颜色,默认是黑色
                    canvas.moveTo(circle.centerX, circle.centerY + circle.raduis);
                    canvas.bezierCurveTo(line.lineOnePointX, line.lineOnePointY, line.lineTwoPointX, line.lineTwoPointY, line.lineEndPointX, line.lineEndPointY)
                    canvas.stroke();

                    canvas.moveTo(tailLine.startX, tailLine.startY);
                    canvas.lineTo(tailLine.endX, tailLine.endY);
                    canvas.stroke();

                    circle.centerY -= circle.speed;

                    //贝塞尔
                    line.lineOnePointY = circle.centerY + raduis * 2;
                    line.lineTwoPointY = circle.centerY + raduis * 3;
                    line.lineEndPointY = circle.centerY + raduis * 4;

                    //尾线
                    tailLine.startX = line.lineEndPointX;
                    tailLine.startY = line.lineEndPointY;
                    tailLine.endX = line.lineOnePointX;
                    tailLine.endY = circle.centerY + raduis * 4.5;

这里分成了三部分,头,身,尾,
身部贝塞尔曲线的起点在圆的正下方,外加两个控制点形成S型,尾部直线起点在贝塞尔曲线的终点。

5.接着设置定时器让气球动起来:

interval = setInterval(function () {
             //绘制代码
            }, 30)

每30毫秒刷新一次Canvas, 动起来的原因是,我们每次刷新画布时,都会动态更新三个部位的属性,所以刷新后他们的绘制位置就会发生该改变,这里面也是写得比较死了,好像不是相对一个点,还有待优化。。。。。

**值得注意的是,在每个气球飞出画面之后,要将气球清除,并在所有气球都游出画面后,停止定时器,直到重新有气球生成时再打开定时器,以防止不必要的内存开销。

下面是源码,see see:
https://github.com/amggg/JsParticalDemo/tree/master

相关文章

网友评论

      本文标题:Js Canvas实现 迎风而上的气球效果

      本文链接:https://www.haomeiwen.com/subject/bpeyultx.html