Canvas<小球自由落体效果>

效果图:
tantiao.gif

此效果参考他人代码,并加以注释和改造,想直接看源地址效果的话,可直接点击下方链接

参考地址:http://www.jq22.com/webqd6697

提供以下地址,方便你们理解和学习
1. canvas绘制圆
2. requestAnimationFrame更新动画
3. 清空画布

代码的注释我感觉已经很详细了,方便大家理解,这里就不说那么多废话了(本人之前有了解过canvas,接下来有机会,会从基础的知识点开始更新 😄)

代码如下:
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<style>
    * {
        margin: 0;
        padding: 0;
    }

    canvas {
        display: block;
    }
</style>

<body>
    <canvas id="canvas"></canvas>
</body>
<script>
    let w, h;                          // 定义一个窗口宽高的变量
    let ball_num = 1;                  //每次点击生成的小球个数
    let Gravity = 0.8;                 //小球下落速度 越小越慢
    let Firction = 0.9;                //小球弹跳力度 越大越高
    let ballArray = [];               //储存小球的数组

    //获取canvas标签
    let canvas = document.querySelector("#canvas")
    //创建画笔
    let ctx = canvas.getContext("2d");
    //小球颜色数组
    let colorArray = ["rgb(65, 105, 225)", "rgb(65, 166, 225)", "rgb(65, 214, 225)", "rgb(65, 225, 190)", "rgb(65, 225, 132)"];

    // 获取窗口大小方法
    function getWindow_size() {
        w = window.innerWidth;
        h = window.innerHeight;
        canvas.width = w;
        canvas.height = h;
    }


    // 随机生成一个 lower ~ upper 的整数
    function randomIntFronRange(lower, upper) {
        return Math.floor(Math.random() * (upper - lower)) + lower;
    };

    //创建小球的方法(主要是小球运动轨迹的绘制)
    function Ball(x, y, dx, dy, radius, color) {
        //此处并没有直接执行绘制动画,而是事先定义好相关属性值
        this.x = x;
        this.y = y;
        this.dy = dy
        this.dx = dx;
        this.radius = radius;
        this.color = color;

        //绘制一个圆球,并填充颜色
        // https://www.w3school.com.cn/tags/canvas_arc.asp

        this.draw = function () {
            ctx.beginPath();
            ctx.arc(this.x, this.y, this.radius, 0, 2 * Math.PI);
            ctx.fillStyle = this.color;
            ctx.fill();
            ctx.closePath();
        }

        //实时更新动画
        this.update = function () {
            //y 轴临界值判断
            //如果小球在下降过程中到达底部时(及绘制小球的中心坐标位置超出窗口高度时)
            // alert(this.dy)  //不太清楚的可以 alert 一下
            if (this.y + this.radius + this.dy + Gravity > h) {
                //小球 y轴方向改变 (往上)
                this.dy = -this.dy;
                this.dy *= Firction;
                this.dx *= Firction;
            } else {
                //小球  y轴坐标递增 (往下)
                this.dy += Gravity;
            }
            //x 轴临界值判断
            if (this.x + this.radius + this.dx >= w || this.x - this.radius + this.dx <= 0) {
                //小球 x轴方向改变
                this.dx = -this.dx;
            }
            //小球 x,y坐标位置改变(因为之前的 dy,dx有取反过,所以此处会实现上下,左右的运动路线)
            this.y += this.dy;
            this.x += this.dx;
            //根据改变后的坐标位置绘图
            this.draw();
        }
    };

    //创建小球的方法(相关样式,起始坐标位置等)
    function init(m_x, m_y) {
        for (let i = 0; i < ball_num; i++) {
            let radius = randomIntFronRange(2, 10); //圆的半径
            // x,y 为绘制圆的中心坐标
            let x = m_x;
            let y = m_y;
            let dx = randomIntFronRange(-5, 5);//小球 x 轴位置 递增或者递减的一个随机值(小球是往左还是往右弹)
            let dy = randomIntFronRange(1, 2); //小球 y 轴位置 递增或者递减的一个随机值(小球上下弹动高度)
            let color = colorArray[Math.floor(Math.random() * colorArray.length)]; //从颜色数组里面随机取一个颜色
            ballArray.push(new Ball(x, y, dx, dy, radius, color)); //往小球数组里面添加每个小球的相关数值
        }
    };
   
   //执行动画方法
    function animation() {
        // 更新动画
        // https://developer.mozilla.org/zh-CN/docs/Web/API/Window/requestAnimationFrame
        requestAnimationFrame(animation)
        //清除每个小球的运动痕迹
        ctx.clearRect(0, 0, w, h);
        for (let n of ballArray) {
            n.update();
        }
    };

    window.onload = function () {
        getWindow_size();
        //监听鼠标点击事件
        document.addEventListener("mousedown", function (event) {
            //清空画布
            // https://www.w3school.com.cn/tags/canvas_clearrect.asp
            ctx.clearRect(0, 0, w, h);
            //每次点击时获取鼠标位置,以鼠标位置生成小球
            init(event.clientX, event.clientY);
        });
        animation();
    }
</script>

</html>
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,378评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,356评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,702评论 0 342
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,259评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,263评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,036评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,349评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,979评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,469评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,938评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,059评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,703评论 4 323
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,257评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,262评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,485评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,501评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,792评论 2 345