├── CHANGES ├── LICENSE ├── README.md ├── build ├── build-base.bat ├── build-base.py ├── build-doc.bat └── compiler.jar ├── docs ├── api │ ├── index.html │ └── symbols │ │ ├── Audio.html │ │ ├── Bitmap.html │ │ ├── Button.html │ │ ├── CanvasContext.html │ │ ├── Context.html │ │ ├── DOMContext.html │ │ ├── DisplayObject.html │ │ ├── DisplayObjectContainer.html │ │ ├── Drawable.html │ │ ├── EventDispatcher.html │ │ ├── EventManager.html │ │ ├── Graphics.html │ │ ├── ImageLoader.html │ │ ├── MovieClip.html │ │ ├── Quark.html │ │ ├── Stage.html │ │ ├── Text.html │ │ ├── Timer.html │ │ └── Tween.html ├── api_template │ ├── allclasses.tmpl │ ├── allfiles.tmpl │ ├── class.tmpl │ ├── index.tmpl │ ├── publish.js │ ├── static │ │ ├── default.css │ │ ├── header.html │ │ └── index.html │ └── symbol.tmpl ├── css │ ├── bootstrap-responsive.css │ ├── bootstrap-responsive.min.css │ ├── bootstrap.css │ ├── bootstrap.min.css │ └── prettify.css ├── demo.html ├── images │ ├── displayobject.jpg │ ├── displayobject_lifecircle.jpg │ ├── dolphin_260.jpg │ ├── dolphin_main_s.jpg │ ├── dolphin_startup_s.jpg │ ├── fishjoy_260.jpg │ ├── infrastructure.jpg │ ├── logo.jpg │ ├── logo.png │ ├── mine_260.jpg │ ├── quark.jpg │ └── runner_260.jpg ├── img │ ├── glyphicons-halflings-white.png │ └── glyphicons-halflings.png ├── index.html ├── js │ ├── bootstrap.js │ ├── bootstrap.min.js │ ├── jquery.js │ └── prettify.js ├── tutorial.html ├── tutorial_context.html ├── tutorial_displayobject.html ├── tutorial_event.html ├── tutorial_infrastructure.html └── tutorial_squirrel.html ├── examples ├── button.html ├── graphics.html ├── hittest.html ├── imageloader.html ├── images │ ├── bg.jpg │ ├── boy.png │ ├── btns.png │ ├── girl.png │ ├── mask.png │ └── turn.png ├── mask.html ├── simple1.html ├── squirrel │ ├── Squirrel.js │ ├── images │ │ ├── body_walk.png │ │ └── head_idle.png │ └── squirrel.html ├── text.html ├── tween1.html └── tween2.html ├── js ├── quark.base-1.0.0.js └── quark.base-1.0.0.min.js └── src └── base ├── context ├── CanvasContext.js ├── Context.js └── DOMContext.js ├── core └── base.js ├── display ├── Bitmap.js ├── Button.js ├── DisplayObject.js ├── DisplayObjectContainer.js ├── Drawable.js ├── Graphics.js ├── MovieClip.js ├── Stage.js └── Text.js ├── event ├── EventConst.js ├── EventDispatcher.js └── EventManager.js ├── geom ├── Matrix.js └── Rectangle.js └── utils ├── Audio.js ├── ImageLoader.js ├── Timer.js ├── Tween.js ├── UIDUtil.js └── Utils.js /CHANGES: -------------------------------------------------------------------------------- 1 | == 2012.7.10 v1.0.0 build 119 == 2 | 3 | Modified: 4 | * Update API documentation. 5 | 6 | == 2012.4.26 v1.0.0 build 118 == 7 | 8 | Fixed: 9 | * MovieClip._update() - incorrect setRect() method call. 10 | 11 | == 2012.4.25 v1.0.0 build 117 == 12 | 13 | Modified: 14 | * DisplayObject Event Mode - now DisplayObject inherits from EventDispatcher. 15 | 16 | == 2012.4.20 v1.0.0 build 113 == 17 | 18 | Added: 19 | * MovieClip.getNumFrames() - return the number of frames. 20 | 21 | == 2012.4.18 v1.0.0 build 112 == 22 | 23 | Fixed: 24 | * Text.getFontMetrics() - incorrect calculation of ascent and descent. 25 | 26 | == 2012.4.16 v1.0.0 build 111 == 27 | 28 | Fixed: 29 | * Button.setEnabled() - incorrect constant Button.UP. 30 | * Text.render() - set line height for DOMContext. 31 | 32 | == 2012.4.10 v1.0.0 build 110 == 33 | 34 | Fixed: 35 | * DOMContext.draw() - dones't render objects if mix DOMContext with CanvasContext. 36 | * DOMContext.transform() - use css property pointer-events to control whether a object can be a event target. 37 | * Graphics._draw() - each draw should start with a beginPath() to clear all subpaths. 38 | 39 | == 2012.4.6 v1.0.0 build 107 == 40 | 41 | Added: 42 | * Quark.Text - a class for simple text drawing. 43 | 44 | == 2012.3.27 v1.0.0 build 104 == 45 | 46 | Added: 47 | * DisplayObject.cache(), uncache() - now only works for CanvasContext. 48 | * Build version for each build. 49 | 50 | Fixed: 51 | * DisplayObject.mask - incorrent behavior on containers or with background color. 52 | 53 | 54 | == 2012.3.22 v1.0.0 == 55 | 56 | Modified: 57 | * DisplayObject.onEvent() deprecated, use "on" event handlers instead, e.g. onmousedown, onmouseup, onmouseout etc. 58 | 59 | Fixed: 60 | * Button state changes incorrect when move fast. 61 | 62 | 63 | == 2012.3.13 v1.0.0 == 64 | 65 | Added: 66 | * DisplayObject.mask property - only support webkit browsers when use DOMContext. 67 | * Graphics.drawSVGPath() - draw graphics by using SVG path. 68 | * DisplayObject.toImage() - return as an image in DataURL format. it's useful but be careful. 69 | 70 | Modified: 71 | * DisplayObject.update() - now returns true/false. if a container's update() returns false, its children don't update at all. 72 | 73 | Fixed: 74 | * Button.setEnabled() - incorrect skin state change. 75 | * Graphics.clear() - incorrect cache reset. -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License 2 | 3 | Copyright (c) 2010-2011 three.js Authors. All rights reserved. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | QuarkJS - A HTML5 Game Framework 2 | ================================ 3 | 4 | QuarkJS is a HTML5 game framework. The aim is to provide a easy way to create game with HTML5. 5 | 6 | It includes two parts: 7 | 8 | * Quark-Base: A rendering framework which supports both Canvas and DOM rendering approaches. 9 | * Quark-Game: A game framework based on Quark-Base. (in development progress) 10 | 11 | Features 12 | ----------------- 13 | * Object-Oriented programing style. 14 | * A full display object list implementation, simple to use and extend. 15 | * Gain more performace by using difference contexts in difference scenarios. 16 | * Good compatibility and performance in desktop and mobile browsers. 17 | 18 | Wiki 19 | ----------------- 20 | * [Quark Base Infrastructure](http://github.com/quark-dev-team/quarkjs/wiki/Quark-Base-Infrastructure) 21 | * [Context](http://github.com/quark-dev-team/quarkjs/wiki/Context) 22 | * [DisplayObject](http://github.com/quark-dev-team/quarkjs/wiki/DisplayObject) 23 | * [Handle Events](http://github.com/quark-dev-team/quarkjs/wiki/Handle-Events) 24 | * [Performance](http://github.com/quark-dev-team/quarkjs/wiki/Performance) 25 | 26 | Tutorials 27 | ----------------- 28 | * [Get Started](http://github.com/quark-dev-team/quarkjs/wiki/Get-Started) 29 | 30 | API Docs 31 | ----------------- 32 | * [Online API Docs](http://quark-dev-team.github.com/quarkjs/docs/) 33 | 34 | Examples 35 | ----------------- 36 | * [Simple](http://quark-dev-team.github.com/quarkjs/examples/simple1.html) 37 | * [Button](http://quark-dev-team.github.com/quarkjs/examples/button.html) 38 | * [HitTest](http://quark-dev-team.github.com/quarkjs/examples/hittest.html) 39 | * [Graphics](http://quark-dev-team.github.com/quarkjs/examples/graphics.html) 40 | * [Text](http://quark-dev-team.github.com/quarkjs/examples/text.html) 41 | * [Mask](http://quark-dev-team.github.com/quarkjs/examples/mask.html) 42 | * [Tween1](http://quark-dev-team.github.com/quarkjs/examples/tween1.html) 43 | * [Tween2](http://quark-dev-team.github.com/quarkjs/examples/tween2.html) 44 | * [Squirrel](http://quark-dev-team.github.com/quarkjs/examples/squirrel/squirrel.html) 45 | 46 | Showcase 47 | ----------------- 48 | * [Fish Joy](http://www.riaidea.com/html5/fishjoy/) 49 | * [Happy Dolphin](http://www.riaidea.com/html5/dolphin/) 50 | * [Runner](http://www.riaidea.com/html5/runner/) 51 | * [Mine Sweeper](http://www.riaidea.com/html5/minesweeper/) 52 | * [AngryBirds Demo](http://www.riaidea.com/html5/angrybirds/) 53 | 54 | (*Note: Developed by old framework CasualJS) -------------------------------------------------------------------------------- /build/build-base.bat: -------------------------------------------------------------------------------- 1 | cmd /k java -jar compiler.jar --js_output_file ../js/quark.base-1.0.0.alpha.min.js --js ../src/base/core/base.js --js ../src/base/geom/Matrix.js --js ../src/base/geom/Rectangle.js --js ../src/base/event/EventConst.js --js ../src/base/event/EventManager.js --js ../src/base/event/EventDispatcher.js --js ../src/base/context/Context.js --js ../src/base/context/CanvasContext.js --js ../src/base/context/DOMContext.js --js ../src/base/utils/UIDUtil.js --js ../src/base/utils/Utils.js --js ../src/base/utils/Timer.js --js ../src/base/utils/ImageLoader.js --js ../src/base/utils/Tween.js --js ../src/base/utils/Audio.js --js ../src/base/display/Drawable.js --js ../src/base/display/DisplayObject.js --js ../src/base/display/DisplayObjectContainer.js --js ../src/base/display/Stage.js --js ../src/base/display/Bitmap.js --js ../src/base/display/MovieClip.js --js ../src/base/display/Button.js --js ../src/base/display/Graphics.js --js ../src/base/display/Text.js -------------------------------------------------------------------------------- /build/build-base.py: -------------------------------------------------------------------------------- 1 | #coding=utf-8 2 | 3 | import os 4 | 5 | def build(): 6 | 7 | #config 8 | src = "../src/" 9 | output = "../js/" 10 | version = "1.0.0" 11 | filename = "quark.base" 12 | compiler = "compiler.jar" 13 | compress = True 14 | 15 | files = ["base/core/base.js", 16 | "base/geom/Matrix.js", 17 | "base/geom/Rectangle.js", 18 | "base/event/EventConst.js", 19 | "base/event/EventManager.js", 20 | "base/event/EventDispatcher.js", 21 | "base/context/Context.js", 22 | "base/context/CanvasContext.js", 23 | "base/context/DOMContext.js", 24 | "base/utils/UIDUtil.js", 25 | "base/utils/Utils.js", 26 | "base/utils/Timer.js", 27 | "base/utils/ImageLoader.js", 28 | "base/utils/Tween.js", 29 | "base/utils/Audio.js", 30 | "base/display/Drawable.js", 31 | "base/display/DisplayObject.js", 32 | "base/display/DisplayObjectContainer.js", 33 | "base/display/Stage.js", 34 | "base/display/Bitmap.js", 35 | "base/display/MovieClip.js", 36 | "base/display/Button.js", 37 | "base/display/Graphics.js", 38 | "base/display/Text.js"] 39 | 40 | 41 | #build version 42 | buildVer = None 43 | buildName = filename + "-" + version + ".js" 44 | f = open(output + buildName) 45 | for line in f: 46 | index = line.find("Quark " + version) 47 | if index != -1: 48 | buildVer = line[(line.index("build")+6):line.rindex(")")] 49 | break 50 | f.close() 51 | 52 | if buildVer == None: 53 | buildVer = 1 54 | else: 55 | buildVer = int(buildVer) + 1 56 | 57 | #build info 58 | buildInfo = "/*\n" 59 | buildInfo += "Quark " + version + " (build " + str(buildVer)+ ")\n" 60 | buildInfo += "Licensed under the MIT License.\n" 61 | buildInfo += "http://github.com/quark-dev-team/quarkjs\n" 62 | buildInfo += "*/\n\n" 63 | 64 | #read files 65 | content = "" 66 | for f in files: 67 | fileName = src + f 68 | oFile = file(fileName) 69 | content += oFile.read() + "\n\n\n" 70 | oFile.close() 71 | content = buildInfo + content 72 | 73 | #merge content 74 | outputFileName = output + buildName 75 | outputFile = file(outputFileName, "w") 76 | outputFile.write(content) 77 | outputFile.close() 78 | 79 | #compress 80 | if(compress): 81 | compressOutputFileName = outputFileName[:-3] + ".min.js" 82 | os.system("java -jar " + compiler + " --js_output_file " + compressOutputFileName + " --js " + outputFileName) 83 | f = open(compressOutputFileName) 84 | content = buildInfo + f.read() 85 | f.close() 86 | f = file(compressOutputFileName, "w") 87 | f.write(content) 88 | f.close() 89 | 90 | 91 | if __name__ == "__main__": 92 | build() 93 | -------------------------------------------------------------------------------- /build/build-doc.bat: -------------------------------------------------------------------------------- 1 | java -jar /workspace/resource/html5/jsdoc_toolkit-2.4.0/jsrun.jar /workspace/resource/html5/jsdoc_toolkit-2.4.0/app/run.js ../src/base/ -r=3 -a -d=../docs/api/ -t=../docs/api_template/ --exclude="Matrix.js" --exclude="Rectangle.js" --exclude="EventCost.js" -------------------------------------------------------------------------------- /build/compiler.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quark-dev-team/quarkjs/54eb61256ef60cbc15398c544afffb61f5c907ac/build/compiler.jar -------------------------------------------------------------------------------- /docs/api/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | QuarkJS API Reference 7 | 8 | 9 | 10 | 29 | 30 | 31 | 32 | 33 | 54 | 55 |
56 |
57 |
58 | 104 |
105 |
106 |

全部类


107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 |

说明

Audio

Audio类是原生Audio的封装。

Bitmap

Bitmap位图类,表示位图图像的显示对象,简单说它就是Image对象的某个区域的抽象表示。

Button

Button类继承自DisplayObjectContainer,是Quark中的简单按钮实现。

CanvasContext

CanvasContext是Canvas渲染上下文,将显示对象渲染到指定的Canvas上。

Context

Context是Quark框架中显示对象结构的上下文,实现显示对象结构的渲染。此类为抽象类。

DisplayObject

DisplayObject类是可放在舞台上的所有显示对象的基类。DisplayObject类定义了若干显示对象的基本属性。渲染一个DisplayObject其实是进行若干变换后再渲染其drawable对象。

DisplayObjectContainer

DisplayObjectContainer类继承自DisplayObject,是显示列表中显示对象容器的基类。每个DisplayObjectContainer对象都有自己的子级列表children,用于组织对象的Z轴顺序。注意:DisplayObjectContainer对象的宽高默认为0,在autoSize=false的情况下,需要手动设置宽高。

DOMContext

DOMContext是DOM渲染上下文,将显示对象以dom方式渲染到舞台上。

Drawable

Drawable是可绘制图像或DOM的包装。当封装的是HTMLImageElement、HTMLCanvasElement或HTMLVideoElement对象时,可同时支持canvas和dom两种渲染方式,而如果封装的是dom时,则不支持canvas方式。

EventDispatcher

EventDispatcher类是可调度事件的类的基类,它允许显示列表上的任何对象都是一个事件目标。

EventManager

EventManager是一个简单的系统事件管理器。

Graphics

Graphics类包含一组创建矢量图形的方法。

ImageLoader

ImageLoader类是一个图片加载器,用于动态加载图片资源。

MovieClip

MovieClip影片剪辑类,表示一组动画片段。MovieClip是由Image对象的若干矩形区域组成的集合序列,并按照一定规则顺序播放。帧frame的定义格式为:{rect:*required*, label:"", interval:0, stop:0, jump:-1}。

Quark

Quark是QuarkJS框架的全局对象,也是框架内部所有类的全局命名空间。在全局Q未被占用的情况下,也可以使用其缩写Q。

Stage

舞台是显示对象的根,所有显示对象都会被添加到舞台上,必须传入一个context使得舞台能被渲染。舞台是一种特殊显示对象容器,可以容纳子显示对象。

Text

Text类提供简单的文字显示功能。

Timer

Timer是一个计时器。它能按指定的时间序列运行代码。

Tween

Tween类是一个缓动动画类。使用它能实现移动、改变大小、淡入淡出等效果。
161 | 162 |
163 |
164 | 165 |
166 | 169 | 170 |
171 | 172 | 173 | 174 | 175 | -------------------------------------------------------------------------------- /docs/api/symbols/Drawable.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | QuarkJS API Reference - Drawable 8 | 9 | 10 | 32 | 33 | 34 | 35 | 36 | 37 | 58 | 59 |
60 |
61 |
62 | 108 |
109 |
110 | 111 | 112 |

113 | 114 | Class Drawable 115 |


116 | 117 | 118 |

119 | 120 | 121 | 122 | Drawable是可绘制图像或DOM的包装。当封装的是HTMLImageElement、HTMLCanvasElement或HTMLVideoElement对象时,可同时支持canvas和dom两种渲染方式,而如果封装的是dom时,则不支持canvas方式。 123 | 124 |

125 | 126 | 127 | 128 |

构造函数概览

129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 145 | 146 | 147 |
说明
  140 |
141 | Drawable(drawable, isDOM) 142 |
143 |
构造函数.
144 |
148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 |

方法概览

158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 174 | 175 | 176 | 177 | 178 | 183 | 184 | 185 | 186 |
说明
  170 |
get(obj, context) 171 |
172 |
根据context上下文获取不同的Drawable包装的对象。
173 |
  179 |
set(drawable, isDOM) 180 |
181 |
设置Drawable对象。
182 |
187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 |
197 |

构造函数详细信息

198 | 199 |
200 | Drawable(drawable, isDOM) 201 |
202 | 203 |
204 | 构造函数. 205 | 206 |
207 | 208 | 209 | 210 | 211 | 212 |
213 |
参数:
214 | 215 |
216 | drawable 217 | 218 |
219 |
一个可绘制对象。
220 | 221 |
222 | {Boolean} isDOM 223 | 224 |
225 |
指定参数drawable是否为一个DOM对象。默认为false。
226 | 227 |
228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 |
237 |
238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 |

方法详细信息

246 | 247 | 248 | 249 |
250 | 251 | 252 | get(obj, context) 253 | 254 |
255 |
256 | 根据context上下文获取不同的Drawable包装的对象。 257 | 258 | 259 |
260 | 261 | 262 | 263 | 264 |
265 |
参数:
266 | 267 |
268 | {DisplayObject} obj 269 | 270 |
271 |
指定的显示对象。
272 | 273 |
274 | {Context} context 275 | 276 |
277 |
指定的渲染上下文。
278 | 279 |
280 | 281 | 282 | 283 | 284 | 285 |
286 |
返回值:
287 | 288 |
返回包装的可绘制对象。
289 | 290 |
291 | 292 | 293 | 294 | 295 |
296 | 297 | 298 |
299 | 300 | 301 | set(drawable, isDOM) 302 | 303 |
304 |
305 | 设置Drawable对象。 306 | 307 | 308 |
309 | 310 | 311 | 312 | 313 |
314 |
参数:
315 | 316 |
317 | drawable 318 | 319 |
320 |
一个可绘制对象。
321 | 322 |
323 | {Boolean} isDOM 324 | 325 |
326 |
指定参数drawable是否为一个DOM对象。默认为false。
327 | 328 |
329 | 330 | 331 | 332 | 333 | 334 | 335 | 336 | 337 | 338 | 339 | 340 | 341 | 342 | 343 | 344 | 345 |
346 |
347 | 348 |
349 | 352 | 353 |
354 | 355 | 356 | 357 | 358 | 359 | 360 | -------------------------------------------------------------------------------- /docs/api_template/allclasses.tmpl: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/api_template/allfiles.tmpl: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | {! Link.base = ""; /* all generated links will be relative to this */ !} 7 | QuarkJS Reference - File Index 8 | 9 | 10 | 13 | 14 | 15 | 16 | {+include("static/header.html")+} 17 | 18 |
19 | {+publish.classesIndex+} 20 |
21 | 22 |
23 |

File Index

24 | 25 | 26 |
27 |

{+new Link().toSrc(item.alias).withText(item.name)+}

28 | {+resolveLinks(item.desc)+} 29 |
30 | 31 |
Author:
32 |
{+item.author+}
33 |
34 | 35 |
Version:
36 |
{+item.version+}
37 |
38 | {! var locations = item.comment.getTag('location').map(function($){return $.toString().replace(/(^\$ ?| ?\$$)/g, '').replace(/^HeadURL: https:/g, 'http:');}) !} 39 | 40 |
Location:
41 | 42 |
{+location+}
43 |
44 |
45 |
46 |
47 |
48 |
49 | 50 |
51 |
52 | ©{+JSDOC.opt.D.copyright+}
53 | Documentation generated by JsDoc Toolkit {+JSDOC.VERSION+} on {+new Date()+} 54 |
55 | 56 | -------------------------------------------------------------------------------- /docs/api_template/index.tmpl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | QuarkJS API Reference 7 | 8 | 9 | 10 | 29 | 30 | 31 | 32 | 33 | {+include("static/header.html")+} 34 | 35 |
36 |
37 |
38 | {+publish.classesIndex+} 39 |
40 |
41 |

全部类


42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | {! 54 | if (thisClass.alias != "_global_") 55 | { 56 | output += ""; 61 | } 62 | !} 63 | 64 | 65 | 66 |

说明

"; 57 | output += new Link().toSymbol(thisClass.alias); 58 | output += "

"; 59 | output += resolveLinks(summarize(thisClass.classDesc)); 60 | output += "
67 | 68 |
69 |
70 | 71 |
72 | 75 | 76 |
77 | 78 | 79 | 80 | 81 | -------------------------------------------------------------------------------- /docs/api_template/publish.js: -------------------------------------------------------------------------------- 1 | /** Called automatically by JsDoc Toolkit. */ 2 | function publish(symbolSet) { 3 | publish.conf = { // trailing slash expected for dirs 4 | ext: ".html", 5 | outDir: JSDOC.opt.d || SYS.pwd+"../out/jsdoc/", 6 | templatesDir: JSDOC.opt.t || SYS.pwd+"../templates/jsdoc/", 7 | symbolsDir: "symbols/", 8 | srcDir: "symbols/src/" 9 | }; 10 | 11 | // is source output is suppressed, just display the links to the source file 12 | if (JSDOC.opt.s && defined(Link) && Link.prototype._makeSrcLink) { 13 | Link.prototype._makeSrcLink = function(srcFilePath) { 14 | return "<"+srcFilePath+">"; 15 | } 16 | } 17 | 18 | // create the folders and subfolders to hold the output 19 | IO.mkPath((publish.conf.outDir+"symbols/src").split("/")); 20 | 21 | // used to allow Link to check the details of things being linked to 22 | Link.symbolSet = symbolSet; 23 | 24 | // create the required templates 25 | try { 26 | var classTemplate = new JSDOC.JsPlate(publish.conf.templatesDir+"class.tmpl"); 27 | var classesTemplate = new JSDOC.JsPlate(publish.conf.templatesDir+"allclasses.tmpl"); 28 | } 29 | catch(e) { 30 | print("Couldn't create the required templates: "+e); 31 | quit(); 32 | } 33 | 34 | // some ustility filters 35 | function hasNoParent($) {return ($.memberOf == "")} 36 | function isaFile($) {return ($.is("FILE"))} 37 | function isaClass($) {return ($.is("CONSTRUCTOR") || $.isNamespace)} 38 | 39 | // get an array version of the symbolset, useful for filtering 40 | var symbols = symbolSet.toArray(); 41 | 42 | // create the hilited source code files 43 | var files = JSDOC.opt.srcFiles; 44 | for (var i = 0, l = files.length; i < l; i++) { 45 | var file = files[i]; 46 | var srcDir = publish.conf.outDir + "symbols/src/"; 47 | makeSrcFile(file, srcDir); 48 | } 49 | 50 | // get a list of all the classes in the symbolset 51 | var classes = symbols.filter(isaClass).sort(makeSortby("alias")); 52 | 53 | // create a filemap in which outfiles must be to be named uniquely, ignoring case 54 | if (JSDOC.opt.u) { 55 | var filemapCounts = {}; 56 | Link.filemap = {}; 57 | for (var i = 0, l = classes.length; i < l; i++) { 58 | var lcAlias = classes[i].alias.toLowerCase(); 59 | 60 | if (!filemapCounts[lcAlias]) filemapCounts[lcAlias] = 1; 61 | else filemapCounts[lcAlias]++; 62 | 63 | Link.filemap[classes[i].alias] = 64 | (filemapCounts[lcAlias] > 1)? 65 | lcAlias+"_"+filemapCounts[lcAlias] : lcAlias; 66 | } 67 | } 68 | 69 | // create a class index, displayed in the left-hand column of every class page 70 | Link.base = "../"; 71 | publish.classesIndex = classesTemplate.process(classes); // kept in memory 72 | 73 | // create each of the class pages 74 | for (var i = 0, l = classes.length; i < l; i++) { 75 | var symbol = classes[i]; 76 | 77 | symbol.events = symbol.getEvents(); // 1 order matters 78 | symbol.methods = symbol.getMethods(); // 2 79 | 80 | Link.currentSymbol= symbol; 81 | var output = ""; 82 | output = classTemplate.process(symbol); 83 | 84 | IO.saveFile(publish.conf.outDir+"symbols/", ((JSDOC.opt.u)? Link.filemap[symbol.alias] : symbol.alias) + publish.conf.ext, output); 85 | } 86 | 87 | // regenerate the index with different relative links, used in the index pages 88 | Link.base = ""; 89 | publish.classesIndex = classesTemplate.process(classes); 90 | 91 | // create the class index page 92 | try { 93 | var classesindexTemplate = new JSDOC.JsPlate(publish.conf.templatesDir+"index.tmpl"); 94 | } 95 | catch(e) { print(e.message); quit(); } 96 | 97 | var classesIndex = classesindexTemplate.process(classes); 98 | IO.saveFile(publish.conf.outDir, "index"+publish.conf.ext, classesIndex); 99 | classesindexTemplate = classesIndex = classes = null; 100 | 101 | // create the file index page 102 | try { 103 | var fileindexTemplate = new JSDOC.JsPlate(publish.conf.templatesDir+"allfiles.tmpl"); 104 | } 105 | catch(e) { print(e.message); quit(); } 106 | 107 | var documentedFiles = symbols.filter(isaFile); // files that have file-level docs 108 | var allFiles = []; // not all files have file-level docs, but we need to list every one 109 | 110 | for (var i = 0; i < files.length; i++) { 111 | allFiles.push(new JSDOC.Symbol(files[i], [], "FILE", new JSDOC.DocComment("/** */"))); 112 | } 113 | 114 | for (var i = 0; i < documentedFiles.length; i++) { 115 | var offset = files.indexOf(documentedFiles[i].alias); 116 | allFiles[offset] = documentedFiles[i]; 117 | } 118 | 119 | allFiles = allFiles.sort(makeSortby("name")); 120 | 121 | // output the file index page 122 | var filesIndex = fileindexTemplate.process(allFiles); 123 | IO.saveFile(publish.conf.outDir, "files"+publish.conf.ext, filesIndex); 124 | fileindexTemplate = filesIndex = files = null; 125 | } 126 | 127 | 128 | /** Just the first sentence (up to a full stop). Should not break on dotted variable names. */ 129 | function summarize(desc) { 130 | if (typeof desc != "undefined") 131 | return desc.match(/([\w\W]+?\.)[^a-z0-9_$]/i)? RegExp.$1 : desc; 132 | } 133 | 134 | /** Make a symbol sorter by some attribute. */ 135 | function makeSortby(attribute) { 136 | return function(a, b) { 137 | if (a[attribute] != undefined && b[attribute] != undefined) { 138 | a = a[attribute].toLowerCase(); 139 | b = b[attribute].toLowerCase(); 140 | if (a < b) return -1; 141 | if (a > b) return 1; 142 | return 0; 143 | } 144 | } 145 | } 146 | 147 | /** Pull in the contents of an external file at the given path. */ 148 | function include(path) { 149 | var path = publish.conf.templatesDir+path; 150 | return IO.readFile(path); 151 | } 152 | 153 | /** Turn a raw source file into a code-hilited page in the docs. */ 154 | function makeSrcFile(path, srcDir, name) { 155 | if (JSDOC.opt.s) return; 156 | 157 | if (!name) { 158 | name = path.replace(/\.\.?[\\\/]/g, "").replace(/[\\\/]/g, "_"); 159 | name = name.replace(/\:/g, "_"); 160 | } 161 | 162 | var src = {path: path, name:name, charset: IO.encoding, hilited: ""}; 163 | 164 | if (defined(JSDOC.PluginManager)) { 165 | JSDOC.PluginManager.run("onPublishSrc", src); 166 | } 167 | 168 | if (src.hilited) { 169 | IO.saveFile(srcDir, name+publish.conf.ext, src.hilited); 170 | } 171 | } 172 | 173 | /** Build output for displaying function parameters. */ 174 | function makeSignature(params) { 175 | if (!params) return "()"; 176 | var signature = "(" 177 | + 178 | params.filter( 179 | function($) { 180 | return $.name.indexOf(".") == -1; // don't show config params in signature 181 | } 182 | ).map( 183 | function($) { 184 | return $.name; 185 | } 186 | ).join(", ") 187 | + 188 | ")"; 189 | return signature; 190 | } 191 | 192 | /** Find symbol {@link ...} strings in text and turn into html links */ 193 | function resolveLinks(str, from) { 194 | str = str.replace(/\{@link ([^} ]+) ?\}/gi, 195 | function(match, symbolName) { 196 | return new Link().toSymbol(symbolName); 197 | } 198 | ); 199 | 200 | return str; 201 | } 202 | -------------------------------------------------------------------------------- /docs/api_template/static/default.css: -------------------------------------------------------------------------------- 1 | /* default.css */ 2 | body 3 | { 4 | font: 12px Tahoma, Arial, sans-serif; 5 | margin: 0; 6 | padding: 0; 7 | } 8 | 9 | #header 10 | { 11 | clear: both; 12 | background: -moz-linear-gradient(top, #2969ad, #184073); 13 | background: -webkit-gradient(linear, 0 0, 0 bottom, from(#2969ad), to(#184073)); 14 | background: -o-linear-gradient(top, #2969ad, #184073); 15 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#2969ad, endColorstr=#184073); 16 | height: 70px; 17 | margin-bottom: 20px; 18 | } 19 | 20 | #header a 21 | { 22 | color: #222; 23 | display: block; 24 | text-decoration: none; 25 | height: 18px; 26 | } 27 | 28 | a 29 | { 30 | color: #222; 31 | } 32 | 33 | a:hover 34 | { 35 | color: #999; 36 | text-decoration:none; 37 | } 38 | 39 | h1 40 | { 41 | font-size: 150%; 42 | font-weight: bold; 43 | padding: 0; 44 | } 45 | 46 | hr 47 | { 48 | border: none 0; 49 | border-top: 1px solid #1c4b88; 50 | height: 1px; 51 | } 52 | 53 | pre.code 54 | { 55 | display: block; 56 | padding: 8px; 57 | border: 1px dashed #ccc; 58 | } 59 | 60 | #index 61 | { 62 | float: left; 63 | width: 200px; 64 | position: absolute; 65 | left: 10px; 66 | background-color: #F3F3F3; 67 | padding: 0px; 68 | } 69 | 70 | #content 71 | { 72 | margin: 0 8px 0 240px; 73 | } 74 | 75 | .classList 76 | { 77 | list-style-type: none; 78 | padding: 0; 79 | margin: 0 0 0 8px; 80 | font-family: arial, sans-serif; 81 | font-size: 1em; 82 | overflow: auto; 83 | } 84 | 85 | .classList li 86 | { 87 | padding: 0; 88 | margin: 0 0 8px 0; 89 | } 90 | 91 | .summaryTable { width: 100%; } 92 | 93 | h1.classTitle 94 | { 95 | font-size:170%; 96 | line-height:130%; 97 | } 98 | 99 | h2 { font-size: 110%; } 100 | caption, div.sectionTitle 101 | { 102 | background-color: #1c4b88; 103 | color: #fff; 104 | font-size:130%; 105 | text-align: left; 106 | padding: 2px 6px 2px 6px; 107 | border: 1px #1c4b88 solid; 108 | } 109 | 110 | div.sectionTitle { margin-bottom: 8px; } 111 | .summaryTable thead { display: none; } 112 | 113 | .summaryTable td 114 | { 115 | vertical-align: top; 116 | padding: 4px; 117 | border-bottom: 1px #1c4b88 solid; 118 | border-right: 1px #1c4b88 solid; 119 | } 120 | 121 | /*col#summaryAttributes {}*/ 122 | .summaryTable td.attributes 123 | { 124 | border-left: 1px #1c4b88 solid; 125 | width: 140px; 126 | text-align: right; 127 | } 128 | 129 | td.attributes, .fixedFont 130 | { 131 | line-height: 15px; 132 | color: #1c4b88; 133 | font-family: "Courier New",Courier,monospace; 134 | font-size: 13px; 135 | } 136 | 137 | .summaryTable td.nameDescription 138 | { 139 | text-align: left; 140 | font-size: 13px; 141 | line-height: 15px; 142 | } 143 | 144 | .summaryTable td.nameDescription, .description 145 | { 146 | line-height: 15px; 147 | padding: 4px; 148 | padding-left: 4px; 149 | } 150 | 151 | .summaryTable { margin-bottom: 8px; } 152 | 153 | ul.inheritsList 154 | { 155 | list-style: square; 156 | margin-left: 20px; 157 | padding-left: 0; 158 | } 159 | 160 | .detailList { 161 | margin-left: 20px; 162 | line-height: 15px; 163 | } 164 | .detailList dt { margin-left: 20px; } 165 | 166 | .detailList .heading 167 | { 168 | font-weight: bold; 169 | padding-bottom: 6px; 170 | margin-left: 0; 171 | } 172 | 173 | .light, td.attributes, .light a:link, .light a:visited 174 | { 175 | color: #777; 176 | font-style: italic; 177 | } 178 | 179 | .fineprint 180 | { 181 | margin-top: 20px; 182 | margin-bottom: 5px; 183 | text-align: center; 184 | font-size: 10px; 185 | } -------------------------------------------------------------------------------- /docs/api_template/static/header.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/api_template/static/index.html: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | Generated Javascript Documentation 7 | 8 | 9 | 10 | 11 | 12 | <body> 13 | <p> 14 | This document is designed to be viewed using the frames feature. If you see this message, you are using a non-frame-capable web client. 15 | </p> 16 | </body> 17 | 18 | 19 | -------------------------------------------------------------------------------- /docs/api_template/symbol.tmpl: -------------------------------------------------------------------------------- 1 | 2 | {+data.name+} 3 | {+data.memberOf+} 4 | {+data.isStatic+} 5 | {+data.isa+} 6 | {+data.desc+} 7 | {+data.classDesc+} 8 | 9 | 10 | 11 | {+method.name+} 12 | {+method.memberOf+} 13 | {+method.isStatic+} 14 | {+method.desc+} 15 | 16 | 17 | {+param.type+} 18 | {+param.name+} 19 | {+param.desc+} 20 | {+param.defaultValue+} 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | {+property.name+} 29 | {+property.memberOf+} 30 | {+property.isStatic+} 31 | {+property.desc+} 32 | {+property.type+} 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /docs/css/bootstrap-responsive.min.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * Bootstrap Responsive v2.0.4 3 | * 4 | * Copyright 2012 Twitter, Inc 5 | * Licensed under the Apache License v2.0 6 | * http://www.apache.org/licenses/LICENSE-2.0 7 | * 8 | * Designed and built with all the love in the world @twitter by @mdo and @fat. 9 | */.clearfix{*zoom:1}.clearfix:before,.clearfix:after{display:table;content:""}.clearfix:after{clear:both}.hide-text{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.input-block-level{display:block;width:100%;min-height:28px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;-ms-box-sizing:border-box;box-sizing:border-box}.hidden{display:none;visibility:hidden}.visible-phone{display:none!important}.visible-tablet{display:none!important}.hidden-desktop{display:none!important}@media(max-width:767px){.visible-phone{display:inherit!important}.hidden-phone{display:none!important}.hidden-desktop{display:inherit!important}.visible-desktop{display:none!important}}@media(min-width:768px) and (max-width:979px){.visible-tablet{display:inherit!important}.hidden-tablet{display:none!important}.hidden-desktop{display:inherit!important}.visible-desktop{display:none!important}}@media(max-width:480px){.nav-collapse{-webkit-transform:translate3d(0,0,0)}.page-header h1 small{display:block;line-height:18px}input[type="checkbox"],input[type="radio"]{border:1px solid #ccc}.form-horizontal .control-group>label{float:none;width:auto;padding-top:0;text-align:left}.form-horizontal .controls{margin-left:0}.form-horizontal .control-list{padding-top:0}.form-horizontal .form-actions{padding-right:10px;padding-left:10px}.modal{position:absolute;top:10px;right:10px;left:10px;width:auto;margin:0}.modal.fade.in{top:auto}.modal-header .close{padding:10px;margin:-10px}.carousel-caption{position:static}}@media(max-width:767px){body{padding-right:20px;padding-left:20px}.navbar-fixed-top,.navbar-fixed-bottom{margin-right:-20px;margin-left:-20px}.container-fluid{padding:0}.dl-horizontal dt{float:none;width:auto;clear:none;text-align:left}.dl-horizontal dd{margin-left:0}.container{width:auto}.row-fluid{width:100%}.row,.thumbnails{margin-left:0}[class*="span"],.row-fluid [class*="span"]{display:block;float:none;width:auto;margin-left:0}.input-large,.input-xlarge,.input-xxlarge,input[class*="span"],select[class*="span"],textarea[class*="span"],.uneditable-input{display:block;width:100%;min-height:28px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;-ms-box-sizing:border-box;box-sizing:border-box}.input-prepend input,.input-append input,.input-prepend input[class*="span"],.input-append input[class*="span"]{display:inline-block;width:auto}}@media(min-width:768px) and (max-width:979px){.row{margin-left:-20px;*zoom:1}.row:before,.row:after{display:table;content:""}.row:after{clear:both}[class*="span"]{float:left;margin-left:20px}.container,.navbar-fixed-top .container,.navbar-fixed-bottom .container{width:724px}.span12{width:724px}.span11{width:662px}.span10{width:600px}.span9{width:538px}.span8{width:476px}.span7{width:414px}.span6{width:352px}.span5{width:290px}.span4{width:228px}.span3{width:166px}.span2{width:104px}.span1{width:42px}.offset12{margin-left:764px}.offset11{margin-left:702px}.offset10{margin-left:640px}.offset9{margin-left:578px}.offset8{margin-left:516px}.offset7{margin-left:454px}.offset6{margin-left:392px}.offset5{margin-left:330px}.offset4{margin-left:268px}.offset3{margin-left:206px}.offset2{margin-left:144px}.offset1{margin-left:82px}.row-fluid{width:100%;*zoom:1}.row-fluid:before,.row-fluid:after{display:table;content:""}.row-fluid:after{clear:both}.row-fluid [class*="span"]{display:block;float:left;width:100%;min-height:28px;margin-left:2.762430939%;*margin-left:2.709239449638298%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;-ms-box-sizing:border-box;box-sizing:border-box}.row-fluid [class*="span"]:first-child{margin-left:0}.row-fluid .span12{width:99.999999993%;*width:99.9468085036383%}.row-fluid .span11{width:91.436464082%;*width:91.38327259263829%}.row-fluid .span10{width:82.87292817100001%;*width:82.8197366816383%}.row-fluid .span9{width:74.30939226%;*width:74.25620077063829%}.row-fluid .span8{width:65.74585634900001%;*width:65.6926648596383%}.row-fluid .span7{width:57.182320438000005%;*width:57.129128948638304%}.row-fluid .span6{width:48.618784527%;*width:48.5655930376383%}.row-fluid .span5{width:40.055248616%;*width:40.0020571266383%}.row-fluid .span4{width:31.491712705%;*width:31.4385212156383%}.row-fluid .span3{width:22.928176794%;*width:22.874985304638297%}.row-fluid .span2{width:14.364640883%;*width:14.311449393638298%}.row-fluid .span1{width:5.801104972%;*width:5.747913482638298%}input,textarea,.uneditable-input{margin-left:0}input.span12,textarea.span12,.uneditable-input.span12{width:714px}input.span11,textarea.span11,.uneditable-input.span11{width:652px}input.span10,textarea.span10,.uneditable-input.span10{width:590px}input.span9,textarea.span9,.uneditable-input.span9{width:528px}input.span8,textarea.span8,.uneditable-input.span8{width:466px}input.span7,textarea.span7,.uneditable-input.span7{width:404px}input.span6,textarea.span6,.uneditable-input.span6{width:342px}input.span5,textarea.span5,.uneditable-input.span5{width:280px}input.span4,textarea.span4,.uneditable-input.span4{width:218px}input.span3,textarea.span3,.uneditable-input.span3{width:156px}input.span2,textarea.span2,.uneditable-input.span2{width:94px}input.span1,textarea.span1,.uneditable-input.span1{width:32px}}@media(min-width:1200px){.row{margin-left:-30px;*zoom:1}.row:before,.row:after{display:table;content:""}.row:after{clear:both}[class*="span"]{float:left;margin-left:30px}.container,.navbar-fixed-top .container,.navbar-fixed-bottom .container{width:1170px}.span12{width:1170px}.span11{width:1070px}.span10{width:970px}.span9{width:870px}.span8{width:770px}.span7{width:670px}.span6{width:570px}.span5{width:470px}.span4{width:370px}.span3{width:270px}.span2{width:170px}.span1{width:70px}.offset12{margin-left:1230px}.offset11{margin-left:1130px}.offset10{margin-left:1030px}.offset9{margin-left:930px}.offset8{margin-left:830px}.offset7{margin-left:730px}.offset6{margin-left:630px}.offset5{margin-left:530px}.offset4{margin-left:430px}.offset3{margin-left:330px}.offset2{margin-left:230px}.offset1{margin-left:130px}.row-fluid{width:100%;*zoom:1}.row-fluid:before,.row-fluid:after{display:table;content:""}.row-fluid:after{clear:both}.row-fluid [class*="span"]{display:block;float:left;width:100%;min-height:28px;margin-left:2.564102564%;*margin-left:2.510911074638298%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;-ms-box-sizing:border-box;box-sizing:border-box}.row-fluid [class*="span"]:first-child{margin-left:0}.row-fluid .span12{width:100%;*width:99.94680851063829%}.row-fluid .span11{width:91.45299145300001%;*width:91.3997999636383%}.row-fluid .span10{width:82.905982906%;*width:82.8527914166383%}.row-fluid .span9{width:74.358974359%;*width:74.30578286963829%}.row-fluid .span8{width:65.81196581200001%;*width:65.7587743226383%}.row-fluid .span7{width:57.264957265%;*width:57.2117657756383%}.row-fluid .span6{width:48.717948718%;*width:48.6647572286383%}.row-fluid .span5{width:40.170940171000005%;*width:40.117748681638304%}.row-fluid .span4{width:31.623931624%;*width:31.5707401346383%}.row-fluid .span3{width:23.076923077%;*width:23.0237315876383%}.row-fluid .span2{width:14.529914530000001%;*width:14.4767230406383%}.row-fluid .span1{width:5.982905983%;*width:5.929714493638298%}input,textarea,.uneditable-input{margin-left:0}input.span12,textarea.span12,.uneditable-input.span12{width:1160px}input.span11,textarea.span11,.uneditable-input.span11{width:1060px}input.span10,textarea.span10,.uneditable-input.span10{width:960px}input.span9,textarea.span9,.uneditable-input.span9{width:860px}input.span8,textarea.span8,.uneditable-input.span8{width:760px}input.span7,textarea.span7,.uneditable-input.span7{width:660px}input.span6,textarea.span6,.uneditable-input.span6{width:560px}input.span5,textarea.span5,.uneditable-input.span5{width:460px}input.span4,textarea.span4,.uneditable-input.span4{width:360px}input.span3,textarea.span3,.uneditable-input.span3{width:260px}input.span2,textarea.span2,.uneditable-input.span2{width:160px}input.span1,textarea.span1,.uneditable-input.span1{width:60px}.thumbnails{margin-left:-30px}.thumbnails>li{margin-left:30px}.row-fluid .thumbnails{margin-left:0}}@media(max-width:979px){body{padding-top:0}.navbar-fixed-top,.navbar-fixed-bottom{position:static}.navbar-fixed-top{margin-bottom:18px}.navbar-fixed-bottom{margin-top:18px}.navbar-fixed-top .navbar-inner,.navbar-fixed-bottom .navbar-inner{padding:5px}.navbar .container{width:auto;padding:0}.navbar .brand{padding-right:10px;padding-left:10px;margin:0 0 0 -5px}.nav-collapse{clear:both}.nav-collapse .nav{float:none;margin:0 0 9px}.nav-collapse .nav>li{float:none}.nav-collapse .nav>li>a{margin-bottom:2px}.nav-collapse .nav>.divider-vertical{display:none}.nav-collapse .nav .nav-header{color:#999;text-shadow:none}.nav-collapse .nav>li>a,.nav-collapse .dropdown-menu a{padding:6px 15px;font-weight:bold;color:#999;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}.nav-collapse .btn{padding:4px 10px 4px;font-weight:normal;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.nav-collapse .dropdown-menu li+li a{margin-bottom:2px}.nav-collapse .nav>li>a:hover,.nav-collapse .dropdown-menu a:hover{background-color:#222}.nav-collapse.in .btn-group{padding:0;margin-top:5px}.nav-collapse .dropdown-menu{position:static;top:auto;left:auto;display:block;float:none;max-width:none;padding:0;margin:0 15px;background-color:transparent;border:0;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none}.nav-collapse .dropdown-menu:before,.nav-collapse .dropdown-menu:after{display:none}.nav-collapse .dropdown-menu .divider{display:none}.nav-collapse .navbar-form,.nav-collapse .navbar-search{float:none;padding:9px 15px;margin:9px 0;border-top:1px solid #222;border-bottom:1px solid #222;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.1);-moz-box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.1);box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.1)}.navbar .nav-collapse .nav.pull-right{float:none;margin-left:0}.nav-collapse,.nav-collapse.collapse{height:0;overflow:hidden}.navbar .btn-navbar{display:block}.navbar-static .navbar-inner{padding-right:10px;padding-left:10px}}@media(min-width:980px){.nav-collapse.collapse{height:auto!important;overflow:visible!important}} 10 | -------------------------------------------------------------------------------- /docs/css/prettify.css: -------------------------------------------------------------------------------- 1 | .com { color: #93a1a1; } 2 | .lit { color: #195f91; } 3 | .pun, .opn, .clo { color: #93a1a1; } 4 | .fun { color: #dc322f; } 5 | .str, .atv { color: #D14; } 6 | .kwd, .linenums .tag { color: #1e347b; } 7 | .typ, .atn, .dec, .var { color: teal; } 8 | .pln { color: #48484c; } 9 | 10 | .prettyprint { 11 | padding: 8px; 12 | background-color: #f7f7f9; 13 | border: 1px solid #e1e1e8; 14 | } 15 | .prettyprint.linenums { 16 | -webkit-box-shadow: inset 40px 0 0 #fbfbfc, inset 41px 0 0 #ececf0; 17 | -moz-box-shadow: inset 40px 0 0 #fbfbfc, inset 41px 0 0 #ececf0; 18 | box-shadow: inset 40px 0 0 #fbfbfc, inset 41px 0 0 #ececf0; 19 | } 20 | 21 | /* Specify class=linenums on a pre to get line numbering */ 22 | ol.linenums { 23 | margin: 0 0 0 33px; /* IE indents via margin-left */ 24 | } 25 | ol.linenums li { 26 | padding-left: 12px; 27 | color: #bebec5; 28 | line-height: 18px; 29 | text-shadow: 0 1px 0 #fff; 30 | } -------------------------------------------------------------------------------- /docs/demo.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | QuarkJS - An HTML5 Game Framework 7 | 8 | 9 | 10 | 11 | 12 | 13 | 22 | 23 | 24 | 25 | 26 | 29 | 30 | 31 | 32 | 33 | 54 | 55 |
56 | 57 |

作品演示



58 | 88 | 89 |

说明:带*的作品由QuarkJS的老版本CasualJS开发。

90 |
91 | 92 | 95 | 96 |
97 | 98 | 99 | 100 | 101 | 102 | 103 | -------------------------------------------------------------------------------- /docs/images/displayobject.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quark-dev-team/quarkjs/54eb61256ef60cbc15398c544afffb61f5c907ac/docs/images/displayobject.jpg -------------------------------------------------------------------------------- /docs/images/displayobject_lifecircle.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quark-dev-team/quarkjs/54eb61256ef60cbc15398c544afffb61f5c907ac/docs/images/displayobject_lifecircle.jpg -------------------------------------------------------------------------------- /docs/images/dolphin_260.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quark-dev-team/quarkjs/54eb61256ef60cbc15398c544afffb61f5c907ac/docs/images/dolphin_260.jpg -------------------------------------------------------------------------------- /docs/images/dolphin_main_s.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quark-dev-team/quarkjs/54eb61256ef60cbc15398c544afffb61f5c907ac/docs/images/dolphin_main_s.jpg -------------------------------------------------------------------------------- /docs/images/dolphin_startup_s.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quark-dev-team/quarkjs/54eb61256ef60cbc15398c544afffb61f5c907ac/docs/images/dolphin_startup_s.jpg -------------------------------------------------------------------------------- /docs/images/fishjoy_260.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quark-dev-team/quarkjs/54eb61256ef60cbc15398c544afffb61f5c907ac/docs/images/fishjoy_260.jpg -------------------------------------------------------------------------------- /docs/images/infrastructure.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quark-dev-team/quarkjs/54eb61256ef60cbc15398c544afffb61f5c907ac/docs/images/infrastructure.jpg -------------------------------------------------------------------------------- /docs/images/logo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quark-dev-team/quarkjs/54eb61256ef60cbc15398c544afffb61f5c907ac/docs/images/logo.jpg -------------------------------------------------------------------------------- /docs/images/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quark-dev-team/quarkjs/54eb61256ef60cbc15398c544afffb61f5c907ac/docs/images/logo.png -------------------------------------------------------------------------------- /docs/images/mine_260.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quark-dev-team/quarkjs/54eb61256ef60cbc15398c544afffb61f5c907ac/docs/images/mine_260.jpg -------------------------------------------------------------------------------- /docs/images/quark.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quark-dev-team/quarkjs/54eb61256ef60cbc15398c544afffb61f5c907ac/docs/images/quark.jpg -------------------------------------------------------------------------------- /docs/images/runner_260.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quark-dev-team/quarkjs/54eb61256ef60cbc15398c544afffb61f5c907ac/docs/images/runner_260.jpg -------------------------------------------------------------------------------- /docs/img/glyphicons-halflings-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quark-dev-team/quarkjs/54eb61256ef60cbc15398c544afffb61f5c907ac/docs/img/glyphicons-halflings-white.png -------------------------------------------------------------------------------- /docs/img/glyphicons-halflings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quark-dev-team/quarkjs/54eb61256ef60cbc15398c544afffb61f5c907ac/docs/img/glyphicons-halflings.png -------------------------------------------------------------------------------- /docs/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | QuarkJS - An HTML5 Game Framework 7 | 8 | 9 | 10 | 11 | 12 | 13 | 32 | 33 | 34 | 35 | 38 | 39 | 40 | 41 | 42 | 63 | 64 |
65 |
66 |
67 | 76 |
77 | 78 |
79 |
80 |

QuarkJS


81 |

QuarkJS是一个HTML5游戏框架,它的目标是提供一套简单高效的方法创建HTML5游戏。

82 |

它具有以下特性:

83 |
    84 |
  • 面向对象编程模式。
  • 85 |
  • 完整的显示对象架构。使用简单、易于扩展。
  • 86 |
  • 支持Canvas和DOM两种渲染模式。
  • 87 |
  • 兼容各种常见的桌面和移动浏览器。
  • 88 |
89 |
90 |

91 | 查看项目(GitHub)

92 |

93 |
94 | 95 |
96 |
97 | 98 |
99 | 100 | 103 | 104 |
105 | 106 | 107 | 108 | 109 | 110 | -------------------------------------------------------------------------------- /docs/tutorial.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | QuarkJS - An HTML5 Game Framework 7 | 8 | 9 | 10 | 11 | 12 | 13 | 22 | 23 | 24 | 25 | 26 | 29 | 30 | 31 | 32 | 33 | 54 | 55 |
56 |
57 |
58 | 71 |
72 | 73 |
74 | 77 | 78 |
79 |
80 |

1. 下载安装


81 |

到GitHub上下载quarkjs的最新版本:http://github.com/quark-dev-team/quarkjs 82 | 直接下载 »

83 |

然后把quarkjs类库引入到html页面:

84 |
<script src="js/quark.base-1.0.0.js"></script>
85 |
86 | 87 |
88 |

2. 创建渲染上下文


89 |

上下文Context在quark中负责渲染,目前有DOMContext和CanvasContext两种。

90 |
//create a DOMContext
 91 | var container = Quark.getDOM("container");
 92 | var domContext = new Quark.DOMContext({canvas:container});
 93 | 
 94 | //or create a CanvasContext
 95 | var container = Quark.getDOM("container");
 96 | var canvas = Quark.createDOM("canvas", {width:480, height:320, style:
 97 | {
 98 |     position:"absolute",
 99 |     backgroundColor:"#fff"
100 | }});
101 | container.appendChild(canvas);
102 | var canvasContext = new Quark.CanvasContext({canvas:canvas});
103 |
104 | 105 |
106 |

3. 创建舞台


107 |

显示对象通过Context在舞台Stage上被渲染出来。

108 |
var stage = new Quark.Stage({width:480, height:320, context:canvasContext, update:function()
109 | {
110 |     //write your own update code here
111 | }});
112 |
113 | 114 |
115 |

4. 创建计时器


116 |

舞台Stage上的物体的运动等变化,都是通过一个计时器Timer不断地调用Stage.step()方法来实现刷新的。

117 |
var fps = 60;
118 | var timer = new Q.Timer(1000/fps);
119 | timer.addListener(stage);
120 | timer.start();
121 |
122 | 123 |
124 |

5. 注册舞台事件


125 |

要想舞台上的显示对象能响应用户的点击、触碰等交互事件,就必需为舞台注册相应的事件。

126 |
var em = new Quark.EventManager();
127 | var events = Quark.supportTouch ? ["touchstart", "touchmove", "touchend"] : ["mousedown", "mousemove", "mouseup"];
128 | em.registerStage(stage, events);
129 |
130 | 131 |
132 |

6. 准备工作完成


133 |

至此,初始化工作基本完成。你可以开始利用quark提供的各种类和方法来创建各种显示对象。开始创建你的第一个HTML5游戏吧!

134 |
var bmp = new Quark.Bitmap({image:imgElem, rect:[0,0,100,100], update:function()
135 | {
136 |     //update code here
137 | }});
138 | stage.addChild(bmp);
139 |
140 | 141 |
142 |
143 |
144 | 145 |
146 | 147 | 150 | 151 |
152 | 153 | 154 | 155 | 156 | 157 | 158 | -------------------------------------------------------------------------------- /docs/tutorial_context.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | QuarkJS - An HTML5 Game Framework 7 | 8 | 9 | 10 | 11 | 12 | 13 | 22 | 23 | 24 | 25 | 26 | 29 | 30 | 31 | 32 | 33 | 54 | 55 |
56 |
57 |
58 | 71 |
72 | 73 |
74 | 77 | 78 |
79 |
80 |

HTML5提供了一些图形渲染方法,比如Canvas、DIV+CSS3、VML、SVG等。一般的我们使用Canvas,但是在一些移动设备上(如iPhone),Canvas性能还不够好,我们在实际开发中发现DIV+CSS3在某些应用场景中性能更好。因此我们设计了上下文Context来实现不同的渲染方式,类似CanvasRenderingContext2D的设计。

81 |
82 |
83 | 84 |
85 |

  • 使用方法

  • 86 |

    当前,我们有两种上下文:CanvasContext 和 DOMContext。

    87 |

    CanvasContext示例:

    88 |
    var canvas = document.getElementById("myCanvas"); //myCanvas是一个canvas元素
     89 | var context = new Quark.CanvasContext({canvas:canvas});
    90 |

    DOMContext示例:

    91 |
    var container = document.getElementById("container"); //container是一个div元素
     92 | var context = new Quark.DOMContext({canvas:container}); //把container作为canvas参数传给DOMContext
    93 |

    当上下文Context初始化并传给一个舞台stage后,你就可以几乎不用关心它的存在,而集中专注于游戏逻辑的开发。

    94 |
    95 | 96 |
    97 |
    98 |
    99 |
    100 | 101 | 104 | 105 |
    106 | 107 | 108 | 109 | 110 | 111 | 112 | -------------------------------------------------------------------------------- /docs/tutorial_displayobject.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | QuarkJS - An HTML5 Game Framework 7 | 8 | 9 | 10 | 11 | 12 | 13 | 22 | 23 | 24 | 25 | 26 | 29 | 30 | 31 | 32 | 33 | 54 | 55 |
    56 |
    57 |
    58 | 71 |
    72 | 73 |
    74 | 77 | 78 |
    79 | 80 |
    81 |


    82 |
      83 |
    • 显示对象是Quark显示对象列表结构的顶级对象。
    • 84 |
    • Image即图片。一般包括 HTMLImageElement、HTMLCanvasElement 和 HTMLVideoElement。在Quark中图片会被封装成一个Quark.Drawable 的对象。通过 setDrawable() 和 getDrawable() 接口来设置和获取。
    • 85 |
    • Data即数据。包括显示对象的 x、y、width、height、alpha、rotation、visible、scaleX、scaleY、regX、regY、eventEnabled、polyArea等属性以及用户自定义的各种数据。
    • 86 |
    • 可以通过继承扩展不同的显示对象。
    • 87 |
    88 |
    89 |
    90 | 91 |
    92 |

  • 显示对象容器(DisplayObjectContainer)

  • 93 |
      94 |
    • 显示对象容器就是一种可以容纳子对象的显示对象。显示对象和显示对象容器的嵌套就构成了Quark显示对象列表结构。这跟HTML的DOM树结构非常相似。
    • 95 |
    • 舞台Stage是一种特殊的显示对象。他是显示对象结构的根root,总入口。
    • 96 |
    • 显示对象容器通过 addChild() 和 removeChild() 等方法来添加和删除子对象。
    • 97 |
    • 显示对象容器里的子对象采用自动深度管理方法。一般新添加的对象会显示在之前添加的对象之上。可以通过 setChildIndex() 等方法来改变子对象在容器中的索引位置,即深度。
    • 98 |
    • 显示对象容器提供 getObjectUnderPoint() 方法来获得某一点下的子对象。
    • 99 |
    100 |
    101 |
    102 | 103 |
    104 |

  • 显示对象生命周期(DisplayObject LifeCircle)

  • 105 |

    106 |
      107 |
    • 显示对象的生命周期开始于添加到显示对象列表 container.addChild(obj)。
    • 108 |
    • 显示对象的生命周期结束于移除显示对象列表 container.removeChild(obj)。
    • 109 |
    • 在通过 stage.step() 方法刷新舞台的显示对象列表时,会依次循环调用显示对象的 update() 和 render() 方法来实现更新对象数据和渲染。
    • 110 |
    111 |
    112 |
    113 | 114 |
    115 |

  • 显示对象的事件处理机制(Event Mechanism)

  • 116 |
      117 |
    • Quark提供一个简单的 EventManager 来做系统事件的监听和回调,通过 EventManager.registerStage() 方法注册相应的事件如mousedown、touchstart等到舞台,舞台会自动转发给触发事件的显示对象。
    • 118 |
    • 可以通过 obj.addEventListener() 方法让显示对象监听和响应各种事件。
    • 119 |
    120 |
    121 |
    122 | 123 |
    124 |

  • 显示对象的碰撞检测(Object Collision)

  • 125 |
      126 |
    • Quark目前只提供矩形碰撞(Rectangle Collision),暂不支持像素级别的碰撞检测(Pixel Collision)。
    • 127 |
    • 显示对象提供 getBounds() 方法获得其外包围矩形区域。
    • 128 |
    • 显示对象提供 hitTestPoint() 和 hitTestObject() 等方法来做点或对象的碰撞检测。
    • 129 |
    130 |
    131 | 132 |
    133 |
    134 |
    135 | 136 |
    137 | 138 | 141 | 142 |
    143 | 144 | 145 | 146 | 147 | 148 | 149 | -------------------------------------------------------------------------------- /docs/tutorial_event.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | QuarkJS - An HTML5 Game Framework 7 | 8 | 9 | 10 | 11 | 12 | 13 | 22 | 23 | 24 | 25 | 26 | 29 | 30 | 31 | 32 | 33 | 54 | 55 |
    56 |
    57 |
    58 | 71 |
    72 | 73 |
    74 | 77 | 78 |
    79 |
    80 | 81 |
    82 |

  • 使用 Quark.EventManager 注册舞台事件

  • 83 |
    var em = new Q.EventManager();
     84 | var events = Q.supportTouch ? ["touchstart", "touchmove", "touchend"] : ["mousedown", "mousemove", "mouseup"];
     85 | em.registerStage(stage, events);
    86 |
    87 |
    88 | 89 |
    90 |

  • 为显示对象编写事件侦听函数

  • 91 |
    obj.addEventListener("touchend", function(e)
     92 | {
     93 |   //do something
     94 | });
    95 |

    事件侦听函数会接收一个事件参数e,它包含e.eventX,e.eventY,e.eventTarget,e.lastEventTarget等属性。

    96 |
    97 |
    98 | 99 |
    100 |

  • 删除事件侦听

  • 101 |
    //删除指定事件类型的指定侦听函数
    102 | obj.removeEventListener("touchend", touchendHandler);
    103 | 
    104 | //删除指定事件类型的所有侦听函数
    105 | obj.removeEventListener("touchend");
    106 |
    107 |
    108 | 109 |
    110 |

  • 删除舞台事件

  • 111 |
    em.unregisterStage(stage, events);
    112 |
    113 |
    114 | 115 |
    116 |

  • 一些方法的简写

  • 117 |
    obj.on = obj.addEventListener
    118 | obj.un = obj.removeEventListener
    119 | obj.fire = obj.dispatchEvent
    120 |
    121 | 122 | 123 |
    124 |
    125 |
    126 | 127 |
    128 | 129 |
    130 |

    © QuarkJS Dev-Team 2012

    131 |
    132 | 133 |
    134 | 135 | 136 | 137 | 138 | 139 | 140 | -------------------------------------------------------------------------------- /docs/tutorial_infrastructure.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | QuarkJS - An HTML5 Game Framework 7 | 8 | 9 | 10 | 11 | 12 | 13 | 22 | 23 | 24 | 25 | 26 | 29 | 30 | 31 | 32 | 33 | 54 | 55 |
    56 |
    57 |
    58 | 71 |
    72 | 73 |
    74 | 77 | 78 |
    79 |
    80 |

    Quark的基础架构图:


    81 |


    82 |
    83 | 84 |
    85 |

  • 显示对象列表(Display Object List)

  • 86 |
      87 |
    • 显示对象列表是Quark中参照Actionscript3中的显示对象列表设计的一套显示和管理对象的结构。他跟HTML的DOM树结构非常相似。
    • 88 |
    • 显示对象列表的根是舞台stage,可以通过调用 stage.step() 方法来更新显示对象列表。
    • 89 |
    90 |
    91 |
    92 | 93 |
    94 |

  • 上下文(Context)

  • 95 |
      96 |
    • Context在Quark中负责对象的渲染,还包括位移、旋转、缩放等变换。参照CanvasRenderingContext2D的设计思路,我们实现了CanvasContext和DOMContext。
    • 97 |
    • CanvasContext采用canvas渲染,DOMContext采用DOM和CSS的 background 和 transform(3d) 进行渲染。
    • 98 |
    • Context有一个画布canvas属性,这是显示对象将被渲染到的地方。canvas属性是一个 HTMLCanvasElement 或 HTMLDivElement 对象。
    • 99 |
    • Context会被注入到舞台stage里,显示对象列表更新的时候会调用context的 transform() 进行变换,再调用 draw() 方法绘制对象。
    • 100 |
    101 |
    102 |
    103 | 104 |
    105 |

  • 计时器(Timer)

  • 106 |
      107 |
    • Timer是一个计时器。在Quark中用来驱动显示对象列表的更新和渲染。
    • 108 |
    • Timer通过 addListener() 方法来注册侦听器(侦听器需实现 step() 方法)。
    • 109 |
    110 |
    111 |
    112 | 113 |
    114 |

    显示对象列表、上下文、计时器三者分工合作,共同组成了Quark Base的架构。

    115 |
    116 | 117 |
    118 |
    119 |
    120 | 121 |
    122 | 123 |
    124 |

    © QuarkJS Dev-Team 2012

    125 |
    126 | 127 |
    128 | 129 | 130 | 131 | 132 | 133 | 134 | -------------------------------------------------------------------------------- /docs/tutorial_squirrel.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | QuarkJS - An HTML5 Game Framework 7 | 8 | 9 | 10 | 11 | 12 | 13 | 22 | 23 | 24 | 25 | 26 | 29 | 30 | 31 | 32 | 33 | 54 | 55 |
    56 |
    57 |
    58 | 71 |
    72 | 73 |
    74 | 77 | 78 |
    79 |
    80 |

    地址:http://quark-dev-team.github.com/quarkjs/examples/squirrel/squirrel.html

    81 |

    此demo演示了如何使用quark创建一个基本的交互动画。下面将一步一步介绍是如何实现的。

    82 | 83 | 84 |
    85 | 86 |
    87 |

    1. 准备游戏舞台容器


    88 |
    <div id="container" style="position:absolute;left:0;top:0;width:480px;height:320px;background:#eee;"></div>
     89 | <img id="bodyWalk" src="images/body_walk.png" style="display:none;" />
     90 | <img id="headIdle" src="images/head_idle.png" style="display:none;" />
    91 |

    这里的容器就是一个普通的div,并设定好其宽高。另外为了演示方便,我们把项目所需的2个图片素材使用img标签做了预加载。

    92 |
    93 | 94 |
    95 |

    2. 设置游戏的背景


    96 |
    container = Q.getDOM("container");
     97 | container.style.background = "-ms-linear-gradient(top, #00889d, #94d7e1, #58B000)";
     98 | container.style.background = "-moz-linear-gradient(top, #00889d, #94d7e1, #58B000)";
     99 | container.style.background = "-webkit-gradient(linear, 0 0, 0 bottom, from(#00889d), to(#58B000), color-stop(0.5,#94d7e1))";
    100 | container.style.background = "-o-linear-gradient(top, #00889d, #94d7e1, #58B000)";
    101 | container.style.filter = "progid:DXImageTransform.Microsoft.gradient(startColorstr=#00889d, endColorstr=#94d7e1)";
    102 |

    这里使用了css的线性渐变背景。

    103 |
    104 | 105 |
    106 |

    3. 初始化上下文


    107 |
    params = Q.getUrlParams();
    108 | if(params.canvas)
    109 | {
    110 |     var canvas = Quark.createDOM("canvas", {width:480, height:320, style:{position:"absolute",backgroundColor:"#eee"}});
    111 |     container.appendChild(canvas);
    112 |     context = new Quark.CanvasContext({canvas:canvas});
    113 | }else{
    114 |     context = new Quark.DOMContext({canvas:container});
    115 | }
    116 |

    上下文在quark中负责渲染工作。这里可以根据URL参数canvas来选择使用CanvasContext还是DOMContext。

    117 |
    118 | 119 |
    120 |

    4. 初始化舞台


    121 |
    stage = new Q.Stage({context:context, width:480, height:320, 
    122 | update:function()
    123 | {
    124 |   frames++;
    125 | }});
    126 |   
    127 | timer = new Q.Timer(1000/30);
    128 | timer.addListener(stage);
    129 | timer.start();
    130 | 
    131 | em = new Q.EventManager();
    132 | var events = Q.supportTouch ? ["touchend"] : ["mouseup"];
    133 | em.registerStage(stage, events, true, true);
    134 |

    在这一步,我们初始化了一个舞台,并把刚才创建的上下文context传给舞台。这样quark就知道如何把舞台上面的元素渲染出来了。但是舞台默认是静止的,不会主动刷新,因此我们需要一个计时器timer来定时更新舞台,从而驱动整个游戏运行。然后注册舞台事件,使舞台上的元素能接收交互事件,这里只接收touchend和mouseup事件。

    135 |
    136 | 137 |
    138 |

    5. 把小松鼠添加到舞台


    139 |
    squirrel = new Squirrel({id:"squirrel", x:200, y:160, autoSize:true});
    140 | stage.addChild(squirrel);
    141 | 
    142 | squirrel.addEventListener(events[0], squirrel.jump);
    143 |

    创建一只小松鼠,并使用stage.addChild()方法添加到舞台。这里的松鼠类Squirrel是我们预先创建好的,待会再讲解如何创建这个类。通过addEventListener()方法为松鼠添加touchend或mouseup事件侦听,这样玩家就可以控制其跳跃。

    144 |
    145 | 146 |
    147 |

    6. 创建松鼠类Squirrel


    148 |
    var Squirrel = function(props)
    149 | { 
    150 |   Squirrel.superClass.constructor.call(this, props);
    151 |   this.init();
    152 | };
    153 | Q.inherit(Squirrel, Q.DisplayObjectContainer);
    154 |

    Squirrel类是在Squirrel.js文件中实现的。在这里松鼠是由头部和身体两部分组成,因此Squirrel类继承自DisplayObjectContainer容器类。

    155 |
    156 | 157 |
    158 |

    7. 构建松鼠的形象


    159 |
    this.head = new Q.MovieClip({id:"head", image:Q.getDOM("headIdle"), useFrames:true, interval:2, x:5, y:0});
    160 | this.head.addFrame([
    161 | {rect:[0,0,66,56]},
    162 | {rect:[69,0,66,56]},
    163 | {rect:[138,0,66,56]},
    164 | {rect:[207,0,66,56]}]);
    165 | 
    166 | this.body = new Q.MovieClip({id:"body", image:Q.getDOM('bodyWalk'), useFrames:true, interval:2, x:0, y:25});
    167 | this.body.addFrame([
    168 | {rect:[0,0,108,66]},
    169 | {rect:[109,0,108,66]},
    170 | {rect:[218,0,108,66]},
    171 | {rect:[327,0,108,66]},
    172 | {rect:[436,0,108,66]},
    173 | {rect:[545,0,108,66]},
    174 | {rect:[0,70,108,66]},
    175 | {rect:[109,70,108,66]},
    176 | {rect:[218,70,108,66]},
    177 | {rect:[327,70,108,66]},
    178 | {rect:[436,70,108,66]}]);
    179 | 
    180 | this.addChild(this.body, this.head);
    181 |

    松鼠的头部和身体都有各自的动作,因此head和body都采用MovieClip类来实现。再用addChild()方法添加到Squirrel容器类里,这样一只松鼠的形象就组成了。

    182 |
    183 | 184 |
    185 |

    8. 实现松鼠的跳跃逻辑


    186 |
    Squirrel.prototype.jump = function(e)
    187 | {
    188 |   if(!this.jumping) 
    189 |   {
    190 |     this.jumping = true;
    191 |     this.currentSpeedY = this.speedY;
    192 |   }
    193 | };
    194 | 
    195 | Squirrel.prototype.update = function()
    196 | {
    197 |     if(this.jumping)
    198 |     {
    199 |         this.currentSpeedY -= 0.3;
    200 |         this.y -= this.currentSpeedY;
    201 |         if(this.originY <= this.y)
    202 |         {
    203 |             this.y = this.originY;
    204 |             this.jumping = false;
    205 |         }
    206 |     }
    207 | };
    208 |

    为了实现松鼠的跳跃,我们首先创建jump方法,在第5步中可以看到我们把touchend或mouseup事件绑定到了jump方法。然后我们在Squirrel的update方法里实现具体的跳跃逻辑。

    209 |
    210 | 211 |
    212 |
    213 |
    214 | 215 |
    216 | 217 |
    218 |

    © QuarkJS Dev-Team 2012

    219 |
    220 | 221 |
    222 | 223 | 224 | 225 | 226 | 227 | 228 | -------------------------------------------------------------------------------- /examples/button.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Quark Framework Example - Button 7 | 8 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 |
    19 |
    20 | 21 | 22 | 83 | 84 | 85 | -------------------------------------------------------------------------------- /examples/graphics.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Quark Framework Example - Graphics 7 | 8 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 |
    20 |
    21 | 22 | 94 | 95 | 96 | -------------------------------------------------------------------------------- /examples/hittest.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Quark Framework Example - HitTest 7 | 8 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 |
    20 |
    21 | 22 | 23 | 24 | 120 | 121 | 122 | -------------------------------------------------------------------------------- /examples/imageloader.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Quark Framework Example - ImageLoader 6 | 7 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 |
    18 |
    19 | 20 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /examples/images/bg.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quark-dev-team/quarkjs/54eb61256ef60cbc15398c544afffb61f5c907ac/examples/images/bg.jpg -------------------------------------------------------------------------------- /examples/images/boy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quark-dev-team/quarkjs/54eb61256ef60cbc15398c544afffb61f5c907ac/examples/images/boy.png -------------------------------------------------------------------------------- /examples/images/btns.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quark-dev-team/quarkjs/54eb61256ef60cbc15398c544afffb61f5c907ac/examples/images/btns.png -------------------------------------------------------------------------------- /examples/images/girl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quark-dev-team/quarkjs/54eb61256ef60cbc15398c544afffb61f5c907ac/examples/images/girl.png -------------------------------------------------------------------------------- /examples/images/mask.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quark-dev-team/quarkjs/54eb61256ef60cbc15398c544afffb61f5c907ac/examples/images/mask.png -------------------------------------------------------------------------------- /examples/images/turn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quark-dev-team/quarkjs/54eb61256ef60cbc15398c544afffb61f5c907ac/examples/images/turn.png -------------------------------------------------------------------------------- /examples/mask.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Quark Framework Example - DisplayObject Mask 7 | 8 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 |
    20 |
    21 | 22 | 23 | 24 | 118 | 119 | 120 | -------------------------------------------------------------------------------- /examples/simple1.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Quark Framework Example - simple 7 | 8 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 |
    19 |
    20 | 21 | 22 | 23 | 126 | 127 | 128 | -------------------------------------------------------------------------------- /examples/squirrel/Squirrel.js: -------------------------------------------------------------------------------- 1 | 2 | var Squirrel = function(props) 3 | { 4 | Squirrel.superClass.constructor.call(this, props); 5 | this.init(); 6 | }; 7 | Q.inherit(Squirrel, Q.DisplayObjectContainer); 8 | 9 | Squirrel.prototype.init = function() 10 | { 11 | //松鼠的头部,是一个MovieClip类型。 12 | this.head = new Q.MovieClip({id:"head", image:Q.getDOM("headIdle"), useFrames:true, interval:2, x:5, y:0}); 13 | this.head.addFrame([ 14 | {rect:[0,0,66,56]}, 15 | {rect:[69,0,66,56]}, 16 | {rect:[138,0,66,56]}, 17 | {rect:[207,0,66,56]} 18 | ]); 19 | 20 | //松鼠的身体,也是一个MovieClip类型。 21 | this.body = new Q.MovieClip({id:"body", image:Q.getDOM('bodyWalk'), useFrames:true, interval:2, x:0, y:25}); 22 | this.body.addFrame([ 23 | {rect:[0,0,108,66]}, 24 | {rect:[109,0,108,66]}, 25 | {rect:[218,0,108,66]}, 26 | {rect:[327,0,108,66]}, 27 | {rect:[436,0,108,66]}, 28 | {rect:[545,0,108,66]}, 29 | {rect:[0,70,108,66]}, 30 | {rect:[109,70,108,66]}, 31 | {rect:[218,70,108,66]}, 32 | {rect:[327,70,108,66]}, 33 | {rect:[436,70,108,66]} 34 | ]); 35 | 36 | //由头部和身体组成了一只松鼠。 37 | this.addChild(this.body, this.head); 38 | 39 | //初始化数据。 40 | this.eventChildren = false; 41 | this.jumping = false; 42 | this.speedY = this.currentSpeedY = 8; 43 | this.originY = this.y; 44 | }; 45 | 46 | //控制松鼠的跳跃 47 | Squirrel.prototype.jump = function(e) 48 | { 49 | if(!this.jumping) 50 | { 51 | this.jumping = true; 52 | this.currentSpeedY = this.speedY; 53 | } 54 | }; 55 | 56 | //松鼠的更新函数,此方法会不断的被quark系统调用而产生跳跃动画。 57 | Squirrel.prototype.update = function() 58 | { 59 | if(this.jumping) 60 | { 61 | this.currentSpeedY -= 0.3; 62 | this.y -= this.currentSpeedY; 63 | if(this.originY <= this.y) 64 | { 65 | this.y = this.originY; 66 | this.jumping = false; 67 | } 68 | } 69 | }; -------------------------------------------------------------------------------- /examples/squirrel/images/body_walk.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quark-dev-team/quarkjs/54eb61256ef60cbc15398c544afffb61f5c907ac/examples/squirrel/images/body_walk.png -------------------------------------------------------------------------------- /examples/squirrel/images/head_idle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quark-dev-team/quarkjs/54eb61256ef60cbc15398c544afffb61f5c907ac/examples/squirrel/images/head_idle.png -------------------------------------------------------------------------------- /examples/squirrel/squirrel.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Squirrel - Quark Framework Tutorials 7 | 8 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 |
    20 |
    21 | 22 | 23 | 24 | 96 | 97 | 98 | -------------------------------------------------------------------------------- /examples/text.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Quark Framework Example - DisplayObject Mask 7 | 8 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 |
    19 |
    20 | 21 | 22 | 96 | 97 | 98 | -------------------------------------------------------------------------------- /examples/tween1.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Quark Framework Example - Tween 7 | 8 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 |
    19 |
    20 | 21 | 22 | 23 |
    24 |
    25 | 26 | 82 | 83 | 84 | -------------------------------------------------------------------------------- /examples/tween2.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Quark Framework Example - Tween 7 | 8 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 |
    19 |
    20 | 21 | 22 | 23 | 24 | 83 | 84 | 85 | -------------------------------------------------------------------------------- /src/base/context/CanvasContext.js: -------------------------------------------------------------------------------- 1 | 2 | (function(){ 3 | 4 | /** 5 | * 构造函数. 6 | * @name CanvasContext 7 | * @augments Context 8 | * @class CanvasContext是Canvas渲染上下文,将显示对象渲染到指定的Canvas上。 9 | * @param {Object} props 一个对象。包含以下属性: 10 | *

    canvas - 渲染上下文所对应的canvas,HTMLCanvasElement对象。

    11 | */ 12 | var CanvasContext = Quark.CanvasContext = function(props) 13 | { 14 | CanvasContext.superClass.constructor.call(this, props); 15 | this.context = this.canvas.getContext("2d"); 16 | }; 17 | Quark.inherit(CanvasContext, Quark.Context); 18 | 19 | /** 20 | * 准备绘制,保存当前上下文。 21 | */ 22 | CanvasContext.prototype.startDraw = function() 23 | { 24 | this.context.save(); 25 | }; 26 | 27 | /** 28 | * 绘制指定的显示对象到Canvas上。 29 | * @param {DisplayObject} target 要绘制的显示对象。 30 | */ 31 | CanvasContext.prototype.draw = function(target) 32 | { 33 | //ignore children drawing if the parent has a mask. 34 | if(target.parent != null && target.parent.mask != null) return; 35 | 36 | if(target.mask != null) 37 | { 38 | //we implements the mask function by using 'source-in' composite operation. 39 | //so can't draw objects with masks into this canvas directly. 40 | var w = target.width, h = target.height; 41 | var context = Q._helpContext, canvas = context.canvas, ctx = context.context; 42 | canvas.width = 0; 43 | canvas.width = w; 44 | canvas.height = h; 45 | context.startDraw(); 46 | target.mask._render(context); 47 | ctx.globalCompositeOperation = 'source-in'; 48 | 49 | //this is a trick for ignoring mask drawing during object drawing. 50 | var mask = target.mask; 51 | target.mask = null; 52 | if(target instanceof Quark.DisplayObjectContainer) 53 | { 54 | //container's children should draw at once in 'source-in' mode. 55 | var cache = target._cache || Quark.cacheObject(target); 56 | ctx.drawImage(cache, 0, 0, w, h, 0, 0, w, h); 57 | }else 58 | { 59 | target.render(context); 60 | } 61 | context.endDraw(); 62 | target.mask = mask; 63 | 64 | arguments[0] = canvas; 65 | this.context.drawImage.apply(this.context, arguments); 66 | }else if(target._cache != null) 67 | { 68 | //draw cache if exist 69 | this.context.drawImage(target._cache, 0, 0); 70 | }else if(target instanceof Quark.Graphics || target instanceof Quark.Text) 71 | { 72 | //special drawing 73 | target._draw(this.context); 74 | }else 75 | { 76 | //normal draw 77 | var img = target.getDrawable(this); 78 | if(img != null) 79 | { 80 | arguments[0] = img; 81 | this.context.drawImage.apply(this.context, arguments); 82 | } 83 | } 84 | }; 85 | 86 | /** 87 | * 绘制完毕,恢复上下文。 88 | */ 89 | CanvasContext.prototype.endDraw = function() 90 | { 91 | this.context.restore(); 92 | }; 93 | 94 | /** 95 | * 对指定的显示对象进行context属性设置或变换。 96 | * @param {DisplayObject} target 要进行属性设置或变换的显示对象。 97 | */ 98 | CanvasContext.prototype.transform = function(target) 99 | { 100 | var ctx = this.context; 101 | 102 | if(target instanceof Q.Stage) 103 | { 104 | //Use style for stage scaling 105 | if(target._scaleX != target.scaleX) 106 | { 107 | target._scaleX = target.scaleX; 108 | this.canvas.style.width = target._scaleX * target.width + "px"; 109 | } 110 | if(target._scaleY != target.scaleY) 111 | { 112 | target._scaleY = target.scaleY; 113 | this.canvas.style.height = target._scaleY * target.height + "px"; 114 | } 115 | }else 116 | { 117 | if(target.x != 0 || target.y != 0) ctx.translate(target.x, target.y); 118 | if(target.rotation%360 != 0) ctx.rotate(target.rotation%360*Quark.DEG_TO_RAD); 119 | if(target.scaleX != 1 || target.scaleY != 1) ctx.scale(target.scaleX, target.scaleY); 120 | if(target.regX != 0 || target.regY != 0) ctx.translate(-target.regX, -target.regY); 121 | } 122 | 123 | if(target.alpha > 0) ctx.globalAlpha *= target.alpha; 124 | }; 125 | 126 | /** 127 | * 清除画布上的指定区域内容。 128 | * @param {Number} x 指定区域的x轴坐标。 129 | * @param {Number} y 指定区域的y轴坐标。 130 | * @param {Number} width 指定区域的宽度。 131 | * @param {Number} height 指定区域的高度。 132 | */ 133 | CanvasContext.prototype.clear = function(x, y, width, height) 134 | { 135 | this.context.clearRect(x, y, width, height); 136 | //this.canvas.width = this.canvas.width; 137 | }; 138 | 139 | })(); -------------------------------------------------------------------------------- /src/base/context/Context.js: -------------------------------------------------------------------------------- 1 | 2 | (function(){ 3 | 4 | /** 5 | * 构造函数. 6 | * @name Context 7 | * @class Context是Quark框架中显示对象结构的上下文,实现显示对象结构的渲染。此类为抽象类。 8 | * @param {Object} props 一个对象。包含以下属性: 9 | *

    canvas - 渲染上下文所对应的画布。

    10 | */ 11 | var Context = Quark.Context = function(props) 12 | { 13 | if(props.canvas == null) throw "Quark.Context Error: canvas is required."; 14 | 15 | this.canvas = null; 16 | Quark.merge(this, props); 17 | }; 18 | 19 | /** 20 | * 为开始绘制显示对象做准备,需要子类来实现。 21 | */ 22 | Context.prototype.startDraw = function(){ }; 23 | 24 | /** 25 | * 绘制显示对象,需要子类来实现。 26 | */ 27 | Context.prototype.draw = function(){ }; 28 | 29 | /** 30 | * 完成绘制显示对象后的处理方法,需要子类来实现。 31 | */ 32 | Context.prototype.endDraw = function(){ }; 33 | 34 | /** 35 | * 对显示对象进行变换,需要子类来实现。 36 | */ 37 | Context.prototype.transform = function(){ }; 38 | 39 | /** 40 | * 从画布中删除显示对象,需要子类来实现。 41 | * @param {DisplayObject} target 要删除的显示对象。 42 | */ 43 | Context.prototype.remove = function(target){ }; 44 | 45 | })(); -------------------------------------------------------------------------------- /src/base/context/DOMContext.js: -------------------------------------------------------------------------------- 1 | 2 | (function(){ 3 | 4 | /** 5 | * 检测浏览器是否支持transform或transform3D。 6 | */ 7 | var testElem = document.createElement("div"); 8 | var supportTransform = testElem.style[Quark.cssPrefix + "Transform"] != undefined; 9 | var supportTransform3D = testElem.style[Quark.cssPrefix + "Perspective"] != undefined; 10 | var docElem = document.documentElement; 11 | if(supportTransform3D && 'webkitPerspective' in docElem.style) 12 | { 13 | testElem.id = 'test3d'; 14 | var st = document.createElement('style'); 15 | st.textContent = '@media (-webkit-transform-3d){#test3d{height:3px}}'; 16 | document.head.appendChild(st); 17 | docElem.appendChild(testElem); 18 | 19 | supportTransform3D = testElem.offsetHeight === 3; 20 | 21 | st.parentNode.removeChild(st); 22 | testElem.parentNode.removeChild(testElem); 23 | }; 24 | Quark.supportTransform = supportTransform; 25 | Quark.supportTransform3D = supportTransform3D; 26 | if(!supportTransform) 27 | { 28 | trace("Warn: DOMContext requires css transfrom support."); 29 | return; 30 | } 31 | 32 | /** 33 | * 构造函数. 34 | * @name DOMContext 35 | * @augments Context 36 | * @class DOMContext是DOM渲染上下文,将显示对象以dom方式渲染到舞台上。 37 | * @param {Object} props 一个对象。包含以下属性: 38 | *

    canvas - 渲染上下文所对应的画布,HTMLDivElement对象。

    39 | */ 40 | var DOMContext = Quark.DOMContext = function(props) 41 | { 42 | DOMContext.superClass.constructor.call(this, props); 43 | }; 44 | Quark.inherit(DOMContext, Quark.Context); 45 | 46 | /** 47 | * 绘制指定对象的DOM到舞台上。 48 | * @param {DisplayObject} target 要绘制的显示对象。 49 | */ 50 | DOMContext.prototype.draw = function(target) 51 | { 52 | if(!target._addedToDOM) 53 | { 54 | var parent = target.parent; 55 | var targetDOM = target.getDrawable(this); 56 | if(parent != null) 57 | { 58 | var parentDOM = parent.getDrawable(this); 59 | if(targetDOM.parentNode != parentDOM) parentDOM.appendChild(targetDOM); 60 | if(parentDOM.parentNode == null && parent instanceof Quark.Stage) 61 | { 62 | this.canvas.appendChild(parentDOM); 63 | parent._addedToDOM = true; 64 | } 65 | target._addedToDOM = true; 66 | } 67 | } 68 | }; 69 | 70 | /** 71 | * 对指定的显示对象的DOM进行css属性设置或变换。 72 | * @param {DisplayObject} target 要进行属性设置或变换的显示对象。 73 | */ 74 | DOMContext.prototype.transform = function(target) 75 | { 76 | var image = target.getDrawable(this); 77 | //优化:可以对那些添加到DOM后就不再需要变换的显示对象设置transformEnabled=false。 78 | if(!target.transformEnabled && target._addedToDOM) return; 79 | 80 | var prefix = Quark.cssPrefix, 81 | origin = prefix + "TransformOrigin", 82 | transform = prefix + "Transform", 83 | style = image.style; 84 | 85 | if(!style.display || target.propChanged("visible", "alpha")) 86 | { 87 | style.display = (!target.visible || target.alpha <= 0) ? "none" : ""; 88 | } 89 | if(!style.opacity || target.propChanged("alpha")) 90 | { 91 | style.opacity = target.alpha; 92 | } 93 | if(!style.backgroundPosition || target.propChanged("rectX", "rectY")) 94 | { 95 | style.backgroundPosition = (-target.rectX) + "px " + (-target.rectY) + "px"; 96 | } 97 | if(!style.width || target.propChanged("width", "height")) 98 | { 99 | style.width = target.width + "px"; 100 | style.height = target.height + "px"; 101 | } 102 | if(!style[origin] || target.propChanged("regX", "regY")) 103 | { 104 | style[origin] = target.regX + "px " + target.regY + "px"; 105 | } 106 | if(!style[transform] || target.propChanged("x", "y", "regX", "regY", "scaleX", "scaleY", "rotation")) 107 | { 108 | var css = Quark.supportTransform3D ? getTransformCSS(target, true) : getTransformCSS(target, false); 109 | style[transform] = css; 110 | } 111 | if(!style.zIndex || target.propChanged("_depth")) 112 | { 113 | style.zIndex = target._depth; 114 | } 115 | if(target.mask != null) 116 | { 117 | style[Q.cssPrefix + "MaskImage"] = target.mask.getDrawable(this).style.backgroundImage; 118 | style[Q.cssPrefix + "MaskRepeat"] = "no-repeat"; 119 | style[Q.cssPrefix + "MaskPosition"] = target.mask.x + "px " + target.mask.y + "px"; 120 | } 121 | style.pointerEvents = target.eventEnabled ? "auto" : "none"; 122 | }; 123 | 124 | /** 125 | * 根据指定对象生成css变换的样式。 126 | * @param {DisplayObject} target 显示对象。 127 | * @param {Boolean} useTransform3D 是否采用transform—3d变换。在支持transform—3d的浏览器中推荐使用。默认为false。 128 | * @return {String} 生成的css样式。 129 | */ 130 | function getTransformCSS(target, useTransform3D) 131 | { 132 | var css = ""; 133 | 134 | if(useTransform3D) 135 | { 136 | css += "translate3d(" + (target.x-target.regX) + "px, " + (target.y-target.regY) + "px, 0px)" 137 | + "rotate3d(0, 0, 1, " + target.rotation + "deg)" 138 | + "scale3d(" + target.scaleX + ", " + target.scaleY + ", 1)"; 139 | }else 140 | { 141 | css += "translate(" + (target.x-target.regX) + "px, " + (target.y-target.regY) + "px)" 142 | + "rotate(" + target.rotation + "deg)" 143 | + "scale(" + target.scaleX + ", " + target.scaleY + ")"; 144 | } 145 | return css; 146 | }; 147 | 148 | /** 149 | * 隐藏指定对象渲染的dom节点,用于当显示对象visible=0或alpha=0等情况,由显示对象内部方法调用。 150 | * @param {DisplayObject} target 要隐藏的显示对象。 151 | */ 152 | DOMContext.prototype.hide = function(target) 153 | { 154 | target.getDrawable(this).style.display = "none"; 155 | }; 156 | 157 | /** 158 | * 删除指定显示对象渲染的dom节点,由显示对象内部方法调用。 159 | * @param {DisplayObject} target 要删除的显示对象。 160 | */ 161 | DOMContext.prototype.remove = function(target) 162 | { 163 | var targetDOM = target.getDrawable(this); 164 | var parentNode = targetDOM.parentNode; 165 | if(parentNode != null) parentNode.removeChild(targetDOM); 166 | target._addedToDOM = false; 167 | }; 168 | 169 | })(); -------------------------------------------------------------------------------- /src/base/display/Bitmap.js: -------------------------------------------------------------------------------- 1 | 2 | (function(){ 3 | 4 | /** 5 | * 构造函数. 6 | * @name Bitmap 7 | * @augments DisplayObject 8 | * @class Bitmap位图类,表示位图图像的显示对象,简单说它就是Image对象的某个区域的抽象表示。 9 | * @argument {Object} props 一个对象,包含以下属性: 10 | *

    image - Image对象。

    11 | *

    rect - Image对象的矩形区域。格式为:[0,0,100,100]

    12 | */ 13 | var Bitmap = Quark.Bitmap = function(props) 14 | { 15 | this.image = null; 16 | this.rectX = 0; //ready-only 17 | this.rectY = 0; //ready-only 18 | this.rectWidth = 0; //ready-only 19 | this.rectHeight = 0; //ready-only 20 | 21 | props = props || {}; 22 | Bitmap.superClass.constructor.call(this, props); 23 | this.id = props.id || Quark.UIDUtil.createUID("Bitmap"); 24 | 25 | this.setRect(props.rect || [0, 0, this.image.width, this.image.height]); 26 | this.setDrawable(this.image); 27 | this._stateList.push("rectX", "rectY", "rectWidth", "rectHeight"); 28 | }; 29 | Quark.inherit(Bitmap, Quark.DisplayObject); 30 | 31 | /** 32 | * 设置Bitmap对象的image的显示区域。 33 | * @param {Array} rect 要设置的显示区域数组。格式为:[rectX, rectY, rectWidth, rectHeight]。 34 | */ 35 | Bitmap.prototype.setRect = function(rect) 36 | { 37 | this.rectX = rect[0]; 38 | this.rectY = rect[1]; 39 | this.rectWidth = this.width = rect[2]; 40 | this.rectHeight = this.height = rect[3]; 41 | }; 42 | 43 | /** 44 | * 覆盖父类的渲染方法。渲染image指定的显示区域。 45 | * @param {Context} context 渲染上下文。 46 | */ 47 | Bitmap.prototype.render = function(context) 48 | { 49 | context.draw(this, this.rectX, this.rectY, this.rectWidth, this.rectHeight, 0, 0, this.width, this.height); 50 | }; 51 | 52 | })(); -------------------------------------------------------------------------------- /src/base/display/Button.js: -------------------------------------------------------------------------------- 1 | 2 | (function(){ 3 | 4 | /** 5 | * 构造函数. 6 | * @name Button 7 | * @augments DisplayObjectContainer 8 | * @class Button类继承自DisplayObjectContainer,是Quark中的简单按钮实现。 9 | * @argument {Object} props 一个对象,包含以下属性: 10 | *

    image - Image对象。

    11 | *

    up - 按钮弹起状态下的显示帧数组对象。如:[0,0,50,50]。 12 | *

    over - 按钮经过状态下的显示帧数组对象。如:[50,0,50,50]。 13 | *

    down - 按钮按下状态下的显示帧数组对象。如:[100,0,50,50]。 14 | *

    disabled - 按钮不可用状态下的显示帧数组对象。如:[150,0,50,50]。 15 | */ 16 | var Button = Quark.Button = function(props) 17 | { 18 | this.state = Button.UP; 19 | this.enabled = true; 20 | 21 | props = props || {}; 22 | Button.superClass.constructor.call(this, props); 23 | this.id = props.id || Quark.UIDUtil.createUID("Button"); 24 | 25 | this._skin = new Quark.MovieClip({id:"skin", image:props.image}); 26 | this.addChild(this._skin); 27 | this._skin.stop(); 28 | 29 | this.eventChildren = false; 30 | if(props.useHandCursor === undefined) this.useHandCursor = true; 31 | if(props.up) this.setUpState(props.up); 32 | if(props.over) this.setOverState(props.over); 33 | if(props.down) this.setDownState(props.down); 34 | if(props.disabled) this.setDisabledState(props.disabled); 35 | }; 36 | Quark.inherit(Button, Quark.DisplayObjectContainer); 37 | 38 | /** 39 | * 按钮的弹起状态。常量值。 40 | */ 41 | Button.UP = "up"; 42 | /** 43 | * 按钮的经过状态。常量值。 44 | */ 45 | Button.OVER = "over"; 46 | /** 47 | * 按钮的按下状态。常量值。 48 | */ 49 | Button.DOWN = "down"; 50 | /** 51 | * 按钮的不可用状态。常量值。 52 | */ 53 | Button.DISABLED = "disabled"; 54 | 55 | /** 56 | * 设置按钮弹起状态的显示帧。 57 | * @param {Array} upState 弹起状态的显示帧。 58 | * @return {Button} 返回按钮本身。 59 | */ 60 | Button.prototype.setUpState = function(upState) 61 | { 62 | upState.label = Button.UP; 63 | this._skin.setFrame(upState, 0); 64 | this.upState = upState; 65 | return this; 66 | }; 67 | 68 | /** 69 | * 设置按钮经过状态的显示帧。 70 | * @param {Array} overState 经过状态的显示帧。 71 | * @return {Button} 返回按钮本身。 72 | */ 73 | Button.prototype.setOverState = function(overState) 74 | { 75 | overState.label = Button.OVER; 76 | this._skin.setFrame(overState, 1); 77 | this.overState = overState; 78 | return this; 79 | }; 80 | 81 | /** 82 | * 设置按钮按下状态的显示帧。 83 | * @param {Array} downState 点击状态的显示帧。 84 | * @return {Button} 返回按钮本身。 85 | */ 86 | Button.prototype.setDownState = function(downState) 87 | { 88 | downState.label = Button.DOWN; 89 | this._skin.setFrame(downState, 2); 90 | this.downState = downState; 91 | return this; 92 | }; 93 | 94 | /** 95 | * 设置按钮不可用状态的显示帧。 96 | * @param {Array} disabledState 不可用状态的显示帧。 97 | * @return {Button} 返回按钮本身。 98 | */ 99 | Button.prototype.setDisabledState = function(disabledState) 100 | { 101 | disabledState.label = Button.DISABLED; 102 | this._skin.setFrame(disabledState, 3); 103 | this.disabledState = disabledState; 104 | return this; 105 | }; 106 | 107 | /** 108 | * 设置按钮是否启用。 109 | * @param {Boolean} enabled 指定按钮是否启用。默认为false。 110 | * @return {Button} 返回按钮本身。 111 | */ 112 | Button.prototype.setEnabled = function(enabled) 113 | { 114 | if(this.enabled == enabled) return this; 115 | this.eventEnabled = this.enabled = enabled; 116 | if(!enabled) 117 | { 118 | if(this.disabledState) this._skin.gotoAndStop(Button.DISABLED); 119 | else this._skin.gotoAndStop(Button.UP); 120 | }else 121 | { 122 | if(this._skin.currentFrame == 3) this._skin.gotoAndStop(Button.UP); 123 | } 124 | return this; 125 | }; 126 | 127 | /** 128 | * 改变按钮的显示状态。 129 | * @param {String} state 指定按钮的显示状态。 130 | * @return {Button} 返回按钮本身。 131 | */ 132 | Button.prototype.changeState = function(state) 133 | { 134 | if(this.state == state) return; 135 | this.state = state; 136 | 137 | switch(state) 138 | { 139 | case Button.OVER: 140 | case Button.DOWN: 141 | case Button.UP: 142 | if(!this.enabled) this.eventEnabled = this.enabled = true; 143 | this._skin.gotoAndStop(state); 144 | break; 145 | case Button.DISABLED: 146 | this.setEnabled(false); 147 | break; 148 | } 149 | return this; 150 | }; 151 | 152 | /** 153 | * 按钮的默认事件处理行为。 154 | * @private 155 | */ 156 | Button.prototype.dispatchEvent = function(e) 157 | { 158 | if(!this.enabled) return; 159 | 160 | switch(e.type) 161 | { 162 | case "mousemove": 163 | if(this.overState) this.changeState(Button.OVER); 164 | break; 165 | case "mousedown": 166 | case "touchstart": 167 | case "touchmove": 168 | if(this.downState) this.changeState(Button.DOWN); 169 | break; 170 | case "mouseup": 171 | if(this.overState) this.changeState(Button.OVER); 172 | else this.changeState(Button.UP); 173 | break; 174 | case "mouseout": 175 | case "touchout": 176 | case "touchend": 177 | if(this.upState) this.changeState(Button.UP); 178 | break; 179 | } 180 | Button.superClass.dispatchEvent.call(this, e); 181 | }; 182 | 183 | /** 184 | * 把Button的drawable置空,否则传入image参数时会绘制成Button的背景。 185 | * @private 186 | */ 187 | Button.prototype.setDrawable = function(drawable) 188 | { 189 | Button.superClass.setDrawable.call(this, null); 190 | }; 191 | 192 | })(); -------------------------------------------------------------------------------- /src/base/display/DisplayObjectContainer.js: -------------------------------------------------------------------------------- 1 | (function(){ 2 | 3 | /** 4 | * 构造函数. 5 | * @name DisplayObjectContainer 6 | * @augments DisplayObject 7 | * @class DisplayObjectContainer类继承自DisplayObject,是显示列表中显示对象容器的基类。每个DisplayObjectContainer对象都有自己的子级列表children,用于组织对象的Z轴顺序。注意:DisplayObjectContainer对象的宽高默认为0,在autoSize=false的情况下,需要手动设置宽高。 8 | * @property eventChildren 指示DisplayObjectContainer的子元素是否接受交互事件,如mousedown,touchstart等。默认为true。 9 | * @property autoSize 指示DisplayObjectContainer是否随子元素自动设置大小。默认为false。 10 | */ 11 | var DisplayObjectContainer = Quark.DisplayObjectContainer = function(props) 12 | { 13 | this.eventChildren = true; 14 | this.autoSize = false; 15 | 16 | props = props || {}; 17 | DisplayObjectContainer.superClass.constructor.call(this, props); 18 | this.id = props.id || Quark.UIDUtil.createUID("DisplayObjectContainer"); 19 | this.setDrawable(props.drawable || props.image || null); 20 | 21 | this.children = []; 22 | if(props.children) 23 | { 24 | for(var i = 0; i < props.children.length; i++) 25 | { 26 | this.addChild(props.children[i]); 27 | } 28 | } 29 | }; 30 | Quark.inherit(DisplayObjectContainer, Quark.DisplayObject); 31 | 32 | /** 33 | * 将一个DisplayObject子实例添加到该DisplayObjectContainer实例的子级列表中的指定位置。 34 | * @param {DisplayObject} child 要添加的显示对象。 35 | * @param {Integer} index 指定显示对象要被添加到的索引位置。 36 | * @return {DisplayObjectContainer} 返回显示容器本身。 37 | */ 38 | DisplayObjectContainer.prototype.addChildAt = function(child, index) 39 | { 40 | if(index < 0) index = 0; 41 | else if(index > this.children.length) index = this.children.length; 42 | 43 | var childIndex = this.getChildIndex(child); 44 | if(childIndex != -1) 45 | { 46 | if(childIndex == index) return this; 47 | this.children.splice(childIndex, 1); 48 | }else if(child.parent) 49 | { 50 | child.parent.removeChild(child); 51 | } 52 | 53 | this.children.splice(index, 0, child); 54 | child.parent = this; 55 | 56 | if(this.autoSize) 57 | { 58 | var rect = new Quark.Rectangle(0, 0, this.rectWidth || this.width, this.rectHeight || this.height); 59 | var childRect = new Quark.Rectangle(child.x, child.y, child.rectWidth || child.width, child.rectHeight || child.height); 60 | rect.union(childRect); 61 | this.width = rect.width; 62 | this.height = rect.height; 63 | } 64 | 65 | return this; 66 | }; 67 | 68 | /** 69 | * 将一个DisplayObject子实例添加到该DisplayObjectContainer实例的子级列表中。 70 | * @param {DisplayObject} child 要添加的显示对象。 71 | * @return {DisplayObjectContainer} 返回显示容器本身。 72 | */ 73 | DisplayObjectContainer.prototype.addChild = function(child) 74 | { 75 | var start = this.children.length; 76 | for(var i = 0; i < arguments.length; i++) 77 | { 78 | var child = arguments[i]; 79 | this.addChildAt(child, start + i); 80 | } 81 | return this; 82 | }; 83 | 84 | /** 85 | * 从DisplayObjectContainer的子级列表中指定索引处删除子对象。 86 | * @param {Integer} index 指定要删除的显示对象的索引位置。 87 | * @return {Boolean} 删除成功返回true,否则返回false。 88 | */ 89 | DisplayObjectContainer.prototype.removeChildAt = function(index) 90 | { 91 | if (index < 0 || index >= this.children.length) return false; 92 | var child = this.children[index]; 93 | if (child != null) 94 | { 95 | var stage = this.getStage(); 96 | if(stage != null) stage.context.remove(child); 97 | child.parent = null; 98 | } 99 | this.children.splice(index, 1); 100 | return true; 101 | }; 102 | 103 | /** 104 | * 从DisplayObjectContainer的子级列表中删除指定子对象。 105 | * @param {DisplayObject} child 指定要删除的显示对象。 106 | * @return {Boolean} 删除成功返回true,否则返回false。 107 | */ 108 | DisplayObjectContainer.prototype.removeChild = function(child) 109 | { 110 | return this.removeChildAt(this.children.indexOf(child)); 111 | }; 112 | 113 | /** 114 | * 删除DisplayObjectContainer的所有子对象。 115 | */ 116 | DisplayObjectContainer.prototype.removeAllChildren = function() 117 | { 118 | while(this.children.length > 0) this.removeChildAt(0); 119 | }; 120 | 121 | /** 122 | * 返回DisplayObjectContainer的位于指定索引处的子显示对象。 123 | * @param {Integer} index 指定子显示对象的索引位置。 124 | * @return {DisplayObject} 返回指定的子显示对象。 125 | */ 126 | DisplayObjectContainer.prototype.getChildAt = function(index) 127 | { 128 | if (index < 0 || index >= this.children.length) return null; 129 | return this.children[index]; 130 | }; 131 | 132 | /** 133 | * 返回指定对象在DisplayObjectContainer的子级列表中的索引位置。 134 | * @param {Integer} child 指定子显示对象。 135 | * @return {Integer} 返回指定子显示对象的索引位置。 136 | */ 137 | DisplayObjectContainer.prototype.getChildIndex = function(child) 138 | { 139 | return this.children.indexOf(child); 140 | }; 141 | 142 | /** 143 | * 设置指定对象在DisplayObjectContainer的子级列表中的索引位置。 144 | * @param {DisplayObject} child 指定子显示对象。 145 | * @param {Integer} index 指定子显示对象新的索引位置。 146 | */ 147 | DisplayObjectContainer.prototype.setChildIndex = function(child, index) 148 | { 149 | if(child.parent != this) return; 150 | var oldIndex = this.children.indexOf(child); 151 | if(index == oldIndex) return; 152 | this.children.splice(oldIndex, 1); 153 | this.children.splice(index, 0, child); 154 | }; 155 | 156 | /** 157 | * 交换在DisplayObjectContainer的子级列表中的两个子对象的索引位置。 158 | * @param {DisplayObject} child1 指定交换索引位置的子显示对象1。 159 | * @param {DisplayObject} child2 指定交换索引位置的子显示对象2。 160 | */ 161 | DisplayObjectContainer.prototype.swapChildren = function(child1, child2) 162 | { 163 | var index1 = this.getChildIndex(child1), index2 = this.getChildIndex(child2); 164 | this.children[index1] = child2; 165 | this.children[index2] = child1; 166 | }; 167 | 168 | /** 169 | * 交换在DisplayObjectContainer的子级列表中的指定索引位置的两个子对象。 170 | * @param {Integer} index1 指定交换索引位置1。 171 | * @param {Integer} index2 指定交换索引位置2。 172 | */ 173 | DisplayObjectContainer.prototype.swapChildrenAt = function(index1, index2) 174 | { 175 | var child1 = this.getChildAt(index1), child2 = this.getChildAt(index2); 176 | this.children[index1] = child2; 177 | this.children[index2] = child1; 178 | }; 179 | 180 | /** 181 | * 返回DisplayObjectContainer中指定id的子显示对象。 182 | * @param {String} 指定子显示对象的id。 183 | * @return {DisplayObject} 返回指定id的子显示对象。 184 | */ 185 | DisplayObjectContainer.prototype.getChildById = function(id) 186 | { 187 | for(var i = 0, len = this.children.length; i < len; i++) 188 | { 189 | var child = this.children[i]; 190 | if(child.id == id) return child; 191 | } 192 | return null; 193 | }; 194 | 195 | /** 196 | * 删除并返回DisplayObjectContainer中指定id的子显示对象。 197 | * @param {String} 指定子显示对象的id。 198 | * @return {DisplayObject} 返回删除的指定id的子显示对象。 199 | */ 200 | DisplayObjectContainer.prototype.removeChildById = function(id) 201 | { 202 | for(var i = 0, len = this.children.length; i < len; i++) 203 | { 204 | if(this.children[i].id == id) 205 | { 206 | return this.removeChildAt(i); 207 | } 208 | } 209 | return null; 210 | }; 211 | 212 | /** 213 | * 根据参数keyOrFunction指定的子元素键值或自定义函数对DisplayObjectContainer的子元素进行排序。 214 | * @param keyOrFunction 指定排序的子元素的键值或自定义函数。 215 | */ 216 | DisplayObjectContainer.prototype.sortChildren = function(keyOrFunction) 217 | { 218 | var f = keyOrFunction; 219 | if(typeof(f) == "string") 220 | { 221 | var key = f; 222 | f = function(a, b) 223 | { 224 | return b[key] - a[key]; 225 | }; 226 | } 227 | this.children.sort(f); 228 | }; 229 | 230 | /** 231 | * 确定指定对象是否为DisplayObjectContainer的子显示对象。 232 | * @param {DisplayObject} child 指定的显示对象。 233 | * @return {Boolean} 指定对象为DisplayObjectContainer的子显示对象返回true,否则返回false。 234 | */ 235 | DisplayObjectContainer.prototype.contains = function(child) 236 | { 237 | return this.getChildIndex(child) != -1; 238 | }; 239 | 240 | /** 241 | * 返回DisplayObjectContainer的子显示对象的数量。 242 | * @return {Integer} 返回子显示对象的数量。 243 | */ 244 | DisplayObjectContainer.prototype.getNumChildren = function() 245 | { 246 | return this.children.length; 247 | }; 248 | 249 | /** 250 | * 覆盖父类DisplayObject的_update方法,更新所有子显示对象的深度。 251 | * @protected 252 | */ 253 | DisplayObjectContainer.prototype._update = function(timeInfo) 254 | { 255 | //先更新容器本身的数据,再更新子元素的数据 256 | var result = true; 257 | if(this.update != null) result = this.update(timeInfo); 258 | if(result === false) return; 259 | 260 | var copy = this.children.slice(0); 261 | for(var i = 0, len = copy.length; i < len; i++) 262 | { 263 | var child = copy[i]; 264 | child._depth = i + 1; 265 | child._update(timeInfo); 266 | } 267 | }; 268 | 269 | /** 270 | * 渲染DisplayObjectContainer本身及其所有子显示对象。 271 | * @param {Context} 渲染上下文。 272 | */ 273 | DisplayObjectContainer.prototype.render = function(context) 274 | { 275 | DisplayObjectContainer.superClass.render.call(this, context); 276 | 277 | for(var i = 0, len = this.children.length; i < len; i++) 278 | { 279 | var child = this.children[i]; 280 | child._render(context); 281 | } 282 | }; 283 | 284 | /** 285 | * 返回x和y指定点下的DisplayObjectContainer的子项(或孙子项,依此类推)的数组集合。默认只返回最先加入的子显示对象。 286 | * @param {Number} x 指定点的x轴坐标。 287 | * @param {Number} y 指定点的y轴坐标。 288 | * @param {Boolean} usePolyCollision 指定是否采用多边形碰撞检测。默认为false。 289 | * @param {Boolean} returnAll 指定是否返回指定点下的所有显示对象。默认为false。 290 | * @return 返回指定点下的显示对象集合,当然returnAll为false时只返回最先加入的子显示对象。 291 | */ 292 | DisplayObjectContainer.prototype.getObjectUnderPoint = function(x, y, usePolyCollision, returnAll) 293 | { 294 | if(returnAll) var result = []; 295 | 296 | for(var i = this.children.length - 1; i >= 0; i--) 297 | { 298 | var child = this.children[i]; 299 | if(child == null || (!child.eventEnabled && child.children == undefined) || !child.visible || child.alpha <= 0) continue; 300 | 301 | if(child.children != undefined && child.eventChildren && child.getNumChildren() > 0) 302 | { 303 | var obj = child.getObjectUnderPoint(x, y, usePolyCollision, returnAll); 304 | if(obj) 305 | { 306 | if(returnAll) {if(obj.length > 0) result = result.concat(obj);} 307 | else return obj; 308 | }else if(child.hitTestPoint(x, y, usePolyCollision) >= 0) 309 | { 310 | if(returnAll) result.push(child); 311 | else return child; 312 | } 313 | }else 314 | { 315 | if(child.hitTestPoint(x, y, usePolyCollision) >= 0) 316 | { 317 | if(returnAll) result.push(child); 318 | else return child; 319 | } 320 | } 321 | } 322 | if(returnAll) return result; 323 | return null; 324 | }; 325 | 326 | })(); 327 | -------------------------------------------------------------------------------- /src/base/display/Drawable.js: -------------------------------------------------------------------------------- 1 | 2 | (function(){ 3 | 4 | /** 5 | * 构造函数. 6 | * @name Drawable 7 | * @class Drawable是可绘制图像或DOM的包装。当封装的是HTMLImageElement、HTMLCanvasElement或HTMLVideoElement对象时,可同时支持canvas和dom两种渲染方式,而如果封装的是dom时,则不支持canvas方式。 8 | * @param drawable 一个可绘制对象。 9 | * @param {Boolean} isDOM 指定参数drawable是否为一个DOM对象。默认为false。 10 | */ 11 | var Drawable = Quark.Drawable = function(drawable, isDOM) 12 | { 13 | this.rawDrawable = null; 14 | this.domDrawable = null; 15 | this.set(drawable, isDOM); 16 | }; 17 | 18 | /** 19 | * 根据context上下文获取不同的Drawable包装的对象。 20 | * @param {DisplayObject} obj 指定的显示对象。 21 | * @param {Context} context 指定的渲染上下文。 22 | * @return 返回包装的可绘制对象。 23 | */ 24 | Drawable.prototype.get = function(obj, context) 25 | { 26 | if(context == null || context.canvas.getContext != null) 27 | { 28 | return this.rawDrawable; 29 | }else 30 | { 31 | if(this.domDrawable == null) 32 | { 33 | this.domDrawable = Quark.createDOMDrawable(obj, {image:this.rawDrawable}); 34 | } 35 | return this.domDrawable; 36 | } 37 | }; 38 | 39 | /** 40 | * 设置Drawable对象。 41 | * @param drawable 一个可绘制对象。 42 | * @param {Boolean} isDOM 指定参数drawable是否为一个DOM对象。默认为false。 43 | */ 44 | Drawable.prototype.set = function(drawable, isDOM) 45 | { 46 | if(isDrawable(drawable)) this.rawDrawable = drawable; 47 | if(isDOM === true) 48 | { 49 | this.domDrawable = drawable; 50 | }else if(this.domDrawable) 51 | { 52 | this.domDrawable.style.backgroundImage = "url(" + this.rawDrawable.src + ")"; 53 | } 54 | }; 55 | 56 | function isDrawable(elem) 57 | { 58 | if(elem == null) return false; 59 | return (elem instanceof HTMLImageElement) || 60 | (elem instanceof HTMLCanvasElement) || 61 | (elem instanceof HTMLVideoElement); 62 | }; 63 | 64 | })(); -------------------------------------------------------------------------------- /src/base/display/Graphics.js: -------------------------------------------------------------------------------- 1 | (function(){ 2 | 3 | /** 4 | * 构造函数. 5 | * @name Graphics 6 | * @augments DisplayObject 7 | * @class Graphics类包含一组创建矢量图形的方法。 8 | */ 9 | var Graphics = Quark.Graphics = function(props) 10 | { 11 | this.lineWidth = 1; 12 | this.strokeStyle = "0"; 13 | this.lineAlpha = 1; 14 | this.lineCap = null; //"butt", "round", "square" 15 | this.lineJoin = null; //"miter", "round", "bevel" 16 | this.miterLimit = 10; 17 | 18 | this.hasStroke = false; 19 | this.hasFill = false; 20 | 21 | this.fillStyle = "0"; 22 | this.fillAlpha = 1; 23 | 24 | props = props || {}; 25 | Graphics.superClass.constructor.call(this, props); 26 | this.id = Quark.UIDUtil.createUID("Graphics"); 27 | 28 | this._actions = []; 29 | this._cache = null; 30 | }; 31 | Quark.inherit(Graphics, Quark.DisplayObject); 32 | 33 | /** 34 | * 指定绘制图形的线条样式。 35 | */ 36 | Graphics.prototype.lineStyle = function(thickness, lineColor, alpha, lineCap, lineJoin, miterLimit) 37 | { 38 | this._addAction(["lineWidth", (this.lineWidth = thickness || 1)]); 39 | this._addAction(["strokeStyle", (this.strokeStyle = lineColor || "0")]); 40 | this._addAction(["lineAlpha", (this.lineAlpha = alpha || 1)]); 41 | if(lineCap != undefined) this._addAction(["lineCap", (this.lineCap = lineCap)]); 42 | if(lineJoin != undefined) this._addAction(["lineJoin", (this.lineJoin = lineJoin)]); 43 | if(miterLimit != undefined) this._addAction(["miterLimit", (this.miterLimit = miterLimit)]); 44 | this.hasStroke = true; 45 | return this; 46 | }; 47 | 48 | /** 49 | * 指定绘制图形的填充样式和透明度。 50 | */ 51 | Graphics.prototype.beginFill = function(fill, alpha) 52 | { 53 | this._addAction(["fillStyle", (this.fillStyle = fill)]); 54 | this._addAction(["fillAlpha", (this.fillAlpha = alpha || 1)]); 55 | this.hasFill = true; 56 | return this; 57 | }; 58 | 59 | /** 60 | * 应用并结束笔画的绘制和图形样式的填充。 61 | */ 62 | Graphics.prototype.endFill = function() 63 | { 64 | if(this.hasStroke) this._addAction(["stroke"]); 65 | if(this.hasFill) this._addAction(["fill"]); 66 | return this; 67 | }; 68 | 69 | /** 70 | * 指定绘制图形的线性渐变填充样式。 71 | */ 72 | Graphics.prototype.beginLinearGradientFill = function(x0, y0, x1, y1, colors, ratios) 73 | { 74 | var gradient = Graphics._getContext().createLinearGradient(x0, y0, x1, y1); 75 | for (var i = 0, len = colors.length; i < len; i++) 76 | { 77 | gradient.addColorStop(ratios[i], colors[i]); 78 | } 79 | this.hasFill = true; 80 | return this._addAction(["fillStyle", (this.fillStyle = gradient)]); 81 | }; 82 | 83 | /** 84 | * 指定绘制图形的放射性渐变填充样式。 85 | */ 86 | Graphics.prototype.beginRadialGradientFill = function(x0, y0, r0, x1, y1, r1, colors, ratios) 87 | { 88 | var gradient = Graphics._getContext().createRadialGradient(x0, y0, r0, x1, y1, r1); 89 | for (var i = 0, len = colors.length; i < len; i++) 90 | { 91 | gradient.addColorStop(ratios[i], colors[i]); 92 | } 93 | this.hasFill = true; 94 | return this._addAction(["fillStyle", (this.fillStyle = gradient)]); 95 | }; 96 | 97 | /** 98 | * 开始一个位图填充样式。 99 | * @param {HTMLImageElement} image 指定填充的Image对象。 100 | * @param {String} repetition 指定填充的重复设置参数。它可以是以下任意一个值:repeat, repeat-x, repeat-y, no-repeat。默认为""。 101 | */ 102 | Graphics.prototype.beginBitmapFill = function(image, repetition) 103 | { 104 | var pattern = Graphics._getContext().createPattern(image, repetition || ""); 105 | this.hasFill = true; 106 | return this._addAction(["fillStyle", (this.fillStyle = pattern)]); 107 | }; 108 | 109 | /** 110 | * 开始一个新的路径。 111 | */ 112 | Graphics.prototype.beginPath = function() 113 | { 114 | return this._addAction(["beginPath"]); 115 | }; 116 | 117 | /** 118 | * 关闭当前的路径。 119 | */ 120 | Graphics.prototype.closePath = function() 121 | { 122 | return this._addAction(["closePath"]); 123 | }; 124 | 125 | /** 126 | * 绘制一个矩形。 127 | */ 128 | Graphics.prototype.drawRect = function(x, y, width, height) 129 | { 130 | return this._addAction(["rect", x, y, width, height]); 131 | }; 132 | 133 | /** 134 | * 绘制一个复杂的圆角矩形。 135 | */ 136 | Graphics.prototype.drawRoundRectComplex = function(x, y, width, height, cornerTL, cornerTR, cornerBR, cornerBL) 137 | { 138 | this._addAction(["moveTo", x + cornerTL, y]); 139 | this._addAction(["lineTo", x + width - cornerTR, y]); 140 | this._addAction(["arc", x + width - cornerTR, y + cornerTR, cornerTR, -Math.PI/2, 0, false]); 141 | this._addAction(["lineTo", x + width, y + height - cornerBR]); 142 | this._addAction(["arc", x + width - cornerBR, y + height - cornerBR, cornerBR, 0, Math.PI/2, false]); 143 | this._addAction(["lineTo", x + cornerBL, y + height]); 144 | this._addAction(["arc", x + cornerBL, y + height - cornerBL, cornerBL, Math.PI/2, Math.PI, false]); 145 | this._addAction(["lineTo", x, y + cornerTL]); 146 | this._addAction(["arc", x + cornerTL, y + cornerTL, cornerTL, Math.PI, Math.PI*3/2, false]); 147 | return this; 148 | }; 149 | 150 | /** 151 | * 绘制一个圆角矩形。 152 | */ 153 | Graphics.prototype.drawRoundRect = function(x, y, width, height, cornerSize) 154 | { 155 | return this.drawRoundRectComplex(x, y, width, height, cornerSize, cornerSize, cornerSize, cornerSize); 156 | }; 157 | 158 | /** 159 | * 绘制一个圆。 160 | */ 161 | Graphics.prototype.drawCircle = function(x, y, radius) 162 | { 163 | return this._addAction(["arc", x + radius, y + radius, radius, 0, Math.PI * 2, 0]); 164 | }; 165 | 166 | /** 167 | * 绘制一个椭圆。 168 | */ 169 | Graphics.prototype.drawEllipse = function(x, y, width, height) 170 | { 171 | if(width == height) return this.drawCircle(x, y, width); 172 | 173 | var w = width / 2, h = height / 2, C = 0.5522847498307933, cx = C * w, cy = C * h; 174 | x = x + w; 175 | y = y + h; 176 | 177 | this._addAction(["moveTo", x + w, y]); 178 | this._addAction(["bezierCurveTo", x + w, y - cy, x + cx, y - h, x, y - h]); 179 | this._addAction(["bezierCurveTo", x - cx, y - h, x - w, y - cy, x - w, y]); 180 | this._addAction(["bezierCurveTo", x - w, y + cy, x - cx, y + h, x, y + h]); 181 | this._addAction(["bezierCurveTo", x + cx, y + h, x + w, y + cy, x + w, y]); 182 | return this; 183 | }; 184 | 185 | /** 186 | * 根据参数指定的SVG数据绘制一条路径。 187 | * 代码示例: 188 | *

    var path = "M250 150 L150 350 L350 350 Z";

    189 | *

    var shape = new Quark.Graphics({width:500, height:500});

    190 | *

    shape.drawSVGPath(path).beginFill("#0ff").endFill();

    191 | */ 192 | Graphics.prototype.drawSVGPath = function(pathData) 193 | { 194 | var path = pathData.split(/,| (?=[a-zA-Z])/); 195 | 196 | this._addAction(["beginPath"]); 197 | for(var i = 0, len = path.length; i < len; i++) 198 | { 199 | var str = path[i], cmd = str[0].toUpperCase(), p = str.substring(1).split(/,| /); 200 | if(p[0].length == 0) p.shift(); 201 | 202 | switch(cmd) 203 | { 204 | case "M": 205 | this._addAction(["moveTo", p[0], p[1]]); 206 | break; 207 | case "L": 208 | this._addAction(["lineTo", p[0], p[1]]); 209 | break; 210 | case "C": 211 | this._addAction(["bezierCurveTo", p[0], p[1], p[2], p[3], p[4], p[5]]); 212 | break; 213 | case "Z": 214 | this._addAction(["closePath"]); 215 | break; 216 | default: 217 | break; 218 | } 219 | } 220 | return this; 221 | }; 222 | 223 | /** 224 | * 执行全部绘制动作。内部私有方法。 225 | * @private 226 | */ 227 | Graphics.prototype._draw = function(context) 228 | { 229 | context.beginPath(); 230 | for(var i = 0, len = this._actions.length; i < len; i++) 231 | { 232 | var action = this._actions[i], 233 | f = action[0], 234 | args = action.length > 1 ? action.slice(1) : null; 235 | 236 | if(typeof(context[f]) == "function") context[f].apply(context, args); 237 | else context[f] = action[1]; 238 | } 239 | }; 240 | 241 | /** 242 | * Override method. 243 | * @private 244 | */ 245 | Graphics.prototype.getDrawable = function(context) 246 | { 247 | //for DOMContext drawing only 248 | if(this.drawable == null) this.setDrawable(this.toImage()); 249 | return this.drawable.get(this, context); 250 | }; 251 | 252 | /** 253 | * 缓存graphics到一个canvas或image。可用来提高渲染效率。 254 | */ 255 | Graphics.prototype.cache = function(toImage) 256 | { 257 | var canvas = Quark.createDOM("canvas", {width:this.width, height:this.height}); 258 | this._draw(canvas.getContext("2d")); 259 | 260 | this._cache = canvas; 261 | if(toImage) this._cache = this.toImage(); 262 | return this._cache; 263 | }; 264 | 265 | /** 266 | * 清除缓存。 267 | */ 268 | Graphics.prototype.uncache = function() 269 | { 270 | this._cache = null; 271 | }; 272 | 273 | /** 274 | * 把Graphics对象转换成dataURL格式的位图。 275 | * @param {String} type 指定转换为DataURL格式的图片mime类型。默认为"image/png"。 276 | */ 277 | Graphics.prototype.toImage = function(type) 278 | { 279 | var cache = this._cache || this.cache(true); 280 | if(cache instanceof HTMLImageElement) return cache; 281 | 282 | var img = new Image(); 283 | img.src = cache.toDataURL(type || "image/png"); 284 | img.width = this.width; 285 | img.height = this.height; 286 | return img; 287 | }; 288 | 289 | /** 290 | * 清除所有绘制动作并复原所有初始状态。 291 | */ 292 | Graphics.prototype.clear = function() 293 | { 294 | this._actions.length = 0; 295 | this._cache = null; 296 | 297 | this.lineWidth = 1; 298 | this.strokeStyle = "0"; 299 | this.lineAlpha = 1; 300 | this.lineCap = null; 301 | this.lineJoin = null; 302 | this.miterLimit = 10; 303 | this.hasStroke = false; 304 | 305 | this.fillStyle = "0"; 306 | this.fillAlpha = 1; 307 | }; 308 | 309 | /** 310 | * 添加一个绘制动作。内部私有方法。 311 | * @private 312 | */ 313 | Graphics.prototype._addAction = function(action) 314 | { 315 | this._actions.push(action); 316 | return this; 317 | }; 318 | 319 | /** 320 | * @private 321 | */ 322 | Graphics._getContext = function() 323 | { 324 | var ctx = Quark.createDOM("canvas").getContext("2d"); 325 | this._getContext = function() 326 | { 327 | return ctx; 328 | }; 329 | return ctx; 330 | }; 331 | 332 | })(); 333 | -------------------------------------------------------------------------------- /src/base/display/MovieClip.js: -------------------------------------------------------------------------------- 1 | 2 | (function(){ 3 | 4 | /** 5 | * 构造函数. 6 | * @name MovieClip 7 | * @augments Bitmap 8 | * @class MovieClip影片剪辑类,表示一组动画片段。MovieClip是由Image对象的若干矩形区域组成的集合序列,并按照一定规则顺序播放。帧frame的定义格式为:{rect:*required*, label:"", interval:0, stop:0, jump:-1}。 9 | */ 10 | var MovieClip = Quark.MovieClip = function(props) 11 | { 12 | this.interval = 0; 13 | this.paused = false; 14 | this.useFrames = false; 15 | this.currentFrame = 0; //read-only 16 | 17 | this._frames = []; 18 | this._frameLabels = {}; 19 | this._frameDisObj = null; 20 | this._displayedCount = 0; 21 | 22 | props = props || {}; 23 | MovieClip.superClass.constructor.call(this, props); 24 | this.id = props.id || Quark.UIDUtil.createUID("MovieClip"); 25 | 26 | if(props.frames) this.addFrame(props.frames); 27 | }; 28 | Quark.inherit(MovieClip, Quark.Bitmap); 29 | 30 | /** 31 | * 向MovieClip中添加帧frame,可以是单个帧或多帧的数组。 32 | */ 33 | MovieClip.prototype.addFrame = function(frame) 34 | { 35 | var start = this._frames.length; 36 | if(frame instanceof Array) 37 | { 38 | for(var i = 0; i < frame.length; i++) this.setFrame(frame[i], start + i); 39 | }else 40 | { 41 | this.setFrame(frame, start); 42 | } 43 | return this; 44 | }; 45 | 46 | /** 47 | * 指定帧frame在MovieClip的播放序列中的位置(从0开始)。 48 | */ 49 | MovieClip.prototype.setFrame = function(frame, index) 50 | { 51 | if(index == undefined || index > this._frames.length) index = this._frames.length; 52 | else if(index < 0) index = 0; 53 | 54 | this._frames[index] = frame; 55 | if(frame.label) this._frameLabels[frame.label] = frame; 56 | if(frame.interval == undefined) frame.interval = this.interval; 57 | if(index == 0 && this.currentFrame == 0) this.setRect(frame.rect); 58 | }; 59 | 60 | /** 61 | * 获得指定位置或标签的帧frame。 62 | */ 63 | MovieClip.prototype.getFrame = function(indexOrLabel) 64 | { 65 | if(typeof(indexOrLabel) == "number") return this._frames[indexOrLabel]; 66 | return this._frameLabels[indexOrLabel]; 67 | }; 68 | 69 | /** 70 | * 从当前位置开始播放动画序列。 71 | */ 72 | MovieClip.prototype.play = function() 73 | { 74 | this.paused = false; 75 | }; 76 | 77 | /** 78 | * 停止播放动画序列。 79 | */ 80 | MovieClip.prototype.stop = function() 81 | { 82 | this.paused = true; 83 | }; 84 | 85 | /** 86 | * 跳转到指定位置或标签的帧,并停止播放动画序列。 87 | */ 88 | MovieClip.prototype.gotoAndStop = function(indexOrLabel) 89 | { 90 | this.currentFrame = this.getFrameIndex(indexOrLabel); 91 | this.paused = true; 92 | }; 93 | 94 | /** 95 | * 跳转到指定位置或标签的帧,并继续播放动画序列。 96 | */ 97 | MovieClip.prototype.gotoAndPlay = function(indexOrLabel) 98 | { 99 | this.currentFrame = this.getFrameIndex(indexOrLabel); 100 | this.paused = false; 101 | }; 102 | 103 | /** 104 | * 获得指定参数对应的帧的位置。 105 | */ 106 | MovieClip.prototype.getFrameIndex = function(indexOrLabel) 107 | { 108 | if(typeof(indexOrLabel) == "number") return indexOrLabel; 109 | var frame = this._frameLabels[indexOrLabel], frames = this._frames; 110 | for(var i = 0; i < frames.length; i++) 111 | { 112 | if(frame == frames[i]) return i; 113 | } 114 | return -1; 115 | }; 116 | 117 | /** 118 | * 播放动画序列的下一帧。 119 | */ 120 | MovieClip.prototype.nextFrame = function(displayedDelta) 121 | { 122 | var frame = this._frames[this.currentFrame]; 123 | 124 | if(frame.interval > 0) 125 | { 126 | var count = this._displayedCount + displayedDelta; 127 | this._displayedCount = frame.interval > count ? count : 0; 128 | } 129 | 130 | if(frame.jump >= 0 || typeof(frame.jump) == "string") 131 | { 132 | if(this._displayedCount == 0 || !frame.interval) 133 | { 134 | return this.currentFrame = this.getFrameIndex(frame.jump); 135 | } 136 | } 137 | 138 | if(frame.interval > 0 && this._displayedCount > 0) return this.currentFrame; 139 | else if(this.currentFrame >= this._frames.length - 1) return this.currentFrame = 0; 140 | else return ++this.currentFrame; 141 | }; 142 | 143 | /** 144 | * 返回MovieClip的帧数。 145 | */ 146 | MovieClip.prototype.getNumFrames = function() 147 | { 148 | return this._frames.length; 149 | }; 150 | 151 | /** 152 | * 更新MovieClip对象的属性。 153 | */ 154 | MovieClip.prototype._update = function(timeInfo) 155 | { 156 | var frame = this._frames[this.currentFrame]; 157 | if(frame.stop) 158 | { 159 | this.stop(); 160 | return; 161 | } 162 | 163 | if(!this.paused) 164 | { 165 | var delta = this.useFrames ? 1 : timeInfo && timeInfo.deltaTime; 166 | frame = this._frames[this.nextFrame(delta)]; 167 | } 168 | this.setRect(frame.rect); 169 | 170 | MovieClip.superClass._update.call(this, timeInfo); 171 | }; 172 | 173 | /** 174 | * 渲染当前帧到舞台。 175 | */ 176 | MovieClip.prototype.render = function(context) 177 | { 178 | var frame = this._frames[this.currentFrame], rect = frame.rect; 179 | context.draw(this, rect[0], rect[1], rect[2], rect[3], 0, 0, this.width, this.height); 180 | }; 181 | 182 | })(); -------------------------------------------------------------------------------- /src/base/display/Stage.js: -------------------------------------------------------------------------------- 1 | 2 | (function(){ 3 | 4 | /** 5 | * 构造函数. 6 | * @name Stage 7 | * @augments DisplayObjectContainer 8 | * @class 舞台是显示对象的根,所有显示对象都会被添加到舞台上,必须传入一个context使得舞台能被渲染。舞台是一种特殊显示对象容器,可以容纳子显示对象。 9 | * @property stageX 舞台在页面中的X偏移量,即offsetLeft。只读属性。可通过调用updatePosition()方法更新。 10 | * @property stageY 舞台在页面中的Y偏移量,即offsetTop。只读属性。可通过调用updatePosition()方法更新。 11 | * @property paused 指示舞台更新和渲染是否暂停。默认为false。 12 | * @argument props 参数JSON格式为:{context:context} context上下文必须指定。 13 | */ 14 | var Stage = Quark.Stage = function(props) 15 | { 16 | this.stageX = 0; 17 | this.stageY = 0; 18 | this.paused = false; 19 | 20 | this._eventTarget = null; 21 | 22 | props = props || {}; 23 | Stage.superClass.constructor.call(this, props); 24 | this.id = props.id || Quark.UIDUtil.createUID("Stage"); 25 | if(this.context == null) throw "Quark.Stage Error: context is required."; 26 | 27 | this.updatePosition(); 28 | }; 29 | Quark.inherit(Stage, Quark.DisplayObjectContainer); 30 | 31 | /** 32 | * 更新舞台Stage上的所有显示对象。可被Quark.Timer对象注册调用。 33 | */ 34 | Stage.prototype.step = function(timeInfo) 35 | { 36 | if(this.paused) return; 37 | this._update(timeInfo); 38 | this._render(this.context); 39 | }; 40 | 41 | /** 42 | * 更新舞台Stage上所有显示对象的数据。 43 | */ 44 | Stage.prototype._update = function(timeInfo) 45 | { 46 | //Stage作为根容器,先更新所有子对象,再调用update方法。 47 | var copy = this.children.slice(0); 48 | for(var i = 0, len = copy.length; i < len; i++) 49 | { 50 | var child = copy[i]; 51 | child._depth = i + 1; 52 | child._update(timeInfo); 53 | } 54 | //update方法提供渲染前更新舞台对象的数据的最后机会。 55 | if(this.update != null) this.update(timeInfo); 56 | }; 57 | 58 | /** 59 | * 渲染舞台Stage上的所有显示对象。 60 | */ 61 | Stage.prototype._render = function(context) 62 | { 63 | //在canvas渲染方式下,先清除整个画布。 64 | if(context.clear != null) context.clear(0, 0, this.width, this.height); 65 | Stage.superClass._render.call(this, context); 66 | }; 67 | 68 | /** 69 | * 舞台Stage默认的事件处理器。 70 | */ 71 | Stage.prototype.dispatchEvent = function(e) 72 | { 73 | var x = e.pageX || e.clientX, y = e.pageY || e.clientY; 74 | x = (x - this.stageX) / this.scaleX; 75 | y = (y - this.stageY) / this.scaleY; 76 | var obj = this.getObjectUnderPoint(x, y, true), target = this._eventTarget; 77 | 78 | e.eventX = x; 79 | e.eventY = y; 80 | 81 | var leave = e.type == "mouseout" && !this.context.canvas.contains(e.relatedTarget); 82 | if(target != null && (target != obj || leave)) 83 | { 84 | e.lastEventTarget = target; 85 | //派发移开事件mouseout或touchout到上一个事件对象 86 | var outEvent = (leave || obj == null || e.type == "mousemove") ? "mouseout" : e.type == "touchmove" ? "touchout" : null; 87 | if(outEvent) target.dispatchEvent({type:outEvent}); 88 | this._eventTarget = null; 89 | } 90 | 91 | //派发事件到目标对象 92 | if(obj!= null && obj.eventEnabled && e.type != "mouseout") 93 | { 94 | e.eventTarget = target = this._eventTarget = obj; 95 | obj.dispatchEvent(e); 96 | } 97 | 98 | //设置光标状态 99 | if(!Quark.supportTouch) 100 | { 101 | var cursor = (target && target.useHandCursor && target.eventEnabled) ? "pointer" : ""; 102 | this.context.canvas.style.cursor = cursor; 103 | } 104 | 105 | if(leave || e.type != "mouseout") Stage.superClass.dispatchEvent.call(this, e); 106 | }; 107 | 108 | /** 109 | * 更新舞台Stage在页面中的偏移位置,即stageX/stageY。 110 | */ 111 | Stage.prototype.updatePosition = function() 112 | { 113 | var offset = Quark.getElementOffset(this.context.canvas); 114 | this.stageX = offset.left; 115 | this.stageY = offset.top; 116 | }; 117 | 118 | })(); -------------------------------------------------------------------------------- /src/base/display/Text.js: -------------------------------------------------------------------------------- 1 | 2 | (function(){ 3 | 4 | /** 5 | * 构造函数。 6 | * @name Text 7 | * @augments DisplayObject 8 | * @class Text类提供简单的文字显示功能。 9 | * @property text 指定要显示的文本内容。 10 | * @property font 指定使用的字体样式。 11 | * @property color 指定使用的字体颜色。 12 | * @property textAlign 指定文本的对齐方式。可以是以下任意一个值:"start", "end", "left", "right", and "center"。 13 | * @property outline 指定文本是绘制边框还是填充。 14 | * @property maxWidth 指定文本绘制的最大宽度。仅在canvas中使用。 15 | * @property lineWidth 指定文本行的最大宽度。 16 | * @property lineSpacing 指定文本的行距。单位为像素。 17 | * @property fontMetrics 指定字体的度量对象。一般可忽略此属性,可用于提高性能。 18 | */ 19 | var Text = Quark.Text = function(props) 20 | { 21 | this.text = ""; 22 | this.font = "12px arial"; 23 | this.color = "#000"; 24 | this.textAlign = "start"; 25 | this.outline = false; 26 | this.maxWidth = 10000; 27 | this.lineWidth = null; 28 | this.lineSpacing = 0; 29 | this.fontMetrics = null; 30 | 31 | props = props || {}; 32 | Text.superClass.constructor.call(this, props); 33 | this.id = Quark.UIDUtil.createUID("Text"); 34 | 35 | if(this.fontMetrics == null) this.fontMetrics = Text.getFontMetrics(this.font); 36 | } 37 | Quark.inherit(Text, Quark.DisplayObject); 38 | 39 | 40 | /** 41 | * 在指定的渲染上下文上绘制文本。 42 | * @private 43 | */ 44 | Text.prototype._draw = function(context) 45 | { 46 | if(!this.text || this.text.length == 0) return; 47 | 48 | //set drawing style 49 | context.font = this.font; 50 | context.textAlign = this.textAlign; 51 | context.textBaseline = "top"; 52 | if(this.outline) context.strokeStyle = this.color; 53 | else context.fillStyle = this.color; 54 | 55 | //find and draw all explicit lines 56 | var lines = this.text.split(/\r\n|\r|\n|/); 57 | var y = 0, lineHeight = this.fontMetrics.height + this.lineSpacing; 58 | this.width = this.lineWidth || 0; 59 | 60 | for(var i = 0, len = lines.length; i < len; i++) 61 | { 62 | var line = lines[i], width = context.measureText(line).width; 63 | 64 | //check if the line need to split 65 | if(this.lineWidth == null || width < this.lineWidth) 66 | { 67 | if(width > this.width) this.width = width; 68 | this._drawTextLine(context, line, y); 69 | y += lineHeight; 70 | continue; 71 | } 72 | 73 | //split the line by each single word, loop to find the break 74 | //TODO: optimize the regular expression 75 | var words = line.split(/([^\x00-\xff]|\b)/), str = words[0]; 76 | for(var j = 1, wlen = words.length; j < wlen; j++) 77 | { 78 | var word = words[j]; 79 | if(!word || word.length == 0) continue; 80 | 81 | var newWidth = context.measureText(str + word).width; 82 | if(newWidth > this.lineWidth) 83 | { 84 | this._drawTextLine(context, str, y); 85 | y += lineHeight; 86 | str = word; 87 | }else 88 | { 89 | str += word; 90 | } 91 | } 92 | 93 | //draw remaining string 94 | this._drawTextLine(context, str, y); 95 | y += lineHeight; 96 | } 97 | 98 | this.height = y; 99 | }; 100 | 101 | /** 102 | * 在指定的渲染上下文上绘制一行文本。 103 | * @private 104 | */ 105 | Text.prototype._drawTextLine = function(context, text, y) 106 | { 107 | var x = 0; 108 | switch(this.textAlign) 109 | { 110 | case "center": 111 | x = this.width*0.5; 112 | break; 113 | case "right": 114 | case "end": 115 | x = this.width; 116 | break; 117 | }; 118 | if(this.outline) context.strokeText(text, x, y, this.maxWidth); 119 | else context.fillText(text, x, y, this.maxWidth); 120 | }; 121 | 122 | /** 123 | * 指定渲染文本的字体样式。 124 | */ 125 | Text.prototype.setFont = function(font, ignoreFontMetrics) 126 | { 127 | if(this.font == font) return; 128 | this.font = font; 129 | if(!ignoreFontMetrics) this.fontMetrics = Text.getFontMetrics(this.font); 130 | }; 131 | 132 | /** 133 | * Overrideed. 134 | * @private 135 | */ 136 | Text.prototype.render = function(context) 137 | { 138 | if(context instanceof Quark.DOMContext) 139 | { 140 | var dom = this.getDrawable(context), style = dom.style; 141 | style.font = this.font; 142 | style.textAlign = this.textAlign; 143 | style.color = this.color; 144 | //Notice: be care of width/height might be 0. 145 | style.width = this.width + "px"; 146 | style.height = this.height + "px"; 147 | style.lineHeight = (this.fontMetrics.height + this.lineSpacing) + "px"; 148 | dom.innerHTML = this.text; 149 | } 150 | Text.superClass.render.call(this, context); 151 | }; 152 | 153 | /** 154 | * Overrideed. 155 | * @private 156 | */ 157 | Text.prototype.getDrawable = function(context) 158 | { 159 | //for DOMContext drawing only 160 | if(this.drawable == null) this.setDrawable(Quark.createDOM("div"), true); 161 | return this.drawable.get(this, context); 162 | }; 163 | 164 | /** 165 | * 此方法可帮助我们得到指定字体的行高、基准线等度量信息。 166 | * @method getFontMetrics 167 | * @return {Object} 返回字体的度量信息,包括height、ascent、descent等。 168 | */ 169 | Text.getFontMetrics = function(font) 170 | { 171 | var metrics = { }; 172 | var elem = Quark.createDOM("div", {style:{font:font, position:"absolute"}, innerHTML:"M"}); 173 | document.body.appendChild(elem); 174 | //the line height of the specific font style. 175 | metrics.height = elem.offsetHeight; 176 | 177 | //trick: calculate baseline shift by creating 1px height element that will be aligned to baseline. 178 | elem.innerHTML = '
    '; 179 | var baseline = elem.childNodes[0]; 180 | //the ascent value is the length from the baseline to the top of the line height. 181 | metrics.ascent = baseline.offsetTop + baseline.offsetHeight; 182 | //the descent value is the length from the baseline to the bottom of the line height. 183 | metrics.descent = metrics.height - metrics.ascent; 184 | 185 | document.body.removeChild(elem); 186 | return metrics; 187 | }; 188 | 189 | 190 | })(); -------------------------------------------------------------------------------- /src/base/event/EventConst.js: -------------------------------------------------------------------------------- 1 | 2 | (function(){ 3 | 4 | /** 5 | * 按钮Key的code映射表。 6 | */ 7 | Quark.KEY = { 8 | 9 | MOUSE_LEFT : 1, 10 | MOUSE_MID : 2, 11 | MOUSE_RIGHT : 3, 12 | 13 | BACKSPACE : 8, 14 | TAB : 9, 15 | NUM_CENTER : 12, 16 | ENTER : 13, 17 | RETURN : 13, 18 | SHIFT : 16, 19 | CTRL : 17, 20 | ALT : 18, 21 | PAUSE : 19, 22 | CAPS_LOCK : 20, 23 | ESC : 27, 24 | ESCAPE : 27, 25 | SPACE : 32, 26 | PAGE_UP : 33, 27 | PAGE_DOWN : 34, 28 | END : 35, 29 | HOME : 36, 30 | LEFT : 37, 31 | UP : 38, 32 | RIGHT : 39, 33 | DOWN : 40, 34 | PRINT_SCREEN : 44, 35 | INSERT : 45, 36 | DELETE : 46, 37 | 38 | ZERO : 48, 39 | ONE : 49, 40 | TWO : 50, 41 | THREE : 51, 42 | FOUR : 52, 43 | FIVE : 53, 44 | SIX : 54, 45 | SEVEN : 55, 46 | EIGHT : 56, 47 | NINE : 57, 48 | 49 | A : 65, 50 | B : 66, 51 | C : 67, 52 | D : 68, 53 | E : 69, 54 | F : 70, 55 | G : 71, 56 | H : 72, 57 | I : 73, 58 | J : 74, 59 | K : 75, 60 | L : 76, 61 | M : 77, 62 | N : 78, 63 | O : 79, 64 | P : 80, 65 | Q : 81, 66 | R : 82, 67 | S : 83, 68 | T : 84, 69 | U : 85, 70 | V : 86, 71 | W : 87, 72 | X : 88, 73 | Y : 89, 74 | Z : 90, 75 | 76 | CONTEXT_MENU : 93, 77 | NUM_ZERO : 96, 78 | NUM_ONE : 97, 79 | NUM_TWO : 98, 80 | NUM_THREE : 99, 81 | NUM_FOUR : 100, 82 | NUM_FIVE : 101, 83 | NUM_SIX : 102, 84 | NUM_SEVEN : 103, 85 | NUM_EIGHT : 104, 86 | NUM_NINE : 105, 87 | NUM_MULTIPLY : 106, 88 | NUM_PLUS : 107, 89 | NUM_MINUS : 109, 90 | NUM_PERIOD : 110, 91 | NUM_DIVISION : 111, 92 | F1 : 112, 93 | F2 : 113, 94 | F3 : 114, 95 | F4 : 115, 96 | F5 : 116, 97 | F6 : 117, 98 | F7 : 118, 99 | F8 : 119, 100 | F9 : 120, 101 | F10 : 121, 102 | F11 : 122, 103 | F12 : 123 104 | }; 105 | 106 | })(); -------------------------------------------------------------------------------- /src/base/event/EventDispatcher.js: -------------------------------------------------------------------------------- 1 | 2 | (function(){ 3 | 4 | /** 5 | * 构造函数. 6 | * @name EventDispatcher 7 | * @class EventDispatcher类是可调度事件的类的基类,它允许显示列表上的任何对象都是一个事件目标。 8 | */ 9 | var EventDispatcher = Quark.EventDispatcher = function() 10 | { 11 | //事件映射表,格式为:{type1:[listener1, listener2], type2:[listener3, listener4]} 12 | this._eventMap = {}; 13 | }; 14 | 15 | /** 16 | * 注册事件侦听器对象,以使侦听器能够接收事件通知。 17 | */ 18 | EventDispatcher.prototype.addEventListener = function(type, listener) 19 | { 20 | var map = this._eventMap[type]; 21 | if(map == null) map = this._eventMap[type] = []; 22 | 23 | if(map.indexOf(listener) == -1) 24 | { 25 | map.push(listener); 26 | return true; 27 | } 28 | return false; 29 | }; 30 | 31 | /** 32 | * 删除事件侦听器。 33 | */ 34 | EventDispatcher.prototype.removeEventListener = function(type, listener) 35 | { 36 | if(arguments.length == 1) return this.removeEventListenerByType(type); 37 | 38 | var map = this._eventMap[type]; 39 | if(map == null) return false; 40 | 41 | for(var i = 0; i < map.length; i++) 42 | { 43 | var li = map[i]; 44 | if(li === listener) 45 | { 46 | map.splice(i, 1); 47 | if(map.length == 0) delete this._eventMap[type]; 48 | return true; 49 | } 50 | } 51 | return false; 52 | }; 53 | 54 | /** 55 | * 删除指定类型的所有事件侦听器。 56 | */ 57 | EventDispatcher.prototype.removeEventListenerByType = function(type) 58 | { 59 | var map = this._eventMap[type]; 60 | if(map != null) 61 | { 62 | delete this._eventMap[type]; 63 | return true; 64 | } 65 | return false; 66 | }; 67 | 68 | /** 69 | * 删除所有事件侦听器。 70 | */ 71 | EventDispatcher.prototype.removeAllEventListeners = function() 72 | { 73 | this._eventMap = {}; 74 | }; 75 | 76 | /** 77 | * 派发事件,调用事件侦听器。 78 | */ 79 | EventDispatcher.prototype.dispatchEvent = function(event) 80 | { 81 | var map = this._eventMap[event.type]; 82 | if(map == null) return false; 83 | if(!event.target) event.target = this; 84 | map = map.slice(); 85 | 86 | for(var i = 0; i < map.length; i++) 87 | { 88 | var listener = map[i]; 89 | if(typeof(listener) == "function") 90 | { 91 | listener.call(this, event); 92 | } 93 | } 94 | return true; 95 | }; 96 | 97 | /** 98 | * 检查是否为指定事件类型注册了任何侦听器。 99 | */ 100 | EventDispatcher.prototype.hasEventListener = function(type) 101 | { 102 | var map = this._eventMap[type]; 103 | return map != null && map.length > 0; 104 | }; 105 | 106 | //添加若干的常用的快捷缩写方法 107 | EventDispatcher.prototype.on = EventDispatcher.prototype.addEventListener; 108 | EventDispatcher.prototype.un = EventDispatcher.prototype.removeEventListener; 109 | EventDispatcher.prototype.fire = EventDispatcher.prototype.dispatchEvent; 110 | 111 | })(); -------------------------------------------------------------------------------- /src/base/event/EventManager.js: -------------------------------------------------------------------------------- 1 | 2 | (function(){ 3 | 4 | /** 5 | * 构造函数. 6 | * @name EventManager 7 | * @class EventManager是一个简单的系统事件管理器。 8 | */ 9 | var EventManager = Quark.EventManager = function() 10 | { 11 | this.keyState = {}; 12 | this._evtHandlers = {}; 13 | }; 14 | 15 | /** 16 | * 注册Quark.Stage事件侦听,使得Stage能够接收和处理指定的事件。 17 | * @param stage Quark.Stage舞台对象。 18 | * @param events 要注册的事件类型数组。 19 | */ 20 | EventManager.prototype.registerStage = function(stage, events, preventDefault, stopPropagation) 21 | { 22 | this.register(stage.context.canvas, events, {host:stage, func:stage.dispatchEvent}, preventDefault, stopPropagation); 23 | }; 24 | 25 | /** 26 | * 删除Quark.Stage事件侦听。 27 | * @param stage Quark.Stage舞台对象。 28 | * @param events 要删除的事件类型数组。 29 | */ 30 | EventManager.prototype.unregisterStage = function(stage, events) 31 | { 32 | this.unregister(stage.context.canvas, events, stage.dispatchEvent); 33 | }; 34 | 35 | /** 36 | * 注册DOM事件侦听,当事件触发时调用callback函数。 37 | * @param target 事件目标DOM对象。 38 | * @param events 要注册事件类型数组。 39 | */ 40 | EventManager.prototype.register = function(target, events, callback, preventDefault, stopPropagation) 41 | { 42 | if(callback == null || (typeof callback == "function")) callback = {host:null, func:callback}; 43 | var params = {prevent:preventDefault, stop:stopPropagation}; 44 | 45 | var me = this, handler = function(e){me._onEvent(e, params, callback);}; 46 | 47 | for(var i = 0; i < events.length; i++) 48 | { 49 | var type = events[i], list = this._evtHandlers[type] || (this._evtHandlers[type] = []); 50 | for(var j = 0, has = false; j < list.length; j++) 51 | { 52 | var li = list[j]; 53 | if(li.target == target && li.callback.func == callback.func) 54 | { 55 | trace("duplicate callback"); 56 | has = true; 57 | break; 58 | } 59 | } 60 | if(!has) 61 | { 62 | list.push({target:target, callback:callback, handler:handler}); 63 | target.addEventListener(type, handler, false); 64 | } 65 | } 66 | }; 67 | 68 | /** 69 | * 删除对象事件侦听。 70 | * @param target 事件目标DOM对象。 71 | * @param events 要删除的事件类型数组。 72 | */ 73 | EventManager.prototype.unregister = function(target, events, callback) 74 | { 75 | for(var i = 0; i < events.length; i++) 76 | { 77 | var type = events[i], list = this._evtHandlers[type]; 78 | for(var j = 0; j < list.length; j++) 79 | { 80 | var li = list[j]; 81 | if(li.target == target && (li.callback.func == callback || callback == null)) 82 | { 83 | target.removeEventListener(type, li.handler); 84 | list.splice(j, 1); 85 | break; 86 | } 87 | } 88 | } 89 | }; 90 | 91 | /** 92 | * 内部事件处理器。 93 | * @private 94 | */ 95 | EventManager.prototype._onEvent = function(e, params, callback) 96 | { 97 | //correct touch events 98 | var ne = e, type = e.type, isTouch = e.type.indexOf("touch") == 0; 99 | if(isTouch) 100 | { 101 | ne = (e.touches && e.touches.length > 0) ? e.touches[0] : 102 | (e.changedTouches && e.changedTouches.length > 0) ? e.changedTouches[0] : e; 103 | ne.type = type; 104 | ne.rawEvent = e; 105 | } 106 | 107 | if(type == "keydown" || type == "keyup" || type == "keypress") 108 | { 109 | this.keyState[e.keyCode] = type; 110 | } 111 | 112 | //e.eventTime = Date.now(); 113 | 114 | if(callback.func != null) callback.func.call(callback.host, ne); 115 | 116 | EventManager.stop(e, !params.prevent, !params.stop); 117 | }; 118 | 119 | /** 120 | * 停止事件。 121 | * @param e 要停止的事件对象。 122 | * @param continueDefault 是否继续事件的默认行为。 123 | * @param continuePropagation 是否继续事件的冒泡。 124 | */ 125 | EventManager.stop = function(e, continueDefault, continuePropagation) 126 | { 127 | if(!continueDefault) e.preventDefault(); 128 | if(!continuePropagation) 129 | { 130 | e.stopPropagation(); 131 | if(e.stopImmediatePropagation) e.stopImmediatePropagation(); 132 | } 133 | }; 134 | 135 | })(); -------------------------------------------------------------------------------- /src/base/geom/Matrix.js: -------------------------------------------------------------------------------- 1 | 2 | (function(){ 3 | 4 | var Matrix = Quark.Matrix = function(a, b, c, d, tx, ty) 5 | { 6 | this.a = a; 7 | this.b = b; 8 | this.c = c; 9 | this.d = d; 10 | this.tx = tx; 11 | this.ty = ty; 12 | }; 13 | 14 | Matrix.prototype.concat = function(mtx) 15 | { 16 | var a = this.a; 17 | var c = this.c; 18 | var tx = this.tx; 19 | 20 | this.a = a * mtx.a + this.b * mtx.c; 21 | this.b = a * mtx.b + this.b * mtx.d; 22 | this.c = c * mtx.a + this.d * mtx.c; 23 | this.d = c * mtx.b + this.d * mtx.d; 24 | this.tx = tx * mtx.a + this.ty * mtx.c + mtx.tx; 25 | this.ty = tx * mtx.b + this.ty * mtx.d + mtx.ty; 26 | return this; 27 | }; 28 | 29 | Matrix.prototype.rotate = function(angle) 30 | { 31 | var cos = Math.cos(angle); 32 | var sin = Math.sin(angle); 33 | 34 | var a = this.a; 35 | var c = this.c; 36 | var tx = this.tx; 37 | 38 | this.a = a * cos - this.b * sin; 39 | this.b = a * sin + this.b * cos; 40 | this.c = c * cos - this.d * sin; 41 | this.d = c * sin + this.d * cos; 42 | this.tx = tx * cos - this.ty * sin; 43 | this.ty = tx * sin + this.ty * cos; 44 | return this; 45 | }; 46 | 47 | Matrix.prototype.scale = function(sx, sy) 48 | { 49 | this.a *= sx; 50 | this.d *= sy; 51 | this.tx *= sx; 52 | this.ty *= sy; 53 | return this; 54 | }; 55 | 56 | Matrix.prototype.translate = function(dx, dy) 57 | { 58 | this.tx += dx; 59 | this.ty += dy; 60 | return this; 61 | }; 62 | 63 | Matrix.prototype.identity = function() 64 | { 65 | this.a = this.d = 1; 66 | this.b = this.c = this.tx = this.ty = 0; 67 | return this; 68 | }; 69 | 70 | Matrix.prototype.invert = function() 71 | { 72 | var a = this.a; 73 | var b = this.b; 74 | var c = this.c; 75 | var d = this.d; 76 | var tx = this.tx; 77 | var i = a * d - b * c; 78 | 79 | this.a = d / i; 80 | this.b = -b / i; 81 | this.c = -c / i; 82 | this.d = a / i; 83 | this.tx = (c * this.ty - d * tx) / i; 84 | this.ty = -(a * this.ty - b * tx) / i; 85 | return this; 86 | }; 87 | 88 | Matrix.prototype.transformPoint = function(point, round, returnNew) 89 | { 90 | var x = point.x * this.a + point.y * this.c + this.tx; 91 | var y = point.x * this.b + point.y * this.d + this.ty; 92 | if(round) 93 | { 94 | x = x + 0.5 >> 0; 95 | y = y + 0.5 >> 0; 96 | } 97 | if(returnNew) return {x:x, y:y}; 98 | point.x = x; 99 | point.y = y; 100 | return point; 101 | }; 102 | 103 | Matrix.prototype.clone = function() 104 | { 105 | return new Matrix(this.a, this.b, this.c, this.d, this.tx, this.ty); 106 | }; 107 | 108 | Matrix.prototype.toString = function() 109 | { 110 | return "(a="+this.a+", b="+this.b+", c="+this.c+", d="+this.d+", tx="+this.tx+", ty="+this.ty+")"; 111 | }; 112 | 113 | })(); -------------------------------------------------------------------------------- /src/base/geom/Rectangle.js: -------------------------------------------------------------------------------- 1 | 2 | (function(){ 3 | 4 | var Rectangle = Quark.Rectangle = function(x, y, width, height) 5 | { 6 | this.x = x; 7 | this.y = y; 8 | this.width = width; 9 | this.height = height; 10 | }; 11 | 12 | Rectangle.prototype.intersects = function(rect) 13 | { 14 | return (this.x <= rect.x + rect.width && rect.x <= this.x + this.width && 15 | this.y <= rect.y + rect.height && rect.y <= this.y + this.height); 16 | }; 17 | 18 | Rectangle.prototype.intersection = function(rect) 19 | { 20 | var x0 = Math.max(this.x, rect.x); 21 | var x1 = Math.min(this.x + this.width, rect.x + rect.width); 22 | 23 | if(x0 <= x1) 24 | { 25 | var y0 = Math.max(this.y, rect.y); 26 | var y1 = Math.min(this.y + this.height, rect.y + rect.height); 27 | 28 | if(y0 <= y1) 29 | { 30 | return new Rectangle(x0, y0, x1 - x0, y1 - y0); 31 | } 32 | } 33 | return null; 34 | }; 35 | 36 | Rectangle.prototype.union = function(rect, returnNew) 37 | { 38 | var right = Math.max(this.x + this.width, rect.x + rect.width); 39 | var bottom = Math.max(this.y + this.height, rect.y + rect.height); 40 | 41 | var x = Math.min(this.x, rect.x); 42 | var y = Math.min(this.y, rect.y); 43 | var width = right - x; 44 | var height = bottom - y; 45 | if(returnNew) 46 | { 47 | return new Rectangle(x, y, width, height); 48 | }else 49 | { 50 | this.x = x; 51 | this.y = y; 52 | this.width = width; 53 | this.height = height; 54 | } 55 | }; 56 | 57 | Rectangle.prototype.containsPoint = function(x, y) 58 | { 59 | return (this.x <= x && x <= this.x + this.width && this.y <= y && y <= this.y + this.height); 60 | }; 61 | 62 | Rectangle.prototype.clone = function() 63 | { 64 | return new Rectangle(this.x, this.y, this.width, this.height); 65 | }; 66 | 67 | Rectangle.prototype.toString = function() 68 | { 69 | return "(x=" + this.x + ", y=" + this.y + ", width=" + this.width + ", height=" + this.height + ")"; 70 | }; 71 | 72 | })(); -------------------------------------------------------------------------------- /src/base/utils/Audio.js: -------------------------------------------------------------------------------- 1 | 2 | (function(){ 3 | 4 | /** 5 | * 构造函数. 6 | * @name Audio 7 | * @class Audio类是原生Audio的封装。 8 | * @param src 要加载的声音的地址。 9 | * @param preload 指示是否自动加载,在某些浏览器下无效,如IOS上的Safari。 10 | * @param autoPlay 指示是否自动播放,在某些浏览器下无效,如IOS上的Safari。 11 | * @param loop 指示是否循环播放。 12 | */ 13 | var Audio = Quark.Audio = function(src, preload, autoPlay, loop) 14 | { 15 | Audio.superClass.constructor.call(this); 16 | 17 | this.src = src; 18 | this.autoPlay = preload && autoPlay; 19 | this.loop = loop; 20 | 21 | this._loaded = false; 22 | this._playing = false; 23 | this._evtHandler = Quark.delegate(this._evtHandler, this); 24 | 25 | this._element = document.createElement('audio'); 26 | this._element.preload = preload; 27 | this._element.src = src; 28 | if(preload) this.load(); 29 | }; 30 | Quark.inherit(Audio, Quark.EventDispatcher); 31 | 32 | /** 33 | * 开始加载声音文件。 34 | */ 35 | Audio.prototype.load = function() 36 | { 37 | this._element.addEventListener("canplay", this._evtHandler, false); 38 | this._element.addEventListener("ended", this._evtHandler, false); 39 | this._element.addEventListener("error", this._evtHandler, false); 40 | try{ 41 | this._element.load(); 42 | }catch(e){trace(e);}; 43 | 44 | }; 45 | 46 | /** 47 | * 内部的声音事件处理。 48 | * @private 49 | */ 50 | Audio.prototype._evtHandler = function(e) 51 | { 52 | if(e.type == "canplay") 53 | { 54 | this._element.removeEventListener("canplay", this._evtHandler); 55 | this._element.removeEventListener("error", this._evtHandler); 56 | this._loaded = true; 57 | this.dispatchEvent({type:"loaded", target:this}); 58 | if(this.autoPlay) this.play(); 59 | }else if(e.type == "ended") 60 | { 61 | this.dispatchEvent({type:"ended", target:this}); 62 | if(this.loop) this.play(); 63 | else this._playing = false; 64 | }else if(e.type == "error") 65 | { 66 | trace("Quark.Audio Error: " + e.target.src); 67 | } 68 | }; 69 | 70 | /** 71 | * 开始播放。 72 | */ 73 | Audio.prototype.play = function() 74 | { 75 | if (this._loaded) 76 | { 77 | this._element.play(); 78 | this._playing = true; 79 | }else 80 | { 81 | this.autoPlay = true; 82 | this.load(); 83 | } 84 | }; 85 | 86 | /** 87 | * 停止播放。 88 | */ 89 | Audio.prototype.stop = function() 90 | { 91 | if(this._playing) 92 | { 93 | this._element.pause(); 94 | this._playing = false; 95 | } 96 | }; 97 | 98 | /** 99 | * 指示声音文件是否已被加载。 100 | */ 101 | Audio.prototype.loaded = function() 102 | { 103 | return this._loaded; 104 | }; 105 | 106 | /** 107 | * 指示声音是正在播放。 108 | */ 109 | Audio.prototype.playing = function() 110 | { 111 | return this._playing; 112 | }; 113 | 114 | })(); -------------------------------------------------------------------------------- /src/base/utils/ImageLoader.js: -------------------------------------------------------------------------------- 1 | 2 | (function(){ 3 | 4 | /** 5 | * 构造函数. 6 | * @name ImageLoader 7 | * @augments EventDispatcher 8 | * @class ImageLoader类是一个图片加载器,用于动态加载图片资源。 9 | * @param source 要加载的图片资源,可以是一个单独资源或多个资源的数组。图片资源格式为:{src:$url, id:$id, size:$size}。 10 | */ 11 | var ImageLoader = Quark.ImageLoader = function(source) 12 | { 13 | ImageLoader.superClass.constructor.call(this); 14 | 15 | this.loading = false; //ready-only 16 | 17 | this._index = -1; 18 | this._loaded = 0; 19 | this._images = {}; 20 | this._totalSize = 0; 21 | this._loadHandler = Quark.delegate(this._loadHandler, this); 22 | 23 | this._addSource(source); 24 | }; 25 | Quark.inherit(ImageLoader, Quark.EventDispatcher); 26 | 27 | /** 28 | * 开始顺序加载图片资源。 29 | * @param source 要加载的图片资源,可以是一个单独资源或多个资源的数组。 30 | */ 31 | ImageLoader.prototype.load = function(source) 32 | { 33 | this._addSource(source); 34 | if(!this.loading) this._loadNext(); 35 | }; 36 | 37 | /** 38 | * 添加图片资源。 39 | * @private 40 | */ 41 | ImageLoader.prototype._addSource = function(source) 42 | { 43 | if(!source) return; 44 | source = (source instanceof Array) ? source : [source]; 45 | for(var i = 0; i < source.length; i++) 46 | { 47 | this._totalSize+= source[i].size || 0; 48 | } 49 | if(!this._source) this._source = source; 50 | else this._source = this._source.concat(source); 51 | }; 52 | 53 | /** 54 | * 加载下一个图片资源。 55 | * @private 56 | */ 57 | ImageLoader.prototype._loadNext = function() 58 | { 59 | this._index++; 60 | if(this._index >= this._source.length) 61 | { 62 | this.dispatchEvent({type:"complete", target:this, images:this._images}); 63 | this._source = []; 64 | this.loading = false; 65 | this._index = -1; 66 | return; 67 | } 68 | 69 | var img = new Image(); 70 | img.onload = this._loadHandler; 71 | img.src = this._source[this._index].src; 72 | this.loading = true; 73 | }; 74 | 75 | /** 76 | * 图片加载处理器。 77 | * @private 78 | */ 79 | ImageLoader.prototype._loadHandler = function(e) 80 | { 81 | this._loaded++; 82 | var image = this._source[this._index]; 83 | image.image = e.target; 84 | var id = image.id || image.src; 85 | this._images[id] = image; 86 | this.dispatchEvent({type:"loaded", target:this, image:image}); 87 | this._loadNext(); 88 | }; 89 | 90 | /** 91 | * 返回已加载图片资源的数目。 92 | */ 93 | ImageLoader.prototype.getLoaded = function() 94 | { 95 | return this._loaded; 96 | }; 97 | 98 | /** 99 | * 返回所有图片资源的总数。 100 | */ 101 | ImageLoader.prototype.getTotal = function() 102 | { 103 | return this._source.length; 104 | }; 105 | 106 | /** 107 | * 返回已加载的图片资源的大小之和(在图片资源的大小size已指定的情况下)。 108 | */ 109 | ImageLoader.prototype.getLoadedSize = function() 110 | { 111 | var size = 0; 112 | for(var id in this._images) 113 | { 114 | var item = this._images[id]; 115 | size += item.size || 0; 116 | } 117 | return size; 118 | }; 119 | 120 | /** 121 | * 返回所有图片资源的大小之和(在图片资源的大小size已指定的情况下)。 122 | */ 123 | ImageLoader.prototype.getTotalSize = function() 124 | { 125 | return this._totalSize; 126 | }; 127 | 128 | })(); -------------------------------------------------------------------------------- /src/base/utils/Timer.js: -------------------------------------------------------------------------------- 1 | 2 | (function(){ 3 | 4 | /** 5 | * 构造函数. 6 | * @name Timer 7 | * @class Timer是一个计时器。它能按指定的时间序列运行代码。 8 | * @param interval 计时器的时间间隔。以毫秒为单位。 9 | */ 10 | var Timer = Quark.Timer = function(interval) 11 | { 12 | this.interval = interval || 50; 13 | this.paused = false; 14 | this.info = {lastTime:0, currentTime:0, deltaTime:0, realDeltaTime:0}; 15 | 16 | this._startTime = 0; 17 | this._intervalID = null; 18 | this._listeners = []; 19 | }; 20 | 21 | /** 22 | * 启动计时器。 23 | */ 24 | Timer.prototype.start = function() 25 | { 26 | if(this._intervalID != null) return; 27 | this._startTime = this.info.lastTime = this.info.currentTime = Date.now(); 28 | var me = this; 29 | var run = function(){me._intervalID = setTimeout(run, me.interval);me._run();}; 30 | run(); 31 | }; 32 | 33 | /** 34 | * 停止计时器。 35 | */ 36 | Timer.prototype.stop = function() 37 | { 38 | clearTimeout(this._intervalID); 39 | this._intervalID = null; 40 | this._startTime = 0; 41 | }; 42 | 43 | /** 44 | * 暂停计时器。 45 | */ 46 | Timer.prototype.pause = function() 47 | { 48 | this.paused = true; 49 | }; 50 | 51 | /** 52 | * 恢复计时器。 53 | */ 54 | Timer.prototype.resume = function() 55 | { 56 | this.paused = false; 57 | }; 58 | 59 | /** 60 | * 计时器的运行回调。当达到执行条件时,调用所有侦听器的step方法。 61 | * @private 62 | */ 63 | Timer.prototype._run = function() 64 | { 65 | if(this.paused) return; 66 | 67 | var info = this.info; 68 | var time = info.currentTime = Date.now(); 69 | info.deltaTime = info.realDeltaTime = time - info.lastTime; 70 | 71 | for(var i = 0, len = this._listeners.length, obj, runTime; i < len; i++) 72 | { 73 | obj = this._listeners[i]; 74 | runTime = obj.__runTime || 0; 75 | if(runTime == 0) 76 | { 77 | obj.step(this.info); 78 | }else if(time > runTime) 79 | { 80 | obj.step(this.info); 81 | this._listeners.splice(i, 1); 82 | i--; 83 | len--; 84 | } 85 | } 86 | 87 | info.lastTime = time; 88 | }; 89 | 90 | /** 91 | * 延迟一定时间time调用callback方法。 92 | * @param callback 调用的方法。 93 | * @param time 延迟的时间,以毫秒为单位。 94 | */ 95 | Timer.prototype.delay = function(callback, time) 96 | { 97 | var obj = {step:callback, __runTime:Date.now() + time}; 98 | this.addListener(obj); 99 | }; 100 | 101 | /** 102 | * 添加侦听器对象,计时器会按照指定的时间间隔来调用侦听器的step方法。即listner必需有step方法。 103 | * @param obj 侦听器对象。 104 | **/ 105 | Timer.prototype.addListener = function(obj) 106 | { 107 | if(obj == null || typeof(obj.step) != "function") throw "Timer Error: The listener object must implement a step() method!"; 108 | this._listeners.push(obj); 109 | }; 110 | 111 | /** 112 | * 删除侦听器。 113 | */ 114 | Timer.prototype.removeListener = function(obj) 115 | { 116 | var index = this._listeners.indexOf(obj); 117 | if(index > -1) 118 | { 119 | this._listeners.splice(index, 1); 120 | } 121 | }; 122 | 123 | })(); -------------------------------------------------------------------------------- /src/base/utils/UIDUtil.js: -------------------------------------------------------------------------------- 1 | 2 | (function(){ 3 | 4 | /** 5 | * UIDUtil用来生成一个全局唯一的ID。 6 | * @private 7 | */ 8 | var UIDUtil = Quark.UIDUtil = { _counter:0 }; 9 | 10 | /** 11 | * 根据指定名字生成一个全局唯一的ID,如Stage1,Bitmap2等。 12 | */ 13 | UIDUtil.createUID = function(name) 14 | { 15 | var charCode = name.charCodeAt(name.length - 1); 16 | if (charCode >= 48 && charCode <= 57) name += "_"; 17 | return name + this._counter++; 18 | }; 19 | 20 | /** 21 | * 为指定的displayObject显示对象生成一个包含路径的字符串表示形式。如Stage1.Container2.Bitmap3。 22 | */ 23 | UIDUtil.displayObjectToString = function(displayObject) 24 | { 25 | var result; 26 | for(var o = displayObject; o != null; o = o.parent) 27 | { 28 | var s = o.id != null ? o.id : o.name; 29 | result = result == null ? s : (s + "." + result); 30 | if (o == o.parent) break; 31 | } 32 | return result; 33 | }; 34 | 35 | })(); -------------------------------------------------------------------------------- /src/base/utils/Utils.js: -------------------------------------------------------------------------------- 1 | 2 | (function(){ 3 | 4 | /** 5 | * 获取URL参数。 6 | * @return {Object} 包含URL参数的键值对对象。 7 | */ 8 | Quark.getUrlParams = function() 9 | { 10 | var params = {}; 11 | var url = window.location.href; 12 | var idx = url.indexOf("?"); 13 | if(idx > 0) 14 | { 15 | var queryStr = url.substring(idx + 1); 16 | var args = queryStr.split("&"); 17 | for(var i = 0, a, nv; a = args[i]; i++) 18 | { 19 | nv = args[i] = a.split("="); 20 | params[nv[0]] = nv.length > 1 ? nv[1] : true; 21 | } 22 | } 23 | return params; 24 | }; 25 | 26 | var head = document.getElementsByTagName("head")[0]; 27 | var metas = head.getElementsByTagName("meta"); 28 | var metaAfterNode = metas.length > 0 ? metas[metas.length-1].nextSibling : head.childNodes[0]; 29 | 30 | /** 31 | * 动态添加meta到head中。 32 | * @param {Object} props 要添加的meta的属性. 格式如:{name:'viewport', content:'width=device-width'}。 33 | */ 34 | Quark.addMeta = function(props) 35 | { 36 | var meta = document.createElement("meta"); 37 | for(var p in props) meta.setAttribute(p, props[p]); 38 | head.insertBefore(meta, metaAfterNode); 39 | }; 40 | 41 | /** 42 | * 显示或关闭舞台上所有显示对象的外包围矩形。此方法主要用于调试物体碰撞区域等。 43 | * @param {Stage} stage 要调试的舞台对象。 44 | */ 45 | Quark.toggleDebugRect = function(stage) 46 | { 47 | stage.debug = !stage.debug; 48 | if(stage.debug) 49 | { 50 | stage._render = function(context) 51 | { 52 | if(context.clear != null) context.clear(0, 0, stage.width, stage.height); 53 | Quark.Stage.superClass._render.call(stage, context); 54 | 55 | var ctx = stage.context.context; 56 | if(ctx != null) 57 | { 58 | ctx.save(); 59 | ctx.lineWidth = 1; 60 | ctx.strokeStyle = "#f00"; 61 | ctx.globalAlpha = 0.5; 62 | } 63 | drawObjectRect(stage, ctx); 64 | if(ctx != null) ctx.restore(); 65 | }; 66 | }else 67 | { 68 | stage._render = function(context) 69 | { 70 | if(context.clear != null) context.clear(0, 0, stage.width, stage.height); 71 | Quark.Stage.superClass._render.call(stage, context); 72 | }; 73 | } 74 | }; 75 | 76 | /** 77 | * 绘制显示对象的外包围矩形。 78 | * @private 79 | */ 80 | function drawObjectRect(obj, ctx) 81 | { 82 | for(var i = 0; i < obj.children.length; i++) 83 | { 84 | var child = obj.children[i]; 85 | if(child.children) 86 | { 87 | drawObjectRect(child, ctx); 88 | }else 89 | { 90 | if(ctx != null) 91 | { 92 | var b = child.getBounds(); 93 | 94 | ctx.globalAlpha = 0.2; 95 | ctx.beginPath(); 96 | var p0 = b[0]; 97 | ctx.moveTo(p0.x-0.5, p0.y-0.5); 98 | for(var j = 1; j < b.length; j++) 99 | { 100 | var p = b[j]; 101 | ctx.lineTo(p.x-0.5, p.y-0.5); 102 | } 103 | ctx.lineTo(p0.x-0.5, p0.y-0.5); 104 | ctx.stroke(); 105 | ctx.closePath(); 106 | ctx.globalAlpha = 0.5; 107 | 108 | ctx.beginPath(); 109 | ctx.rect((b.x>>0)-0.5, (b.y>>0)-0.5, b.width>>0, b.height>>0); 110 | ctx.stroke(); 111 | ctx.closePath(); 112 | }else 113 | { 114 | if(child.drawable.domDrawable) child.drawable.domDrawable.style.border = "1px solid #f00"; 115 | } 116 | } 117 | } 118 | }; 119 | 120 | /** 121 | * 把DisplayObject对象绘制到一个新的画布上。可作为缓存使用,也可转换成dataURL格式的位图。 122 | * @param {DisplayObject} obj 要缓存的显示对象。 123 | * @param {Boolean} toImage 指定是否把缓存转为DataURL格式的。默认为false。 124 | * @param {String} type 指定转换为DataURL格式的图片mime类型。默认为"image/png"。 125 | * @return {Object} 显示对象的缓存结果。根据参数toImage不同而返回Canvas或Image对象。 126 | */ 127 | Quark.cacheObject = function(obj, toImage, type) 128 | { 129 | var w = obj.width, h = obj.height, mask = obj.mask; 130 | var canvas = Quark.createDOM("canvas", {width:w, height:h}); 131 | var context = new Quark.CanvasContext({canvas:canvas}); 132 | obj.mask = null; 133 | obj.render(context); 134 | obj.mask = mask; 135 | 136 | if(toImage) 137 | { 138 | var img = new Image(); 139 | img.width = w; 140 | img.height = h; 141 | img.src = canvas.toDataURL(type || "image/png"); 142 | return img; 143 | } 144 | return canvas; 145 | }; 146 | 147 | 148 | /** 149 | * 用于Quark内部实现的一个上下文。 150 | * @private 151 | */ 152 | Quark._helpContext = new Quark.CanvasContext({canvas:Quark.createDOM("canvas")}); 153 | 154 | })(); --------------------------------------------------------------------------------