教你用PixiJs实现复杂动画
前言
此篇文章源于前段时间商业有个项目需求,要实现一个比较复杂的H5交互动画。那说到动画常用的技术方案无非是下面几种:
gif图
css3动画属性
原生Javascript实现
Canvas
WebGL
gif图和css3动画属性显然只能实现展示型动画,而通过原生代码实现交互动画又是很复杂的,同时还得考虑动画的兼容性和性能问题。WebGL因为可提供硬件加速渲染,其渲染性能肯定是高于canvas的,但考虑到canvas与WebGL兼容性对比(如下图所示)及综合我们的项目要求,最初方案选定了用canvas实现。
但交互动画的核心在于用户交互,用户交互都是基于事件的。在canvas上绘制的图形自身不支持DOM事件,只有canvas标签支持DOM事件监听,因此还需要对canvas事件进行封装,实现相对应事件的监听及处理,还挺复杂的,这时候想要是有个canvas框架就好了,网上去搜索并对比了常用的三款canvas框架fabric.js、pixi.js及Phaser.js如下:
框架 | canvas功能支持 | 渲染 | 量级 | 事件 | 端 |
---|---|---|---|---|---|
fabric.js | 全 | svg、canvas | 轻 | 封装了canvas标签监听事件 | pc |
pixi.js | 全 | webGL、canvas | 轻 | 绘制元素上直接支持事件 | pc、移动、桌面 |
phaser.js | 全 | webGL、canvas | 重 | 绘制元素上直接支持事件 | pc、移动、桌面 |
对比发现pixi在框架量级上及渲染上都特别优秀,而且它的api简单易用,事件操作也很简单在绘制的对象上可直接操作事件,同时提供有鼠标和移动端touch事件;而fabric在渲染、事件的灵活性及端的支持上不如pixi;phaser是基于pixi封装的,在pixi优秀的渲染基础上又封装了很多游戏功能如游戏键盘手柄输入、声音支持等,所以phaser更适合做游戏,它是一款游戏引擎。
综合上面的选型分析,PixiJs很适合我们用来做交互动画及小游戏。
PixiJs
那PixiJs具体是什么样的呢?
官网的介绍总结一下是这样的:它是一款基于canvas的2D WebGL渲染引擎,可以创建丰富的交互式图形、动画和游戏。pixi的目标是提供一个快速的、轻量级且是兼容所有设备的2D库,无需了解WebGL就可以让开发者享受到硬件加速,它默认使用WebGL渲染,但在浏览器不支持的情况下可优雅降级成Canvas渲染。同时对绘制内容支持完整的鼠标和触摸事件。
其特征总结起来就是:
支持WebGL渲染,因为能调用GPU渲染,所以渲染性能高
支持canvas渲染,当设备不支持WebGL时自动使用canvas渲染,也可以手动选择canvas渲染
简单易用的api,提供了很多封装的模块
丰富的交互事件,支持完整的鼠标和移动端touch事件
不侵入你的编码风格,可以自由选择使用它的多少功能
与其他插件或框架无缝集成
了解了pixi后看它是如何使用的,Pixi的引用很方便
npm i pixi.js
import * as PIXI from "pixi.js"
引入后我们去用pixi创建一个动画的流程大概是这样的:
创建舞台
创建画布
把画布挂载到DOM上
创建精灵
显示精灵
操作精灵
1、创建舞台、画布
先解释下什么是舞台,什么是画布?
舞台是你的创作场景中所有可见对象的根容器,我们可以将它看做一个空盒子,我们在舞台上放的内容都会在画布上呈现,所有要渲染的对象是只有添加到舞台中才能被显示出来的。
画布就是一个渲染区域,把画布添加进DOM后,就会创建一个canvas标签,画布对象会默认选择WebGL引擎渲染模式。
pixi直接提供了一个应用类PIXI.Application可以自动创建舞台(stage)和画布(renderer),如下图所示:
(1)app.stage就是一个舞台对象,添加渲染对象到舞台上直接app.stage.addChild(XXX)就可以了。
(2)app.renderer是画布对象,如果你需要在创建canvas标签之后改变它的背景色,设置app.renderer对象的backgroundColor属性为一个任何的十六进制颜色即可
app.renderer.backgroundColor = 0xffffff;
如果你想获取画布的宽高,直接使用app.renderer.view.width 和app.renderer.view.height即可,同时还可以用画布的resize方法重新设置画布的宽高
app.renderer.autoResize = true;app.renderer.resize(512, 512);
2、把画布挂载到DOM上
舞台和画布已经创建好,把Pixi应用对象创建出来的HTMLCanvasElement(即app.view)添加到dom上,就可以在浏览器上看到一个白色背景的canvas渲染区了,如下图所示:
document.getElementById('draw').appendChild(app.view)
3、创建精灵
现在我们已经有了舞台和画布,就可以往舞台上添加图片,然后在画布上显示了。
我们把能放到舞台上的特殊图像对象称为精灵,精灵就是我们能用代码控制的图片,你能够控制他们的位置、大小、层次,用它来产生交互和动画,是pixi制作动画的关键因子。
pixi有一个精灵类PIXI.Sprite,直接在创建精灵方法中传入单个图片、或者雪碧图、或者一个包含图像信息的JSON对象都可以创建一个或多个精灵。
但pixi因为用WebGL和GPU去渲染图像,所以图像需要转化成GPU可以处理的形式才行,我们把可以被GPU处理的图像称作纹理。一般不能直接在PIXI.Sprite里直接传图片,要传纹理才行。而怎么加载图像并将它转化成纹理呢?pixi提供了强大的loader对象可以通过loader把上面三种类型(单张、雪碧图、JSON)图像资源转化成纹理资源,如下面代码所示:
PIXI.loader.add(['image1.png']) // 加载图片.load(setup);
// 图片加载完成时用setup的方法来使用它
function setup() {// 生成精灵let sprite = new PIXI.Sprite(// 图片转换成纹理PIXI.loader.resources['image1.png'].texture);
}
4、将精灵添加到舞台
已经制作好了精灵,按照上面介绍的舞台对象操作方法把精灵添加到舞台上就可以在画布上显示图片了。
app.stage.addChild(sprite)
单个精灵已经创建好了,如果你的动画场景比较复杂想管理一组图片,那么可以用PIXI.Container对象,把一组精灵聚合起来,如果要同时操控这一组精灵,直接操作container对象就可以了,如下图所示就是创建了2行2列的小鸟精灵,这些精灵都添加到了容器container中且容器在画布居中旋转:
代码如下:
const container = new PIXI.Container();
app.stage.addChild(container);
const birdTexture = PIXI.Texture.fromImage('bird.png');
for (let i = 0; i < 4; i++) {const bird = new PIXI.Sprite(birdTexture);bird.width = 40bird.height = 40bird.anchor.set(0.5);bird.x = (i % 2) * 40;bird.y = Math.floor(i / 2) * 40;container.addChild(bird);
}
// 设置container位置
container.x = 300;
container.y = 300;
// 设置container容器原点
container.pivot.x = container.width / 2;
container.pivot.y = container.height / 2;
// 循环旋转
app.ticker.add((delta) => {container.rotation -= 0.01 * delta;
});
一个pixi实例实际上就是一个树状结构,由一个root container(app.stage)包含所有的renderable元素,而Container也可以包含其他Container,下图是pixi实例的树状结构:
5、操作精灵
单个精灵或者一组精灵创建完后,就可以控制精灵的位置、大小、层次等进行动画交互了,Pixi常用的交互事件有:
pointer事件(兼容鼠标和触摸屏的共同触发)
mouse事件(鼠标触发)
touch事件(触摸屏触发)
事件的运用在下面的例子中会有详细介绍。这五步大概涵盖了完整动画的创建流程,下面会用一个有天空背景,鼠标拖动小鸟在天空舞动的例子介绍下pixi动画的具体实现。
PixiJs实践
1、搭建舞台、画布
const app = new PIXI.Application({width: 600,height: 600,antialias: true,transparent: false,resolution: 2,autoResize: true,backgroundColor: 0xffffff})const drawing: any = document.getElementById('draw')drawing.appendChild(this.app.view)
2、设置蓝天背景
PIXI.loader.add('sky.png').load(setup)
function setup() {let bgSprite = new PIXI.Sprite(PIXI.loader.resources['sky.png'].texture)bgSprite.width = 600bgSprite.height = 600app.stage.addChild(bgSprite);
}
效果图如下:
3、添加小鸟精灵
let birdSprite = new PIXI.Sprite(PIXI.loader.resources['bird.png'].texture)
birdSprite.width = 80
birdSprite.height = 80
birdSprite.position.set(20, 20) // 设置位置
app.stage.addChild(birdSprite)
效果图如下:
4、拖拽小鸟舞动
// 给小鸟精灵添加事件
birdSprite
.on('pointerdown', this.onDragStart)
.on('pointermove', this.onDragMove)
.on('pointerup', this.onDragEnd)
.on('pointerupoutside', this.onDragEnd)
//开始拖拽
onDragStart(event) {this.dragging = truethis.data = event.data// 鼠标点击位置和小鸟位置的偏移量,用于移动计算this.diff = { x: event.data.global.x - this.x, y: event.data.global.y - this.y }
}
//拖拽移动中
onDragMove() {if (this.dragging) {const newPosition = this.data.getLocalPosition(this.parent)// 拖拽中保证小鸟不超过背景区域this.x = Math.min(Math.max(this.boundary.left || 0, newPosition.x - this.diff.x), this.boundary.right)this.y = Math.min(Math.max(this.boundary.top || 0, newPosition.y - this.diff.y), this.boundary.bottom)}
}
//拖拽完成,松开鼠标或抬起手指
onDragEnd() {if (this.dragging) {this.dragging = falsethis.data = null}
}
5、总体效果图
总结
至此怎么用pixi实现一个交互动画就讲完了,如果动画场景再设置复杂点,然后加上音频、加上动效等开发一个酷炫的小游戏也不在话下呢~,当然pixi不仅仅只有介绍的这些功能,它还支持绘制文本、绘制几何图形、支持20多种滤镜、设置遮罩层及提供动画属性等。下图是对pixi支持功能的一个细节分类:
pixi功能很强大,是好多人制作复杂动画和小游戏的首选,但学习pixi的中文资料不多,更复杂些的功能需要查看官方英文文档和研究源码了解,欢迎大家一起研究、探讨pixi的更多更好玩的功能!
参考资料
Pixi官方文档
pixi_github
文末福利
转发本文并留下评论,我们将抽取第 10 名留言者(依据公众号后台排序),转转纪念 T 恤一件,大家快转发起来吧~
教你用PixiJs实现复杂动画相关推荐
- 一步一步教你实现iOS音频频谱动画(一)
如果你想先看看最终效果再决定看不看文章 -> bilibili 示例代码下载 第二篇:一步一步教你实现iOS音频频谱动画(二) 基于篇幅考虑,本次教程分为两篇文章,本篇文章主要讲述音频播放和频谱 ...
- 电脑制作泡泡的html代码,Flash教你如何制作吹泡泡动画特效 -电脑资料
教程贴士:这个Flash实例制作了一个有趣的"小丑吹泡泡"动画,主要运用了椭圆.直线工具,以及任意变形和渐变填充等,操作简洁易懂,适合练习, 这个Flash实例制作了一个有趣的&q ...
- html5快速制作,html5动画制作(教你如何快速绘制HTML5动画)
html5动画制作(教你如何快速绘制HTML5动画) 本周在给学生讲授JavaScript课程中setInterval方法时,想到了我们在网上看到的各类GIF动图比较有意思,就将其引入到教学中,教学内 ...
- 【PR】简单一招教你使用蒙版做文字动画
更多PR简单技巧尽在专栏中,会一直更新PR使用技巧 简单一招教你使用蒙版做文字动画 效果图 制作步骤 还可以加一个文字的缩放,从小到大的过程 博主微信欢迎交流 效果图 制作步骤 点击选择的字幕 点击钢 ...
- 手把手教你solidworks重力下落物体动画制作
手把手教你solidworks重力下落物体动画制作 1.首先建立装配体,导入圆柱和圆弧面. 2.对它们进行装配,配合方式为相切,配合的面为圆柱的圆弧面和绿色零件的弧面.然后再用宽度配合,宽度选择为圆柱 ...
- 一步一步教你实现iOS音频频谱动画(二)
如果你想先看看最终效果再决定看不看文章 -> bilibili 示例代码下载 第一篇:一步一步教你实现iOS音频频谱动画(一) 本文是系列文章中的第二篇,上篇讲述了音频播放和频谱数据计算,本篇讲 ...
- 教您自制android的开机动画LOGO
效果视频:http://v.youku.com/v_show/id_XMjcxODMxMTI0.html 第一次看到别人说改里程碑的LOGO我很激动,就安卓那些帖子的方法,我改了,开始用着还行,可是用 ...
- 学习 PixiJS — 补间动画
说明 补间动画指的是,我们可以通过为精灵的位置.比例.透明度,等属性,设置开始值和结束值,制作动画,动画中间需要的部分由软件自动计算填充. Pixi 没有内置补间引擎,但是你可以使用很多很好的开源的补 ...
- 3dmax导出fbx ue4_Maya建模师分享干货的时间到啦,教你用UE4如何导入动画
UE4中每个骨架网格物体只能将一个动画导出/导入到单个文件中,那么你知道UE4是怎么导入动画的呢? 下面使用Maya软件进行操作: 命名 当使用FBX格式将动画导入UE4时,AnimationSequ ...
最新文章
- VS 2019要来了,是时候了解一下C# 8.0新功能
- EBS并发管理器启动失败,系统暂挂,在重置计数器之前修复管理程序
- Codeforces 914D - Bash and a Tough Math Puzzle 线段树,区间GCD
- Ubuntu 局域网下查看ip及计算机名
- python调用大漠插件、检测么_python调用大漠插件教程05字库
- java 设置excel宽度_javaexcel如何设置指定列宽
- 计算机键盘数字和确键失控,电脑键盘数字键失灵怎么办
- 您全面了解“含胸拔背”吗?
- 面试官:如何用最少的老鼠试出有毒的牛奶?
- 【NOI1999、LOJ#10019】生日蛋糕(搜索、最优化剪枝、可行性剪枝)
- HTML中利用JS调用PHP (以登录为例)
- 图像处理(三)——中国传统工艺画风格的图像转换应用
- 查询起止时间为同一天,需要查到当天数据
- vs2012 nuget 基础连接已经关闭:发送时发生错误
- 憨牛女装旗舰店开业啦!
- 人体红外传感器HC-SR501
- js操作数组前面插入,后面插入
- MDK5怎么查看GPIO
- JAVA程序员工作常用英语(细心整理)计算机常用英语汇总
- Rockchip开发系列 - 3.1.GPIO IO引脚复用问题
热门文章
- mStar 6A648 双 WiFi
- iOS - 适配iOS 11
- python爬虫和定位_Python网络爬虫实战(三)照片定位与B站弹幕
- 【前端大屏实战1】Vue+Echarts -- 大屏简介初体验 => 大屏自适应缩放解决方案 => 使用transform:scale => 组件化抽离ScaleBox=>【两分钟实现大屏宽高等比例】
- Java:判断外面天气,如果下雨,男性带黑色雨伞,女性带红色雨伞;如果晴天,如果高于温度30度,男性戴墨镜,女性涂防晒霜(控制选择结构if、if else语句及其嵌套结构)
- pdf.js使用(在线预览pdf文件)
- mysql索引长度超过767bytes问题解决。Specified key was too long; max key length is 767 bytes
- oracle转行交流群,oracle多列转行
- ZYNQ裸机实现 USB MASS STORAGE (usb+sd卡 实现U盘功能)
- 苟延残喘,回光返照:从Cheetah 10K.7到Cheetah NS