前言

据说在编程语言的发展过程中,面向对象语言是为了解决GUI编程的问题而出现的。计算机一开始是用纸带,命令行等来和人进行交互,..不对,是人用纸带跟计算机交互(lll¬ω¬)。而图形界面的出现是一次重大的改进,使普通人很容易就能使用计算机。

我们知道,显示器通常是以60Hz频率刷新的。在显示器的眼中,没有什么按钮,窗口,输入框这些组件的概念,你只需要告诉它在哪个时间,渲染什么样的画面就好了,而我们叫的按钮,窗口等通通都是这一帧画面的一部分。尽管这符合浏览器的习惯,但是这不符合人们的思维习惯。在我们眼里,按钮就是一个物体,它有宽度,高度,还有位置颜色,而不会把它看成是一帧的一部分画面。随着界面的复杂,这种思维上的差异会表现的越来越明显。巧合的是,canvas和GUI编程很像,提供的接口也是一次一次在是刷新画布。下面利用canvas举几个场景来说明这种差异。

场景

  1. 画一个正方形:demo
let cvs = document.querySelector('canvas');
let ctx = cvs.getContext('2d');
ctx.fillStyle = 'red';
ctx.fillRect(10,10,20,20);
  1. 让这个正方形动起来:codepen链接

按显示器的思维,就是擦掉上次的画面,然后在另一个地方重新画一次

let x = 0,y = 0,speed={x:1,y:1};
function draw(){
ctx.clearRect(0,0,400,400);
ctx.fillRect(x,y,20,20);
x+=speed.x;
y+=speed.y;
if(x>400 || x<0){
speed.x = -speed.x;
speed.y = -speed.y;
}
}
  1. 正方形在移动的时候还会不断缩放

这时你可能会再增加一个长度变量,然后在每一帧的绘制中,改变这个长度变量,来实现这个效果:demo

let x = 0,y = 0,len = 10;speed={x:1,y:1,scale:1};
function draw(){
ctx.clearRect(0,0,400,400);
ctx.fillRect(x,y,len,len);
x+=speed.x;
y+=speed.y;
len += speed.scale;
if(x>400 || x<0){
speed.x = -speed.x;
}
if(y>400 || y<0){
speed.y = -speed.y;
}
if(len>20 || len<10){
speed.scale = -speed.scale;
}
}

我们将方块的位置,大小,颜色这些称为方块的状态。通过三个例子可以发现,随着方块的状态越来越多,比方说可以发射子弹。或者除了方块之外,还有草花,红桃也在来回移动,程序会变得越来越难于管理。这时候就需要面向对象了。

面向对象的思考方式

按照我们的思考方式,上面的场景就是一个方块的位置和大小在发生变化,所以有以下代码:

function Block(x, y, len, color,speed){
this.x = x || 0;
this.y = y || 0;
this.len = len || 10;
this.color = color || 'red';
this.speed = speed ||{
x:1,y:1,scale:1
}
}
let redBlock = new Block(0,0,10,'red');

这样,就把一个方块相关的属性放到一个对象里,而不像上面的一堆变量,毫无结构。同时,还能很方便的new 出大小,位置,颜色各不相同的方块。

另一个要注意的地方是speed这个属性,一开始写的时候,我计划是将speed作为函数move的参数,但是这样是不行的,原因是,函数move不会保留方块的移动状态,因此要作为方块的属性存放。

下面我们让方块动起来,我们把方块会动当成是方块的一个行为的话,就有下面的代码:

Block.prototype.move = function(speed){
this.speed = speed || {
x:1,y:1,scale:1
}
this.x += this.speed.x;
this.y += this.speed.y;
this.len += this.speed.scale;
if(this.x>400 || this.x<0){
this.speed.x = -this.speed.x;
}
if(this.y>400 || this.y<0){
this.speed.y = -this.speed.y;
}
if(this.len>20 || this.len<10){
this.speed.scale = -this.speed.scale;
}
}

于是我们就有了一个会动的方块,最后一步是渲染,不妨把这个行为作为Block这个类的一个静态方法:

Block.render = function(block){
let cvs = document.querySelector('canvas');
let ctx = cvs.getContext('2d');
setInterval(function(){
ctx.clearRect(0,0,400,400);
ctx.fillStyle = block.color;
ctx.fillRect(block.x,block.y,block.len,block.len);
block.move();
},100)
}

渲染多个方块也容易:

Block.renderMany = function(blocks){
let cvs = document.querySelector('canvas');
let ctx = cvs.getContext('2d');
setInterval(function(){
ctx.clearRect(0,0,400,400);
for(let block of blocks){
ctx.fillStyle = block.color;
ctx.fillRect(block.x,block.y,block.len,block.len);
block.move();
}
},100)
}

渲染方块:demo

let redBlock = new Block(0,0,10,'red');
let blueBlock = new Block(200,200,20,'blue',{x:-1,y:1,scale:2})
// Block.render(redBlock);
Block.renderMany([redBlock,blueBlock])

到这里,我理解的面向对象就算告一段落了,如果有不对的地方,希望各位看官指出。到这里也就算是基础,回到开始那个问题,如果有红桃,草花也在里面运动呢,那就要用到继承了。

从canvas理解面向对象的更多相关文章

  1. 摘抄--全面理解面向对象的 JavaScript

    全面理解面向对象的 JavaScript JavaScript 函数式脚本语言特性以及其看似随意的编写风格,导致长期以来人们对这一门语言的误解,即认为 JavaScript 不是一门面向对象的语言,或 ...

  2. Java 雇员管理小练习(理解面向对象编程)

    在学习集合框架的时候,初学者很容易练习到学生管理系统.雇员管理体统等练习题.在学习集合框架之前,基本上Java基本语法都学完了,集合框架也从侧面的检验对前面学习的理解.下面用一个曾经做过的练习题,回顾 ...

  3. 深入全面理解面向对象的 JavaScript

    深入全面理解面向对象的 JavaScript (原著: 曾 滢, 软件工程师, IBM,2013 年 4 月 17 日) JavaScript 函数式脚本语言特性以及其看似随意的编写风格,导致长期以来 ...

  4. 全面理解面向对象的 JavaScript (share)

     以下分享自:  http://www.ibm.com/developerworks/cn/web/1304_zengyz_jsoo/   简介: JavaScript 函数式脚本语言特性以及其看似随 ...

  5. 全面理解面向对象的 JavaScript

    前言 当今 JavaScript 大行其道,各种应用对其依赖日深.web 程序员已逐渐习惯使用各种优秀的 JavaScript 框架快速开发 Web 应用,从而忽略了对原生 JavaScript 的学 ...

  6. 从一些简单代码实例彻底理解面向对象编程思想|OOP本质是什么?

    从Rob Pike 的 Google+上的一个推看到了一篇叫<Understanding Object Oriented Programming>的文章,我先把这篇文章简述一下,然后再说说 ...

  7. canvas+js+面向对象的圆形封装

    效果: Circle.js /* 1. 封装属性: x, y r, fillStyle strokeStyle opacity 2.render */ function Circle(option) ...

  8. canvas+js+面向对象的矩形封装

    效果: Rect.js /* 1. 封装属性: x, y w , h, fillStyle strokeStyle rotation opacity 2.render */ function Rect ...

  9. java高级特性(1)--理解面向对象思想

    前言: 优秀的代码具备:高性能.可重用.可扩展.易维护.易理解 具体实现: 高性能:合理使用算法,数据结构等等 可重用:封装.继承 可扩展:多态 易维护.易理解:命名规范 + 注解 面向对象是一种思想 ...

随机推荐

  1. 201521123069 《Java程序设计》 第5周学习总结

    1. 本章学习总结 1.1 尝试使用思维导图总结有关多态与接口的知识点. 1.2 可选:使用常规方法总结其他上课内容. 参考资料: 百度脑图 XMind 1.1 1.2 (1)用Arrays.sort ...

  2. 201521123030《Java程序设计》第5周学习总结

    1. 本周学习总结 1.代码阅读:Child压缩包内源代码 1.1 com.parent包中Child.java文件能否编译通过?哪句会出现错误?试改正该错误.并分析输出结果. 因为i在类中是priv ...

  3. 201521123103 《Java程序设计》第三周学习总结

    一.本周学习总结 二.书面作业 1.代码阅读 public class Test1 { private int i = 1;//这行不能修改 private static int j = 2; pub ...

  4. 201521123096《Java程序设计》第三周学习总结

    1. 本周学习总结 2. 书面作业 (1)代码阅读 public class Test1 { private int i = 1;//这行不能修改 private static int j = 2; ...

  5. response 常用详解(1)

    我们在创建Servlet时会覆盖service()方法,或doGet()/doPost(),这些方法都有两个参数,一个为代表请求的request和代表响应response. service方法中的re ...

  6. Struts框架2

    1.框架:是一个半成品,可以在其基础上在次开发. 2.struts2框架:它是一个web层使用的mvc框架. 3.struts2核心 1.struts2核心 2.xwork核心 4.struts2入门 ...

  7. Eclipse 版本选择

    查看Eclipse的版本号: 1. 找到eclipse安装目录 2. 进入readme文件夹,打开readme_eclipse.html 3. readme_eclipse.html呈现的第二行即数字 ...

  8. express 安装和运行

    1.npm install -g express-generator 2.进入服务目录(自己定义的文件夹,或者express Myapp && cd Myapp 新建Myapp文件夹并 ...

  9. 风趣的JavaScript面向对象入门课程一

    在我们程序猿界一直流传这这么一个joke,没女票我们可以new一个.没房子没票子没车子我们同样new一个!当然这听着更像是一种自嘲,毕竟我们程序猿都爱自嘲,哈哈,废话不多说,今天就由我带着你们来入Ja ...

  10. 关于高德地图Android开发时地图只显示一次、第二次打开不定位的解决办法

    我按照高德官方Demo改的 第一次是可以定位的,如左图 第二次就不能定位了,如右图 在onDestory中把aMap置为空即可 aMap = null; 修改完如下图: 原理是第二次打开时aMap不为 ...