从canvas理解面向对象
前言
据说在编程语言的发展过程中,面向对象语言是为了解决GUI编程的问题而出现的。计算机一开始是用纸带,命令行等来和人进行交互,..不对,是人用纸带跟计算机交互(lll¬ω¬)。而图形界面的出现是一次重大的改进,使普通人很容易就能使用计算机。
我们知道,显示器通常是以60Hz频率刷新的。在显示器的眼中,没有什么按钮,窗口,输入框这些组件的概念,你只需要告诉它在哪个时间,渲染什么样的画面就好了,而我们叫的按钮,窗口等通通都是这一帧画面的一部分。尽管这符合浏览器的习惯,但是这不符合人们的思维习惯。在我们眼里,按钮就是一个物体,它有宽度,高度,还有位置颜色,而不会把它看成是一帧的一部分画面。随着界面的复杂,这种思维上的差异会表现的越来越明显。巧合的是,canvas和GUI编程很像,提供的接口也是一次一次在是刷新画布。下面利用canvas举几个场景来说明这种差异。
场景
- 画一个正方形:demo
let cvs = document.querySelector('canvas');
let ctx = cvs.getContext('2d');
ctx.fillStyle = 'red';
ctx.fillRect(10,10,20,20);
- 让这个正方形动起来: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;
}
}
- 正方形在移动的时候还会不断缩放
这时你可能会再增加一个长度变量,然后在每一帧的绘制中,改变这个长度变量,来实现这个效果: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理解面向对象的更多相关文章
- 摘抄--全面理解面向对象的 JavaScript
全面理解面向对象的 JavaScript JavaScript 函数式脚本语言特性以及其看似随意的编写风格,导致长期以来人们对这一门语言的误解,即认为 JavaScript 不是一门面向对象的语言,或 ...
- Java 雇员管理小练习(理解面向对象编程)
在学习集合框架的时候,初学者很容易练习到学生管理系统.雇员管理体统等练习题.在学习集合框架之前,基本上Java基本语法都学完了,集合框架也从侧面的检验对前面学习的理解.下面用一个曾经做过的练习题,回顾 ...
- 深入全面理解面向对象的 JavaScript
深入全面理解面向对象的 JavaScript (原著: 曾 滢, 软件工程师, IBM,2013 年 4 月 17 日) JavaScript 函数式脚本语言特性以及其看似随意的编写风格,导致长期以来 ...
- 全面理解面向对象的 JavaScript (share)
以下分享自: http://www.ibm.com/developerworks/cn/web/1304_zengyz_jsoo/ 简介: JavaScript 函数式脚本语言特性以及其看似随 ...
- 全面理解面向对象的 JavaScript
前言 当今 JavaScript 大行其道,各种应用对其依赖日深.web 程序员已逐渐习惯使用各种优秀的 JavaScript 框架快速开发 Web 应用,从而忽略了对原生 JavaScript 的学 ...
- 从一些简单代码实例彻底理解面向对象编程思想|OOP本质是什么?
从Rob Pike 的 Google+上的一个推看到了一篇叫<Understanding Object Oriented Programming>的文章,我先把这篇文章简述一下,然后再说说 ...
- canvas+js+面向对象的圆形封装
效果: Circle.js /* 1. 封装属性: x, y r, fillStyle strokeStyle opacity 2.render */ function Circle(option) ...
- canvas+js+面向对象的矩形封装
效果: Rect.js /* 1. 封装属性: x, y w , h, fillStyle strokeStyle rotation opacity 2.render */ function Rect ...
- java高级特性(1)--理解面向对象思想
前言: 优秀的代码具备:高性能.可重用.可扩展.易维护.易理解 具体实现: 高性能:合理使用算法,数据结构等等 可重用:封装.继承 可扩展:多态 易维护.易理解:命名规范 + 注解 面向对象是一种思想 ...
随机推荐
- Linux命令行学习
"mkdir + 文件夹名字" 创建文件夹 "pwd" 显示当前工作目录的绝对路径. "touch" 创建空文件. "cat /p ...
- 201521123013 《Java程序设计》第13周学习总结
1. 本周学习总结 2. 书面作业 Q1. 网络基础 1.1 比较ping www.baidu.com与ping cec.jmu.edu.cn,分析返回结果有何不同?为什么会有这样的不同? ping值 ...
- Java课程设计——学生信息系统(团队)
团队名称.团队成员介绍 1.1 团队名称 1.2 团队成员 高可心 网络1514 201521123097 组长 黄滢滢 网络1514 201521123095 组员 2.项目git地址 http:/ ...
- 201521123057《Java程序设计》第14周学习总结
0. 本周课程设计发布 Java课程设计 1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结多数据库相关内容. 数据库基本操作(目前为止主要介绍了表的基本操作) 创建表 CREATE ...
- 201521123008 《Java程序设计》 第九周学习总结
1. 本周学习总结 2. 书面作业 本次PTA作业题集异常 1.常用异常 题目5-1 1.1 截图你的提交结果(出现学号) 1.2 自己以前编写的代码中经常出现什么异常.需要捕获吗(为什么)?应如何避 ...
- ThinkPHP空操作及命名空间
空操作是指访问不存在的路径: 解决方法:在控制其中创建 _empty方法 空控制器是指访问存在的控制器: 解决方法:创建EmptyController控制器 命名空间: 初识命名空间是Library: ...
- 控制结构(4) 局部化(localization)
// 上一篇:状态机(state machine) // 下一篇:必经之地(using) 基于语言提供的基本控制结构,更好地组织和表达程序,需要良好的控制结构. 前情回顾 上一次,我们说到状态机结构( ...
- Rabbitmq集群安装配置
Rabbitmq集群安装与配置 一.rabbitmq安装环境准备 1.安装环境准备 这里,我们以两个节点为例进行安装,一个节点为内存节点,另一个节点为硬盘节点,具体可根据自己需要分配节点. 安装系统 ...
- [js高手之路]Node.js+jade抓取博客所有文章生成静态html文件
这个周末,恶补了一下jade模板引擎,就为生成静态html文件,这篇文章需要知道jade以及看过我的上篇文章,我先给出他们的参考链接: [js高手之路]Node.js模板引擎教程-jade速学与实战1 ...
- OSGi-入门篇之模块层(02)
1 什么是模块化 模块层是OSGi框架中最基础的一部分,其中Java的模块化特性在这一层得到了很好的实现.但是这种实现与Java本身现有的一些模块化特性又有明显的不同. 在OSGi中模块的定义可以参考 ...