Skip to content
Ali Shakiba edited this page Apr 28, 2016 · 6 revisions

Translated by Villerio, Email vrbvillor@126.com
我英语也不太好哈,如果大家发现问题,请联系我哈
QQ1192637443,邮箱vrbvillor@126.com

Stage.js is a 2D HTML5 JavaScript library for cross-platform game development, it is lightweight, fast and open-source.
Stage.js是一个2D的HTML5 Javascript库,用于跨平台游戏开发,它量轻,快速,且开源。

Why 为什么

Canvas is the graphic component of HTML5 game development, but it only has a drawing API, there is no data model like DOM to compose your application; you have to manually draw your application and manage rendering cycles to play it. Moreover, mouse events are only available at entire Canvas level and they also need to be processed manually.
Canvas是HTML游戏开发中的图形元素,但它只支持绘图接口,但它没有任何可以像DOM那样支持你应用程序操作的数据模型,你必须手动绘制你的应用程序,并且管理渲染循环才可以“玩”它。再有,鼠标事件也仅仅在整个的画布层级上可用,它们也需要被手动处理。

Stage.js provides a DOM-like tree data model to compose your application and internally manages rendering cycles and drawing of your application, it also processes and distributes mouse and touch events to targeted tree nodes.
Stage.js提供了类似于DOM的树型数据模型,来操作你的应用程序,且在内部管理渲染循环及应用程序的绘制,它也处理且向目标树节点,发布鼠标及触摸事件。

How it Works 它如何工作

A Stage.js application consists of a tree of nodes. Each node is pinned (transformed) against its parent and has zero, one or more image textures.
一个Stage.js应用包含了许多的树节点,每个节点都相对于它的父级节点定位(变型),且拥有0/1/或更多个图像纹理。

Each rendering cycle consists of ticking and drawing tree nodes. On ticking nodes adjust themselves to recent updates and then on drawing each node transforms according to its pinning and draws its textures.
每次渲染循环都包含了激活及绘制树节点,在激活节点时,会将它们调节为最近一次更新(的样子),然后在绘制每个节点时,会按照它们的“钉”对它们进行转换,再绘制它们的纹理。

Rendering is retained and is paused when there is no changed.
渲染在它没有变化时仍然被保留了下来,且为暂停状态。

// Create new app 创建一个新应用
Stage(function(stage) {

  // Set view box 设置可视区
  stage.viewbox(300, 200);

  // Create an image and append it to stage 创建一个图象,并将其加入到舞台
  var box = Stage.image('box').appendTo(stage);

  // Align box to center 将方块对准舞台中心
  box.pin('align', 0.5);

  // On mouse click... 当鼠标点击时……
  box.on('click', function(point) {
    // ...tween scale values of this node
    this.tween().ease('bounce').pin({
      scaleX : Math.random() + 0.5,
      scaleY : Math.random() + 0.5
    });
  });
});

// Adding a texture 添加纹理
Stage({
  image : 'sample.png',
  textures : {
    box : { x : 0, y : 0, width : 30, height : 30 }
  }
});

Installation 安装

Download 下载
Latest builds are available in project releases page.
最新的版本在工程发布页面上可以下载

NPM 使用NPM安装

npm install stage-js --save

Bower 使用Bower安装

bower install stage-js --save

Usage 用法

Browser 在浏览器端使用

Include an appropriate build file from dist directory in your HTML page before your application, for example:
在你的应用程序之前,将适合的构建文件,从dist目录中包含到你的HTML页面上,例如:

<script src="path/to/stage.web.min.js"></script>
<script src="path/to/your-app.js"></script>

Browserify, CommonJS, Node.js 使用这三个东西

Generally it is preferred to directly include a browser build file in HTML pages, however it is also possible to use CommonJS require instead, for example:
通常它更货币于直接将浏览器构建文件包含进HTML页,但它也可能需要使用CommonJS代替,例如:

var Stage = require('stage-js/platform/web');
See platform directory for other available modules.

API Doc 接口文档

Application 应用程序

An application is created by passing a callback function to Stage(). The library will load, create and initialize all required components and then will call the provided function with the application root node and display container which normally is a Canvas element.
应用程序就是通过Stage()的回调函数来创建的,库会先调用,创建并初始化所有包含的组件,并会在应用程序根节点上调用所提供的(回调)函数,然后将容器显示出来(通常为一个Canvas元素)。

// Create and start an application  创建并启动一个应用程序
Stage(function(stage, display) {

  // Set viewbox for stage, see pinning for valid modes
  // 设置舞台的可视区,查看可用形式的定位
  stage.viewbox(width, height, mode = 'in-pad');

  // Listen to view port resize events
  // 监听可视区的形变事件
  stage.on('viewport', function(viewport) {
    // `viewport` attributes are `width`, `height` and `ratio`
  });

  // Pause playing
  // 暂停游戏(渲染)
  stage.pause();

  // Resume playing
  // 恢复暂停
  stage.resume();
});

Tree Model 树模型

Every app consists of a tree, tree's root is provided as stage.
每个应用都包含了一个树,树的根节点(由程序)提供作为舞台。

// Create a new node instance (with no textures)
// 创建一个新节点实例(没有纹理)
var node = Stage.create();

// Append/prepend child to parent's children (accepts array)
// 追加/预加child节点,作为父元素的子节点(接受数组)
parent.append(child);
parent.prepend(child);

// Append/prepend child to parent's children
// 追加/预加child节点作为父元素的子节点
child.appendTo(parent);
child.prependTo(parent);

// Insert sibling after/before child (accepts array)
// 在child节点的后边/前边插入一个邻节点(接受数组)
child.insertNext(sibling);
child.insertPrev(sibling);

// Insert sibling after/before child
// 在child节点的后边/前边插入一个邻节点
sibling.insertAfter(child);
sibling.insertBefore(child);

// Remove child from its parent
// 将child节点从其父节点下移除
child.remove();

// Remove child from parent (accepts array)
// 将child节点从父节点下移除(接受数组)
parent.remove(child);

// Remove all of parent's children
// 删除父节点的所有子节点
parent.empty();

// Get parent's first/last (visible) child
// 获取父节点的第1个/最后1个(可见的)子节点
parent.first(onlyVisible = false);
parent.last(onlyVisible = false);

// Get immediate parent
// 获取即时的父节点
child.parent();

// Get child's next/prev (visible) sibling
// 获取子节点的下一个/上一个(可见的)邻节点
child.next(onlyVisible = false);
child.prev(onlyVisible = false);

// Get node's visiblity
// 获取节点的可见性
node.visible();
// Set node's visiblity
// 设置节点的可见性
node.visible(visible);
node.hide();
node.show();

// Iterate over parent's children, child can not be removed
// 遍历父节点的所有子节点,此种方法下子节点---不能被删除
for (var child = parent.first(); child; child = child.next()) {
  // use child 使用子节点
}

// Iterate over parent's children, child can be removed
// 遍历父节点的所有子节点,此种方法下子节点---可以被删除
var child, next = parent.first();
while (child = next) {
  next = child.next();
  // use child 使用子节点
}

// Visit node's sub-tree including node itself
// 访问节点的子树(包含本节点自己在内)
node.visit({
  start : function(node) {
    return skipChildren;
    //返回值为:是否跳过子节点
  },
  end : function(node) {
    return stopVisit;
    //返回值为:是否停止访问
  },
  reverse : reverseChildrenOrder = false,
  //参数为:是否倒序访问子节点
  visible : onlyVisibleNodes = false
  //参数为:是否只访问可见的子节点
});

Game Loop 游戏循环

Each rendering cycle consists of ticking and redrawing application tree. Application and its nodes can be updated during ticking. Depending on application activities there can be three different follow-ups after ticking:
每次渲染循环都包含了激活及重绘应用程序树。应用程序及它的节点都可以在激活时被更新,根据应用程序的活动性,下边有三种在激活后不同方式的后续行为:

  • If at least one node is touched then entire application tree will be redrawn and game loop will continue.
  • 如果至少有一个节点被触及,那个整个应用程序树都被重绘,且游戏循环会继续
  • If no node is touched but at least one ticking function returns true then game loop will continue but previous drawing will be retained.
  • 如果没有节点被触及,但至少有一个激活函数返回了true那么游戏循环会继续,但会保持之前的绘制状态
  • If no node is touched and no ticking function returns true then application will pause until it is touched directly or indirectly.
  • 如果没有节点被触及,也没有任何一个激活函数返回true那么应用程序会暂停,直到它被直接或间接地触及

Nodes can be touched directly by calling node.touch() but usually they are touched indirectly by other actions such as pinning or tree manipulation.
节点可以被直接触及,使用node.touch()方法,但通常它们都是被其它动作间接触及的,比如说定位或树的操作。

// Register a function to be called on ticking
// 注册一个用来激活的函数
node.tick(function(millisecElapsed) {
  return continueGameLoop;
}, beforeChildren = false);

// Touch node 触及节点
node.touch();

Pinning 定位

Pinning specifies how a node is attached to its parent. Pinning consists of size, transformation, positioning and transparency.
定位指定了一个节点如何附加在它的父节点上,定位包含了尺寸、转换、定位及透明度。

// Get a pinning value 获取一个定位值
node.pin(name);

// Set a pinning value 设置一个定位值
node.pin(name, value);

// Set one or more pinning values
// 设置一个或多个定位值
node.pin({
  name : value,
  ...
});

When nameX equals nameY, name shorthand can be used instead.
nameX等于nameY时,就可以简短地使用name来代替它们。

Size 尺寸

For some nodes, such as images, strings, rows and columns, size is set automatically.
对于一些节点来说,比如说图像、字符串、行和列,尺寸的设置是自动进行的

node.pin({
  height : height,
  width : width
});

// Shortcut for setting size:
// 简写的设置尺寸方法
node.size(width, height);
node.width(width);
node.height(height);

// Shortcut for getting size:
// 简写的获取尺寸方法
node.width();
node.height();

Transformation 转换

Transformation consists of scaling, skewing and rotating. Rotation is applied after scaling and skewing.
转换包含了缩放、错切及旋转。转换要应用在缩放和错切之后。

node.pin({
  scaleX : 1,
  scaleY : 1,
  skewX : 0,
  skewY : 0,
  rotation : 0
});

// Shortcut for setting transformation:
// 简写的设置转换的方法
node.scale(x, y = x);
node.scale({ x : x, y : y });
node.skew(x, y = x);
node.skew({ x : x, y : y });
node.rotate(angle);

Positioning 定位

When positioning, handle point on self is positioned at offset distance from align point on parent. Handle and align are defined as ratio of width/height, 0 is top/left and 1 is bottom/right. Handle defaults to align value when it is not specified.
当定位时,自身上的控制点,以父节点上对齐点的位置(作为参照)进行偏移。控制点及对齐点定义为width宽或height高的比例,0代表左上,1代表右下(同CSS中的background-position的关键字left/top/bottom/right的意义)。如果没指定的话,控制点默认就是对齐点的值。

node.pin({
  alignX : 0,
  alignY : 0,
  handleX : 0,
  handleY : 0,
  offsetX : 0,
  offsetY : 0
});

// Shortcut methods for setting positioning:
// 简写的用来设置定位的方法
node.offset(x, y);
node.offset({ x : x, y : y });

By default axis-aligned bounding box (AABB) after transformation is used for positioning, however it is possible to use non-transformed box by setting pivot location. Pivot location is defined as ratio of non-transformed width/height and is used as central point on self for scale, skew and rotation.
默认轴对齐包围盒(AABB盒)是要在转换后才使用定位的,但也可能会使用未转换的盒来设置枢纽定位。枢纽定位用未转换的宽高来定义,它被用作自身的缩放、错切及旋转的中心点。

node.pin({
  pivotX : 0,
  pivotY : 0
});

Transparency 透明度

Transparency can be applied to both node textures and subtree nodes or only node textures.
透明度既可以应用在节点纹理及子树节点上,又可以只应用在节点纹理自己上。

node.pin({
  alpha : 1,
  textureAlpha : 1
});

// Shortcut methods for setting transparency:
// 简写的设置透明度的方法
node.alpha(alpha);
node.alpha(alpha, textureAlpha);

Scale To 缩放至

Scale to new width/height, if mode is set scale proportionally. Valid modes are:
缩放到新的宽高,如果设置了按比例缩放,可以使用的模式有:
四种模式

in: maximum scale which keeps node edges inside scaleWidth/Height
最大化缩放,保持各边缘在scaleWidthscaleHeight(下边都使用“指定的尺寸”)的里边
in-pad: like in, but evenly pads node to fill entire scaleWidth/Height
比较像in模式,但均匀地将整个节点填充到指定的尺寸里边
out: minimum scale which keeps node edges outside scaleWidth/Height
最小化缩放,各边缘保持在指定的尺寸之外
out-crop: like out, but evenly crops it to scaleWidth/Height
out一样,但是会均匀地剪裁画面到指定的尺寸

node.pin({
  scaleMode : mode,
  scaleWidth : width,
  scaleHeight : height
});

// Shortcut method:
// 简写的方法
node.scaleTo(width, height, mode);

Events 事件

Event listeners can be registered and unregistered to nodes, listeners are called when an event is published to a node. Some events may be published to multiple nodes, but events do not propagate.
事件监听器可以用来在节点上注册及解注册(事件),监听器是在有事件发布在节点上时被调用的。有些事件可以被发布在多个节点上,但事件却不会传播(冒泡)。

// Register a listener to node
// 给节点注册一个监听器
// Event `name` can be one or an array of strings or spaced separated strings
// 事件`name`可以为一个字符串,或字符串数组,或空格隔开的字符串
node.on(name, listener);

// Unregister a listener from node.
// 解注册节点上的监听器
node.off(name, listener);

// Get listeners registered to node
// 获取节点上注册的监听器
// Returns an array or undefined
// 返回一个数组或 undefined
node.listeners(name);

// Call listeners with args
// 带参数调用监听器
// Returns number of listeners called
// 返回被调用的监听器数量
node.publish(name, args);

Mouse and Touch 鼠标和触摸

Native mouse and touch events are captured, processed and published to application nodes. Nodes receive mouse events in local coordinate, that is mouse location is specified as distance to top-left of the node.
本地的鼠标及触摸事件可以被捕获、处理及发布到应用程序的节点上,节点接收局部坐标的鼠标事件,也就是鼠标相对于节点的左上角的指定的位置

// Add click listener to node
// 向节点添加点击事件 
node.on('click', function(point) {
  // point.x and point.y are relative to this node left and top
  // point.x 和 point.y 都相对于节点左上角的
  // point.raw is original event
  // point.raw 是原始的 event 对象
});

Instead of native click events, syntatic click events are created and published to nodes. In addition to standard event types, syntatic mousecancel event type is also supported which is similar to touchcancel but is published when a mousedown is not followed by mouseup.

// Mouse events: 鼠标事件
Stage.Mouse.CLICK = 'click';
Stage.Mouse.START = 'touchstart mousedown';
Stage.Mouse.MOVE = 'touchmove mousemove';
Stage.Mouse.END = 'touchend mouseup';
Stage.Mouse.CANCEL = 'touchcancel mousecancel';

Texture 纹理

Textures are drawable objects which are used by tree nodes to draw graphics on the Canvas surface.
纹理是可绘制的对象,树节点会使用它,来在画布表面绘制图像。

Texture Atlas 纹理图集

A texture atlas (sprite sheet) consists of a set of named textures which are referenced by name in an application.
纹理图集(精灵图)包含了命名为纹理的一个集合,在应用程序中,它通过名称来被引用。

Atlases are usually created using static image files. Images referenced in atlases are automatically preloaded.
图集通常使用静态图像文件来建立,图集中的图像引用是自动预调用的。

// Adding texture atlas 添加一个纹理图集
Stage({
  name : 'mario', // optional 可选项
  image : {
    src : 'mario.png',
    ratio : 1, // optional, for high-res images 可选项,用以获取高分辨率的图像
  }
  textures : {
    stand : { x : 0,   y : 0, width : 40, height : 60 },
    walk : [
      { x : 40,  y : 0, width : 40, height : 60 },
      { x : 80,  y : 0, width : 40, height : 60 },
      { x : 120, y : 0, width : 40, height : 60 }
    ],
    number : {
      '0' : { x : 0,  y : 60, width : 10, height : 14 },
      '1' : { x : 10, y : 60, width : 10, height : 14 },
      '2' : { x : 20, y : 60, width : 10, height : 14 },
      '3' : { x : 30, y : 60, width : 10, height : 14 },
      '4' : { x : 40, y : 60, width : 10, height : 14 },
      '5' : { x : 50, y : 60, width : 10, height : 14 },
      '6' : { x : 60, y : 60, width : 10, height : 14 },
      '7' : { x : 70, y : 60, width : 10, height : 14 },
      '8' : { x : 80, y : 60, width : 10, height : 14 },
      '9' : { x : 90, y : 60, width : 10, height : 14 }
    }
  }
});

Stage.image('mario:stand');

Stage.anim('mario:walk').play();

Stage.string('mario:number').value(100);

If image src starts with ./ it will be resolved relative to current script URL.
如果图像的src./开头的话,它会被解释成相对于当前脚本URL的位置

Image 图片

An image is a node with one texture.
图片就是带有一种纹理的节点

// Create a new image instance 创建一个新的图片实例
var image = Stage.image(texture);

// Change image texture 更改图片实例
image.image(texture);

// Tile/Stretch image when pinning width and/or height
// 在定义宽或高时,平铺/拉伸图片
// To define borders add top, bottom, left and right to texture
// 要定义边框的话,就要给纹理加上top/bottom/left/right属性
image.tile();
image.stretch();

Animation 动画

An animation or anim is a node with an array of textures as frames.
动画或anim对象是带有纹理数组的节点,纹理被用作帧

// Create a new anim instance 创建一个anim实例
var anim = Stage.anim(textures, fps = 15);

// Get or set animation frame-per-second
// 获取或设置动画的帧率
anim.fps();
anim.fps(fps);

// Set animation frames, `textures` can be an array or a texture selector
// 设置动画的帧,`textures`可以是数组或纹理选择器(类似CSS选择器)
anim.frames(textures);

// Go to n-th frame 跳转到第n帧
anim.gotoFrame(n);

// Move n frames forward (or backward if n is negative)
// 向前移动n帧(如果是负数就向后n帧)
anim.moveFrame(n);

// Get number of frames 获取帧总数
anim.length();

// Start playing (from `frameName` if specified)
// 开始播放(从`frameName`开始,如果指定了的话)
anim.play(frameName = undefined);

// Stop playing (and jump to `frameName` if specified)
// 停止播放(并且跳到`frameName`帧,如果指定了的话)
anim.stop(frameName = undefined);

// Play `repeat * length` frames and then stop and call `callback`
// 播放 `repeat * length` 帧,并且停止,然后调用`callback`回调方法
anim.repeat(repeat, callback = null);

String 字符串动画

String is a row of images which are dynamically selected from frames using characters of a string value (or items of an array value).
字符串是一行图片,它使用字符串值中的每个字符(或数组值中的元素)来动态地选择帧

// Create a new string instance with frames
// 使用 frames 创建一个字符串实例
var string = Stage.string(frames);

// Set frames, a string referencing a map in an atlas 
// 设置帧,字符串所引用的图集的映射
string.frames("digits");

// Set frames, a map with textures as values and frame names as keys 
// 设置帧,一个映射,值为纹理,键为帧名称
string.frames({
  '0' : zeroTexture,
  '1' : oneTexture,
  ...
});

// Set frames, a function which takes a char (or item) and returns a texture
// 设置帧,一个接收单字符(或元素)的函数,它返回一个纹理
string.frames(function(char) {
  // create a texture for char 为这个字符创建一个纹理
  return texture;
});

// Set value, it can be a string (or an array)
// 设置值,它可以是一个字符串(或一个数组)
// Characters (or items) are used to select frames and create a row of images
// 这些字符(或元素)可以用来选择帧,创建一行图片
string.value(value);

// Get assigned value 获取分配到的值
string.value();

Row and Column 行和列

A row/column is a node which organizes its children as a horizontal/vertical sequence.
行/列也是一种节点,用来组织它的子元素,呈现横向/纵向的序列

// Create a new row/column 创建一个新的行/列
var row = Stage.row(childrenAlignY = 0);
var column = Stage.column(childrenAlignX = 0);

// Make node a row/column 将一个节点变成行/列
node.row(childrenAlignY = 0);
node.column(childrenAlignX = 0);

// Add spacing between row/column cells
// 给行/列的每一个单元添加间隙
node.spacing(space);

Box (experimental) 盒(试验中)

A box resizes to wrap its children. It can be applied to tiled/stretched images to create variable size components such as windows and buttons.
盒会重新调整尺寸以包裹它的子元素。它可以被用来平铺/拉伸图像,来创建一个变化尺寸的元素,比如说窗口或按钮

// Create a new box 创建一个新的盒元素
var box = Stage.box();

// Make node a box 将一个节点变成盒元素
node = node.box();

Tweening 补间动画

Tweening is used to apply smooth transitions to pinning values.
补间动画是应用在平滑转换的定位值上的

// Create a tweening entry 创建一个补间元素
// When `append` is true new entry is appended to current entries otherwise replaces them
// 当`append`是true时,会将一个新元素追加到当前元素集的后边,否则就会替换它们
var tween = node.tween(duration = 400, delay = 0, append = false);

// Set pinning values and start tweening
// 设置定位值来启动补间动画
// Pinning shortcut methods, such as `.scale()`, can also be used
// 定位的简写方法,比如`.scale()`也可以使用
tween.pin(pinning);

// Set easing for tweening, it can be either a function or an identifier
// 给补间动画设置缓冲,它可以是一个函数,或一个标识
// defined as 'name[-mode][(params)]', for example 'quad' or 'poly-in-out(3)'
// 定义为 '名称[-模式][(参数)]',例如'quad' 或 'poly-in-out(3)'
// Names: linear, quad, cubic, quart, quint, poly(p), sin/sine, 
//        exp, circle/circ, bounce, elastic(a, p), back(s)
// 以上这些是可用的名称
// Modes: in, out, in-out, out-in
// 以上这些是可用的模式
tween.ease(easing);

// Set duration in milliseconds
// 设置毫秒值的持续时间
tween.duration(ms);

// Set delay in milliseconds
// 设置毫秒值的延迟时间
tween.delay(ms);

// Callback when tweening is done
// 当补间动画完成后,执行回调
tween.done(function() {
  // this === node
});

// Remove this node when tweening ends
// 当补间动画完成后删除这个节点
tween.remove();

// Hide this node when tweening ends
// 当补间动画完成后隐藏这个节点
tween.hide();

// Create and chain a new tweening to this entry
// 创建一个新的补间动画,并将其链接到本元素上
var nextTween = tween.tween(duration = 400, delay = 0);

Global Methods 全局方法

// Create a new app 创建一个新应用
Stage(function(stage, display) { });

// Create and preload a texture atlas
// 创建并预调用一个纹理图集
Stage({ });

// A function to be called before starting any app
// 一个函数,可以在任意的应用程序开始之前调用
// Can be used for preloading application assets
// 它可以被用来预调用应用程序的资源
Stage.preload(function(done) {
  // Call `done` when loaded or failed
  // 当调用完成或失败时,执行`done`
  done(error);
});

// Preload and execute a JS file
// 预调用并执行一个JS文件
// URLs starting with `./` are resolved relative to current script URL
// 以`./`开头的URL地址,会被计算为相对于当前脚本URL的地址
Stage.preload(src);

// Pause playing all applications
// 暂停所有正在播放中的应用程序
Stage.pause();

// Resume playing all applications
// 恢复所有播放中的应用程序
Stage.resume();