前言
以往的一些H5运营项目,动画设计师都是先使用Animatecc(原Flash)设计动画原型,然后交给我们进行UI开发实现。 做过动画开发的童鞋都知道,动画开发是费时费力的,需要高质量的还原动画设计师设计的动画,来回沟通的成本也很大高的。
有没有一种高效的方法来改进这些流程,提高开发效率,同时完成高质量的动画呢?
经过一段时间的摸索,我发现AnimateCC(原来的Flash)可以导入canvas动画,而且它是基于createjs这个开发轻量级游戏的js库,非常适合联通上的一些h5动画。 另外还缩短了制作动画所需的时间。 同时它也是一个可视化IDE,无需编写代码即可实现高质量的动画效果; 它还可以通过Javascript为动画效果添加交互性。
比如下面这个页面的动画,如果用传统的htmlcss3动画开发或者用canvas的方式硬写代码来实现,剪图加动画开发应该用不了三天的时间; 而用AnimateCC导入,自己写一个,只需一点代码,一两个小时就可以搞定。
一些需要理解的概念
在开始之前,我们先了解一下 AnimateCC 中动画的概念。
帧率
它是指每秒投影或显示的帧或图像的数量。 设置的值越大,动画的速度就越快,但也会消耗大量的性能。 通常,24 帧就足够了。
图形和电影剪辑
我们可以将各个动画放在单独的影片剪辑中,这样我们就可以更好地控制动画。 几个独立的片段可以组成一个完整的动画。
当我们把图片从资源库拖到舞台上时,此时它只是一个普通的位图,并不能用于帧动画,所以我们必须将其转换为设备。
图形由矢量图形或位图组成。
影片剪辑包含动画影片中的影片片段,并具有自己的时间线和属性。 它是交互式的,是最通用、最实用的部分。
时间线
时间轴是我们在创建动画时使用图层和帧来组织和控制动画内容的窗口。 图层和帧中的内容随时间变化,从而形成动画。 时间线主要由图层、帧和播放头组成。
创造者
CreateJS就是CreateJS库,可以说是一个专门为HTML5游戏开发的引擎。 它目前被 Adobe 集成到 AnimateCC 中,作为导入画布动画的基本 javascript 库。
它是一个为HTML5游戏开发的引擎,包括:
EaselJS:用于绘制精灵、动画、位图和交互体验(包括多点触控)。
TweenJS:“补间动画”引擎
SoundJS:音频播放引擎
PrloadJS:资源预加载
具体的文档和demo介绍,以及API的使用方法,可以通过官网了解:
如何快速导入canvas动画?
通常动画设计会给我们一个由 AnimateCC 导入的单个 fla 源文件。 以我之前提到的demo为例,它看起来像这样:
收到后,我们需要做一些整理,首先在AnimateCC上搭建一个电影编辑设备:
构建完成后,在AnimateCC的库面板中会生成刚才构建的影片编辑器。 点击刚刚搭建的电影编辑器的链接,就会使其可编辑,然后给它起个名字,例如从这里命名为view1:
双击设备后javascript动画基础,时间线为空白。 这时需要做的就是打开动画设计师给我们的fla源文件,将时间线上的所有视口复制粘贴到新创建的影片剪辑的时间线上。
这样,我们名为 page1 的影片剪辑就包含了该页上的所有动画。 想一想,如果你想做一个h5项目,有5页游戏动画,就把每一页的动画放在对应的影片剪辑中。 这几个单独的电影片段组成了一部完整的动画。
完成这一步组织工作后,您可以单击“导入”。
它会直接将资源导入到你当前的fla文件所在的目录中:
images->动画中使用的图像资源
1.hmt->html文件
1.将js->canvas所需要的图形全部转换成canvas绘制的设备库
打开导入的js文件,可以看到刚才在影片剪辑中制作的类链接已经在js中生成了一个view1:
之后可以发现导入的html文件中混杂着js代码。 我们可以新建一个main.js文件,将html文件中的js代码放入其中,专门用于控制动画播放和编写一些交互逻辑,代码整理如下(详细说明已写注释):
html:
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no">
1
<style type="text/css">
body {
overflow:hidden;
}
<body onload="init();" style="margin:0px;">
<canvas id="canvas" width="750" height="1206">
<script src="createjs-2015.11.26.min.js">
<script src="1.js">
<script src="main.js">
然后,只需将js中对应的两行代码改为如下两行代码即可运行我们的动画:
var view1;
view1= new lib.view();
stage.addChild(view);
刚刚在animatecc上链接的影片剪辑的动画可以显示在浏览器上。
但是,有时需要在view1上放置一些额外的对象或方法javascript动画基础,那么该怎么办呢? 我们创建一个新的View1类来复合animatecc中的view1。
//view1
(function() {
"use strict";
function View1(){
this.Container_constructor();
this.back = new lib.view1();
this.addChild(this.back);
this.show = function (){
//这里可以写额外的方法
}
//this.con = new createjs.Container() 这里可以是额外处理的对象
}
var p = createjs.extend(View1,createjs.Container);
cls.View1 = createjs.promote(View1, "Container");
}());
然后创建这个类并将其放到舞台上:
js代码:
view = new cls.View();
stage.addChild(view);
最后js代码整理如下,相关代码有详细注释:
// 定义一些需要用到的变量
var canvas, stage, exportRoot, cls={};
// model来专门处理接收事件,记得要是EventDispatcher类
model = new createjs.EventDispatcher();
stageWidth = document.documentElement.clientWidth;
stageHeight = document.documentElement.clientHeight;
stageScale = stageWidth/(750/2);
canvas = document.getElementById("canvas");
if(stageWidth/stageHeight > 0.665)
{
stageScale = stageHeight/(1206/2);
}
else
{
stageScale = stageWidth/(750/2);
}
canvas.style.width = 750/2*stageScale + 'px';
canvas.style.height = 1206/2*stageScale + 'px';
function init() {
canvas = document.getElementById("canvas");
images = images||{};
// LoadQueue是一个预加载类,可以把需要加载的资源提前加载,基本支持大多数的文件预加载。
//我这里主要处理了它的2个事件,fileload,complete。
var loader = new createjs.LoadQueue(false); //这里一共可以是3个参数 第一个是是否用XHR模式加载 第二个是基础路径 第三个是跨域
loader.addEventListener("fileload", handleFileLoad);
loader.addEventListener("complete", handleComplete);
loader.loadManifest(lib.properties.manifest);
}
function handleFileLoad(evt) {
//这是单个文件加载完成的事件,把它保存到一个地方之后可以直接拿来创建对象
if (evt.item.type == "image") { images[evt.item.id] = evt.result; }
}
function handleComplete(evt) {
var queue = evt.target;
var ssMetadata = lib.ssMetadata;
for(i=0; i<ssMetadata.length; i++) {
ss[ssMetadata[i].name] = new createjs.SpriteSheet( {"images": [queue.getResult(ssMetadata[i].name)], "frames": ssMetadata[i].frames} )
}
view1 = new cls.View1();
stage = new createjs.Stage(canvas); //获取舞台 Stage是我们的舞台类,可以理解为所有canvas内部对象的总容器或者说是根显示对象。
stage.addChild(view1); //将容器放在舞台上
model.addEventListener("complete",function (){
alert("complete");
})
//Ticker是一个计时类,不过他是每过一帧触发一次的,也就是说跟时间其实没关系(因为帧频是会波动的)。
// createjs.Ticker.setFPS();和createjs.Ticker.addEventListener("tick", stageBreakHandler);是必须要加的,stageBreakHandler里面放的是刷新舞台的方法,因为createjs需要不停的刷新舞台来刷新动画,也就是一个重绘的过程。 平时也可以拿Ticker类做动画。
fnStartAnimation = function() {
createjs.Ticker.setFPS(lib.properties.fps);
createjs.Ticker.addEventListener("tick", stageBreakHandler);
}
fnStartAnimation();
}
function stageBreakHandler(event)
{
if(stageWidth!=document.documentElement.clientWidth||stageHeight!= document.documentElement.clientHeight)
{
stageWidth = document.documentElement.clientWidth;
stageHeight = document.documentElement.clientHeight;
if(stageWidth/stageHeight > 0.665)
{
stageScale = stageHeight/(1206/2);
}
else
{
stageScale = stageWidth/(750/2);
}
canvas.style.width = 750/2*stageScale + 'px';
canvas.style.height = 1206/2*stageScale + 'px';
}
stage.update();
}
//view1
(function() {
"use strict";
function View1(){
this.Container_constructor();
this.back = new lib.view1();
this.addChild(this.back);
}
var p = createjs.extend(View1,createjs.Container);
cls.View1 = createjs.promote(View1, "Container");
}());
一个动画效果就完成了,其实一开始可能需要一些时间来熟悉。 一旦熟悉了这个套路,前面就会越来越熟练。
比如下面这个h5小动画,使用前面的animatecc和createjs,7天就可以完成: