需求:自动生成若干气泡,从海底往上浮;

1、基本的HTML结构:

  1. <!DOCTYPE html>
  2. <html>
  3. <head lang="en">
  4. <meta charset="UTF-8">
  5. <title></title>
  6. <style>
  7. * {
  8. margin:0;
  9. padding:0;
  10. }
  11. canvas {
  12. display:block;
  13. }
  14. </style>
  15. </head>
  16. <body>
  17. <canvas></canvas>
  18. </body>
  19. </html>

2、JS代码:

1:创建气泡类Bubble,气泡的大小,上浮的速度,出现的位置,透明度皆随机

创建对象的方法有很多种,这里采用构造函数方法:

  1. var Bubble = function (x, y, radius) {
  2. this.x = x; //出现位置的x坐标
  3. this.y = y; //出现位置的y坐标
  4. this.radius = radius; //气泡的大小
  5. this.vy = -Math.random() * 5; //气泡上浮的速度
  6. this.opacity = 0.2 + Math.random() * 0.5; //气泡的透明度
  7. }

添加绘制的方法,我们可以将绘制方法添加到构造函数里,但是这里有一个问题,这个方法会随着这个类复制很多次,造成内存加多,所以这里采用原型的方式来添加绘制的方法:

  1. Bubble.prototype.draw = function(){
  2. //
  3. //
  4. }

2、接下来开始实现draw的逻辑代码:

  1. Bubble.prototype.draw = function(){
  2. var strokeColor, fillColor;
  3.  
  4. strokeColor = 'rgba(255, 255, 255,' + this.opacity + ')'; /*描边,气泡外围的颜色*/
  5. fillColor = 'rgba(255, 255, 255,' + (this.opacity / 2) + ')'; /*填充,气泡内部的颜色*/
  6.  
  7. ctx.save(); /*存好当前状态*/
  8. ctx.lineWidth = 0.8; /*画笔粗细*/
  9. ctx.strokeStyle = strokeColor; /*描边*/
  10. ctx.fillStyle = fillColor; /*填充*/
  11. ctx.beginPath(); /*开始绘制*/
  12. ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2, true); /*绘制气泡*/
  13. ctx.closePath(); /*关闭路劲*/
  14. ctx.fill(); /*填充路劲*/
  15. ctx.stroke(); /*描边*/
  16. ctx.restore(); /*释放状态*/
  17. }

3、开始生成气泡

  1. function generateBubbles() {
  2. for (var i = 0; i <= 50; i++) {
  3. bubbles.push(new Bubble(Math.random() * width, height + Math.random() * height / 2, 4 + Math.random() * 2));
  4. }
  5. }

4、开始移动气泡:

  1. bubbles.forEach(moveBubble); //forEach() 方法用于调用数组的每个元素,并将元素传递给回调函数。
  2. function moveBubble(bubble) {
  3. bubble.y += bubble.vy;
  4. bubble.draw(ctx);
  5. }

5、刷新画布

  1. function drawFrame() {
  2. window.requestAnimationFrame(drawFrame, canvas);
  3. ctx.fillStyle = '#17293a';
  4. ctx.fillRect(0, 0, width, height);
  5. bubbles.forEach(moveBubble);
  6. }

6、初始化

  1. init();
  2. function init(){
  3. canvas = document.querySelector('canvas');
  4. ctx = canvas.getContext('2d');
  5. width = canvas.width = window.innerWidth;
  6. height = canvas.height = window.innerHeight;
  7.  
  8. generateBubbles(20);
  9.  
  10. drawFrame();
  11. }

完整代码:

  1. <!doctype html>
  2. <html>
  3. <head>
  4. <meta charset="utf-8">
  5. <title>HTML5 Canvas深海海藻动画</title>
  6.  
  7. <style>
  8. * {
  9. margin: 0;
  10. padding: 0;
  11. }
  12.  
  13. canvas {
  14. display: block;
  15. }
  16. </style>
  17. </head>
  18. <body>
  19. <canvas></canvas>
  20. <script>
  21. var canvas, ctx, width, height, stems, bubbles;
  22. stems = [];
  23. bubbles = [];
  24. var Bubble = function (x, y, radius) {
  25. this.x = x; //出现位置的x坐标
  26. this.y = y; //出现位置的y坐标
  27. this.radius = radius; //气泡的大小
  28. this.vy = -Math.random() * 5; //气泡上浮的速度
  29. this.opacity = 0.2 + Math.random() * 0.5; //气泡的透明度
  30. this.oldY = y;
  31. };
  32. Bubble.prototype.draw = function () {
  33. var strokeColor, fillColor;
  34. strokeColor = 'rgba(255, 255, 255,' + this.opacity + ')';
  35. /*描边,气泡外围的颜色*/
  36. fillColor = 'rgba(255, 255, 255,' + (this.opacity / 2) + ')';
  37. /*填充,气泡内部的颜色*/
  38. ctx.save();
  39. /*存好当前状态*/
  40. ctx.lineWidth = 0.8;
  41. /*画笔粗细*/
  42. ctx.strokeStyle = strokeColor;
  43. /*描边*/
  44. ctx.fillStyle = fillColor;
  45. /*填充*/
  46. ctx.beginPath();
  47. /*开始绘制*/
  48. ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2, true);
  49. /*绘制气泡*/
  50. ctx.closePath();
  51. /*关闭路劲*/
  52. ctx.fill();
  53. /*填充路劲*/
  54. ctx.stroke();
  55. /*描边*/
  56. ctx.restore();
  57. /*释放状态*/
  58. }
  59. init();
  60. function init() {
  61. canvas = document.querySelector('canvas');
  62. ctx = canvas.getContext('2d');
  63. width = canvas.width = window.innerWidth;
  64. height = canvas.height = window.innerHeight;
  65. generateBubbles(20);
  66. drawFrame();
  67. }
  68. function generateBubbles(bubblesLimit) {
  69. for (var i = 0; i <= bubblesLimit; i++) {
  70. bubbles.push(new Bubble(Math.random() * width, height + Math.random() * height / 2, 4 + Math.random() * 2));
  71. }
  72. }
  73. function drawFrame() {
  74. window.requestAnimationFrame(drawFrame, canvas);
  75. ctx.fillStyle = '#17293a';
  76. ctx.fillRect(0, 0, width, height);
  77. bubbles.forEach(moveBubble);
  78. }
  79. function moveBubble(bubble) {
  80. /*当气上浮至超过页面窗口时,也就是消失的时候,将气泡的位置拉回一开始出现的位置,再次上浮,造成次循环的效果*/
  81. if (bubble.y + bubble.radius <= 0) {
  82. bubble.y = bubble.oldY;
  83. }
  84. bubble.y += bubble.vy;
  85. bubble.draw(ctx);
  86. }
  87. </script>
  88. </body>
  89. </html>

canvas-海底气泡(面向对象编程)的更多相关文章

  1. JAVA的面向对象编程--------课堂笔记

    面向对象主要针对面向过程. 面向过程的基本单元是函数.   什么是对象:EVERYTHING IS OBJECT(万物皆对象)   所有的事物都有两个方面: 有什么(属性):用来描述对象. 能够做什么 ...

  2. JAVA的面向对象编程

    JAVA的面向对象编程 面向对象主要针对面向过程. 面向过程的基本单元是函数. 什么是对象:EVERYTHING IS OBJECT(万物皆对象) 全部的事物都有两个方面: 有什么(属性):用来描写叙 ...

  3. angular2系列教程(六)两种pipe:函数式编程与面向对象编程

    今天,我们要讲的是angualr2的pipe这个知识点. 例子

  4. 带你一分钟理解闭包--js面向对象编程

    上一篇<简单粗暴地理解js原型链--js面向对象编程>没想到能攒到这么多赞,实属意外.分享是个好事情,尤其是分享自己的学习感悟.所以网上关于原型链.闭包.作用域等文章多如牛毛,很多文章写得 ...

  5. PHP 面向对象编程和设计模式 (1/5) - 抽象类、对象接口、instanceof 和契约式编程

    PHP高级程序设计 学习笔记 2014.06.09 什么是面向对象编程 面向对象编程(Object Oriented Programming,OOP)是一种计算机编程架构.OOP 的一条基本原则是计算 ...

  6. Delphi_09_Delphi_Object_Pascal_面向对象编程

    今天这里讨论一下Delphi中的面向对象编程,这里不做过多过细的讨论,主要做提纲挈领的描述,帮助自己抓做重点. 本随笔分为两部分: 一.面向对象编程 二.面向对象编程详细描述 ------------ ...

  7. python基础-面向对象编程

    一.三大编程范式 编程范式即编程的方法论,标识一种编程风格 三大编程范式: 1.面向过程编程 2.函数式编程 3.面向对象编程 二.编程进化论 1.编程最开始就是无组织无结构,从简单控制流中按步写指令 ...

  8. 面向对象编程(OOP)

    什么是面向对象编程,对于面向对象编程与面向过程编程的解释随处可见,个人认为对面向对象编程解释最好的一个定义是:依赖倒转原则是面向对象编程的标志,面向对象编程是一种思想,无论使用哪一种编程语言,如果在编 ...

  9. python 学习笔记7 面向对象编程

    一.概述 面向过程:根据业务逻辑从上到下写垒代码 函数式:将某功能代码封装到函数中,日后便无需重复编写,仅调用函数即可 面向对象:对函数进行分类和封装,让开发"更快更好更强..." ...

  10. 进击的Python【第七章】:Python的高级应用(四)面向对象编程进阶

    Python的高级应用(三)面向对象编程进阶 本章学习要点: 面向对象高级语法部分 静态方法.类方法.属性方法 类的特殊方法 反射 异常处理 Socket开发基础 一.面向对象高级语法部分 静态方法 ...

随机推荐

  1. 洛谷 P1055 ISBN号码【字符串+模拟】

    P1055 ISBN号码 题目描述 每一本正式出版的图书都有一个ISBN号码与之对应,ISBN码包括9位数字.1位识别码和3位分隔符,其规定格式如“x-xxx-xxxxx-x”,其中符号“-”就是分隔 ...

  2. Spring框架学习笔记(3)——配置bean

    1.属性注入 (1)根据setter方法属性注入,这里使用的是property标签.需要bean属性提供对应的setter方法,比如笔记(1)里的 HelloWorld使用的就是这种方法. <! ...

  3. UE4 多线程(一)

    UE4中使用多线程的有两种方式,一种方式就是使用FRunnable和FRunnableThread,另一种方式是Task Graph System.Task Graph System有时会占用游戏线程 ...

  4. 久未更 ~ 二之 —— TextView 文字省略

    > > > > > 久未更 系列一:关于TextView内容超过n行文尾省略问题 //在 TextView 中 实现 超过n行省略 为.. 可用以下属性 实现 andro ...

  5. 平安E行销扫脸打卡/人寿国寿e店云参会钉钉考勤,原来这么轻易被破解!

    由于近几年人们的保险意识越来越强,身边有很多朋友都在中国人寿,中国平安等保险公司上班薪水高,工作自由,又可以学习很多保险理财的知识,每天早会个2~3个小时,剩下的基本都是自己的时间,(vx:99508 ...

  6. vueThink权限配置

    vueThink中的 admin 默认是展示所有权限,其他的权限组用户就要自己去特定进行配置 http://vuedemo.cn:8181 这里我是默认本地配置了apache到  php\public ...

  7. 坑爹的file_exists

       介绍   我发现了一个问题,今天与大家分享.我把整个过程描述一下.   问题   公司有个框架是基于smarty写的,我负责php的升级,维护人员把新环境布上来之后,测试人员找我提出经常报错(错 ...

  8. 【编程技巧】NSDate,NSDateFormatter,NSTimeInterval

    //获取日期 todaysDate=[NSDate date]; //显示日期和时间 dateFormat = [[NSDateFormatter alloc] init];//NSDate没有自己的 ...

  9. .netCore数据库迁移

    程序包管理器控制台下Nuget 命令: 初始迁移命令: add-migration init -Context DAL.ProductContext 全称:migrations add Initial ...

  10. J.U.C ThreadPoolExecutor解析

    Java里面线程池顶级接口是Executor,但严格意义上讲Executor并不是一个线程池,而是一个线程执行工具,真正的线程池接口是ExecutorService.关系类图如下: 首先Executo ...