CreateJS在活动中的简单应用

一、CreateJS框架介绍

CreateJS是基于HTML5开发的一套模块化的库和工具。基于这些库,可以非常快捷地开发出基于HTML5的游戏、动画和交互应用。
它包含了四个方面:EaselJSTweenJSSoundJSPreloadJS,四个库之间可以独立使用。EaselJS主要处理图形和交互一套API,是CreateJS的核心;TweenJS是补间动画库;SoundJS是声音处理库;PreloadJS是资源预先加载库,可加载图像、声音、数据、或其他的JS。

二、活动背景

活动采用看图猜诗句形式,每个画面里包含动画声音处理,有点击交互操作,猜完诗句后进行结算,我们可以尝试使用CreateJS四个库来实现。

三、实现

1、引入四个合并的js库

1
<script src="https://code.createjs.com/createjs-2015.11.26.min.js"></script>

或者

1
require('createjs-2015.11.26.combined.js');

2、几个概念

  • 舞台(stage):所有动画元件都是在舞台上才能演出。
  • 容器(container):进行包裹作用,对它操作会影响容器里的子元件,类似一个div,可以理解为动画里的场景(scene),舞台就是一个特殊的容器。
  • 计时器(ticker):可以设置帧率,监听心跳更新舞台,达到动画效果。
  • 形状(shape):数学里的形状基本能画,里面有个强大的功能:graphics继承自Graphics类。
  • 位图(bitmap):主要处理静态图,对静态图进行操作。
  • 精灵(sprite):配合spritesheet处理帧动画。
  • 滤镜(filter)和阴影(shadow):对任意元件进行颜色变换、模糊,阴影等效果。
    其实和flash操作的概念一样,只不过这是代码方式罢了,理解了这些概念,后面的工作就是堆代码,叠积木了

3、资源加载(LoadQueue

这里使用PreloadJS中的LoadQueue类处理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var i=0, manifest = [
{src : 'bg.jpg', id : 'bg'},
{src : 'cover.jpg', id : 'cover'},
{src : 'start-btn.png', id : 'start'}
];
var loader = new createjs.LoadQueue(false);//采用标签形式加载
loader.loadManifest(manifest, true, 'img/');
loader.addEventListener('fileload', function () {
i++;
console.log((i / (manifest.length).toFixed(2) + '%');
});
loader.addEventListener('complete', function(){
console.log('load complete!');
});
  • 实例化LoadQueue ([preferXHR=true],[basePath=’’],[crossOrigin=’’]) ,设置preXHR=false,采用标签形式加载资源。
  • loadManifest (manifest,[loadNow=true],[basePath]) 接受三个参数,第一个资源的数组,第二个是否现在加载,第三个加载路径。
    • 设置了basePath=’img/‘,上面的’bg.jpg’路径变为’img/bg.jpg’
  • manifest可以有四种形式:
    • 一条字符串指向json文件,如’manifest.json’,这个json文件必须包含manifest属性
    • 一个对象object,必须包含manifest属性,其实就是上面的manifest.json文件的内容
    • 一个对象object,必须包含src属性,可以指定别名id,后续可以通过id得到这个资源
    • 一个数组,包含了一堆文件列表。

如果需要加载声音资源,需要安装SoundJS。

1
loader.installPlugin(createjs.Sound);

4、创建舞台(Stage

HTML:

1
2
<!--根据设计稿尺寸创建canvas元素-->
<canvas id="app" width="1125" height="1810"></canvas>

JS:

1
2
3
4
5
6
var stage, w, h;
stage = new createjs.Stage('app');//实例化舞台
createjs.Touch.enable(stage);//开启触摸
createjs.Ticker.addEventListener('tick', stage);//监听舞台并更新舞台
w = stage.canvas.width;
h = stage.canvas.height;

舞台已经创建好,我们可以设置一个容器stageContainer,将这个容器添加到舞台,后续需要上台的表演的元件添加到这个容器即可。

1
2
var stageContainer = new createjs.Container();
stage.addChild(stageContainer);

至此,舞台已创建好,但是什么也看不到,因为还没有添加过DisplayObject类的元件上去。

5、创建容器(Container

对页面划分区域,除了背景图外,将页面划分为四个区域,一个是图片区,二个是诗句操作区,三个是提交按钮,四个是背景区。每个区用容器包裹并命名:pictureContainer,listContainer,submitContainer和backgroundContainer。

1
2
3
4
5
6
7
8
var pictureContainer = new createjs.Container().set({name : 'pictureContainer'});
var listContainer = new createjs.Container().set({name : 'listContainer'});
var submitContainer = new createjs.Container().set({name : 'submitContainer'});
var backgroundContainer = new createjs.Container().set({
name : 'backgroundContainer',
children : [new createjs.Bitmap(loader.getResult('bg'))]//添加背景图
});
stageContainer.addChild(backgroundContainer, pictureContainer, listContainer, submitContainer);//添加到舞台

6、添加文字(Text

1
2
3
4
5
6
7
8
9
10
11
12
13
//面包屑
var navContainer = new createjs.Container().set({name : 'navContainer'});
navContainer.x = (w - 1028) / 2 + 16;
navContainer.y = 50 + 16;
//获得面包屑背景图
var nav = loader.getResult('nav');
//实例化Text类
var navText = new createjs.Text('1/10', 'normal 48px Helvetica, STHeiti STXihei, Microsoft JhengHei, Microsoft YaHei, Arial', '#000000');
navText.x = (nav.width - navText.getBounds().width) / 2;
navText.y = (nav.height - navText.getBounds().height) / 2 - 5;
navContainer.addChild(new createjs.Bitmap(nav), navText);
//缓存
navContainer.cache(0, 0, nav.width, nav.height);

Text ([text],[font],[color]) 实例化接受三个可选参数:

  • Text:显示的文本
  • Font:字体属性,css中可以用的字体属性都可以
  • color:字体颜色,css中可以用的字体颜色都可以,如”#F00”, “red”, 或 “#FF0000”
    通过getBounds()方法获得文字宽高并与背景的宽高的绝对值,取一半即可文字居中。

7、导入图片(Bitmap

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
//添加背景图
var container = new createjs.Container();
var bg = loader.getResult('p7Bg');
//让背景充满容器
container.width = bg.width;
container.height = bg.height;
container.x = (w - container.width) / 2;
container.y = 50;

//爱心
var aiXin1 = new createjs.Bitmap(loader.getResult('p7AiXin1'));
aiXin1.set({
x : 505,
y : 660,
alpha : 0,
});
var aiXin2 = new createjs.Bitmap(loader.getResult('p7AiXin2'));
aiXin2.set({
x : 476,
y : 550,
});
//鸟
var niaoYou = new createjs.Bitmap(loader.getResult('p7NiaoYou'));
niaoYou.set({
x : 485,
y : 670 + loader.getResult('p7NiaoYou').height,
regY : loader.getResult('p7NiaoYou').height,
});
var niaoZuo = new createjs.Bitmap(loader.getResult('p7NiaoZuo'));
niaoZuo.set({
x : 344,
y : 670 + loader.getResult('p7NiaoZuo').height,
regY : loader.getResult('p7NiaoZuo').height,
});

Bitmap (imageOrUri) 实例化接受一个必选参数:

  • imageOrUri:四个类型,HTMLImageElement | HTMLCanvasElement | HTMLVideoElement | String
    regX和regY属性可以理解为中心点,默认是0,0即左上角,和css是一致的。

8、创建帧动画(SpriteSheet

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//柳
var liu = new createjs.SpriteSheet({
'images' : [loader.getResult('p7Liu')],
'frames' : [
[1, 344, 538, 341, 0, -4, 0],
[1, 1, 539, 341, 0, 0, 0],
[1, 687, 537, 341, 0, -1, 0],
[1, 1373, 516, 341, 0, -12, 0],
[1, 1030, 536, 341, 0, -6, 0],
],
'animations' : {
'piao' : {
'frames' : [0, 1, 2, 3, 4],
'next' : 'piao',
'speed' : 0.4,
},
}
);

SpriteSheet (data) 实例化接受一个帧动画参数,可以使用TexturePacker生成帧动画json数据。
上面描述了一个5帧的图片,定义了一个piao的帧动画,这个piao的帧动画有5帧,播放速度为0.4倍率,执行循环播放。
再通过Sprite执行这个动画

1
var liuSprite = new createjs.Sprite(liu, 'piao').set({x : -50, y : 0, scaleX : 1.9, scaleY : 1.9});

Sprite (spriteSheet, [frameOrAnimation])

  • spriteSheet:SpriteSheet的实例
  • frameOrAnimation:初始化播放的帧数或者动画名称

9、处理影片剪辑和缓动(MovieClipTween

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
var duration = 10;
var loveMC = new createjs.MovieClip();
loveMC.timeline.addTween(
//右边鸟
createjs.Tween.get(niaoYou)
.to({scaleY : 0.99}, duration * 1.5, createjs.Ease.bounceOut),
//左边鸟
createjs.Tween.get(niaoZuo)
.to({scaleY : 0.97}, duration, createjs.Ease.bounceOut),
//心形
createjs.Tween.get(aiXin1)
.wait(duration / 4)
.to({alpha : 1})
.to({
x : 490,
y : 550,
rotation : 26,
scaleX : 2,
scaleY : 2,
alpha : 1
}, duration, createjs.Ease.bounceOut)
.to({x : 490, y : 550, rotation : 26, scaleX : 2, scaleY : 2, alpha : 0}, duration)
);
loveMC.play();

这里的影片剪辑是由3段动画组成的影片,使用了TweenJS库的Tween类。
Tween是一个静态方法,直接使用,而且和jQuery的链式方式使用一样,甚至和$.fn.animate的用法及属性基本一致。

  • get:获得运动的目标,这里是一张图片
  • to:目标运动后达到的状态,第一个参数是运行的属性,第二个是运动的时间,第三个是运动的曲线(Ease)。如果运动时间为0,就直接到达目标,如果没有指定运动曲线,默认是线性运动linear。
  • wait:等待,暂停
    MovieClip([mode=independent], [startPosition=0], [loop=true], [labels=null]) 实例化可以不用传参。
  • mode:影片剪辑模式,有三个独立模式(INDEPENDENT),单帧模式(SINGLE_FRAME),和同步模式(SYNCHED),默认是独立模式,每一个剪辑都可以单独拿出去用
  • startPosition:起始位置,默认为0
  • loop:是否循环,默认循环
  • labels:给影片剪辑的时间轴加标签

10、添加事件,处理诗句


诗句都是文字和图片的操作,使用上述的Text和Bitmap类实例化即可。
监听事件使用addEventListener,对舞台开启Touch后,监听pressup即监听touch事件。

1
2
3
submitBtn.addEventListener('pressup', function () {
console.log('touched');
});

最后成品:

四、总结

CreateJS是一门简单的入门轻量动画库,熟悉flash的同学很容易上手,关键是要理解里面的概念,及时查阅官方文档。它使用了css3动画的众多属性,如scale、rotation等,又加入了类似jQuery中animate的链式写法,上手还是很快的。进入高阶用法后,还可以配合Adobe Animate或者ZOE导出素材,使用Audio Sprite生成声音的Sprite等等。