canvas画小蝌蚪模拟气象风场

预览地址:http://bl.ocks.org/chengquan223/raw/505d935f54bf0fe86195642464e77ce7/

<style type="text/css">
    canvas {
        margin: 20px 0;
    }
</style>

<h1>小蝌蚪模拟风场</h1>
<canvas id="canvas" width=700 height=500 style="border: 1px solid #ccc;"></canvas>
html、css

javascript

<script>
    $(function () {
        var Arrow = function (x, y, angle, speed, alive) {
            this.x = x;
            this.y = y;
            this.angle = angle; //游走方向
            this.swingAngle = 6; //尾巴摆动角度
            this.speed = speed || 8; //小蝌蚪长度来代表速度
            this.alive = alive || true; //是否活着
            this.liveLength = Math.random() * 10 + 20; //生命长度
        };

        self.init = function () {
            this.canvas = document.getElementById('canvas');
            this.ctx = canvas.getContext('2d');
            this.cw = this.canvas.width;
            this.ch = this.canvas.height;
            this.arrows = this.initArrows();
        };

        self.initArrows = function () {
            var count = 200, arrowArray = [], arrow = {};
            while (count--) {
                arrow = new Arrow(Math.random() * this.cw, Math.random() * this.ch, Math.random() * 360, 8, true);
                arrowArray.push(arrow);
            }
            return arrowArray;
        };

        self.createArrows = function () {
            this.ctx.clearRect(0, 0, this.cw, this.ch);
            var i = this.arrows.length;
            while (i--) {
                var arrow = this.arrows[i];
                arrow.reset();
                arrow.alive ? arrow.draw() : arrow.relive();
            }
        };

        Arrow.prototype.reset = function () {
            this.liveLength--;
            if (this.liveLength <= 0) {
                this.alive = false;
            }
            if (this.x < 0 || this.y < 0 || this.x > self.cw || this.y > self.ch) {
                this.alive = false;
            }
        };

        Arrow.prototype.draw = function () {
            var ex = ey = 0;
            ex = this.x - this.speed * Math.sin((180 - this.angle + this.swingAngle) * (Math.PI / 180)); //↓0°←90°
            ey = this.y - this.speed * Math.cos((180 - this.angle + this.swingAngle) * (Math.PI / 180));
            ctx.beginPath();
            ctx.translate(0, 0, 0); //坐标源点
            ctx.moveTo(this.x, this.y);
            ctx.lineTo(ex, ey);
            ctx.fill();
            ctx.stroke();
            ctx.save();

            ctx.translate(ex, ey);
            //我的箭头本垂直向下,算出直线偏离Y的角,然后旋转 ,rotate是顺时针旋转的,所以加个负号
            var ang = (ex - this.x) / (ey - this.y);
            ang = Math.atan(ang);
            ey - this.y >= 0 ? ctx.rotate(-ang) : ctx.rotate(Math.PI - ang);//加个180度,反过来
            ctx.lineTo(-2, -2);
            ctx.lineTo(0, -3);
            ctx.lineTo(2, -2);
            ctx.lineTo(0, 0);
            ctx.fill(); //箭头是个封闭图形
            ctx.restore(); //用来恢复Canvas之前保存的状态,否则会影响后续绘制
            ctx.closePath();

            this.x = ex; //终点当起点
            this.y = ey;
            this.swingAngle *= -1; //摆动角度正反互换
        };

        Arrow.prototype.relive = function () {
            this.alive = true;
            this.x = Math.random() * self.cw;
            this.y = Math.random() * self.ch;
            this.liveLength = Math.random() * 20;
        };

        var animateArrow = function () {
            self.createArrows();
        };

        self.init();

        animateArrow();

        var timer = setInterval(animateArrow, 170);
    });
</script>

 

posted @ 2016-02-03 17:42  Jack、Chen  阅读(1412)  评论(0编辑  收藏  举报