基于 createJs 实现长图绘制加动画的效果,用户可通过上下滑动屏幕控制长图进度。
之前公司要开发一个长图加动画的H5项目,我看到很多类似的案例是基于白鹭来开发,但因为本人没接触过白鹭,于是自己就基于 createJs 扩展开发一个长图加动画的框架。
因为后来很多同事问我拿源码开发类似的项目,所以就决定把源码分享出来一起学习。
在这里不需要掌握 createJs,如果想做类似项目的朋友可直接使用。
当然,如果熟悉 createJs 的朋友,可基于源码 SRC 扩展更多满足自己想要的功能。
HTML
<body>
<canvas id="gallery-canvas" style="width:100%"></canvas>
</body>
<script src="easeljs.min.js"></script>
<script src="time-gallery.min.js"></script>
JS
var gallery = new TimeGallery({
id: 'gallery-canvas', // 定义画布的id(必选)
width: 750, // 定义画布的宽度,根据设计稿定义(必选)
height: window.innerHeight/window.innerWidth * 750, // 定义画布的高度,目前是屏幕高度(必选)
resourcesPath: 'assets/images/', // 定义资源文件的默认路劲(可选)
resources: [ // 定义资源文件(必选)
{ src: 'demo.png', id: 'demo' },
{ src: 'demo-sprite.png', id: 'demo-sprite' },
],
data: [], // 定义画布数据(必选)
});
gallery.play();
这里我们就成功的创建了一个空白的画布,下一步我们需要建立数据。
TimeGallery 是通过遍历 data 属性里定义的数据来创建对象,data 可定义函数并接收 TimeGallery 实例作为参数。
可能当你往下看的时候,你可能会觉得贴的代码很多,有点复杂。其实你主要了解如何创建数据,数据有哪些类型与属性,然后练练手,你就大概知道怎样创建数据。
// 定义画布数据
function canvasData(ctx) {
return [
{
id: 'demo-container',
prop: {
x: 0,
y: 0,
},
children: [
{
id: 'demo-bitmap',
type: 'bitmap',
image: ctx.getImage('demo'),
prop: {
x: 100,
y: 100,
}
}
]
}
]
}
// 把数据传给 data
var gallery = new TimeGallery({
id: 'gallery-canvas',
width: 750,
height: window.innerHeight/window.innerWidth * 750,
resourcesPath: 'assets/images/',
resources: [
{ src: 'demo.png', id: 'demo' },
{ src: 'demo-sprite.png', id: 'demo-sprite' },
],
data: canvasData, // 这里
});
gallery.play();
这里我们定义了一个 ID 为 demo-container 的容器, 位于画布 x: 0,y: 0 的位置,容器内定义了一个为 Bitmap 的子类型,位于 demo-container 容器 x: 100, y: 100的位置。
把函数 canvasData 定义的数据目录传给 data 属性。
这时候,你应该看到一张静态的图片在画面上。
数据类型分别有 Container, Bitmap, Text, Shape, Sprite,以下是每个类型的基本属性:
{
id: 'name', // 为元素指定 ID,方便其他元素调用 startById,endById,afterById
type: '', // 为元素指定数据类型,默认是 Container
// 定义基础属性
prop: {
x: 0, // 基于父元素定义初始 X 位置
y: 0, // 基于父元素定义初始 Y 位置
regX: 0, // 定义元素 X 中心点
regY: 0, // 定义元素 Y 中心点
scaleX: 1, // 定义元素初始 Scale X
scaleY: 1, // 定义元素初始 Scale Y
skewX: null, // 定义元素初始 Skew X
skewY: null, // 定义元素初始 Skew Y
rotation: 0, // 定义元素初始旋转度数
alpha: 1, // 定义元素初始透明度(0-1)
visible: true, // 定义元素是否可见
},
// 定义动画属性
animation: {
startById: '', // 与指定 ID 元素同步执行动画,不能与 afterById 共用,ID 元素必须已创建。
endById: '', // 与指定 ID 元素同步结束动画,ID 元素必须已创建,动画开始位置必须小于指定 ID 元素的结束位置。
afterById: '', // 在指定 ID 元素结束后执行动画,ID 元素必须已创建。
musicById: '', // 当动画开始执行时候,播放指定 ID <audio>
x: 0, // 动画结束后的 X 位置
y: 0, // 动画结束后的 Y 位置
top: 0, // 调整动画执行位置,例如 top:-100, 则元素在执行动画的时候延迟100像素
scaleX: 1, // 动画结束后的 Scale X
scaleY: 1, // 动画结束后的 Scale Y
skewX: null, // 动画结束后的 Skew X
skewY: null, // 动画结束后的 Skew Y
rotation: 0, // 动画结束后的旋转度数
alpha: 1, // 动画结束后透明度
sprite: [], // 动画组,根据执行进度按索引替换图片
duration: 0, // 动画执行长度
},
// 定义事件
event: {
type: 'click',
handle: function(e) {
console.log(e)
}
}
}
// 可理解是空的 DIV 容器,可多层封装
{
type: 'container', // 可不写,默认是 Container
children: [
// 定义类型
]
}
{
type: 'bitmap',
image: 'image.jpg', // 建议通过 ctx.getImage(id) 获取 resources 定义的资源
}
{
type: 'text',
prop: {
text: '你输入的文字内容',
font: 'normal 36px Arial', // '样式 大小 字体'
color: '#000',
}
}
type: 'shape',
prop: {
width: 750,
height: 750,
y: 0,
graphics: {
beginFill: ['#e8340c'], // [填充颜色]
drawRect: [0, 0, 750, 750] // 创建矩形 [填充坐标X,填充坐标Y,填充宽度,填充高度]
// drawCircle: [0, 0, 25]; // 创建圆形 [填充坐标X,填充坐标Y,半径]
}
}
// 创建序列帧动画
{
type: 'sprite',
sheet: {
images:[ctx.getImage('demo')], // [图片路径]
frames: {'height': 292, 'width': 165, 'count': 64, 'regX': 0, 'regY': 0}, // 每帧的尺寸,count是总帧数
animations: {
run: [0, 5, 'jump', 0.05], //[开始帧,结束帧,动画完成后的动作,速度]
jump: [26]
}
},
method: {
gotoAndPlay: ['run'] // 执行 run 帧动画
}
}
// 模拟序列帧,创建一帧的雪碧图
{
type: 'sprite',
sheet: {
images:[ctx.getImage('demo')], // [图片路径]
frames: [ // [定义多组一帧的动作]
[0, 1032, 489, 103],
[0, 944, 489, 67],
[0, 817, 489, 48],
],
animations: { // 指定每组动作对应 frames 帧
sprite_1: [0],
sprite_2: [1],
sprite_3: [2],
}
},
method: {
gotoAndPlay: ['run'] // 执行 run 帧动画
}
}
以上属性都是比较常用,更多属性可参考 http://www.createjs.cc/src/docs/easeljs/classes/Container.html
- 可通过 prop 定义对象的 Properties, 如 prop: {name: 'name'}
- 可通过 method 定义对象 Methods 方法,通过 [] 传参,如method: {cache: [0, 0, 100, 100]}
-
Width: window.innerWidth
定义画布宽 -
Height: window.innerHeight
定义画布高 -
isState: false
是否启动 Stage.js 用于测试FPS, 须引入 stage.js 文件 -
isLog: false
是否打印 data 数据结构,方便了解 -
resourcesPath: ''
图片资源加载的默认路劲 -
resources: []
图片资源列表,可 'name.png' 、['name.png', 'name-2.png'] 或 { id: 'name', src: 'name.png'} -
sprites: []
存放 sprite 数据,在创建 sprite 类型对象时候可通过 TimeGallery 实例获取,适合重复调用与统一管理 -
data: []
定义画布数据结构,通过遍历数据渲染画面 -
direction: vertical
定义画布滑动方向,可设置水平(horizontal)或垂直(vertical) -
mapStart: 0
定义画布开始的位置 -
mapActive: 0
定义或获取画布当前停顿的位置,因为画布可能到时候会创建很长,为了方便测试,可通过定义此属性定义开始停顿的位置 -
mapEnd: 0
定义画布结束的位置(默认取最后一个动画结束位置或画布的高度/宽度中的最大值) -
mapPlay: 屏高或屏宽
定义画布开始执行动画的位置(如垂直方向则元素从屏幕底部出现的时候执行动画,水平方向则屏幕右边) -
touchSpeed:1
设置用户滑动速度,越大,滑动的速度越快 -
autoPlay:false
设置自动播放 -
autoSpeed:1
设置自动播放的速度
onInit()
渲染完成后的回调onEnd()
滑动到最底后的回调,当回调执行后,画布动画则结束onTickStart(timeGallery)
每一帧的开始前回调,可选 TimeGallery 实例作为参数onTickEnd(timeGallery)
每一帧的结束后回调,可选 TimeGallery 实例作为参数
play()
开始动画stop()
停止动画replay()
重新开始getImage(id)
获取 resources 图片信息