效果如下:



代码目录如下:

  1. <!DOCTYPE html>
  2. <html lang="zh-CN">
  3. <head>
  4. <meta charset="utf-8">
  5. <title>弹球</title>
  6. <link rel="stylesheet" href="style.css">
  7. <script src="main.js" defer></script>
  8. </head>
  9. <body>
  10. <h1>弹球</h1>
  11. <canvas></canvas>
  12. </body>
  13. </html>
  1. //main.js
  2. const BALLS_COUNT = 25;
  3. const BALL_SIZE_MIN = 10;
  4. const BALL_SIZE_MAX = 20;
  5. const BALL_SPEED_MAX = 7;
  6. // 设定画布
  7. const canvas = document.querySelector('canvas');
  8. const ctx = canvas.getContext('2d');
  9. // 将画布窗尺寸置为窗口内尺寸
  10. const width = canvas.width = window.innerWidth;
  11. const height = canvas.height = window.innerHeight;
  12. // 定义一个数组来保存所有的球
  13. const balls = [];
  14. // 生成随机数的函数
  15. function random(min,max) {
  16. return Math.floor(Math.random()*(max-min)) + min;
  17. }
  18. // 生成随机颜色的函数
  19. function randomColor() {
  20. return 'rgb(' +
  21. random(0, 255) + ', ' +
  22. random(0, 255) + ', ' +
  23. random(0, 255) + ')';
  24. }
  25. // 定义 Ball 构造器
  26. function Ball(x, y, velX, velY, color, size) {
  27. this.x = x;
  28. this.y = y;
  29. this.velX = velX;
  30. this.velY = velY;
  31. this.color = color;
  32. this.size = size;
  33. }
  34. // 定义绘制球的函数
  35. Ball.prototype.draw = function() {
  36. ctx.save();
  37. ctx.beginPath();
  38. ctx.fillStyle = this.color;
  39. ctx.arc(this.x, this.y, this.size, 0, 2 * Math.PI);
  40. ctx.fill();
  41. ctx.restore();
  42. };
  43. // 定义更新球的函数
  44. Ball.prototype.update = function() {
  45. if((this.x + this.size) >= width) {
  46. this.velX = -(this.velX);
  47. }
  48. if((this.x - this.size) <= 0) {
  49. this.velX = -(this.velX);
  50. }
  51. if((this.y + this.size) >= height) {
  52. this.velY = -(this.velY);
  53. }
  54. if((this.y - this.size) <= 0) {
  55. this.velY = -(this.velY);
  56. }
  57. this.x += this.velX;
  58. this.y += this.velY;
  59. };
  60. // 定义碰撞检测函数
  61. Ball.prototype.collisionDetect = function() {
  62. for(let j = 0; j < balls.length; j++) {
  63. if( this !== balls[j]) {
  64. const dx = this.x - balls[j].x;
  65. const dy = this.y - balls[j].y;
  66. const distance = Math.sqrt(dx * dx + dy * dy);
  67. if (distance < this.size + balls[j].size) {
  68. balls[j].color = this.color = randomColor();
  69. }
  70. }
  71. }
  72. };
  73. // 定义一个循环来不停地播放
  74. function loop() {
  75. ctx.fillStyle = 'rgb(0, 0, 0, 0.25)';
  76. ctx.fillRect(0, 0, width, height);
  77. while(balls.length < BALLS_COUNT) {
  78. const size = random(BALL_SIZE_MIN, BALL_SIZE_MAX);
  79. const ball = new Ball(
  80. // 为避免绘制错误,球至少离画布边缘球本身一倍宽度的距离
  81. random(0 + size, width - size),
  82. random(0 + size, height - size),
  83. random(-BALL_SPEED_MAX, BALL_SPEED_MAX),
  84. random(-BALL_SPEED_MAX, BALL_SPEED_MAX),
  85. randomColor(),
  86. size
  87. );
  88. balls.push(ball);
  89. }
  90. for(let i = 0; i < balls.length; i++) {
  91. balls[i].draw();
  92. balls[i].update();
  93. balls[i].collisionDetect();
  94. }
  95. requestAnimationFrame(loop);
  96. }
  97. loop();
  1. //style.css
  2. body {
  3. margin: 0;
  4. overflow: hidden;
  5. font-family: '微软雅黑', sans-serif;
  6. height: 100%;
  7. }
  8. h1 {
  9. font-size: 2rem;
  10. letter-spacing: -1px;
  11. position: absolute;
  12. margin: 0;
  13. top: -4px;
  14. right: 5px;
  15. color: transparent;
  16. text-shadow: 0 0 4px white;
  17. }

bouncing-balls的更多相关文章

  1. HTML5 Canvas核心技术图形动画与游戏开发(读书笔记)----第一章,基础知识

    一,canvas元素 1 为了防止浏览器不支持canvas元素,我们设置“后备内容”(fallback content),下面紫色的字即为后备内容 <canvas id="canvas ...

  2. Android Animation简述

    Android Animation简述 一.动画(Animation)          Android框架提供了两种动画系统:属性动画(Android3.0)和视图动画.同时使用两种动画是可行的,但 ...

  3. 论文笔记之:RATM: RECURRENT ATTENTIVE TRACKING MODEL

    RATM: RECURRENT ATTENTIVE TRACKING MODEL ICLR 2016 本文主要内容是 结合 RNN 和 attention model 用来做目标跟踪. 其中模型的组成 ...

  4. android 动画NineOldAndroid

    NineOldAndroid 1.之前我们用到的第动画是frame和tween动画也就是帧动画,补间动画现在多了一种动画,它包含完了前面动画的所有状态. 属性动画(Property Anmation) ...

  5. JavaScript对象入门指南

    前言 不少开发对JavaScript实现面向对象编程存在一知半解,并且不少的在项目实践中写的都是面向过程编程的代码,因此,希望能从零入手介绍面向对象的一些概念到实现简单的面向对象的例子让大家包括我自己 ...

  6. 201771010126 王燕《面向对象程序设计(Java)》第十六周学习总结

    实验十六  线程技术 实验时间 2017-12-8 1.实验目的与要求 (1) 掌握线程概念: ‐多线程 是进程执行过中产生的多条线索. 是进程执行过中产生的多条线索. 是进程执行过中产生的多条线索. ...

  7. 马凯军201771010116《面向对象与程序设计Java》第十六周知识学习总结

    一:理论知识部分 1.线程的概念: 程序是一段静态的代码,它是应用程序执行的蓝 本. ‐进程是程序的一次动态执行,它对应了从代码加 载.执行至执行完毕的一个完整过程. 多线程是进程执行过程中产生的多条 ...

  8. 第三部分:Android 应用程序接口指南---第四节:动画和图形---第一章 属性动画及动画与图形概述

    第1章 属性动画及动画与图形概述 Android提供了一系列强大的API来把动画加到UI元素中,以及绘制自定义的2D和3D图像中去.下面的几节将综述这些可用的API以及系统的功能,同时帮你做出最优的选 ...

  9. iPhone Tutorials

    http://www.raywenderlich.com/tutorials This site contains a ton of fun written tutorials – so many t ...

  10. android动画具体解释四 创建动画

    使用ValueAnimator进行动画 通过指定一些int, float或color等类型的值的集合.ValueAnimator 使你能够对这些类型的值进行动画.你需通过调用ValueAnimator ...

随机推荐

  1. nodejs 利用zip-local模块压缩文件夹

    var zipper = require("zip-local"); zipper.sync.zip("./folder").compress().save(& ...

  2. 解决Jupyter notebook[import tensorflow as tf]报错

    参考: https://blog.csdn.net/caicai_zju/article/details/70245099

  3. python3 阿里云控制SLB权重

    一.配置好RAM账号的权限(SLB管理权限) 二.安装依赖 pip3 install aliyun-python-sdk-slb pip3 install aliyun-python-sdk-core ...

  4. linux 地址解析协议 arp

    随便转载,保留出处:http://www.cnblogs.com/aaron-agu/ arp –na #查看 arp –s 123.253.68.209 00:19:56:6F:87:D4 #添加

  5. Delphi调用MSSQL存储过程返回的多个数据集的方法

    varaintf:_Recordset;RecordsAffected:OleVariant; begin ADOStoredProc1.Close;ADOStoredProc1.Open;aintf ...

  6. ExportHandler.ashx

    using KYZWeb.Common;using Liger.Data;//using Microsoft.Office.Interop.Excel;using System;using Syste ...

  7. Android组件化、模块化、插件化

    组件:指的是单一的功能组件,如地图组件(MapSDK).扫码组件(QRCode).支付组件(AnjukePay).路由组件(Router)等等: 模块:指的是独立的业务模块,如新房模块(NewHous ...

  8. python之旅七【第七篇】面向对象之类成员

    面向对象的类成员 相关知识点 一  字段 字段包括:普通字段和静态字段,他们在定义和使用中有所区别,而最本质的区别是内存中保存的位置不同, 普通字段属于对象 静态字段属于类 class Provinc ...

  9. Android中HttpURLConnection对象是怎么生成的

    try { URL mUrl = new URL("https://www.jianshu.com/"); HttpURLConnection http = (HttpURLCon ...

  10. 洛谷3822 [NOI2017] 整数 【线段树】【位运算】

    题目分析: 首先这题的询问和位(bit)有关,不难想到是用线段树维护位运算. 现在我们压32位再来看这道题. 对于一个加法操作,它的添加位置可以得到,剩下的就是做不超过32的位移.这样根据压位的理论. ...