spine介绍
从前端程序员的角度来说,spine就是一种动画,严格来说是一种 2D 骨骼动画,具有体积小、流畅性、方便控制等优点,功能十分强大,更多详见Spine是什么?
一个spine动画一般由三个文件组成
- 精灵图集,一个图片文件,动画用到的所有图片拼合到一张图上,以
.png结尾 - 图集数据,一个文本文件,包含各部分骨骼图片在精灵图中位置、宽高的数据,以
.atlas结尾 - 动画数据,一个json文本文件,包含动画播放过程中的所有信息:动画的整体宽高,每个骨骼图片的宽高,以及每个动画播放时骨骼的位置、缩放、旋转等信息,以
.json结尾
以上两个文本文件都有固定的格式,但咱们作为前端程序员不需要研究太多,只需要懂得如何播放就可以了
一般设计伙伴提供的spine文件都是一个文件夹,以spine的名字命名,其下是三个同名文件,文件不允许重命名,否则动画无法正常播放
播放环境
spine动画的使用场景很多,本文只介绍在Cocos Creator和h5中如何加载、播放spine。
其中Cocos版本是3.7,原生支持spine动画的播放。h5中借助pixi(v7.2.4)与pixi-spine(v4.0.4)
设计伙伴提供的spine版本为3.8.99,体现在json文件中,spine文件版本过低可能导致加载后不能正常解析
准备数据
播放spine的前提是在服务器上准备好动画数据,也就是之前提到的三个文件。为了能够正常加载与播放,我们需要这三个文件处在服务器的同一目录下,并且文件名称与动画名称一致。
具体的校验规则:
- 三个文件分别以
.png.atlas.json结尾,且文件名相同 - Atlas文件的第一行为空行,第二行为图片文件的名称
动效名称.png(如下图)
播放spine
接下来分别介绍Cocos和h5中播放spine的具体步骤
Cocos Creator
由于Cocos Creator原生支持spine的播放,实现相对简单一点,可以参考官方文档
我们现在有三个同路径的spine动画文件,并在cocos页面中创建一个节点并添加sp.Skeleton组件,接下来编写js代码
- 加载文本数据,在Cocos中使用
assetManager加载远程资源,其中先加载两个文本资源,这里设置后缀名Cocos自动帮我们解析了json对象 - 加载图片资源,同样使用
assetManager加载,其中获取的图片格式为ImageAsset。不在第一步一同加载是因为loadAny下载的图片在Web端会变成<img>节点 - 创建纹理对象,官方文档中下载的图片资源自动解析成
Texture2D格式,但估计很久没更新了,实际运行时下载的图片格式为ImageAsset,需要手动创建Texture2D对象并绑定图片资源 - 创建骨骼并设置数据,将我们前几步准备的资源按照官方教程绑定上去,其中图片名字从路径中获取
- 从json对象中获取动画名称,播放动画~
具体代码如下:
// 三个文件的远程资源路径
let imageUrl = 'https://xxx/xxx/xxx.png';
let jsonUrl = 'https://xxx/xxx/xxx.json';
let atlasUrl = 'https://xxx/xxx/xxx.atlas';
// 加载图集数据和动画数据
assetManager.loadAny(
[
{url: atlasUrl, ext: '.txt'}, // 解析为文本
{url: jsonUrl, ext: '.json'}, // 解析为json对象
],
(error, assets) => {
if (error) {
console.log('json/atlas加载出错');
return;
}
// 读取图集文本和json对象
const atlas = assets[0];
const json = assets[1];
// 加载图片 返回的结果是ImageAsset类型
assetManager.loadRemote(imageUrl, (error, imageAsset) => {
if (error) {
console.log('图片加载出错');
return;
}
// 我们要用的是Texture2D对象,需要手动创建并绑定
const texture = new Texture2D();
texture.image = imageAsset;
// 创建骨骼对象并设置数据
let asset = new sp.SkeletonData();
asset.skeletonJson = json; // 设置动画数据 这里传递json文本和json对象都可以
asset.atlasText = atlas; // 设置图集数据
asset.textures = [texture]; // 设置文本库
// 从路径中获取图片文件名称(包含.png)
let spineName = imageUrl.slice(image.lastIndexOf('/') + 1)
asset.textureNames = [spineName];// 设置图片名称
// 获取Skeleton组件 spineNode是提前在页面中准备的节点
const comp = this.spineNode.getComponent(sp.Skeleton);
// 设置spine数据
comp.skeletonData = asset;
// 循环播放动效 从json文件中读取第一个动画的名称
comp.setAnimation(0, Object.keys(json.animations)[0], true);
});
}
);
其实cocos播放在线spine不要求三个远程文件目录一致,但需要图片的文件名称与动效名相同
h5
在h5中我们采用PIXI来播放spine,createjs、min2d也是不错的动画库,但使用它们还需要根据spine数据编写许多的代码才能支持运行,不如PIXI开箱即用,具体流程如下
- 在html文件中加载
pixi.js和pixi-spine.js,这里会在window身上绑定PIXI对象,在我们加载spine时访问调用就行了 - 加载数据,PIXI也提供了资源加载的方法
Assets.load,只需要提供json文件的路径,他会自动加载同目录下的atlas和png文件 - 创建应用,这里可以传入页面中的
canvas节点,若不传则自动创建,后续需要手动添加到页面上 - 创建spine动画对象并添加到画布中,然后设置动画的位置,获取动画名称,播放动画~
html
<script src="../static/js/pixi.min.js"></script>
<script src="../static/js/pixi-spine.min.js"></script>
js
// json文件的远程资源路径
let jsonUrl = 'https://xxx/xxx/xxx.json';
// 加载图集数据和动画数据
window.PIXI.Assets.load(jsonUrl).then(resources => {
// 从骨骼数据中读取宽高
const {width, height, animations} = resources.spineData;
// 绑定canvas画布,设置宽高
const app = new window.PIXI.Application({
view: document.querySelector('#canvas'), // 设置canvas节点
backgroundAlpha: 0, // 背景透明
width,
height,
});
// 创建spine动画对象并添加到画布中
let animation = new window.PIXI.spine.Spine(resources.spineData);
app.stage.addChild(animation);
// 设置动画位置为画布中心
animation.x = width / 2;
animation.y = height / 2;
// 循环播放动画
animation.state.setAnimation(0, animations[0].name, true);
});
其实h5播放在线spine不需要文件名称与动效名相同,但要求三个远程文件的目录与名称一致
官方还介绍了通过npm导入的方式使用,但实际使用时发现下载的资源并没有被PIXI解析,无法直接使用,不如通过脚本引入
结语
以上就是Cocos和h5播放在线spine的方案,当时在寻找方案时发现网上的教程都较为落后,所以在实现功能后总结沉淀,希望能帮助到大家~