前言

据说在编程语言的发展过程中,面向对象语言是为了解决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. 201521123097《Java程序设计》第五周学习总结

    1. 本周学习总结 1.1 尝试使用思维导图总结有关多态与接口的知识点. 2. 书面作业 1.代码阅读:Child压缩包内源代码 1.1 com.parent包中Child.java文件能否编译通过? ...

  2. temp--达州银行

    达州银行现场 服务器IP地址 192.168.1.234 ilink / ilink 自己电脑需要设置为固定IP 192.168.1.XXX 子网掩码 255.255.255.0 192.168.1. ...

  3. Spring-hibernate-BaseDao

    <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w ...

  4. Angular2 Service实践

    引言: 如果说组件系统(Component)是ng2应用的躯体,那把服务(Service)认为是流通于组件之间并为其带来生机的血液再合适不过了.组件间通信的其中一种优等选择就是使用服务,在ng1里就有 ...

  5. Postman高级应用——流程控制、调试、公共函数、外部数据文件

    postman客户端下载地址:https://www.getpostman.com/apps 目录 流程控制 调试 公共函数 外部数据文件 流程控制 流程控制简言之就是设置接口的执行顺序,流程控制只有 ...

  6. Spring Boot Document Part II(下)

    Part II. Getting started 11. 开发第一个Spirng Boot Application使用Spring Boot的关键特征开发一个基于JAVA Web的“Hello Wor ...

  7. 用ES6巧妙的解决传统面试中的算法小问题!

    最近自己也在准备面试,在复习算法的时候,机智的用了一波ES6.一起来瞧瞧吧! 1.数组的去重 var arr=str.split(''); for(var i=0;i<arr.length-1; ...

  8. Java 中的语法糖

    百度百科对语法糖的定义 语法糖(Syntactic sugar),也译为糖衣语法,是由英国计算机科学家彼得·约翰·兰达(Peter J. Landin)发明的一个术语,指计算机语言中添加的某种语法,这 ...

  9. Greatest Common Increasing Subsequence hdu1423

    Greatest Common Increasing Subsequence Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536 ...

  10. codevs 种树3

    codevs上的题目,自从wikioi改名后,就不怎么做题了. 这道题的话注释在代码中就可以了,还是求最长路,相较返回如果中间可以种多个的话,那就种越多越好,因为这样可以减少种的棵树, 所以这个i与i ...