【基础知识】HTML5 Canvas 动画项目-100个弹射小球(带控制器)

我的处女作《Canvas系列教程》在我的Github上正在连载更新,希望能得到您的关注和支持,让我有更多的动力进行创作。

教程介绍、教程目录等能在README里查阅。

传送门:https://github.com/827652549/CanvasStudy

介绍

实现100个随机弹射的小球在Canvas中碰撞,另外用一个玻璃窗格作为控制台,控制动画的开始与暂停。

演示链接

https://827652549.github.io/Canvas/Unit1/BouncingBalls.html

实现效果

思路

  1. 将玻璃窗格控制器潜入Canvas中

  2. 生成100个不同属性的小球

  3. 通过短间隔的计时器不断的擦除并绘制新的Canvas图层

 

注意:在Canvas标签中使用HTML元素是不行的,因为只有在Canvas不被支持时,标签内的元素才被显示(一般都是<canvas

>Canvas not supported</canvas>),所以只能让其他元素看起来像是Canvas范围内。

代码实现

<!DOCTYPE html>

<html>
<head>
    <title>Bouncing Balls运动小球</title>

    <meta charset="UTF-8">

    <style>
        body {
            background: #dddddd;
        }

        #canvas {
            margin-left: 10px;
            margin-top: 10px;
            background: #ffffff;
            border: thin solid #aaaaaa;
        }

        #glasspane {
            position: absolute;
            left: 50px;
            top: 50px;
            padding: 0px 20px 10px 10px;
            background: rgba(0, 0, 0, 0.3);
            border: thin solid rgba(0, 0, 0, 0.6);
            color: #eeeeee;
            font-family: Droid Sans, Arial, Helvetica, sans-serif;
            font-size: 12px;
            cursor: pointer;
            -webkit-box-shadow: rgba(0, 0, 0, 0.5) 5px 5px 20px;
            -moz-box-shadow: rgba(0, 0, 0, 0.5) 5px 5px 20px;
            box-shadow: rgba(0, 0, 0, 0.5) 5px 5px 20px;
        }

        #glasspane h2 {
            font-weight: normal;
        }

        #glasspane .title {
            font-size: 2em;
            color: rgba(255, 255, 0, 0.8);
        }

        #glasspane a:hover {
            color: yellow;
        }

        #glasspane a {
            text-decoration: none;
            color: #cccccc;
            font-size: 3.5em;
        }

        #glasspane p {
            margin: 10px;
            color: rgba(65, 65, 220, 1.0);
            font-size: 12pt;
            font-family: Palatino, Arial, Helvetica, sans-serif;
        }
    </style>
</head>

<body>
<!--玻璃窗格 glass pane-->
<div id='glasspane'>
    <h2 class='title'>弹射小球</h2>

    <p>一百个小球弹射</p>

    <a id='startButton'>Start</a>
</div>

<canvas id='canvas' width='750' height='500'>
    Canvas not supported
</canvas>

<script>
    var context = document.getElementById('canvas').getContext('2d'),
        startButton = document.getElementById('startButton'),
        glasspane = document.getElementById('glasspane'),
        paused = true,
        circles = [];

    drawGird(context, 'lightgray', 10, 10);

    context.lineWidth = 0.5;
    context.font = '32pt Ariel';

    //给100个小球设置不同的方向,半径,颜色
    for (var i = 0; i < 100; i++) {
        circles[i] = {
            x: 100,
            y: 100,
            //向x方向移动的像素
            velocityX: 3 * Math.random(),
            velocityY: 3 * Math.random(),
            radius: 50 * Math.random(),
            color: 'rgba(' + (Math.random() * 255).toFixed(0) + ',' +
                (Math.random() * 255).toFixed(0) + ',' +
                (Math.random() * 255).toFixed(0) + ',1.0)'
        };
    }

    startButton.onclick = function (ev) {
        //取消默认行为
        ev.preventDefault();
        //阻止冒泡
        ev.stopPropagation();
        paused = !paused;
        startButton.innerText = paused ? '启动' : '暂停';
    };

    glasspane.onmousedown = function (ev) {
        ev.preventDefault();
        ev.stopPropagation();
    };

    context.canvas.onmousedown = function (ev) {
        ev.preventDefault();
        ev.stopPropagation();
    };

    setInterval(function () {
        if (!paused) {
            context.clearRect(0, 0, context.canvas.width, context.canvas.height);
            drawGird(context, 'lightgray', 10, 10);

            circles.forEach(function (circle) {
                context.beginPath();
                context.arc(circle.x, circle.y, circle.radius,
                    0, Math.PI * 2, false);
                context.fillStyle = circle.color;
                context.fill();
                adjustPosition(circle);


            });
        }
    }, 1000 / 60);

    /**
     * 调整每个球的位置,如果触碰到边缘,就调整方向
     * @param circle
     */
    function adjustPosition(circle) {
        if (circle.x + circle.velocityX + circle.radius > context.canvas.width || circle.x - circle.radius + circle.velocityX<0)
            circle.velocityX = -circle.velocityX;

        if (circle.y + circle.velocityY + circle.radius > context.canvas.height || circle.y - circle.radius + circle.velocityY<0)
            circle.velocityY = -circle.velocityY;

        circle.x += circle.velocityX;
        circle.y += circle.velocityY;
    }

    /**
     * 画网格线
     * @param context
     * @param color
     * @param stepX X方向网格间距
     * @param stepY Y方向网格间距
     */
    function drawGird(context,color,stepX,stepY) {
        context.strokeStyle = color;
        context.lineWidth = 0.5;

        for (var i = stepX+0.5;i<context.canvas.width;i+=stepX){
            context.beginPath();
            context.moveTo(i,0);
            context.lineTo(i, context.canvas.height);
            context.stroke();
        }

        for (var i = stepY + 0.5; i < context.canvas.height; i+=stepY) {
            context.beginPath();
            context.moveTo(0, i);
            context.lineTo(context.canvas.width, i);
            context.stroke();
        }
    }
</script>
</body>
</html>

 

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值