现在这几篇写的都是比较基础的东西,有过相应开发经验的朋友可直接忽略啦。

  计算机模拟的动画都是由很多静态的一连串影像(sprite)在一定帧率(fps)内逐帧播放出来的。

  对于js来说,我们可以用提供的定时器(setInterval或setTimeout,两者其实都可以),制造一个逐帧播放的舞台现场(stage),每一帧清空画布后再把所有的精灵全画上去,下一帧再清再画,只要改变精灵的相应属性就能产生动画的效果。所以我们对于精灵(Sprite)类来说,要提供一个画(draw)的方法,一个进入每一帧时(onenter)要执行的方法;对于舞台(stage)对象,就提供往舞台添加和删除精灵(addChild/removeChild)的方法,定时器的相关操作方法(start,stop,step)。再来看,其实Sprite也是可以添加精灵达到一样的层次关系的,所以也依然可以提供addChild,removeChild的方法,所以我们可以把Sprite做为基类,stage对象继承了Sprite的方法后可根据需要重写和添加自己的方法

  Sprite类

  根据实际需要实现了其他一些方法。在js/lib/目录下新建一个Sprite.js文件(不了解文件目录结构请查看上一篇介绍文章,如果是读者自己规划的文件结构那还是按自己的方法来放吧):

  

this.Sprite = __class__({

    x: 0,         // 精灵的中心点在stage上的x坐标
y: 0, // 精灵的中心点在stage上的y坐标
width: 0, // 宽
height: 0, // 高
alpha: 1, // 透明度 0 ~ 1
scaleX: 1, // X轴上的缩放比
scaleY: 1, // Y轴上的缩放比
rotation: 0, // 旋转角度
visible: true, // 可见否
DEG_TO_RAD: Math.PI / 180, // 一角度多少弧度,常量 __init__: function () {
this._object = [] // 存放精灵
},

// 把精灵画到画布前的修正,如把x,y修正为sprite的中心点坐标,画的时候不会以左上角为锚点
__beforedraw__: function (ctx) {
ctx.translate(-this.width/2, -this.height/2)
if (this.scaleX !== 1 || this.scaleY !== 1)
ctx.scale(this.scaleX, this.scaleY)
if (this.rotation % 360 !== 0)
ctx.rotate(this.DEG_TO_RAD * this.rotation)
if (this.alpha !== 1)
ctx.globalAlpha = this.alpha
this.draw(ctx) // 真正调用画的方法
this._drawall(ctx) // 把所有的子精灵都 画出来
}, draw: function (ctx) { // 现阶段版本要自己实现画的方法
// implement your own draw method
}, _drawall: function (ctx) {
if (this.size() > 0)
for (var i = 0, obj; obj = this._object[i]; i++) {
this.onenter()
if (obj.visible) { // 精灵可见才画,不可见它与它的子精灵都不会画到stage上
ctx.save()
obj.__beforedraw__(ctx)
ctx.restore()
}
}
},

// 进入每帧时调用,如果有做逐帧动画的需求可以实现(就是重写)该方法
onenter: function () {
// implement your own onenter method
}, addChild: function (obj) {
return this.addChildAt(this.size(), obj)
}, removeChild: function (obj) {
this.removeChildAt(this.indexOf(obj))
return this
},

// 获取指定索引的子精灵
child: function (index) {
return this._object[index]
},

// 添加精灵到指定位置
addChildAt: function (index, obj) {
if (this._object.indexOf(obj) === -1)
this._object.splice(index, 0, obj)
return this
},

// 删除指定位置的精灵,如果存在
removeChildAt: function (index) {
if (this.child(index) !== void 0)
this._object.splice(index, 1)
return this
},

// 获取指定精灵的索引
indexOf: function (obj) {
return this._object.indexOf(obj)
},

// 获取包含的精灵个数
size: function () {
return this._object.length
},

// 移除所有精灵
clear: function () {
this._object.length = 0
return this
} })

  stage

  舞台管理对象,之所以不用写成一个类是基本不会反复生成多个舞台实例,一个界面一个canvas就够了。上面也提到stage具有的很多方法Sprite类都有,所以我们可以继承Sprite类,又因为只用做成一个对象,所以直接实例化Sprite类就OK了,然后在这个实例中添加或重写方法:

  js/lib/stage.js

this.stage = new Sprite()

// 拷贝方法到stage对象中
__copy__({ // 初始化stage,传入一个canvas dom对象
init: function (canvas) {
this.canvas = canvas
this.context = canvas.getContext('2d')
this.width = canvas.width
this.height = canvas.height
return this
}, // 运行,参数fps为帧率,默认每秒24帧
run: function (fps) {
fps = Number(fps) || 24
this._interval = Math.round(1000 / fps)
this._starttimer()
this.running = true
return this
}, // 停止运行
stop: function () {
this.running = false
this._stoptimer()
return this
}, running: false,
__timer: null, _starttimer: function () {
if (!this.__timer)
this.__timer = setInterval(function (obj) {
obj._drawall()
}, this._interval, this)
}, _stoptimer: function () {
if (this.__timer) {
clearInterval(this.__timer)
this.__timer = null
}
}, // override
_drawall: function () {
if (this.size()) {
// 清空画布
this.context.clearRect(0, 0, this.width, this.height)
Sprite.prototype._drawall.call(this, this.context)
}
} }, stage)

  这两个东西都实现了,现在尝试来使用它们。

其实还有一个大前提,就是你已经基本了解 html5 canvas的API,如果这个条件不满足可以先去补习一下下,很简单的几个东西。

  感慨web前端这块好象没有特别智能如 android eclipse和ios xcode这样的ide,对文件的引用什么的都不是很友好,或者是我寡闻了,除了静态语言其他时间全是vi的可悲啊……先来调整一下之前定义的东西,在js/lib/sys.js里再加一个工具吧,路径添加和获取的对象,稍稍方法我们用来加载js文件:

this.__path__ = function () {
var arr = []
return { // 添加路径
add: function () {
for (var i = 0, str; str = arguments[i]; ++i)
arr.push(str)
}, // 获取所有路径,供__load__使用
list: function () {
return arr.slice()
}
}
}()

修改js/etc/mtm_module.js文件吧,不用再为每个目录定义一个数组了

__path__.add(
'js/mtm/Test.js',
'js/mtm/OtherTest.js'
)

  个性一个js/bin/main.js里开头调用__load__方法的参数为:

// __path__.list() 可获取所添加的要加载的路径
__load__(__path__.list(), function () {})

  因为现在在Lib下加了两个文件 (Sprite.js,stage.js),以后要是再加其他类文件 的话都要手动去写标签太麻烦(个人感觉),在js/etc/目录下新建一个lib_module.js文件

__path__.add(
'js/lib/Sprite.js',
'js/lib/stage.js'
)

痛苦的是还要在Index.html里用标签引用lib_module.js ……

  好了先来初始化stage,在main.js中加载完文件的回调函数里写:

__load__(__path__.list(), function () {

    var cvs = document.createElement('CANVAS'),
doc = document.documentElement
cvs.width = doc.clientWidth
cvs.height = doc.clientHeight
document.body.appendChild(cvs) stage.init(cvs).run() // 初始化并运行 })

  我们在js/mtm/Ball.js里写一个例子,Ball类:

var Ball = __class__(Sprite, {

    __init__: function (color, radius) {
Sprite.call(this)
this.color = color || 'red'
this.radius = radius || 20
}, draw: function (ctx) {
ctx.fillStyle = this.color
ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2, true)
ctx.fill()
} })

使用这个Ball类只要生成实例,并添加到stage就OK了,在js/bin/main.js的 初始化stage完后试试吧.

var ball = new Ball()

// 设置ball的位置在stage中央
ball.x = stage.width / 2
ball.y = stage.height / 2 stage.addChild(ball)

用浏览器打开Index.html页面就看到一个红色圆球在浏览器中心点上了,如果一路进来都没写错什么东西的话。

  工具都基本准备完了,下去就开始一个个实现精彩的例子(有些例子没必要就不实现了)。

Make Things Move -- Javascript html5版(二)实现最基本的Sprite类和stage管理对象的更多相关文章

  1. Make Things Move -- Javascript html5版(一)文件目录结构和工具方法准备

    从这一篇开始,就来开始我们的make things move之旅吧 在此之前,要知道ActionScript(AS)的语法和JS是不一样的,AS是相对于JS而言更好的支持了面向对象的特性,所以我们可以 ...

  2. Make Things Move -- Javascript html5版(三)三角函数形式的动画

    角度制和弧度制 生活中通常是用角度度来理解的,代码里都是用弧度制来计算. 角度转弧度:DEG_TO_RAD = Math.PI / 180 弧度装角度:RAD_TO_DEG = 180 / Math. ...

  3. JavaScript+html5 canvas实现本地截图教程

    这篇文章主要介绍了JavaScript+html5 canvas实现本地截图教程,对截图功能感兴趣的小伙伴们可以参考一下 最近有时间了解了下html5的各API,发现新浪微博的头像设置是使用canva ...

  4. HTML5版的String Avoider小游戏

    HTML5版的String Avoider小游戏 http://www.newgrounds.com/portal/view/300760 蛮简单也蛮考验耐心,从游戏起始点移动鼠标到终点位置,鼠标移动 ...

  5. javascript+HTMl5游戏下载,开发一个都能月薪上万!舅服你

    HTML5时代已经到来许久了,你是否已经掌握了那么一点呢?今天小编给大家讲讲h5的折叠多设备.跨平台特性, 即用HTML5制作游戏.相比flash,HTML5更加灵活方便,随着浏览器技术的不断升级,H ...

  6. JavaScript+HTML5 实现打地鼠小游戏

    一.游戏简介 打地鼠这个游戏相信大家都不陌生,也是童年时候一款经典的游戏.本次游戏的编写是以html文件形式完成的,并且使用HBulider软件进行编写,使用谷歌浏览器展示效果,游戏将会采用JavaS ...

  7. js操作文件 HTML5版

    js操作文件 HTML5版,有需要的朋友可以参考下. <!DOCTYPE html> <html> <head> <title>JSFileReader ...

  8. JavaScript学习记录二

    title: JavaScript学习记录二 toc: true date: 2018-09-13 10:14:53 --<JavaScript高级程序设计(第2版)>学习笔记 要多查阅M ...

  9. 免费的HTML5版uploadify送上

    相信有不少同学用过uploadify这一款文件上传插件,它支持多文件选择.能显示进度条.可配置性高,总体来说是比较好用的.官网有两个版本供下载,分别是flash版和HTML5版.不过令人惋惜的是,HT ...

随机推荐

  1. POJ 1565 Skew Binary(简单的问题)

    [简要题意]:第二个是数字系统的代表性的定义.而给了你这个号码系统提示的形式和十进制转换之间的关系.现在给你一些这样的系统.让你把它变成2二进制输出. [分析]:当中 base[k]  =  2^(k ...

  2. Lua的多任务机制——协程(coroutine)

    并发是现实世界的本质特征,而聪明的计算机科学家用来模拟并发的技术手段便是多任务机制.大致上有这么两种多任务技术,一种是抢占式多任务(preemptive multitasking),它让操作系统来决定 ...

  3. Spark Standalone模式应用程序开发

    作者:过往记忆 | 新浪微博:左手牵右手TEL | 能够转载, 但必须以超链接形式标明文章原始出处和作者信息及版权声明博客地址:http://www.iteblog.com/文章标题:<Spar ...

  4. how tomcat works 读书笔记九 Session管理

    在看本文之前,请先查阅相关Session与Cookie的资料. 这篇资料不错 http://blog.csdn.net/fangaoxin/article/details/6952954 Catali ...

  5. JS时间戳比较大小:对于一组时间戳(开始时间~结束时间)和另一组时间戳进行比较,用于判断被比较时间戳组是否在要求范围内

    /* *JS时间戳比较大小:对于一组时间戳(开始时间~结束时间)和另一组时间戳进行比较,用于判断被比较时间戳组是否在要求范围内 *@param date1 date2(形如:'2015-01-01'类 ...

  6. sql点滴38—SQL Server 2008和SQL Server 2008 R2导出数据的选项略有不同

    原文:sql点滴38—SQL Server 2008和SQL Server 2008 R2导出数据的选项略有不同 说明: 以前要将一个表中的数据导出为脚本,只有用存储过程.现在在SQL Server ...

  7. Asterisk 未来之路3.0_0003

    原文:Asterisk 未来之路3.0_0003 Asterisk: The Hacker's PBX 如果电信公司忽视了asterisk,那么正在处于危险中.asterisk 良好的扩展性,能够创建 ...

  8. (UML两个汇总)九种图。

    最后总结UML关系,有明确的关系,现在让我们总结一下UML九图..图往往比文字要直观,因此,当我们开发软件.文件必须是不可或缺的人物,. 以下我将这九种图分了一下: 我们还能够将这九种图分为静态图和动 ...

  9. 学习html5的WebSocket连接

    1.什么是WebSocket WebSocket 是一种自然的全双工.双向.单套接字连接.使用WebSocket,你的HTTP 请求变成打开WebSocket 连接(WebSocket 或者WebSo ...

  10. WebIM(4)----Comet的特殊之处

    WebIM系列文章 在一步一步打造WebIM(1)一文中已经使用Comet实现了一个简单的WebIM,那么,Comet究竟和一般的打开网页有何区别,本文将通过编写一个简单的HTTP服务器来说明两者的区 ...